-4

I am returning to C++ after a decade in java and this has held me up for two weeks now. I have seen many posts with getline issues and these have led me to add many "cout"s trying to find exactly what is wrong. I have found out about the bad, fail and eof bits but still have the same issue. getline doesn't populate the string or go into the while loop. Don't know if it matters but I am coding on a Win7 PC in netbeans and compiling/running on a rasberry pi (running raspbian (Debian I think)).

All I am trying to do is read a simple text file using getline! Should be basic ('scuse the pun :-)) I have tried creating the text file with both Unix and ASCII line endings (0x0A and 0x0D0A) - made no difference. I am running the program with the same userid that created the text file so no permissions issues.

Getline sets the fail bit (only...not eof) but perror reports "Success" and I get no data in "work".

Here is most of the class that causes the error - with many debugging annotations. "theFile" is just an fstream ('cos in the future version I might want to open it for output instead). But here, as you can see from the output, I am definitely opening the file with ios::in. The "issue" happens with the getline loop (which is never entered) in the getValue member function. I haven't included the constructor but it only sets a few flags to false. And the caller (MJAppl) just calls MJConfigFile::getValue( "log_dir", false ).

string MJConfigFile::getValue ( string in_key, bool in_restart ) {
    bool   found   = false ;
    string work    , ret   ;
    int    key_len = in_key.length() , loop_count = 0 ;
    //char   workbuf [ 200 ] ;

    cout << "MJConfigFile::getValue entry for key " << in_key << " \n" ;
    cout << "File name is " << getFName () << "\n" ;
    if ( in_restart || !openForInput ) {
        theFile . close () ;
        open ( false ) ;        
    }
    if ( theFile . is_open ()) {
        cout << "File " << fullFileName << " is open." << "\n";
    } else {
        perror ( "Error while opening file " ) ;
    }
    while ( getline ( theFile, work )) {
        if (loop_count++ > 5 ) return "Stopped \n" ;
        cout << "Line '" << work << "'\n";
        if ( in_key.compare ( work ) == 0 ) {
            ret = work.substr ( key_len + 1 ) ;
            break ;
        }
    }
    perror ( "Error reading file. " ) ;
    cout << "Line after loop '" << work << "'\n";
    if ( theFile.bad() | theFile.fail() | theFile.eof()) {
        if ( theFile . bad () ) cout << "Bad  file." << endl ;
        if ( theFile . fail() ) cout << "Fail file." << endl ;
        if ( theFile . eof () ) cout << "eof  file." << endl ;

    }
    return ret ;
}

void MJConfigFile::open () {
    this -> open ( false ) ;
}
void MJConfigFile::open ( bool in_for_output ) {    

    if ( in_for_output ) {
        theFile . open ( fullFileName.c_str (), ios::out ) ;
        if ( theFile . is_open ()) {
            openForOutput = true ;
            cout << "File is open for output. \n" ;
        }
    } else {
        theFile . open ( fullFileName.c_str (), ios::in ) ;
        if ( theFile . is_open ()) { 
            openForInput  = true ;
            cout << "File is open for input. \n" ;
        }
    }    
    if ( openForInput || openForOutput ) {
        exists   = true ;
    }
}

Here is sample output from a run:

    In default MJConfigFile constructor
    File is open for input.
    MJAppl.readConfigFile() entry.
    File is open for input.
    MJConfigFile::getValue entry for key log_dir
    File name is /mjmaint/MJApplCfg/MJApplCfg.cfg
    File /mjmaint/MJApplCfg/MJApplCfg.cfg is open.
    Error reading file. : Success
    Line after loop ''
    Fail file.
    logdir is
    0

And here is a sample input file:

    Aaaaaa
    Bbbbbb
    Cccccc

I am just about ready to give up and go back to java so any help would be REALLY appreciated.

Msj
  • 3
  • 1
  • 6
    Your question fails to meet the requirements for a [mcve]. The help you're looking are the instructions for creating a [mcve] to be included in your question. – Sam Varshavchik Aug 12 '17 at 12:55
  • Looks grossly overcomplicated an contrary to the language style. Did you bother to look for an example first to familiarize yourself with "how things are done in C++"? – ivan_pozdeev Aug 12 '17 at 12:58
  • Possible duplicate of [Read file line by line](https://stackoverflow.com/questions/7868936/read-file-line-by-line) – ivan_pozdeev Aug 12 '17 at 12:59
  • 2
    There is no reason to believe operations on fstream would set errno to an error code. Also, please provide a [mcve](/help/mcve) – MikeMB Aug 12 '17 at 13:00
  • 1
    Have you checked fail bits before you are calling getline? – MikeMB Aug 12 '17 at 13:06
  • "eof file" is RAS syndrome :) – Post Self Aug 12 '17 at 13:21
  • The fact that *"File is open for input."* appears twice in the output looks suspicious. It seems you are calling `open()` on the same `fstream` instance twice. The second time would fail, set `failbit`, and then all subsequent operations would fail immediately. – Igor Tandetnik Aug 12 '17 at 14:12
  • WhooHoo! Thank you Igor: I could kiss you. I knew it had to be something I was doing that was dumb. Thanks also to all who took the time to answer. – Msj Aug 13 '17 at 14:00
  • My apologies for not posting minimal code. And the code I DID provide will look a lot less complicated without all the "couts". As to "how things are done in C++" I am quite confident that this way will suit my future needs. Little point in using an OO language if one doesn't use objects?? – Msj Aug 13 '17 at 14:03

1 Answers1

0

Just in case anyone ever hits this same peculiar set of fail/success conditions again, the issue was that I was calling open twice on the same fstream. The open appeared to succeed but getline wouldn't run because the streams' fail bit was set. Thanks Igor.

Msj
  • 3
  • 1