0

This program is working without the loop, however when I implement the loop, I get a runtime error. I think it might have something to do with my cin.getline but I really have no idea :/ any help would be great thank you!

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


int main ()
{int ans, z;
z=1;
cout << "How many times would you like to execute this string program? " << endl;
cin >> ans;
while (z <= ans)
{  
    int x, i, y, v;
    string answer1, str3;
    string mystring, fname, lname;


    i=0;
    y=0;

    cout << "Please enter your first and last name: ";
    getline(cin, answer1);
    cout << endl;

    x=answer1.length();
    for (int i = 0; i < x; i++)
    {
        cout << answer1[i] << endl;
        if (isspace(answer1[i])) 
        {
            y=i;
        }
    }

    cout << endl << endl;
    cout << setw(80) << answer1;

    mystring = answer1;

    v=answer1.find(" ", 0);

    fname=mystring.substr(0, y);
    lname=mystring.substr(v, x);
    cout << "First name: " << fname << endl;
    cout << "Last name: " << lname << endl;

    mystring=lname+','+fname;

    cout << setw(80) << mystring;
    z++;    

}

return 0;

}
Zach Law
  • 23
  • 1
  • 8

2 Answers2

1

The error happens in this line:

lname=mystring.substr(v, x);

where v happens to have a very large value. So how does your program get there, and how does v get this value? v has value std::string::npos, which is an error code meaning, in this case, that the space you were looking for wasn't there. That this is the case has to do with the difference between formatted and unformatted input and the fact that you're mixing them.

Formatted input means treating an input stream as a stream of tokens. Leading whitespace -- all whitespace, whether space, tab, or newline -- is skipped, and where the token ends, there does the input. One example of formatted input is

cin >> ans;

For formatted input, everything that doesn't fit its pattern looks the same. Whether std::istream::operator>>(int) encounters a space, a tab, a newline, an 'a' or a 'z', that's just the end of the token, and there it stops reading. For example, if you have

int x;
std::string s;
std::cin >> x >> s;

and feed it the input 123abc, then x will have the value 123, and s will be "abc". Crucially, this means that if the user answers

cin >> ans;

with a number and newline, the encountered character after the number -- a newline -- remains in the stream.

Unformatted input, by contrast, means treating an input stream as a stream of characters. For unformatted input functions, whitespaces are just another character, and unless the unformatted input function defines a special meaning for them, it will treat them the same as any other character. An example of unformatted input is

getline(cin, answer1);

which is shorthand for

getline(cin, answer1, '\n'); // that is to say, the delimiter
                             // has a default value of '\n'

(just to make it clear that the newline character '\n' has a special meaning in this case). getline, used this way, will read from the stream until it encounters a newline.

And therein lies your problem. After the previous, formatted input function, there is stuff left in the stream that you don't care about. It is probably just a newline (although if the user provided 123abc, it will be abc\n), in which case getline will give you an empty string -- there's an empty line in the stream, so what else can it do?

There are several ways to deal with this condition. One is to say

#include <iostream>
#include <limits>

cin.ignore(numeric_limits<streamsize>::max(), '\n');

This is essentially saying: ignore everything up to the next newline (the numeric_limits<streamsize>::max() is a very large number that cin.ignore treats as infinity). Another is

cin >> ws;

which says: "ignore everything up to the next non-whitespace character", although this will ignore leading spaces in the next line, and it will not ignore abc if the user provided 123abc. In your case, I believe there is no reason to change gears from formatted input -- you don't want a line but first and last names. I suggest using

string fname, lname;
cin >> fname >> lname;

This will also eliminate the other error (that you're using an error code as string index), because you won't have to search for a space in the string that may not be there.

Wintermute
  • 42,983
  • 5
  • 77
  • 80
0

Do

cin >> ans;
cin >> std::ws;

before the while loop. Also, check

v=answer1.find(" ", 0);

for std::npos

which is the value returned if find was unsuccessful.

hahaha
  • 115
  • 7