problems with the input buffer

Discussion in 'Programmer's Corner' started by mentaaal, Nov 22, 2008.

  1. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hey guys, i am wanting to search for a particular striing inside of an ordiinary text file.
    I could not find anway to do this except using getline to take in the file line by line and then use the string find function to find the string in question. The problem that i am having is when i put this process into a loop, the program fails. As in the loop no longer appears to want to exit at all.

    The code snippet in question is here:
    Code ( (Unknown Language)):
    1. database::database()
    2. {
    3.    
    4.     cout << "Please enter in the name of the database file.\n";
    5.     char Char[200];
    6.     do
    7.     {
    8.         cin >> file_name;
    9.         cout << "the contents of file_name is now:" << file_name  <<"test" << endl;
    10.         strcpy(Char,file_name.c_str());
    11.         file.open(Char, ios::in | ios::out); //open file for both input and output operations. Need to change to null terminated character string
    12.         if(file.fail())
    13.             cout << "Error opening file\nPlease recheck file name and re-enter.\n";
    14.        
    15.     }
    16.     while (file.fail());
    17.    
    18. }
    What happens is if i enter in the filename correctly first time, it appears to work but if i dont enter it in correctly first time, the loop will not exit even if you type it in corectly the second time.

    Being now curious i then tried the code below, which doesnt work at all!
    Code ( (Unknown Language)):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. void main()
    5. {
    6.     char Char[200];
    7.     do
    8.     {
    9.         cout << "enter string.\n";
    10.         cin >> Char;
    11.         cout << Char;
    12.  
    13.     }
    14.     while (Char != "hello");
    15. }
    16.  
    I have spent loads of time trawling the net which makes various references to clearing the input buffer using cin.ignore() and cin.clear() but nothing i try works here. ARRGGGGHHHH!!

    Edit: it may not be clear but file_name is a private data member of type string. I initially tried using file.open(file_name.c_str(), ios::in | ios::eek:ut); but the same problem occurred
    Also, file is an fstream object
    thanks ;-)
     
  2. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    For your first example, I don't think you should be calling file.fail() twice. I'm not able to confirm this looking at the MSDN documentation, but that part makes me a little nervous.

    I would recommend taking the call to file.fail() out of your while condition at the bottom of the loop, and instead doing this:
    Code ( (Unknown Language)):
    1.  
    2. database::database()
    3. {
    4.     boolean file_failure = false;  // added flag variable
    5.     cout << "Please enter in the name of the database file.\n";
    6.     char Char[200];
    7.     do
    8.     {
    9.         cin >> file_name;
    10.         cout << "the contents of file_name is now:" << file_name  <<"test" << endl;
    11.         strcpy(Char,file_name.c_str());
    12.         file.open(Char, ios::in | ios::out); //open file for both input and output operations. Need to change to null terminated character string
    13.         if(file.fail())
    14.         {
    15.             file_failure = true;
    16.             cout << "Error opening file\nPlease recheck file name and re-enter.\n";
    17.         }
    18.        
    19.     }
    20.     while (file_failure != true);  
    21.    
    22. }
    23.  
    The while loop condition could also be written as: while (!file_failure);
    but the way I have it in your code is a bit more readable.

    For your second example, you can't compare two strings for equality, at least you can't compare them in the way you want. Char all by itself doesn't evaluate to whatever is stored in the memory it represents: it evaluates to the location in memory of the first byte of that array. Similarly "hello" doesn't evaluate to those characters; it evaluates to the memory address where the 'h' of that string is stored.

    Here's what should work (this would go in the while condition of your loop):
    Code ( (Unknown Language)):
    1.  
    2.     while (!strcmp (Char, "hello"));
    3.  
    You'll need to #include <string.h>.
    strcmp() returns 0 if the strings are the same.
    Mark
     
  3. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hey again Mark,

    ok well the second answer you gave me works great thanks. I must have mixed up string and cstring. Thats what i get for posting at half past 4 in the morning!

    Ok i tried your first suggestion and it didnt work but i was able to get it working based on your suggestion. You were right about calling the file.fail() multiple times being not a good idea. The key problem that my code had was that i had to reset the flag after file.fail() became true.

    Working code below:
    Code ( (Unknown Language)):
    1. database::database()
    2. {
    3.    
    4.     cout << "Please enter in the name of the database file.\n";
    5.     bool file_failure = false;
    6.     char Char[200];
    7.     do
    8.     {
    9.         cin >> file_name;
    10.  
    11.         file.open(file_name.c_str(), ios::in | ios::out); //open file for both input and output operations. Need to change to null terminated character string
    12.         if(!file)
    13.         {
    14.             cout << "Error opening file\nPlease recheck file name and re-enter.\n";
    15.             file_failure = true;
    16.             file.clear();
    17.         }
    18.         else file_failure = false;
    19.        
    20.     }
    21.     while (file_failure == true);
    Thanks for the help though Mark, invalueble as always.
     
  4. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    I have enocountered a similar problem with my next function. I am trying to find a student based on the student id and return the location. (Which in this case is the first integer number on each line of the database text file. )

    I sucessfully managed to do this which is in the code below but i also want to move the file pointer to the beginning of this line so i can edit the record at a later stage. I have tried looking for a solution to this problem on the net but there doesnt appear to be a way without indexing the file (not really what this is or how to do it.)

    So my question is this: Is it possible to move the file pointer to the beginning of a line?

    Code ( (Unknown Language)):
    1. int database::find_student(const long stud_id)
    2. {
    3.     char Char[200];
    4.     string line;
    5.     int file_location = -1;
    6.     _ltoa_s(stud_id,Char,10); //converts a long to a cstring
    7.     file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    8.     cout << file.tellg();
    9.     while (getline(file,line))
    10.     {
    11.         if (line.find(Char)!= -1)
    12.         {
    13.             int temp;
    14.             cout << "id found!\n";
    15.             istringstream i(line);
    16.             i >> file_location;
    17.             cout << "File record found at location " << file_location << endl;
    18.             cout << "pointer location " << file.tellg() << endl;
    19.             file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    20.             file.seekg(-2,ios::cur);
    21.             file.ignore();
    22.             file.clear();
    23.             while (file.peek() != '\n')
    24.             {
    25.                 temp = file.tellg();
    26.                 if(temp != 0)
    27.                 {
    28.                     file.seekg(-1,ios::cur);
    29.                     file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    30.                 }
    31.             }
    32.             file.get();
    33.            
    34.             getline(file,line);
    35.             cout << line;
    36.             break; //stops searching the database if student id is found.
    37.         }
    38.         file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    39.        
    40.     }
    41.    
    42.    
    43.    
    44.    
    45.  
    46.     return 0;
    47. }
     
  5. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Before i waste anyone's time i think i got it!

    i made a loop finding the previous newline carrier or the beginning of the file like this:

    Code ( (Unknown Language)):
    1. int database::find_student(const long stud_id)
    2. {
    3.     char Char[200];
    4.     string line;
    5.     int file_location = -1;
    6.     _ltoa_s(stud_id,Char,10); //converts a long to a cstring
    7.     file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    8.     cout << file.tellg();
    9.     while (getline(file,line))
    10.     {
    11.         int temp;
    12.         if (line.find(Char)!= -1)
    13.         {
    14.             cout << "id found!\n";
    15.             istringstream i(line);
    16.             i >> file_location;
    17.             cout << "File record found at location " << file_location << endl;
    18.             cout << "pointer location " << file.tellg() << endl;
    19.             file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    20.             file.seekg(-6,ios::cur);
    21.            
    22.             while (file.peek() != '\n')
    23.             {
    24.                 temp = file.tellg();
    25.                 if(temp != 0)
    26.                 {
    27.                     file.seekg(-1,ios::cur);
    28.                     file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    29.                 }
    30.                 else break;
    31.             }
    32.             getline(file,line);
    33.             cout << line;
    34.             break; //stops searching the database if student id is found.
    35.         }
    36.         file.seekg(file.tellg(), ios::beg); // seek to current file position to prevent any problems
    37.        
    38.     }
    Thanks anyway
     
Loading...