Sign in to follow this  
Surg AKA Kunark

Stream Output

Recommended Posts

Hey, I was wondering if anyone knows how to fix this problem. I have a loop that outputs to a file, each time it loops it outputs the following stringarray \t Mark \n Okay, so everything goes out right, but, because of the newline that i put out to the stream, when i try to load the names back into the program, it does everything right but sometimes it reads in an extra value, im assuming the newline, and sometimes it doesn't. I know if I go to the file and press delete once at the end of the file it fixes it, but I was wondering, is their away to go into the file, take the very last line, and if it is a new line delete that line? THank you for the help in advance :)

Share this post


Link to post
Share on other sites
Okay, Im not exactly sure how I would do that, just ignore it when Im reading it.

Here is my function, it is reading in students


/*******************************************************
Function: void LoadStudent()
Description: This function loads the student file
Parameters: None
Returns: void - For now
********************************************************/


void LoadStudent(char szName[10][32], double* dMark, int* iStudentCount){

fstream DataFile("MarksReport.txt", ios::in);
if (DataFile.fail()) {
cout << "File could not be opened or is missing";
cout << "\nPlease make sure file is in proper path\n";
return;
}

int i=*iStudentCount;

while( !DataFile.eof() )
{
DataFile >> szName[i];
DataFile >> dMark[i];
(*iStudentCount)++;
i++;
}

DataFile.close();

return;
}

Share this post


Link to post
Share on other sites
Well, the first mistake you made is .eof().

never loop like that with eof.

it's best to do all the stream reading in the while loop conditional.

so

while( DataFile >> szName[i] >> dMark[i] ) { ... }

In this case, that change will even solve your current problem.

edit: (if you're looking for why, there have been dozens of threads, and google will probably help. in short: it's not eof until you attempt to read past the end of the file, not just up to it)

Share this post


Link to post
Share on other sites
Aye, thanks for the help :) I will do that, never seen a wihle loop coded like that before, Also thanks for the info about the eof, I never knew that either, I feel like I learn something new everytime I read GameDev lol. Like something I just learned, I say lol waaaaaaaaaaaaaaay to much.

Thanks again for the help.

Share this post


Link to post
Share on other sites
Your design has some serious problems:

- You are using all your parameters as output parameters, and passing by pointer to acheive that rather than by reference (which would be preferred in C++). Having "all" of them be output isn't necessarily so bad, but there isn't really any structure to it; you have these parallel lists instead of a list of "students".
- char arrays for text data are bad bad bad. Just don't do it. Evil 80s era hackage.
- You're trying to maintain an array, by passing in the current endpoint and returning the resulting new endpoint. STL to the rescue...
- As mentioned, there's a much nicer idiom for the looping.
- You don't need a "return" at the end of a void function. Meanwhile, however, your function doesn't communicate back to the main program to let it know that file loading failed - it just communicates to the user. That's bad. Doing the actual printing in the function is bad style as well - too much responsibility.
- Hard-coding the file name is probably a bad idea. At least, hard-coding it *here* is. You might need to load students from more than one file in the same program run, in the future.


// A "student". Later, change "struct" to "class" and give the
// thing appropriate functionality.
struct Student {
std::string name;
double mark;
}

// Adds students to the end of the input Student vector.
// Returns whether successful at opening the file.
// (Actually, using an exception may be a better idea...)
// Look how much shorter and clearer it is! And you will never
// have a problem if a student has a longer name, or if there
// are too many students; and you don't have to remember how
// many students there were in the first place...
bool loadStudents(vector<Student>& enrolment, std::string filename){
// "ifstream" is automatically for input, implying ios::in.
ifstream DataFile(filename.c_str());
if (DataFile.fail()) return false;

// Otherwise, read the students in to the vector.
Student current;
while( DataFile >> current.name >> current.mark ) {
// Successfully input the student, so copy it into the vector
// at the end.
enrolment.push_back(current);
}
DataFile.close();
return true;
}
// Calling code can just call the .size() method of the vector
// to find out how many students there are after the loading.



As I mentioned, it probably should use exceptions instead of a return value (to handle corrupt data in a file for example) - also, it probably should do something about the exceptions that might be raised by the I/O operations themselves. But I don't know very much about C++'s exception system, so I will let you look that stuff up for yourself [smile]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this