1

I am using following function:

int getline_count()
{
    boost::smatch resultc;
    string sLine;
    int line_add_tmp;
    ifstream infile;
    infile.open("scripts.txt", ios_base::in);
    if (!infile){
        cerr << "scripts.txt could not be opened!" << endl;
    }
    else {
        getline(infile, sLine);
        if (boost::regex_match(sLine, c)) {
            line_add = 2;
        }
        else {
            line_add = 1;
        }

        return line_add;
    infile.close();
    }
}

Intension for the above function is to test if the first line in the file contains '// new' If true, 2 is returned. If false, 1 is returned. This works fine so far.

What I am confused about is that after the run the file scripts.txt is empty. How can that be since

1.) The '// new' line was correctly identified as I am getting '2' returned (running on an empty file returns 1 as expected). So it can't be that during opening the file scripts.txt it was overwritten with an empty file

2.) ifstream was designed to read only

What is it what I am missing?

Edit:

Definition for c is

static const boost::regex
    c("^(\\/)(\\/)(new|New| new| New)");  // Regexp for line count  
Blacksheep
  • 119
  • 2
  • 9

2 Answers2

2

An ifstream should never manipulate your file. You will need to look elsewhere for your problem, it's not inside this code. Your best bet is to provide a Minimal, Complete, and Verifiable example that demonstrates your problem.

However, you should check your coding, you are missing essentials like error handling and treating compiler warnings. Most likely, if your other code looks the same, that's the source of your problem.

Personally, I'd write your function like this:

bool first_line_in_file_matches(const std::string& filename, const boost::regex& c)
{
    std::string line;
    std::ifstream infile(filename.c_str());

    if (!infile)
    {
        cerr << filename << " could not be opened!" << endl;
        // TODO: THROW AN EXCEPTION MAYBE? OR RETURN FALSE? EXIT HERE
    }

    return getline(infile, line) && boost::regex_match(line, c);
}
Community
  • 1
  • 1
nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Because the OP wants an empty file to return `1` or `false` in your case. I'd say you shouldn't print an error on an empty file. Removing that whole `if`-block and doing this would probably be prefereable: `return getline(infile, line) || boost::regex_match(line, c);` Additionally an early exit if your first `if` fails would be profitable. – Jonathan Mee Mar 22 '16 at 12:13
  • @JonathanMee Yes, maybe. That's something only the OP can say. – nvoigt Mar 22 '16 at 12:15
  • He does say, in the question: "Running on an empty file returns 1 as expected" – Jonathan Mee Mar 22 '16 at 12:16
  • @JonathanMee Wow, didn't read that, you are right. – nvoigt Mar 22 '16 at 12:31
  • Helpful modifications I approve. Have a +1. (Also you don't need the `ios_base::in` argument. That's the default. And if you're using C++11 you don't have to call `c_str`.) – Jonathan Mee Mar 22 '16 at 12:38
  • @JonathanMee The || should have been a &&, right? Or am I missing something? – nvoigt Mar 22 '16 at 12:41
  • Yeah, you have the right of it, I goofed. – Jonathan Mee Mar 22 '16 at 12:42
  • @nvoigt: Thank you for your comment. I am pretty sure that you are right but I am still in the phase of learning (as you might see from my code). I extrated the function into a single program and it works as intended. So this really must have to do with other code. I suspect a "race condition" between other possibly open files. I will try to narrow down this further to completely understand what is happening. Thanks a lot! – Blacksheep Mar 22 '16 at 12:47
  • @Blacksheep Note that this will occur from some file handle to "scripts.txt" So I'd strongly encourage you to search your other code and find that file handle, and spend some time debugging there. – Jonathan Mee Mar 22 '16 at 12:52
  • 1
    @Jonathan Mee: Thanks for your inputs. I am running through gdb right now. When I have the final root cause I will document it here helping others not to run into this kind of trap. – Blacksheep Mar 22 '16 at 12:56
  • @Blacksheep Depending upon how your programs file handles access the file you may be able to disable writing. Ideally that would cause an error in the culprit code, that you could easily find. – Jonathan Mee Mar 22 '16 at 12:59
1

This function will not clear the contents of the file. So if in fact the file is cleared it is cleared externally to getline_count.

To prove this lets inspect the functionality of each call on ifstream relative to the file:

Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it extracts characters from its associated stream buffer object as if calling its member functions sbumpc or sgetc, and finally destroys the sentry object before returning.

  • ifstream::~ifstream This is implicitly declared, so it simply destroys the object, closing the file; if this deleted file contents no one would ever have been able to use an ifstream

The recommended steps to finding the culprit of the file clearing are:

  1. Ensure that you are looking at the correct file and don't have some process external to your code which is clearing the file
  2. Search your code for "scripts.txt" something else has to access the file by name and debug it
  3. Disable writing to "scripts.txt" and see if you can locate the code that fails to write to the file
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288