Odd output when passing file stream as reference

In the code below, I am supposed to read the following from a data file:

Dean DeFino 88 98 99
Sally Johnson 78 89 82
Bill Benny 75 79 81
Thomas Billows 78 84 89

However, I get this output:
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
49
50
Dean DeFino           88        98        99
hnson   78  89        82-1850860984     32742
         0         0        28
         0-413051128        48
-1608528832     32767-415228472
0    -49089-1024065536   6406657
-512190696        48     18048
     32767         0         0
0-1850766544     32742-520043854
0        48-517861416        48
-1608527569     32767-520043904
0     32767-520041858        48
-1564475392    -49089         0
        48-1850766544     32742
-514484708        48     26100
         0-1608527632     32767
`-1608528304     32767-310120049
0        48         0         0
-1608527592     32767-1608527584
        48-520056170        48
`-1850862392     32742-1608528432
     32742 479434334         0
   7491161         0        30
a         0-1608528048     32767
H<@0-1024065536   6406657-1398731262
f 673193995 5371330921477443664
DB(         0         0-1850860160
        48-515832000        48
0      2027         1-520053849
0     32742-1608527968     32767
-1850860160     32742 479434334
         0-1850860160     32742
         6         0-1850860928
        48         6         0
[-310357908        48         0
        48-520056170        48
-310356040        48-1608527984
     32742 725871085         0
  11341735         0        45
0         0-1608527600     32767
H<@0-310281904        48-1850766920
     32767-1850767776     32742
         0         0-1850860808
         0-515832000        48
@@       786         1         0
        48-1608527520     32767
-1850860808     32742 725871085
         0-1850860808     32742
         1     32767-517860984
0         1-310305400        48


It appears that only the first line and a half are read correctly. Given the code below, I do not see where the issue is. Any thoughts?

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  #include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;

const int NAMESIZE = 15;
const int MAXRECORDS = 50;
struct Grades                           
{
	char name[NAMESIZE + 1];
	int test1;
	int test2;
	int final;

};

typedef Grades gradeType[MAXRECORDS];

void readIt(ifstream&, gradeType, const int);

int main()

{
	ifstream indata;
	indata.open("graderoll.dat");
	int numRecord;                
	gradeType studentRecord;
	
	if (!indata)
	{
		cout << "Error opening file. \n";
		cout << "It may not exist where indicated" << endl;
		return 1;
	}

	readIt(indata, studentRecord, MAXRECORDS);

	
	for (int count = 0; count < MAXRECORDS; count++)
	{
		cout << studentRecord[count].name << setw(10)
			 << studentRecord[count].test1
			 << setw(10) << studentRecord[count].test2;
		cout << setw(10) << studentRecord[count].final << endl;
	}

	indata.close();

	return 0;
}

void readIt(ifstream& inData, gradeType gradeRec, const int max)

{
	int total = 0;
	
	inData.get(gradeRec[total].name, NAMESIZE);
	while (inData)
	{
		inData >> gradeRec[total].test1;
		inData >> gradeRec[total].test2;
		inData >> gradeRec[total].final;

		total++;     // add one to total
		
		if (!inData.eof())
			inData.get(gradeRec[total].name, NAMESIZE);
	}

}
Last edited on
This is confusing...
You use std::ifstream but you still use a char-array to represent a string?

Why don't you just use std::string for the name?
you could use operator>> to get the name if you store it as a string.
And even better, you could pass std::istream as parameter, then you could also use this function with std::cin (standardinput from the console)
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
struct Grades                           
{
    std::string name;
    int test1;
    int test2;
    int final;
};

// ...

void readIt(istream& is, gradeType gradeRec, const int max)
{
	int total = 0;
	
	while (is) // this will loop forever if you pass std::cin at the moment
	{
	    // get name
	    std::string pname;
	    is >> gradeRec[total].name;
	    is >> pname;
	    gradeRec[total].name += pname;
	    
	    // get point 
	    is >> gradeRec[total].test1;
	    is >> gradeRec[total].test2;
	    is >> gradeRec[total].final;

	    total++;     // add one to total
	}
}


The random numbers in your output have a pretty simple source.
In your example you only have 4 entries but MAXRECORDS is set to 50.
The other 46 entries of the array are never accessed and/or initialized and so they have some undefined data stored in them which causes random numbers to be printed out everywhere.

To make a workaround you could use the std::vector class from the standard c++ library, it is a class that dynamically allocates data for a new element whenever you need it.

using all things i've talked about now your code and changing the readIt function that it only reads 1 entry your code could look something like this:
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <fstream> // ifstream
#include <iostream> // cout; endl
#include <iomanip> // setw
#include <string> // string
#include <vector> // vector
using namespace std;

struct Grades                           
{
    string name;
    int test1;
    int test2;
    int final;
};

// Works with all istreams now! :D
Grades readIt(istream&);

int main()
{
	ifstream indata;
	indata.open("graderoll.dat");
    vector<Grades> studentRecord;           
	
	if (!indata)
	{
		cout << "Error opening file. \n";
		cout << "It may not exist where indicated" << endl;
		return 1;
	}
	else {
	    while(indata) { // add student records as long as eof is not reached
            studentRecord.push_back(readIt(indata));
	    }
	}
    
    // studentRecord knows it's size! :D
    for (int count = 0; count < studentRecord.size(); count++)
    {
        cout << studentRecord[count].name << setw(10)
             << studentRecord[count].test1
             << setw(10) << studentRecord[count].test2;
        cout << setw(10) << studentRecord[count].final << endl;
    }

    return 0;
}

// Works with all istreams now! :D
Grades readIt(istream& is)
{   
    Grades grade;
    
    // get name
    string pname;
    is >> grade.name;
    is >> pname;
    grade.name += pname;
        
        // get points
    is >> grade.test1;
    is >> grade.test2;
    is >> grade.final;
    
    return grade;
}


I hope you learned a little bit from that post :)
Topic archived. No new replies allowed.