0

This is not homework, it is self study. I am getting an unexpected error that is think is the result of getline requesting after the end of file. I though I was checking to see if input was successful with the while(getline(inf,mystring)) but its not working. How do I effectively check for end of file if this is not the case?

This is my code

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

int main(int argc, char** argv)
{
    string mystring, substring1 = "", substring2 = "";
    int sos;
    ifstream inf (argv[1]);  //open file for reading
    if (!inf)
    {
        // Print an error and exit
        cerr << "Uh oh, " << argv[1] << " could not be opened for reading!" << endl;
        exit(1);
    }
        while(getline(inf,mystring))
        {
                sos = mystring.find_first_not_of(" ");
                if (sos != 0)
                {
                    mystring = mystring.substr(sos, string::npos);
                }
                sos = mystring.find_first_of(" ");
                if (sos != 0)
                {
                    substring1 = mystring.substr(0,sos);
                    substring2 = mystring.substr(sos + 1, string::npos);
                }
                sos = substring2.find_first_of(" ");
                if (sos != 0)
                {
                    substring2 = substring2.substr(0, sos);
                }
                cout << substring2 << " " << substring1;

        }
    return 0;
}

This is the error

World Helloterminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::substr

This is the input file input.in

         Hello World
9
  • 1
    Please use a debugger and pinpoint the crash to a single line of code. That should make life easier for all of us. Commented Mar 1, 2014 at 2:15
  • Do you have empty lines in the file? Commented Mar 1, 2014 at 2:22
  • What exactly are you trying to do? Commented Mar 1, 2014 at 2:39
  • It is supposed to read in one or more lines, remove leading and trailing spaces and then swap the 2 words that are on each line. Commented Mar 1, 2014 at 2:48
  • @WilliamMichaelVondran Then I will supply better code for you. Commented Mar 1, 2014 at 3:01

2 Answers 2

1

Before you extract a sub-string, you need to check that the range of the sub-string is physical (that is, the first index of a call to $substr$ comes before the last). I suspect that your file contains an empty line, in this case a call to $find_first_not_of$ will return $npos$ indicating that nothing was found before the end of the string.

I would suggest adding a check for $npos$ returned from $find_first_not_of$:

// Strip leading spaces
sos = mystring.find_first_not_of(" ");
/* sos == 0 would mean substr(0, npos) -> useless.
   sos == npos would mean substr(npos, npos) -> un-physical. */
if (sos != 0 && sos != string::npos)
{
    mystring = mystring.substr(sos, string::npos);
}

// Split string by first space
sos = mystring.find_first_of(" ");
substring1 = mystring.substr(0, sos); /* sos != 0, since strip leading spaces */
/* Check that sos+1 is inside the string. */
if (sos+1 < mystring.length())
{
    substring2 = mystring.substr(sos+1, string::npos);
}
else
{
    substring2 = "";
}

sos = substring2.find_first_of(" ");
/* sos == 0 would cause substr(0, 0) -> un-physical,
   sos == npos would cause substr(0, npos) -> useless. */
if (sos != 0 && sos != string::npos)
{
    substring2 = substring2.substr(0, sos);
}

count << substring2 << ' ' << substring1 << std::endl;
Sign up to request clarification or add additional context in comments.

Comments

1

Note that find_first_not_of returns string::npos when it doesn't find anything - not zero as you are testing. If you have a line with no spaces (or an empty line) then your test for find_first_not_of(" ") will return string::npos leading to

mystring = mystring.substr(string::npos, string::npos);

which will cause an exception.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.