URGENT: C++ program can't read text file/text file content of user-defined file name

Need help with our final program for the semester.

If I create a student record and open it in the program after, it would successfully print out the record. But if I create multiple records, then try opening them in the program, it would only print out the last record I inputted. Also, once the program is terminated and if I run it again, it would not print out the records which I previously created.

Hope someone could help me. Thanks!
Btw, I'm using Dev C++.

Here's the code:

#include <iostream>
#include <string>
#include <fstream>


using namespace std;


char FileName[10]; //Student Number
char name[60];
int NumViolation;
char violation1[100], violation2[100], violation3[100];
char penalty1[50], penalty2[50], penalty3[50];

void AddViolation();
void ClearRecord();
void Open();

int main()
{
int choice;
system("cls");
system("title ADMIN FUNCTIONS");
cout << "1.CREATE Student Record" << endl;
cout << "2.CLEAR Student Record" << endl;
cout << "3. OPEN Student Record" << endl;
cout << "Enter choice: ";
cin >> choice;

switch (choice)
{
case 1:
AddViolation();
break;
case 2:
ClearRecord();
break;
case 3:
Open();
break;
}

}


void AddViolation()
{
system("cls");
cout << "Enter Student Number: ";
cin >> FileName;
cin.sync();
system("cls");

ofstream StudentFile;
StudentFile.open(FileName,ios::app);

cout << "[Last Name, First Name Middle Initial]" << endl;
cout << "Enter Student's Full Name: ";
cin.getline(name,60);
system("cls");

cout << "Enter No. of Violations: ";
cin >> NumViolation;
system("cls");

switch (NumViolation)
{
case 1:
cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
break;

case 2:

cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
system("cls");
cout << "Enter violation 2:";
cin.getline(violation2,100);
system("cls");
cout << "Enter penalty 2:";
cin.getline(penalty2,50);
break;
case 3:

cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
system("cls");
cout << "Enter violation 2:";
cin.getline(violation2,100);
system("cls");
cout << "Enter penalty 2:";
cin.getline(penalty2,50);
system("cls");
cout << "Enter violation 3:";
cin.getline(violation3,100);
system("cls");
cout << "Enter penalty 3:";
cin.getline(penalty3,50);
break;
}
cin.get();


if (NumViolation == 1)
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile.close();
}
else if (NumViolation == 2)
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile << violation2 << endl;
StudentFile << penalty2 << endl;
StudentFile.close();
}
else
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile << violation2 << endl;
StudentFile << penalty2 << endl;
StudentFile << violation3 << endl;
StudentFile << penalty3 << endl;
StudentFile.close();
}

main();
}

void Open()
{
cout << "Enter SN: ";
cin >> FileName;

ifstream StudentFile;
StudentFile.open(FileName);

if (NumViolation == 1)
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
}
else if (NumViolation == 2)
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
cout << violation2 << endl;
cout << penalty2 << endl;
}
else
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
cout << violation2 << endl;
cout << penalty2 << endl;
cout << violation3 << endl;
cout << penalty3 << endl;
}

StudentFile.close();
system("pause");
main();
}

void ClearRecord()
{
system("cls");
char decision;
cout << "Enter Student Number: ";
cin >> FileName;
cin.get();

cout << "Are you sure? [Y]es [N]o" << endl;
cin >> decision;

if (decision == 'y')
{
ifstream StudentFile;
StudentFile.open(FileName);
system("cls");
cout << "Successfully Completed!" << endl;
system("pause");
StudentFile.close();
main();
}
else
main();

}


Last edited on
With fstream, you need to define multiple fstream instances to open more than one file at once. It is possible that your program doesn't remember what the other file names are.

You could use another text file to record the names of the text files that you created. Tell your program to open that file (the name of which will never change, so you can just hardcode the name into your program) and open every file whose name is in that text file.
You need a container to store the names of multiple files.
You could try using std::vector to store the names of the file names as strings.
fstream takes const char* or const string&, so it can take either a C-string or a standard string as its argument.

