File operations and structured data

Here's the software I wrote:

https://gist.github.com/anonymous/b2e0bf58a4d8ceeb0ca6

Here's the output:

https://gist.github.com/anonymous/dc1b1afa70c92fde059f

The 'students.txt' file writes just fine so I know that's correct, but I get total garbage back when I try to get the information from the file, store it into a new array, and display it. Essentially I just want it to output the array at the very beginning of main, and be able to select and display a particular student if I enter an integer.

Any help is much appreciated.
Your code doesn't compile with my compiler, here is the error message:
main.cpp||In function ‘int main()’:|
main.cpp|40|error: no matching function for call to ‘std::basic_fstream<char>::open(const char [13], bool)’|
/opt/gcc-5.2.0/include/c++/5.2.0/fstream|1001|note: candidate: void std::basic_fstream<_CharT, _Traits>::open(const char*, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::ios_base::openmode = std::_Ios_Openmode]|
/opt/gcc-5.2.0/include/c++/5.2.0/fstream|1001|note: no known conversion for argument 2 from ‘bool’ to ‘std::ios_base::openmode {aka std::_Ios_Openmode}’|
/opt/gcc-5.2.0/include/c++/5.2.0/fstream|1022|note: candidate: void std::basic_fstream<_CharT, _Traits>::open(const string&, std::ios_base::openmode) [with _CharT = char; _Traits = std::char_traits<char>; std::__cxx11::string = std::__cxx11::basic_string<char>; std::ios_base::openmode = std::_Ios_Openmode]|
/opt/gcc-5.2.0/include/c++/5.2.0/fstream|1022|note: no known conversion for argument 2 from ‘bool’ to ‘std::ios_base::openmode {aka std::_Ios_Openmode}’|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 3 second(s)) ===|


This is the problem line:
oFile2.open("students.bin", ios::out || ios::binary);
You should be using a bitwise operator, not a logical operator in this line.

Posting the code in your post would probably garner more help.

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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
using namespace std;

struct studentInfo
{
	char name[20];
	int age;
	float gpa;
	char grade;
};

int main()
{
	//Create an array of student info
	studentInfo students[4] = {
		{ "Ann Annson", 10, 1.10, 'D' },
		{ "Bill Billson", 20, 2.20, 'C' },
		{ "Carl Carlson", 30, 3.30, 'B' },
		{ "Don Donson", 40, 4.00, 'A' },
	};

	//We need two files, just use fstream since we're inputting and outputting as well
	fstream oFile1, oFile2;

	//Write array into a text file
	oFile1.open("students.txt", ios::out);
	for (int i = 0; i < 4; i++)
	{
		oFile1 << students[i].name << "  ";
		oFile1 << students[i].age << "  ";
		oFile1 << students[i].gpa << "  ";
		oFile1 << students[i].grade << "   " << endl;
	}
	oFile1.close(); //Remember to close it

	//Write array into a binary file
	oFile2.open("students.bin", ios::out || ios::binary);
	oFile2.write(reinterpret_cast<char*>(&students), sizeof(students));
	oFile2.close();

	//Declare two new arrays; studentsText, studentsBinary
	studentInfo studentsText[4], studentsBinary[4];

	//Read data from students.txt into studentsText
	oFile1.open("students.txt", ios::in);
	for (int i = 0; i < 4; i++)
	{
		oFile1.getline(studentsText[i].name, 20);
		oFile1 >> studentsText[i].age;
		oFile1 >> studentsText[i].gpa;
		oFile1 >> studentsText[i].grade;
		oFile1.ignore();
	}
	oFile1.close(); //Remember to close it


	//Display the studentsText array
	for (int i = 0; i < 4; i++)
	{
		cout << studentsText[i].name << "   ";
		cout << studentsText[i].age << "   ";
		cout << studentsText[i].gpa << "   ";
		cout << studentsText[i].grade << "   ";
		cout << endl;
	}

	//Get stuff for binary
	oFile2.open("students.bin", ios::in | ios::binary);
	oFile2.read(reinterpret_cast<char *>(&studentsBinary), sizeof(studentsBinary));

	//Display from binary
	for (int i = 0; i < 4; i++)
	{
		cout << studentsBinary[i].name << "  ";
		cout << studentsBinary[i].age << "  ";
		cout << studentsBinary[i].gpa << "  ";
		cout << studentsBinary[i].grade << "   ";
		cout << endl;
	}
	oFile2.close();

	int student;
	studentInfo sTemp;
	oFile2.open("students.dat", ios::in | ios::binary);
	cout << "Which sudent do you want to see? ";
	cin >> student;
	oFile2.seekg((student - 1) * sizeof(student), ios::beg);
	oFile2.read(reinterpret_cast<char *>(&sTemp), sizeof(sTemp));

	cout << sTemp.name << "  "
		<< sTemp.age << "  "
		<< sTemp.gpa << "  "
		<< sTemp.grade << endl;

	return 0;
}
There are a number of errors, I pretty much found all of them, but I went through the program testing it step by step, which is what you need to do.

Here below I note a few problems, not necessarily all of them.

I'll mention that the binary file goes by two different names, "students.dat" and "students.bin", should be consistent.

When reading the text file, there are two errors (or more), first a fixed length of 20 is requested for the name, but the file is in a variable-length format. Second, the getline expects to find a newline delimiter, but there isn't one (only part-way through the line) so the file goes into a 'fail' state and nothing else is read after that. Try using get() instead of getline(). edit: Alternatively, use a delimiting character such as '|' after the name, and use that same delimiter when both writing to and reading from the text file - getline() with this delimiter should work.

In the last part, "Which sudent do you want to see? ", the wrong length is specified in the seek statement.


Last edited on
Topic archived. No new replies allowed.