John500
asked on
Reading and Writing files
Greetings,
I have a database program designed to allow student entry, searching, deleting etc. One thing I need is the ability to read a file into the database.
Below is the code I have and which works but when I try to read a file of 100 entries, the whole file doesn't read in, only about 25.
void Database::readDatabase()
{
char buff[100];
char fname[40];
struct find_t ffblk;
int done;
cout<<"Choose a file from drive A for reading
to databse:\n\n";
// show directory
printf("Directory listing of *.*\n");
done = _dos_findfirst
("*.*",_A_NORMAL,&ffblk);
while (!done)
{
printf(" %s\n", ffblk.name);
done = _dos_findnext(&ffblk);
}
cin>>fname;
ifstream input(fname);
if (!input)
{cout<<"File doesn't exist!\n";
return;}
while(input.getline(buff,1 00)!=0)
{
if(strlen(buff)==0)exit(-1 );
Student *tmp = new Student(buff);
addStudent(tmp);
} cout<<"File read to database"; return;
}
The call to new Student(buff) & addStudent(tmp) dynamically creates and adds a student to the database. There is plenty of memeory on my system so that's not the problem.
Thanks for the help!
I have a database program designed to allow student entry, searching, deleting etc. One thing I need is the ability to read a file into the database.
Below is the code I have and which works but when I try to read a file of 100 entries, the whole file doesn't read in, only about 25.
void Database::readDatabase()
{
char buff[100];
char fname[40];
struct find_t ffblk;
int done;
cout<<"Choose a file from drive A for reading
to databse:\n\n";
// show directory
printf("Directory listing of *.*\n");
done = _dos_findfirst
("*.*",_A_NORMAL,&ffblk);
while (!done)
{
printf(" %s\n", ffblk.name);
done = _dos_findnext(&ffblk);
}
cin>>fname;
ifstream input(fname);
if (!input)
{cout<<"File doesn't exist!\n";
return;}
while(input.getline(buff,1
{
if(strlen(buff)==0)exit(-1
Student *tmp = new Student(buff);
addStudent(tmp);
} cout<<"File read to database"; return;
}
The call to new Student(buff) & addStudent(tmp) dynamically creates and adds a student to the database. There is plenty of memeory on my system so that's not the problem.
Thanks for the help!
ASKER
Alexo,
Glad you could grab this question.
Ok, I replaced that line as you said but still no difference.
Could the problem have anything to do with the file extension being .txt which I'm reading in?
This is a sample of the lines being read into the database:
7868342, Clinton, 00, 0.00, U.S., has a problem with inhaling
2542341, Dick. V., 92, 2.00, U.S., Annoyingly repeats "Baby"
9953891, babson,23, 2.3, alabama, a great guy
9953886, baden, 12, 4, wyoming, nice person
As you can see, each line is not very large.
You may also want to look at the Student::Student constructor that makes each student. I just sent that to you via e-mail because it will probably more readable. Does this type of transmission scrable things when I send them?
I don't think the constructor is the problem but to eliminate all doubt... Also, the addStudent function called in the readDatabase function above, alphabetizes each entry. I'll send that if you think you need to see it.
Standing by, John
Glad you could grab this question.
Ok, I replaced that line as you said but still no difference.
Could the problem have anything to do with the file extension being .txt which I'm reading in?
This is a sample of the lines being read into the database:
7868342, Clinton, 00, 0.00, U.S., has a problem with inhaling
2542341, Dick. V., 92, 2.00, U.S., Annoyingly repeats "Baby"
9953891, babson,23, 2.3, alabama, a great guy
9953886, baden, 12, 4, wyoming, nice person
As you can see, each line is not very large.
You may also want to look at the Student::Student constructor that makes each student. I just sent that to you via e-mail because it will probably more readable. Does this type of transmission scrable things when I send them?
I don't think the constructor is the problem but to eliminate all doubt... Also, the addStudent function called in the readDatabase function above, alphabetizes each entry. I'll send that if you think you need to see it.
Standing by, John
John, I wouldn't have time to check it today. I suggest you reopen the question for other experts.
ASKER
Alex,
Will do as you suggested, thanks for the help thus far.
Anyone out there interested in this question?
John
Will do as you suggested, thanks for the help thus far.
Anyone out there interested in this question?
John
Do you have empty lines in your file?
while(input.getline(buff,1 00)!=0)
{
if(strlen(buff)==0)exit(-1 ); // this will terminate if you have an empty line
Student *tmp = new Student(buff);
addStudent(tmp);
}
Hope that helps
Norbert
while(input.getline(buff,1
{
if(strlen(buff)==0)exit(-1
Student *tmp = new Student(buff);
addStudent(tmp);
}
Hope that helps
Norbert
ASKER
If I have empty lines in my file, and the code below causes termination for empty lines, is there a way to over come these empty lines?
while(input.getline(buff,1 00)!=0)
{
if(strlen(buff)==0)exit(-1 ); // this will terminate if you have an empty line
Student *tmp = new Student(buff);
addStudent(tmp);
}
while(input.getline(buff,1
{
if(strlen(buff)==0)exit(-1
Student *tmp = new Student(buff);
addStudent(tmp);
}
ASKER
How could I make the following line make sense so that getline continues until the end of the file?
while(input.getline(buff,1 00)!eof(in put))
while(input.getline(buff,1
Yes, of course
what about
while(input.getline(buff,1 00)!=0)
{
if(strlen(buff)!=0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
what about
while(input.getline(buff,1
{
if(strlen(buff)!=0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
How about the following?
while(input.getline(buff,1 00) != 0)
{
if(strlen(buff) != 0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
This causes the program to skip empty lines (not use them), but to continue processing when it encounters them.
while(input.getline(buff,1
{
if(strlen(buff) != 0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
This causes the program to skip empty lines (not use them), but to continue processing when it encounters them.
perhaps you should use the endof file function and change your code to
while(!input.eof())
{
input.getline(buff,100);
if(strlen(buff)!=0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
while(!input.eof())
{
input.getline(buff,100);
if(strlen(buff)!=0)
{
Student *tmp = new Student(buff);
addStudent(tmp);
}
}
Norbert, is there an advantage in using the eof() function? (I don't use the C++ file I/O.) I thought that the return vlaue from getline() could be used just as well.
Hi Todd, welcome back. Did she get it?
< lecture mode on >
An ios has three state bits:
ios::eofbit - End of file reached.
ios::failbit - A possibly recoverable formatting or conversion error.
ios::badbit - A severe I/O error.
ios::eof() checks ios::eofbit. ios::operator void*() and ios::operator!() check the other two.
< lecture mode off >
< lecture mode on >
An ios has three state bits:
ios::eofbit - End of file reached.
ios::failbit - A possibly recoverable formatting or conversion error.
ios::badbit - A severe I/O error.
ios::eof() checks ios::eofbit. ios::operator void*() and ios::operator!() check the other two.
< lecture mode off >
ASKER
Todd,
The lines you gave will help I'm sure, but it didn't fix the problem. Below is the code I'm using for the n)ames/notes option. If you agree nothing looks wrong, how about suggesting a way to print the _next and _previous pointers of each student that is being added. I thinking that the pointer logic might be messed up for each student added.
I've tried cout<<pNew->_next<<pNew->_ prev; but the compiler gives me "undefined symbol..." I don't know why this would happen. I insert directly after a student is entered.
I've changed my mind, I'll send the code via e-mail.
John
The lines you gave will help I'm sure, but it didn't fix the problem. Below is the code I'm using for the n)ames/notes option. If you agree nothing looks wrong, how about suggesting a way to print the _next and _previous pointers of each student that is being added. I thinking that the pointer logic might be messed up for each student added.
I've tried cout<<pNew->_next<<pNew->_
I've changed my mind, I'll send the code via e-mail.
John
Alex,
Yes, she got it. She had already defended, this was just the graduation. Food, Family and wine. Especially wine.
What does getline() return though? I thought it was the EOF status. Is it all three state bits?
Yes, she got it. She had already defended, this was just the graduation. Food, Family and wine. Especially wine.
What does getline() return though? I thought it was the EOF status. Is it all three state bits?
Nietod,
Alexo told you someting about the bits
I had a look to the online help of vc++ 4.20 and I saw
basic_istream& getline(E *s, streamsize n, E delim = T::newline());
The unformatted input function extracts up to n - 1 elements and stores them in the array beginning at s. It always stores T::eos() after any extracted elements it stores. In order of testing, extraction stops:
· at end of file
· after the function extracts an element that compares equal to delim, in which case the element is neither put back nor appended to the controlled sequence
· after the function extracts is.max_str() elements
If the function extracts no elements, it calls setstate(failbit). In any case, it returns *this.
so getline returns always *this and that is probably always !FALSE
So I think there is a big advantage :-)
Alexo told you someting about the bits
I had a look to the online help of vc++ 4.20 and I saw
basic_istream& getline(E *s, streamsize n, E delim = T::newline());
The unformatted input function extracts up to n - 1 elements and stores them in the array beginning at s. It always stores T::eos() after any extracted elements it stores. In order of testing, extraction stops:
· at end of file
· after the function extracts an element that compares equal to delim, in which case the element is neither put back nor appended to the controlled sequence
· after the function extracts is.max_str() elements
If the function extracts no elements, it calls setstate(failbit). In any case, it returns *this.
so getline returns always *this and that is probably always !FALSE
So I think there is a big advantage :-)
ASKER
Thanks all for the input.
As I said in the last letter, the eof routine will work well if the data is messed up, but I've made sure the file is clean.
The n)ames/notes menu item still only prints about 25 out of 100
John
As I said in the last letter, the eof routine will work well if the data is messed up, but I've made sure the file is clean.
The n)ames/notes menu item still only prints about 25 out of 100
John
ASKER
I forgot to mention, the routine I'm using to make sure the file is being read is:
...
while(!input.eof())
{
input.getline(buff,100);
if(strlen(buff)!=0)
{
printf("line %02d = [%s]\n",counter,buff);
Student *tmp = new Student(buff);
addStudent(tmp);
counter++;
}
} cout<<"File read to database"; return;
}
I've also printed _numberStudents after each time the new Student constructor is called which tells me all 100 students have been created.
It has to be either the addStudent func or the printNames func
John
...
while(!input.eof())
{
input.getline(buff,100);
if(strlen(buff)!=0)
{
printf("line %02d = [%s]\n",counter,buff);
Student *tmp = new Student(buff);
addStudent(tmp);
counter++;
}
} cout<<"File read to database"; return;
}
I've also printed _numberStudents after each time the new Student constructor is called which tells me all 100 students have been created.
It has to be either the addStudent func or the printNames func
John
Cograts!
>> What does getline() return though?
The stream reference of course! Which is implicitly convertable using the two operators I mentioned above.
>> What does getline() return though?
The stream reference of course! Which is implicitly convertable using the two operators I mentioned above.
ASKER
Todd,
Anything to report??
Anything to report??
ASKER
Open to Alex
ASKER
Open to Alex, please check your e-mail.
John
John
ASKER
Todd,
Please check your mail
John
Please check your mail
John
>> Open to Alex, please check your e-mail.
Several things:
First, although I appreciate your vote of confidence, I suggest you keep the question open for everybody until you get your solution.
Second, I'm in a different time zone from you (7 hours before the east coast). You cannot expect to find me online in "normal" (for you) hours.
Third, send me the whole project as a zipped attachment, including the input file and I'll take a look at it.
Several things:
First, although I appreciate your vote of confidence, I suggest you keep the question open for everybody until you get your solution.
Second, I'm in a different time zone from you (7 hours before the east coast). You cannot expect to find me online in "normal" (for you) hours.
Third, send me the whole project as a zipped attachment, including the input file and I'll take a look at it.
I would like to see the code too.
because I live in germany I am also in a different time zone
because I live in germany I am also in a different time zone
ASKER
To whom it may interest:
For a doubly linked list, do insertions to the head or tail automatically set the necessary pointers (3) and how about insertions to the middle and their pointers (4).
The following code is not alphabetizing my student entries. I believe the entries are unlinked once created:
void Database::addStudent(Stude nt *pNew)
{
Student *p = _head;
Student *NxtPtr = _head;
Student *PrvPtr = NULL;
while (p)
{
if(p->_id == pNew-> _id)
{cout<<"Duplicate ID, can't be entered!\n";
return;}
p = p->_next;
}
while (NxtPtr) // While there are students to test.
{
if (strcmp(NxtPtr->_name,pNew ->_name) > 0)
break; // stop the search.
PrvPtr = NxtPtr; // Save -> current student.
NxtPtr = NxtPtr->_next;
}
if (PrvPtr != NULL)
{PrvPtr->_next = pNew;
_numStudents++; return;}
else if (PrvPtr == 0)
{ _head = pNew;
_numStudents++; return;}
else if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++; return;
} // end of addStudent
For a doubly linked list, do insertions to the head or tail automatically set the necessary pointers (3) and how about insertions to the middle and their pointers (4).
The following code is not alphabetizing my student entries. I believe the entries are unlinked once created:
void Database::addStudent(Stude
{
Student *p = _head;
Student *NxtPtr = _head;
Student *PrvPtr = NULL;
while (p)
{
if(p->_id == pNew-> _id)
{cout<<"Duplicate ID, can't be entered!\n";
return;}
p = p->_next;
}
while (NxtPtr) // While there are students to test.
{
if (strcmp(NxtPtr->_name,pNew
break; // stop the search.
PrvPtr = NxtPtr; // Save -> current student.
NxtPtr = NxtPtr->_next;
}
if (PrvPtr != NULL)
{PrvPtr->_next = pNew;
_numStudents++; return;}
else if (PrvPtr == 0)
{ _head = pNew;
_numStudents++; return;}
else if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++; return;
} // end of addStudent
The problem is you don't want the returns in there! if you move the _numstudents++ to the end (you only want it once) and remove the retuns (or put one at the end) you will be fine.
Actually, that's not 100% true. You put some bad "elses" in too. Why did you mess with it? It should be
while (p)
{
if(p->_id == pNew-> _id)
{
cout<<"Duplicate ID, can't be entered!\n";
return;
}
p = p->_next;
}
while (NxtPtr) // While there are students to test.
{
if (strcmp(NxtPtr->_name,pNew ->_name) > 0)
break; // stop the search.
PrvPtr = NxtPtr; // Save -> current student.
NxtPtr = NxtPtr->_next;
}
if (PrvPtr != NULL)
PrvPtr->_next = pNew;
else
_head = pNew;
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++;
Note, as you said was a requirement, that sets 3 or 4 pointers every time.
Alex, or anyboady out there. Do you agree that this is correct?
while (p)
{
if(p->_id == pNew-> _id)
{
cout<<"Duplicate ID, can't be entered!\n";
return;
}
p = p->_next;
}
while (NxtPtr) // While there are students to test.
{
if (strcmp(NxtPtr->_name,pNew
break; // stop the search.
PrvPtr = NxtPtr; // Save -> current student.
NxtPtr = NxtPtr->_next;
}
if (PrvPtr != NULL)
PrvPtr->_next = pNew;
else
_head = pNew;
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++;
Note, as you said was a requirement, that sets 3 or 4 pointers every time.
Alex, or anyboady out there. Do you agree that this is correct?
ASKER
How can you say you are meeting the pointer requirements??
..."Note, as you said was a requirement, that sets 3 or 4 pointers every time..."
The only place you are setting pointers is when a student is inserted in the middle. The head and tail are not automatic!
..."Note, as you said was a requirement, that sets 3 or 4 pointers every time..."
The only place you are setting pointers is when a student is inserted in the middle. The head and tail are not automatic!
ASKER
...Even when you have set the pointers you left out
PrvPtr->_next = pNew. It isn't automatic either!!
PrvPtr->_next = pNew. It isn't automatic either!!
ASKER
Further more,
One occurence of _numStudents at the end is not good. What happens if no students are entered for some reason? The number of students will still be incremented. The increments should take place in the area the student is entered.
As far as returns go, they should be entered where I put them in. Why stay in the function when the job has been done??
One occurence of _numStudents at the end is not good. What happens if no students are entered for some reason? The number of students will still be incremented. The increments should take place in the area the student is entered.
As far as returns go, they should be entered where I put them in. Why stay in the function when the job has been done??
Do you keep a pointer to the tail? if so that is not being set, although that is a small change (2 lines).
The head is being set. when it needs to, namely when a new first item is inserted. When a new first item is inserted, PrvPtr will be NULL, (Because it was initialized to NULL and was never reset in the loop) In that case the _head pointer is set after the loop ends.
Don't take my word for it! Follow in your mind (or on paper) what happens when you (a) add to a totally empty list and (b) add an item that comes before the first item already in the list.
The head is being set. when it needs to, namely when a new first item is inserted. When a new first item is inserted, PrvPtr will be NULL, (Because it was initialized to NULL and was never reset in the loop) In that case the _head pointer is set after the loop ends.
Don't take my word for it! Follow in your mind (or on paper) what happens when you (a) add to a totally empty list and (b) add an item that comes before the first item already in the list.
You wrote
>> Why stay in the function when the job has been done??
and at the same time you are complaining that the job isn;t getting done (that pointers aren't be set in every case.)
The problem is that the job isn't done at those places you've put in the returns! The code has to run to the end to get done.
Trust me. I've written this sort of thing a couple thousand times in a dozen different languages. Don't assume I'm wrong and try to change it to what seems right. Assume I'm right and try to test it in your mind.
>> Why stay in the function when the job has been done??
and at the same time you are complaining that the job isn;t getting done (that pointers aren't be set in every case.)
The problem is that the job isn't done at those places you've put in the returns! The code has to run to the end to get done.
Trust me. I've written this sort of thing a couple thousand times in a dozen different languages. Don't assume I'm wrong and try to change it to what seems right. Assume I'm right and try to test it in your mind.
ASKER
Granted,
You don't have to set the _head->_prev pointer, it is Null by default but you do have to set _head->_next or it will have a default of Null also! And the _head->_next->_prev must be set.
Same goes with the tail, only the pNew->_prev has to be set and the pNew->_prev->_next pointer. That is the way it is referenced or by your second pointer PrvPtr->_next = pNew.
Let's put it this way, you were right about for loop being bad, but the instructor's method of pointers was at least getting 25 items in the list, not six.
You don't have to set the _head->_prev pointer, it is Null by default but you do have to set _head->_next or it will have a default of Null also! And the _head->_next->_prev must be set.
Same goes with the tail, only the pNew->_prev has to be set and the pNew->_prev->_next pointer. That is the way it is referenced or by your second pointer PrvPtr->_next = pNew.
Let's put it this way, you were right about for loop being bad, but the instructor's method of pointers was at least getting 25 items in the list, not six.
ASKER
Concerning the job being done,
If the while loop is terminated and comes to:
if (PrvPtr != NULL)
and the PrvPtr is Null this condition is passed by, No? If PrvPtr isn't Null then it isn't passed by and it is executed, No? If it is executed then a student is entered, No? If a student is entered then there is no reason to stay in the function. That goes for any other condition that is entered into and which also ends in a student being entered, the whole function should be done, no other jobs to do.
Are you saying that a condition is executed even if it isn't true? For (PrvPtr != NULL)?? is this entered if it isn't true??
Your set up wouldn't compile because of a misplaced else statement by-the-way.
If the while loop is terminated and comes to:
if (PrvPtr != NULL)
and the PrvPtr is Null this condition is passed by, No? If PrvPtr isn't Null then it isn't passed by and it is executed, No? If it is executed then a student is entered, No? If a student is entered then there is no reason to stay in the function. That goes for any other condition that is entered into and which also ends in a student being entered, the whole function should be done, no other jobs to do.
Are you saying that a condition is executed even if it isn't true? For (PrvPtr != NULL)?? is this entered if it isn't true??
Your set up wouldn't compile because of a misplaced else statement by-the-way.
You are soooooo confussed. I have no idea what to say.
(I will say this, the else was placed right in the code above. I'm not sure why it didn't compile.)
I'm going to take a stab at your problem. Do you know that in the code
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
that the last line ("pNew->_next = NxtPtr") will always be executted? It is not part of the "if". only the middle line is part of the "if"? Do you understand that?
If that is not you missunderstanding.... give me a call (405) 844-8647.
(I will say this, the else was placed right in the code above. I'm not sure why it didn't compile.)
I'm going to take a stab at your problem. Do you know that in the code
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
that the last line ("pNew->_next = NxtPtr") will always be executted? It is not part of the "if". only the middle line is part of the "if"? Do you understand that?
If that is not you missunderstanding.... give me a call (405) 844-8647.
ASKER
Todd,
Congrats!!
The reason the code wouldn't compile is because you didn't put parens around the if or the else statements.
Once I did that, all 100 students were entered in the database!
My problem is with things done behind the scene. To me, if an "if" statement is false, than NOTHING under it or within its parenthesis, should be executed.
Anyway, good job! Talk tomorrow
Congrats!!
The reason the code wouldn't compile is because you didn't put parens around the if or the else statements.
Once I did that, all 100 students were entered in the database!
My problem is with things done behind the scene. To me, if an "if" statement is false, than NOTHING under it or within its parenthesis, should be executed.
Anyway, good job! Talk tomorrow
If an "if" is false only the 1st statement after it is not executed. If that statement is a compound statmenet (a set of braces ({ }) then all the statements withing that compound statement will be skipped. However execution will resume after the statemetn folowing the "if".
When it comes to executing the stuff in the the parenthesis. That's a little tricky. If there is an expression in the parenthesis at least part of the expression will be executed and in some cases all of the expression will be executed. The compiler will execute as much it needs to in order to determine whehor or not the the "if" should run. for example if you have
if (F1() || F2())
The compiler will call F1 first. If F1 returns true, then the statmenet in the if should run, so it does not call F2. If F1 returns false, then there still is a possibility that the if should run, depending on F2's return value. So in that case it calls F2
If you have
if (F1() && F2())
It calls F1 first (always goes left to right) If F1 returns false, then the "if" should not run. In that case there is no point in calling F2, so it doesn't. If F1 returns true, the "if" might still run depending on F2's return values, so it does call F2.
As far as the missing parens causing compile problems. I do not see any missing parens in the sample above. It is possible that there were ones in the e-mail. That is my most common typo! (I'm a pascal programmer mascerading as a C++ programmer.)
When it comes to executing the stuff in the the parenthesis. That's a little tricky. If there is an expression in the parenthesis at least part of the expression will be executed and in some cases all of the expression will be executed. The compiler will execute as much it needs to in order to determine whehor or not the the "if" should run. for example if you have
if (F1() || F2())
The compiler will call F1 first. If F1 returns true, then the statmenet in the if should run, so it does not call F2. If F1 returns false, then there still is a possibility that the if should run, depending on F2's return value. So in that case it calls F2
If you have
if (F1() && F2())
It calls F1 first (always goes left to right) If F1 returns false, then the "if" should not run. In that case there is no point in calling F2, so it doesn't. If F1 returns true, the "if" might still run depending on F2's return values, so it does call F2.
As far as the missing parens causing compile problems. I do not see any missing parens in the sample above. It is possible that there were ones in the e-mail. That is my most common typo! (I'm a pascal programmer mascerading as a C++ programmer.)
ASKER
Todd,
Sorry not to write sooner, but my wife went into false labor last night around 3:30. We got back from the hospital mid morning and I've been sleeping ever since.
The above clarification on what is and is not executed will help. I still need to study that procedure to see why it is working. Here is the portion of code I put parenthesis around:
if (PrvPtr != NULL)
{PrvPtr->_next = pNew;} // added parens
else
{_head = pNew;} // added parens
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++;
I cleaned up a couple of other functions in my program last night like the a)ge function and something else (just in case you saw how terrible it was).
I am going to open up a new question now on the delete function, after I study the addStudent one some more. Who knows it may come to me but I've been having trouble figuring all those different scenarios out also. The delete is kind of tricky (swaping pointers and such).
Make this question available for grading and I'll do it. Thanks again for the help!!
Sorry not to write sooner, but my wife went into false labor last night around 3:30. We got back from the hospital mid morning and I've been sleeping ever since.
The above clarification on what is and is not executed will help. I still need to study that procedure to see why it is working. Here is the portion of code I put parenthesis around:
if (PrvPtr != NULL)
{PrvPtr->_next = pNew;} // added parens
else
{_head = pNew;} // added parens
if (NxtPtr != NULL)
NxtPtr->_prev = pNew;
pNew->_next = NxtPtr;
pNew->_prev = PrvPtr;
_numStudents++;
I cleaned up a couple of other functions in my program last night like the a)ge function and something else (just in case you saw how terrible it was).
I am going to open up a new question now on the delete function, after I study the addStudent one some more. Who knows it may come to me but I've been having trouble figuring all those different scenarios out also. The delete is kind of tricky (swaping pointers and such).
Make this question available for grading and I'll do it. Thanks again for the help!!
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Unnecessary, but helpful to ease maintenance if you ever want to change the statement(s)
Well now we're getting into a matter of style....but I think braces are the worst things in the world--other than liver--so I don't use them if I don't have to. I think they make C and C++ too hard to read.
istream::getline() reads a line terminated by a '\n'.
Make sure that no line in the file is longer than 97 characters (100 - carriage-return, line-feed and terminating zero).
Change
while(input.getline(buff,1
to
while(input.getline(buff, sizeoff buff).good())
See if it helps.