also, you should use if (decision == 'y' || decision == 'Y') because the user could enter either 'y' or 'Y', and you want to make sure that you can handle both cases.
Will try. Thanks for the help!:)
Here's what I did. And it isn't working.:/

#include <iostream>
#include <string>
#include <fstream>


using namespace std;


char SN[10], FileName[10]; //Student Number
char name[60];
int NumViolation;
char violation1[100], violation2[100], violation3[100];
char penalty1[50], penalty2[50], penalty3[50];

void AddViolation();
void ClearRecord();
void Open();

int main()
{
int choice;
system("cls");
system("title ADMIN FUNCTIONS");
cout << "1.CREATE Student Record" << endl;
cout << "2.CLEAR Student Record" << endl;
cout << "3. OPEN Student Record" << endl;
cout << "Enter choice: ";
cin >> choice;

switch (choice)
{
case 1:
AddViolation();
break;
case 2:
ClearRecord();
break;
case 3:
Open();
break;
}

}


void AddViolation()
{
system("cls");
ofstream List;
List.open("List.txt",ios::app);
cout << "Enter Student Number: ";
cin >> FileName;
List << FileName << endl;
List.close();

cin.sync();

ofstream StudentFile;
StudentFile.open(FileName,ios::app);

system("cls");
cout << "[Last Name, First Name Middle Initial]" << endl;
cout << "Enter Student's Full Name: ";
cin.getline(name,60);
system("cls");

cout << "Enter No. of Violations: ";
cin >> NumViolation;
system("cls");

switch (NumViolation)
{
case 1:
cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
break;

case 2:

cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
system("cls");
cout << "Enter violation 2:";
cin.getline(violation2,100);
system("cls");
cout << "Enter penalty 2:";
cin.getline(penalty2,50);
break;
case 3:

cin.ignore();
cout << "Enter violation 1:";
cin.getline(violation1,100);
system("cls");
cout << "Enter penalty 1:";
cin.getline(penalty1,50);
system("cls");
cout << "Enter violation 2:";
cin.getline(violation2,100);
system("cls");
cout << "Enter penalty 2:";
cin.getline(penalty2,50);
system("cls");
cout << "Enter violation 3:";
cin.getline(violation3,100);
system("cls");
cout << "Enter penalty 3:";
cin.getline(penalty3,50);
break;
}
cin.get();


if (NumViolation == 1)
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile.close();
}
else if (NumViolation == 2)
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile << violation2 << endl;
StudentFile << penalty2 << endl;
StudentFile.close();
}
else
{
StudentFile << FileName << endl;
StudentFile << name << endl;
StudentFile << NumViolation << endl;
StudentFile << violation1 << endl;
StudentFile << penalty1 << endl;
StudentFile << violation2 << endl;
StudentFile << penalty2 << endl;
StudentFile << violation3 << endl;
StudentFile << penalty3 << endl;
StudentFile.close();
}

main();
}

void Open()
{

ifstream List;
List.open("List.txt");
system("cls");
cout << "Enter SN: ";
cin >> SN;

while (List >> FileName)
{
if (SN == FileName)
{
cin.get();
List.close();
ifstream StudentFile;
StudentFile.open(FileName);


if (NumViolation == 1)
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
}
else if (NumViolation == 2)
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
cout << violation2 << endl;
cout << penalty2 << endl;
}
else
{
cout << FileName << endl;
cout << name << endl;
cout << NumViolation << endl;
cout << violation1 << endl;
cout << penalty1 << endl;
cout << violation2 << endl;
cout << penalty2 << endl;
cout << violation3 << endl;
cout << penalty3 << endl;
}
StudentFile.close();

}

}


system("pause");
main();
}

