Program output different on my computer

My code works on the web compiler for my homework submission website. In other words, I will get full credit for my assignment. However, on my own computer (Windows running cygwin) the output is different. I want to understand why the code doesn't output correctly on my machine even though it apparently works as intended on other computers. Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>
#include <map>
#include <iomanip>
using namespace std;

int main(){
	ifstream inFile("movie_ratings.txt");
	int N;
	float score;
	string Nstring;
	string scoreString;
	string name;

	map<string, float> totalRating;
	map<string, float> numRating;
	map<string, float>::iterator it;

	getline(inFile,Nstring);
	N = atoi(Nstring.c_str());

	for(int i=0; i<N; i++){
		getline(inFile,name);
		if(getline(inFile,scoreString)) score = atof(scoreString.c_str());
		else score = 5;
		if(totalRating.count(name)){
			totalRating[name] += score;
			numRating[name] += 1;
		}
		else{
			totalRating[name] = score;
			numRating[name] = 1;
		}
	}
	inFile.close();

	cout << setprecision(2);
	for(it=totalRating.begin(); it!=totalRating.end(); it++){
		cout << it->first << ": " << numRating[it->first] 
                << " review(s), average of " << it->second/numRating[it->first] << "/5." << endl;
	}
	return 0;
}


movie_ratings.txt is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
7
Poseidon Adventure
4
Poseidon Adventure
5
Rush
3
Poseidon Adventure
4
Rush
4
District 9
5
Star Wars: Phantom Menace
1


When I compile and run the program in cygwin the output is:
1
2
3
4
: 1 review(s), average 5/5.
: 3 review(s), average 4.3/5.
: 2 review(s), average 3.5/5.
: 1 review(s), average 1/5.


But on the homework submission website my code has this output:
1
2
3
4
District 9: 1 review(s), average 5/5.
Poseidon Adventure: 3 review(s), average 4.3/5.
Rush: 2 review(s), average 3.5/5.
Star Wars: Phantom Menace: 1 review(s), average 1/5.


This is what I want. But for some reason the title won't print on my computer. it->first doesn't work. In fact while I was trying to figure out what the problem was before I submitted it and realized my code was "working" all along, I found more weird behavior on my machine. Specifically, if I try to output anything in the iterator loop before it->first it will not be displayed.

For example
1
2
3
4
for(it=totalRating.begin(); it!=totalRating.end(); it++){
		cout << "Hello world" << it->first << ": " << numRating[it->first] 
                << " review(s), average of " << it->second/numRating[it->first] << "/5." << endl;
	}


Not only will it->first content's not output but also "Hello world" will not be displayed.

Anyone know what the problem is? It may not matter for this assignment but in the future I don't want this inconsistency between my machine and other computers to be an issue.

Can anyone test my code on their machine and see if it works for them? Since it worked on the submission website I imagine it's a problem with my computer.

Thank you!

p.s. I know that there are other things about my code that could be improved. Like I'm sure there is a better way of extracting the info from the file than getline and converting with atof/atoi. I would appreciate any other suggestions that you are willing to offer in regards to my code in general. I do know about auto& it offered in c++11 but the submission website doesn't support that compiler so that's why I didn't use auto.
Last edited on
Windows 7, compiled with DevC++ 5.11

C:\Temp>test124
District 9: 1 review(s), average of 5/5.
Poseidon Adventure: 3 review(s), average of 4.3/5.
Rush: 2 review(s), average of 3.5/5.
Star Wars: Phantom Menace: 1 review(s), average of 1/5.
Thanks for testing it for me. Good to know my code works actually works! Now I just have to find out what's wrong with the output on my computer. Maybe I'll reinstall cygwin. It's just weird because I've written 30+ programs on this machine without this inconsistent output showing up before.
make a breakpoint on line 41 and inspect `it->first' on the debugger.
I suspect that the string ends with '\r', so it is overwritting the line.

If that's the case, the problem is on the input file, that was done in another OS.
The cygutils package

The optional cygutils package contains miscellaneous tools that are small enough to not require their own package. It is not included in a default Cygwin install; select it from the Utils category in setup.exe. Several of the cygutils tools are useful for interacting with Windows.

One of the hassles of Unix-Windows interoperability is the different line endings on text files. As mentioned in the section called “Text and Binary modes”, Unix tools such as tr can convert between CRLF and LF endings, but cygutils provides several dedicated programs: conv, d2u, dos2unix, u2d, and unix2dos. Use the --help switch for usage information. http://www.cygwin.com/cygwin-ug-net/using-effectively.html


Another way of writing this program (with just one map):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <fstream>
#include <map>
#include <iomanip>

int main() {

    const char* const file_name = "movie_ratings.txt" ;

    {
        // create a test file (this won't be there in the final code)
        std::ofstream(file_name) << "7\nPoseidon Adventure\n4\nPoseidon Adventure\n5\nRush\n3\n"
        "Poseidon Adventure\n4\nRush\n4\nDistrict 9\n5\nStar Wars: Phantom Menace\n1\n" ;
    }

    // we need just one map, with pair::first holding the count of ratings, pair::second holding the total rating
    std::map< std::string, std::pair<int,double> > ratings ;

    std::ifstream file(file_name);

    int num_entries ;
    file >> num_entries ;

    std::string name ;
    double rating_value ;

    // file >> std::ws discard white space (throw away the new line left in the input buffer after formatted input)
    for( int i = 0 ; i < num_entries && file >> std::ws && std::getline( file, name ) && file >> rating_value ; ++i ) {

        // note: ratings[name] if the key is not present in the map, a new key will be inserted into the map
        // if an insertion is done, the mapped data (pair) will be value initialised ie. will be { 0.0, 0 }
        ++ratings[name].first ;
        ratings[name].second += rating_value ;
    }

    std::cout << std::fixed << std::setprecision(2) ;
    typedef std::map< std::string, std::pair<int,double> >::iterator iterator ;

    for( iterator it = ratings.begin(); it != ratings.end(); ++it ) {

        const int num_ratings = it->second.first ;
        const double total_rating = it->second.second ;

        std::cout << it->first << ": " << num_ratings << " review(s), average of "
                  << total_rating / num_ratings << "/5.\n" ;
    }
}
It's printing the title, you just aren't seeing it.

The problem is line endings of the input file, which I strongly suspect ends in \r\n. On your PC, it thinks \n is the end-of-line character and \r is part of the title. So when it prints the first line (for District 9), it prints:
District 9\r

The \r (carriage return) sends the cursor back to the beginning of the line. Then it continues to print:
: 1 review(s), average 5/5.

This overwrites "District 9".

To verify this, create a line with a very large title:
The Amazing Tales of Dave's Navel Lint and How it Saved the World from Destruction.
5

The output will probably look like this:
:1 review(s), average of 5/5.vel Lint and How it Saved the World from Destruction.

In this case, the text after the \r doesn't completely overwrite the title.

To fix this, just fix the input file.

Topic archived. No new replies allowed.