Thread: Console-based file i/o troubles

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    25

    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.

  2. #2
    Registered User
    Join Date
    Nov 2004
    Posts
    17
    what exactly are you doing with this kind of thing:

    Code:
    if (buffer=="!"){ //IF Proceeding line is a list name
    are you meaning to compare:

    Code:
    if((buffer[0] == 33) && (buffer[1] == 0))
    cause that's what it appears to me.. -though honestly I've only used String on a few occasions so I don't know if that's doing what you are looking for.

    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 ..
    There shouldn't be any reason why you shouldn't be able to do what you want here...

    I'll dl the program and take a glance at it..

  3. #3
    Registered User
    Join Date
    Nov 2004
    Posts
    25

    Thanks, and yeah.

    Thanks for taking a look. =|

    And yea, it reads a line of the file into the string buffer, and then compares it to another string literal. =\ That works, desn't it? =P

    Maybe I'll try that.

    Making the buffer a C string. =|
    Last edited by Callith; 12-08-2004 at 01:15 PM.

  4. #4
    Registered User
    Join Date
    Sep 2004
    Posts
    719
    Quote Originally Posted by Callith
    I'm having a rediculous problem with one of the while loops

    while (!fin.eof())
    read the faq about controlling loops in this fashion


    psuedo-code
    if (string buffer == {'!', '\0'})
    ((string buffer == "!") == true)

    if you really want to learn, now would be a good time to look into using your debugger so you can watch values.
    Last edited by misplaced; 12-25-2004 at 09:27 PM.
    i seem to have GCC 3.3.4
    But how do i start it?
    I dont have a menu for it or anything.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  2. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  3. File I/O Question
    By Achy in forum C Programming
    Replies: 2
    Last Post: 11-18-2005, 12:09 AM
  4. Console Text RPG- File I/O and Inventory
    By Jontay in forum Game Programming
    Replies: 17
    Last Post: 11-23-2003, 02:37 AM
  5. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM