Эта программа работает без цикла, однако, когда я реализую цикл, я получаю ошибку времени выполнения. Я думаю, что это может иметь какое-то отношение к моей cin.getline, но я действительно понятия не имею:/любая помощь была бы большой благодаря вам!
#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;
}
Ошибка в этой строке:
lname=mystring.substr(v, x);
где v
имеет очень большое значение. Итак, как ваша программа попадает туда, и как v
получает эту ценность? v
имеет значение std::string::npos
, что означает код ошибки, в данном случае, что место, которое вы искали, не было. Это связано с различием между форматированным и неформатированным вводом и тем фактом, что вы их смешиваете.
Форматированный вход означает обработку входного потока в виде потока токенов. Ведущие пробелы - пробелы, пробел, табуляция или новая строка - пропущены, а конец токена - вход. Одним из примеров форматированного ввода является
cin >> ans;
Для форматированного ввода все, что не соответствует его шаблону, выглядит одинаково. Будет ли std::istream::operator>>(int)
встречать пробел, вкладку, новую строку, 'a'
или " z'
, это только конец токена, и там он перестает читать. Например, если у вас есть
int x;
std::string s;
std::cin >> x >> s;
и подайте его на вход 123abc
, тогда x
будет иметь значение 123
, а s
будет "abc"
. Реально, это означает, что если пользователь отвечает
cin >> ans;
с номером и новой строкой, встреченный символ после номера - новой строки - остается в потоке.
Неформатированный вход, напротив, означает обработку входного потока как потока символов. Для неформатированных входных функций пробелы - это еще один символ, и если неформатированная функция ввода определяет для них особый смысл, он будет относиться к ним так же, как и любой другой символ. Примером неформатированного ввода является
getline(cin, answer1);
который является сокращением для
getline(cin, answer1, '\n'); // that is to say, the delimiter
// has a default value of '\n'
(просто для того, чтобы было ясно, что символ новой строки '\n'
имеет особый смысл в этом случае). getline
, используемый таким образом, будет считывать из потока до тех пор, пока он не встретит новую строку.
И в этом твоя проблема. После предыдущей форматированной функции ввода в потоке остается материал, который вам неинтересен. Вероятно, это просто 123abc
(хотя, если пользователь предоставил 123abc
, он будет abc\n
), и в этом случае getline даст вам пустую строку - там есть пустая строка в потоке, так что же еще она может сделать?
Существует несколько способов справиться с этим условием. Одно можно сказать
#include <iostream>
#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Это, по существу, означает: игнорировать все до следующей новой строки (numeric_limits<streamsize>::max()
- очень большое число, которое cin.ignore
рассматривает как бесконечность). Другой
cin >> ws;
в котором говорится: "игнорировать все до следующего символа без пробелов", хотя это игнорирует ведущие пробелы в следующей строке и не будет игнорировать abc
если пользователь предоставил 123abc
. В вашем случае я считаю, что нет причин менять передачи с форматированного ввода - вам не нужна строка, но имена и фамилии. Я предлагаю использовать
string fname, lname;
cin >> fname >> lname;
Это также устранит другую ошибку (вы используете код ошибки как индекс строки), потому что вам не нужно искать пространство в строке, которая может отсутствовать.
Делать
cin >> ans;
cin >> std::ws;
перед циклом while. Кроме того, проверьте
v=answer1.find(" ", 0);
для std :: npos
который является возвращаемым значением, если поиск не увенчался успехом.