void ClearRecord()
{
system("cls");
char decision;
cout << "Enter Student Number: ";
cin >> FileName;
cin.get();

cout << "Are you sure? [Y]es [N]o" << endl;
cin >> decision;

if (decision == 'y')
{
ifstream StudentFile;
StudentFile.open(FileName);
system("cls");
cout << "Successfully Completed!" << endl;
system("pause");
StudentFile.close();
main();
}
else
main();

}


One thing to keep in mind: once you write to a file, everything that was in there before gets erased.
Let's say your file has this in it (as ID numbers):
928392
923928
192389
912483
234820

If you write "1" to the file, all of those ID numbers will be erased and your file will look like this:
1

That's it. None of the other text would be there anymore. You need to write all of the old information back into the text file if you want to keep it there.
1
2
3
4
5
6
7
8
9
10
11
12
13
	std::vector<std::string> fileNames;
	std::ifstream in;
	std::string file;
	std::ofstream out;
	in.open("List.txt");
	while (!in.eof())
	{
		std::getline(in, file);
		fileNames.reserve(fileNames.size() + 1);
		fileNames.push_back(file);
	}

	in.close();

Now you have a vector of strings that has the file name for every file that you need to work with. Remember, don't write to List.txt until you have EVERY file name in the vector, and you need to write every file name back to List.txt or fstream will only write the new file names. Meaning, if you want to add 1 file to the list, you need to write all of the old ones AND the new one again.
There may be other ways to getting around this, but I don't know how to do so.
I don't think the contents of a file is erased whenever I write to it again, since I use the ios::app.
Oh wait, you're right. My mistake. You are appending the file. I didn't catch the ios::app.

Before I forget: ofstream will look in the same directory that the executable is in to find files. Are all the text files in that folder?

Is the issue that your program won't open every file again? If you want to output every file, you should use a for loop or something, so that you can open every file, output the stuff that's in it, and then close the files.

There are really a bunch of ways to do this.
This would open every file in the fileNames vector (after the vector as filled).
1
2
3
4
5
6
7
std::ifstream in;
for (int i = 0; i < fileNames.size(); i++)
{
     in.open(fileNames[i]);
     //do your stuff here
     in.close();
}


That would open every file with the names in the fileNames vector.
If you want to add a file name, just output to the file using ios::app.

If you only want to open a file for one student at a time, just ask the user to enter an ID number or name or something like that, then try to open a file with that name. If that file doesn't exist, then you could ask the user if he or she wants to create a new file with that name.
Last edited on
Yes, every file created is within the folder.

And yes, I only want to open a file one at a time. That's what I did, I asked the user to enter an ID number. Then it will open the List.txt and check if it's in there. If it is, then the user defined filename will open and will print out its content. But yeah, it isn't working properly.:):/ Could you check and try to see where I've gone wrong?
Last edited on
I got it to work a little nicer by using std::string rather than character arrays.
It looks like the program isn't finding a match when you compare SN to FileName (in the open function). Because it doesn't find a match, it just exits.

Try using strings, and that might help. That's what I would recommend. You can always change the way that you are comparing the character arrays, but I usually just use std::string unless I have to use an array of characters.
How do I use getline with string? I'm not that familiar with it.:)
And if I use std::string instead of "using namespace std", when/where do I have to put/use the "std::"?

What do you suggest regarding the failure of finding the match from the list of file names?
Last edited on
just do getline(FileName, StringName);
getline works with strings as well.
if you use "using namespace std", you don't need to put "std::". I use "std::" because I don't use "using namespace std"
If you aren't going to use "using namespace std", then you have to put "std::" in front of everything that uses "std" as its namespace (string, getline, cin, cout, etc).

If you're more comfortable with it, just use "using namespace std" for now.

If you use string, you can just compare them directly:
if (StringName == FileName) and it will compare the strings. If the two strings are identical, then it will return true.

If you want to use character arrays, you have to compare each element of each array to each other (i.e. array1[0] == array2[0] && array1[1] == array2[1] etc).
I prefer to use strings because it removes the need for us to have to do that.

