Console-based file i/o troubles
Well, I've been wrestling this program around for awhile now, and decided I'd try the file I/O part on my own. Sadly, I failed.
I did however manage to get a very nice portion of it completed. I was thinking about scrapping it and doing it over, since this seems to help me develop my ideas. Or it has in the past.
Unfortunately, I've spent so much time on this part of the program that I don't want to just throw it out. I'm having a rediculous problem with one of the while loops, and it's been pretty frustrating. =\
I'm glad this isn't due to anyone, teacher or employer. =P
I figured I'd toss it out here before I throw it out, in hopes someone can find what's wrong. I'll try to be as descriptive as possible, and I apologize for the slight lack of comments. It's a habit I need to develop for my own sake, I know.
Anyhow, I've attatched a text file with the whole program incase you need to see that too, but it's nothing special.
The following two functions are member functions of a class 'list' which is a representation of a list of contacts. Somehow it also contains functions for loading other lists and creating lists, which probably isn't good practice, but I'm still learning. I need to be told these things. =P
Code:
void listSave(){
if (loaded==false){
cout<<"There is no list to save. Load, or create one."<<endl;
return;
}
//Get existing listNames
ifstream fin;
ofstream fout;
vector<string> databaseList; //vector of listNames that already exist
string buffer;
fin.open("list.txt", ios::in); //File reading opens "list.txt"
if (!fin.is_open()){ //If there's no file, create one.
cout<<"Error opening file."<<endl;
cout<<"Creating new file."<<endl;
fin.close();
fout.open("list.txt");
fout.close();
/*******
* listNewSave() is the function used for writing both
* new, and already existing lists
********/
listNewSave(); //If there was no file, it means this is a new list
return;
}
while (!fin.eof()){ //Until end of file
fin>>buffer;
if (buffer=="!"){ //IF Proceeding line is a list name
fin>>buffer; //buffer = next listName
cout<<"Existing list: "<<buffer<<endl;
databaseList.push_back(buffer); //add list name to databaseList
}
}
fin.close();
//Compare current 'listName' to 'databaseList' - true or false to 'listExists'
vector<string>::iterator allSavedLists;
bool listExists=false;
for (allSavedLists=databaseList.begin();allSavedLists!=databaseList.end();++allSavedLists){
cout<<"Existing List Comparison: "<<*allSavedLists<<endl;//debug
if (*allSavedLists==listName){ //if current list exists
listExists=true;
}
}
//load a representation of the whole file before saving
//almost like a 'backup'
vector<string> allOtherLists;
vector<contact>::iterator savingContact;
string tempBuffer;
string nextListName;
ifstream fin2;
if (listExists==true){
cout<<"List DOES Exist."<<endl;
fin2.open("list.txt", ios::in);
while (!fin2.eof()){
cout<<"."<<endl;
/******
* Somehow, this if statement only seems to work once, even
* though the while loop executes once for each line of the save file
******/
if ((fin2.peek())==33){//if at beginning of list
cout<<"Found a list..."<<endl;
fin2>>tempBuffer; // Should contain the listname prelimiter '!'
fin2>>nextListName; // Should contain the list's name
cout<<"List's Name: "<<nextListName<<endl;
cout<<"Checking to see if found list is current list"<<endl;
if (nextListName==listName){ //if list being saved is current list...
while (buffer!="!"){
fin2>>buffer;
cout<<"Skipping over: "<<buffer<<endl;//debug
}
allOtherLists.push_back(buffer);//don't exclude the next list's delimeter!
}
else{
cout<<"List was a different list. Including list in representation."<<endl;
allOtherLists.push_back(tempBuffer);
cout<<"Included: "<<tempBuffer<<endl;
allOtherLists.push_back(nextListName);
cout<<"Included: "<<nextListName<<endl;
}
}
fin2>>buffer;
cout<<"Adding to representation: "<<buffer<<endl;//debug
allOtherLists.push_back(buffer);
}
fin.close();
fout.open("list.txt", ios::out | ios::trunc);
for (vector<string>::iterator i=allOtherLists.begin();i!=allOtherLists.end();++i){
//cout<<"Printing... "<<(*i)<<endl;//debug
fout<<(*i)<<endl;
}
fout.close();
}
//if list is new, save to end of file
listNewSave();
return;
}
void listNewSave(){
ofstream fout;
fout.open("list.txt", ios::out|ios::app);
fout<<endl<<"!"<<endl;
fout<<listName<<endl;
cout<<"Saving...";
vector<contact>::iterator savingContact;
for (savingContact=contactList.begin();savingContact!=contactList.end();++savingContact){
fout<<"~"<<endl;
fout<<savingContact->getFirstName()<<endl;
fout<<savingContact->getLastName()<<endl;
fout<<savingContact->getMiddleName()<<endl;
fout<<savingContact->getEMail()<<endl;
fout<<savingContact->getPhoneNumber()<<endl;
}
fout.close();
cout<<"Done."<<endl;
return;
}
Magically, the loading part of the program works perfectly (as far as I can tell), but I've been having trouble getting it to save properly.
Since I recently discovered that console based C++ isn't so friendly towards a lot of seperate file interaction, especially the kind involving user defined filenames and those files which aren't in the programs directory, I had to scrap my original idea of having each instance of a list saved in it's own seperate file, and resort to using one 'super-file' that contains all the lists, seperating groups of similar data using character (pre?)limiters. An example of one such list within this file might be (assume the comments aren't part of the file):
! // This character indicates the following line is the name of a list.
Test-List // The name of the list
~ // This character indicates the following five lines are contact specific data
Callith // The contact's first name
Random // The contact's last name
P // The contact's middle name
[email protected] //The contact's e-mail
123-4567 // The contact's phone number
~ // Begining of a new contact
Etc.
Etc.
Etc.
Etc.
Etc.
! // The beginning of a new list
Test-List-2 //The second list's name
And this would continue until...well, until the computer ran out of space or the user didn't have any more friends to add.
The function (as it exists in this post) is supposed to append any newly created lists to the end of the file. This is not a problem. That part works fine. Overwriting is the strange part.
I've got a loop that reads in the file until it finds a listName. If that listName is the same as the listName being saved, it means that list already exists. The program should read the whole file into a vector of strings, skipping over the already existant list. Once it has the representation of the file minus the old list, it writes the file as represented by the vector, and then appends the changed list to the end, as if it were a new file.
I thought it was foolproof, but there's a slight problem around the part where it checks to see if the next line is a listName, and if it's the current list, skips over it (Actually it reads it, but just discards it).
If you compile the program, try making two seperate lists. Give each list a few contacts, and save them both. No problem so far right?
Now try saving the first list after editing it (you shouldn't have to edit it, but it'll give you the full tested effect). =P This works fine, because the first list detected by the loop, IS the list being skipped. However when you save it, it moves it to the end of the file. (Remember? It appends them to the end.) Try loading that list again, and resaving it. It makes a duplicate of the list! For some reason, it fails to acknowledge any list after the first list, even though the same character is used to represent the beginning of each list! This means it just adds everything to the representation, including the list it's supposed to exclude.
I hope this makes sense, and I hope someone can figure out why.
Thankee in advance.
NOTE: For anyone who missed it earlier, the file attactched is the whole program (Yep, all 621 lines) so you can compile it if you like.