Проблема с cin при вводе пробелов с использованием строкового класса

У меня есть следующий код:

main.cpp
#include <iostream>
#include <string>

using namespace std;

string name;
string age;

int main() {
    cout <<"Name: ";
    cin >> name;
    cout << endl;
    cout <<"Age: ";
    cin >> age;
    cout << endl;
    cout << "Your name is " << name << ", and you are " << age << " years old."  << endl;
    cout << "Press enter to close this application" << endl;
    getchar();
    return 0;
}

Я заметил, что если в поле ввода ввести имя для пробела, он не даст мне возможности ввести имя, и он будет рассматривать запись после пробела как возраст. Я прошу прощения, если это ошибка новичка, что, вероятно, так и есть. Ранее я программировал Java и решил, что хочу перейти на C ++, потому что он лучше соответствует моим потребностям. Я также, вероятно, форматирую свой код странным образом по вашим стандартам, пожалуйста, исправьте его, если хотите.

Screenshot of console

Я также заметил другую ошибку, с которой у меня никогда не было проблем в Java. Я не могу понять, как предотвратить его немедленное закрытие после завершения обработки. Я слышал, что вы можете использовать "систему" ("пауза"); но мне также сказали не использовать его. Я действительно запутался в том, что использовать. Я слышал, что я использую getchar (); но, похоже, он ничего не делает.

Любая помощь будет принята с благодарностью, так как я начинающий, когда дело доходит до C ++.

 Justin11 сент. 2018 г., 05:03
Возможный дубликатstd::cin input with spaces?
 dead beef13 июл. 2012 г., 01:19
@ Крис Я хотел бы выбрать ваш комментарий в качестве ответа, но я действительно не думаю, что он позволил бы мне. Спасибо за помощь. Не могли бы вы опубликовать это или что-то в качестве ответа, чтобы я мог выбрать его?
 chris13 июл. 2012 г., 01:36
Ох, и причина, по которой выgetchar не работает по той же причине, что и мой первый пример заменыsystem("pause") не работает. Это объяснено в ответе.
 chris13 июл. 2012 г., 01:28
Я решил перед вашим комментарием сделать более подробный ответ. Он есть (и, надеюсь, не имеет тонких ошибок), если вы хотите прочитать его.

Ответы на вопрос(2)

Решение Вопроса

std::cin >> name;

Вы ожидаете ввода. Когда вы вводите «Ryan Cleary» и нажимаете ввод, буфер ввода содержит:

Ryan Cleary\n

Теперь вашcin читает ввод как обычно, останавливаясь на пробеле, оставляя ваш буфер следующим образом:

 Cleary\n

Обратите внимание на начало пробела, так как оно останавливается после прочтенияRyan, Ваша первая переменная теперь содержитRyan, Если, однако, вы хотите полное имя, используйтеstd::getline, Он будет читать до новой строки, а не только пробел. Во всяком случае, продолжая:

std::cin >> age;

Теперь вы получаете еще один вход. Там уже что-то есть. Он пропускает пробел, пока не может начать чтение, оставляя буфер просто:

\n

Ваша вторая переменная получает текстCleary, Обратите внимание, что перевод строки все еще находится в буфере, что подводит меня ко второй части. Заменаsystem ("pause"); таким образом, что всегда работает, это сложно. Лучше всего, как правило, жить с менее чем совершенным решением, или, как мне нравится, с тем, которое точно не гарантирует, что оно говорит:

std::cin.get(); //this consumes the left over newline and exits without waiting

Хорошо, итакcin.get() не работал. Как насчет этого:

std::cin.get(); //consume left over newline
std::cin.get(); //wait

Это прекрасно работает, но что, если вы скопируете и вставите его куда-нибудь, где не осталось новой строки? Вам придется дважды нажать Enter!

Решение состоит в том, чтобы очистить новую строку (и все остальное), а затем ждать. Это цельcin.sync(), Однако, как видно из раздела примечаний, не гарантируется очистка буфера, как он говорит, поэтому, если ваш компилятор решит не делать этого, он не сможет быть использован. Для меня, однако, это именно так, оставляя решение:

std::cin.sync(); //clear buffer
std::cin.get(); //wait

Главное плохое вsystem("pause"); в том, что вы не представляете, какую программу он будет запускать на чужом компьютере. Они могли бы изменитьсяpause.exe или поместите тот, который был найден первым, и у вас нет возможности узнать. Это может потенциально разрушить их компьютер из-за того, что возможноany программа.

 04 сент. 2013 г., 21:54
Я сталкивался с этим, пока гуглил. Отличное объяснение. Спасибо большое.
 dead beef13 июл. 2012 г., 01:43
Спасибо, отличный ответ. Это многое мне объяснило. У меня гораздо больше понимания, чем раньше, с тем, как C ++ анализирует входные данные.

cin.getlineТаким образом, поток будет читаться до первого символа новой строки.

Хорошо, плохой совет, как указали некоторые люди. Ты можешь использоватьстанд :: GetLine прочитать целую строку. Опять же, разделителем является новая строка, если не сообщается. Читать изcinВы можете передать его в качестве первого параметра (и строку в качестве второго).

std::string str;
std::getline(cin, str); // to read until the end of line

std::getline(cin, str, ' '); // to read until a space character, for instance

(конечно, вы можете опуститьstd:: часть из строк, так как вы уже сообщили компилятору, что вы используетеstd Пространство имен)

 13 июл. 2012 г., 01:12
-1 плохой совет.std::getline безопасно и легко,cin.getline не является.
 13 июл. 2012 г., 01:27
@BrunoBrant, сейчас содержит правильную информацию. Тот факт, что вы приложили усилия, чтобы изменить его, имеет значение.
 13 июл. 2012 г., 01:14
Я пропустил ту часть, где ОП сказал, что он использует класс string.
 13 июл. 2012 г., 01:20
Исправленный. Но, во всяком случае, я не заслуживаю голосов, так как я просто позаимствовал ответ из комментариев ...
 14 июл. 2012 г., 03:02
хорошо, убрал понижающий голос

Ваш ответ на вопрос