If you just want to open a file based on what the user input, you actually don't need a text file with the files names. Just have the user input the ID or whatever, and then try to open the file. ifstream will fail if it can't find the file, and if it does you can ask the user if they want to create a new file. Your program doesn't look like it needs to open every file, just the files that the user asks for. You just have to hope that the user enters it properly.
I already changed every char to string. But still, the problem's with the searching and opening of the files. Whenever I create a file then open it, it would print out the content, but if I try to open another file, the program prints out the content of the previous file which I created and opened. Any suggestions on what to do about the checking/searching for the file?

Here's the 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
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#include <iostream>
#include <string>
#include <fstream>


using namespace std;


string FileName;
string name;
int NumViolation;
string violation1, violation2, violation3;
string penalty1, penalty2, penalty3;

void AddViolation();
void ClearRecord();
void Open();

int main()
{
    int choice;
    system("cls");
    system("title ADMIN FUNCTIONS");
    cout << "1.CREATE Student Record" << endl;
    cout << "2.CLEAR Student Record" << endl;
    cout << "3. OPEN Student Record" << endl;
    cout << "Enter choice: ";
    cin >> choice;

    switch (choice)
    {
       case 1:
       AddViolation();
       break; 
       case 2:
       ClearRecord();
       break; 
       case 3:
       Open();
       break; 
    }

}


void AddViolation()
{
     system("cls");
     cout << "Enter Student Number: ";
     cin.ignore();
     getline(cin,FileName);
     cin.sync();
     system("cls");

     FileName = FileName + ".txt";
     ofstream StudentFile;
     StudentFile.open(FileName.c_str(),ios::app);

     cout << "[Last Name, First Name Middle Initial]" << endl;
     cout << "Enter Student's Full Name: ";
     getline(cin,name);
     system("cls");

     cout << "Enter No. of Violations: ";
     cin >> NumViolation;
     system("cls");

     switch (NumViolation)
     {
     case 1:
     cin.ignore();
     cout << "Enter violation 1:";
     getline(cin,violation1);
     system("cls");
     cout << "Enter penalty 1:";
     getline(cin,penalty1);
     break;

     case 2:
     cin.ignore();
     cout << "Enter violation 1:";
     getline(cin,violation1);
     system("cls");
     cout << "Enter penalty 1:";
     getline(cin,penalty1);
     system("cls");
     cout << "Enter violation 2:";
     getline(cin,violation2);
     system("cls");
     cout << "Enter penalty 2:";
     getline(cin,penalty2);
     break;
     
     case 3:
     cin.ignore();
     cout << "Enter violation 1:";
     getline(cin,violation1);
     system("cls");
     cout << "Enter penalty 1:";
     getline(cin,penalty1);
     system("cls");
     cout << "Enter violation 2:";
     getline(cin,violation2);
     system("cls");
     cout << "Enter penalty 2:";
     getline(cin,penalty2);
     system("cls");
     cout << "Enter violation 3:";
     getline(cin,violation3);
     system("cls");
     cout << "Enter penalty 3:";
     getline(cin,penalty3);
     break;
     }
     cin.get(); 


     if (NumViolation == 1)
     {
     StudentFile << FileName << endl;
     StudentFile << name << endl;
     StudentFile << NumViolation << endl;
     StudentFile << violation1 << endl;
     StudentFile << penalty1 << endl;
     StudentFile.close(); 
     }
     else if (NumViolation == 2)
     {
     StudentFile << FileName << endl;
     StudentFile << name << endl;
     StudentFile << NumViolation << endl;
     StudentFile << violation1 << endl;
     StudentFile << penalty1 << endl;
     StudentFile << violation2 << endl;
     StudentFile << penalty2 << endl;
     StudentFile.close();
     }
     else 
     { 
     StudentFile << FileName << endl;
     StudentFile << name << endl;
     StudentFile << NumViolation << endl;
     StudentFile << violation1 << endl;
     StudentFile << penalty1 << endl;
     StudentFile << violation2 << endl;
     StudentFile << penalty2 << endl;
     StudentFile << violation3 << endl;
     StudentFile << penalty3 << endl;
     StudentFile.close(); 
     }

     main(); 
}

