3

I'm working on a function that reads in lines of a file until the line "XXX" is reached in the file, and a counter keeps track of how many lines have been read. Then the program counts the remaining number of lines in the file. I'm using an if statement to determine when to break the while loop (when the line read equals "XXX") and the condition is not being met. Even when line == "XXX", the else statement will still run. What's wrong with my code? Thanks!

#include <string>
#include <iostream>
#include <fstream>

using std::string;
using std::endl;
using std::cout;
using std::ifstream;

int main()
{ 
    //Main function
}

void read_file(string input_file_name)
{
    string i_filename = input_file_name;
    ifstream infile;
    infile.open (i_filename);
    string line;
    int num_of_terms1 = 0;
    int num_of_terms2 = 0;

    if (!infile)
    {
        cout << "Your input file could not be opened."<<endl;
    }
    else
    {
        while (!infile.eof())
        {
            getline(infile, line);
            cout << line << endl;

            if (line == "XXX")
            {
                break;
            }
            else
            {
                cout << line << endl;
                num_of_terms1++;
            }
        }
        while (!infile.eof())
        {
            getline(infile, line);
            cout << line << endl;
            num_of_terms2++;
        }
    }
cout << "Terms 1: "<<num_of_terms1 <<endl;
cout << "Terms 2: "<< num_of_terms2 <<endl;
infile.close();
}

Here's a sample input file, inputfile.txt:

-2 3
4 2
XXX
-2 3

Thanks in advance for your help!

drew_
  • 41
  • 1
  • 3
  • What does the output look like? – maxywb Oct 14 '14 at 17:59
  • 1
    Why don't you do some debugging. Start by inspecting the values of `line` on each iteration of the loop. Your real problem is not that the program doesn't work, but that you have not learnt how to debug. Once you do so you can solve all these problems yourself. – David Heffernan Oct 14 '14 at 18:00
  • Why do you think that "Even when line == "XXX", the else statement will still run" ? – Slava Oct 14 '14 at 18:00
  • 1
    Did you check for spaces, carriages, etc.? – Shokwav Oct 14 '14 at 18:00
  • Why are you passing strings by value every where and copying them – UpAndAdam Oct 14 '14 at 18:03
  • Your main function is empty... nothing will happen; that output is impossible. – UpAndAdam Oct 14 '14 at 18:03
  • Notice that you have 2 `cout` statements, did you verify which one printed the `XXX`? – smac89 Oct 14 '14 at 18:04
  • As @Shokwav points out, just because you can't *see* a character, doesn't mean it's not there. You might try [trimming](http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring) – aruisdante Oct 14 '14 at 18:04
  • The output simply prints the whole file, but because the if statement doesn't run the counter num_of_terms1 equals the number of lines in the file, rather than the number of lines leading up to where I'd like to stop the loop. I have used debugging and it shows that line equals "XXX" when the if statement is checked, but it still doesn't work. – drew_ Oct 14 '14 at 18:04
  • I typed the file myself and there are no extra spaces anywhere to cause difficulty. As for the main function, it is full but irrelevant for this question. It gets the name of the input file and correctly sends it to the read_file function. – drew_ Oct 14 '14 at 18:06
  • 2
    `while (!infile.eof())` Related: [Why is iostream::eof inside a loop condition considered wrong?](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – πάντα ῥεῖ Oct 14 '14 at 18:06
  • And the cout statements that I have placed all show exactly what they should, which is why I'm so confused. – drew_ Oct 14 '14 at 18:07
  • see my answer. Your strings are being read with a carriage return character at the end. – Richard Hodges Oct 14 '14 at 18:19
  • @drew_ `I have used debugging and it shows that line equals "XXX" when the if statement is checked, but it still doesn't work` This means that the string has non-printable characters embedded in it somewhere, and the debugger doesn't show you non-printable characters (by default). So you need to investigate how to view the actual characters that make up the string in the debugger. – PaulMcKenzie Oct 14 '14 at 18:50

3 Answers3

3

I tested this code on www.compileonline.com and repeated your findings.

In that environment each string read from the file has a \r character on the end of it.

When I changed the terminating line to if (line == "XXX\r") the code worked as expected.

It seems that your input file's lines are terminated with "\r\n" which is the norm for windows, but unix text files are normally terminated with '\n'.

Update:

Here's a little demo of how one might remove trailing carriage returns and linefeeds (or anything else you want for that matter):

#include <string>
#include <algorithm>
#include <iostream>

void trim_cruft(std::string& buffer)
{
    static const char cruft[] = "\n\r";

    buffer.erase(buffer.find_last_not_of(cruft) + 1);
}

void test(std::string s)
{
    std::cout << "=== testing ===\n";
    trim_cruft(s);
    std::cout << s << '\n';
}

int main()
{
    test("");                   // empty string
    test("hello world\r");      // should trim the trailing \r
    test("hello\nworld\r\n");   // don't trim the first newline
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • Thank you! I tried with "XXX\n" but I didn't realize "\r" would do it. I really appreciate the help. – drew_ Oct 14 '14 at 18:34
  • 2
    I feel that it's important that you understand what's going on here. Embedding `\r` in your test string will make this work on windows but not on unix. It's better to clean any control characters off the string you read before testing it. – Richard Hodges Oct 14 '14 at 18:47
1

First of all you should read this: Why is iostream::eof inside a loop condition considered wrong?

Second your debug lines:

cout << line << endl;

are exactly the same in both cases - you are inside else statement or you are counting num_of_terms2 and it is confusing. Change them, so you can see which one is printed.

After you fix that issues you will see that "else statement will not still run"

Community
  • 1
  • 1
Slava
  • 43,454
  • 1
  • 47
  • 90
0

As I said in the comments, you have 2 cout statements you should verify which one is printing the XXX. If none of them are, then it is likely the problem is that there is a carriage return in the string, you can verify this other case with:

cout << line << endl; // print is here

if (line == "XXX\r")
{
    break;
}
else
{
    cout << line << endl; // print is here
    num_of_terms1++;
}
smac89
  • 39,374
  • 15
  • 132
  • 179