void Open()
{
     system("cls");
     cout << "Enter Student Number: ";
     cin.ignore();
     getline(cin,FileName);
     cin.sync();

     
     FileName = FileName + ".txt";

 
     ifstream StudentFile;
     StudentFile.open(FileName.c_str(),ios::app);

     if (NumViolation == 1)
     {
         cout << FileName << endl;
         cout << name << endl;
         cout << NumViolation << endl;
         cout << violation1 << endl;
         cout << penalty1 << endl;
     }
     else if (NumViolation == 2)
     {
         cout << FileName << endl;
         cout << name << endl;
         cout << NumViolation << endl;
         cout << violation1 << endl;
         cout << penalty1 << endl;
         cout << violation2 << endl;
         cout << penalty2 << endl;
     }
     else
     {
         cout << FileName << endl;
         cout << name << endl;
         cout << NumViolation << endl;
         cout << violation1 << endl;
         cout << penalty1 << endl;
         cout << violation2 << endl;
         cout << penalty2 << endl;
         cout << violation3 << endl;
         cout << penalty3 << endl;
     }

     StudentFile.close();
     system("pause");
     main();
}

void ClearRecord()
{ 
     system("cls");
     char decision;
     cout << "Enter Student Number: ";
     getline(cin,FileName);
     cin.get();

     cout << "Are you sure? [Y]es [N]o" << endl;
     cin >> decision;

     if (decision == 'y')
     {
        FileName = FileName + ".txt";
        ifstream StudentFile;
        StudentFile.open(FileName.c_str());
        system("cls");
        cout << "Successfully Completed!" << endl;
        system("pause");
        StudentFile.close();
        main();
     }
     else
         main();

}
If you are reusing streams you need to be concerned about stream errors. Just closing and opening files doesn't usually clear any stream error states.

Also in a C++ calling main() is illegal. It appears you should just be returning to main() not calling() main.
At the AddViolation function you enter the information and write it in the file, but you do NOT wipe the variables. When you use the open function you also do not get the informations from the file, but rather print out what is already stored in the variables (as it is, old data).

I suggest creating the variables in the function itself so it gets wiped afterwards automaticly.

Well, the part of reading from the file you are completely missing... same as the deleting part (you are cleaning the console from the text, but not the files from its information...)
Last edited on
What do I do in the part of reading from the file and deleting?
For the deleting function just use remove( const char* filename).

For the reading part... you could use something like this
1
2
3
4
5
6
7
8
9
10
char cstring[256];
fstream StudentFile;
StudentFile.open(FileName.c_str(), ios::in);

while (!StudentFile.eof())          // As long as there is still data inside the file
	{
		StudentFile.getline(cstring, sizeof(cstring));
		cout << cstring << endl;
	}
StudentFile.close();
Last edited on
For the reading part... you could use something like this

Okay, as long as you realize that your snippet has several items that many people believe to be bad practices.

First the use of the cstring instead of the std::string, you should prefer std::string over C-strings since std::string is much less error prone.

Second you should use the constructor to open the file in this case, avoiding the unnecessary function call.

Third using eof() to control a data entry loop will quite often cause problems, use the read operation instead.

Fourth since you're just doing reading, you should use an ifstream instead of the fstream.

Lastly in most cases you don't need to close the file, just let the destructor handle the closing when the stream goes out of scope.

1
2
3
4
5
6
7
8
9
string my_string;
ifstream studentFile(fileName.c_str()); // Only doing reading, so just use ifstream.
// Or if using C++11
//ifstream studentFile(fileName);

while (getline(studentFile, my_string))          // As long as there is still data inside the file
{
	cout << my_string << endl;
}





Last edited on
Thanks for correcting me jlb. Guess I was too tired to give some quality code there...
Topic archived. No new replies allowed.