Во-первых, вам нужно знать, что в C++ есть две getline
вещи: одна в области ввода-вывода и одна в стандартном пространстве имен верхнего уровня.
cin.getline(breed, 100)
находится в области ввода-вывода (в частности, istream::getline()
, и он ничего не знает о строках, предпочитая работать с символьными массивами. Вам, вероятно, следует избегать этого.
Тот, который действительно знает о строках, — это std::getline()
, и это, как правило, предпочтительнее, если вы не хотите возвращаться к старым недобрым временам C-устаревших "строк".
Кроме того, вам нужно быть осторожным в C++, когда вы смешиваете операции ввода, зависящие от типа (например, <<
), и операции ввода, зависящие от строки (например, getline
). Важно знать, где находится указатель файла до и после каждой операции.
Например, cin << someInt
оставит указатель файла сразу после считанного целого числа. Это означает, что если вашей следующей операцией будет getline()
, она, скорее всего, найдет все в строке после этого целого числа (как минимум, это будет символ новой строки которую вы ввели для обработки целого числа), не следующая строка, в которой вы собираетесь вводить строку.
Простое исправление для вашего случая - игнорировать все, включая новую строку, прежде чем пытаться получить следующую строку. Это можно сделать с помощью ignore()
:
#include <iostream>
#include <string>
#include <limits>
using namespace std;
int main() {
int birthyear; string breed; bool vaccines;
cout << "Please enter value for dog's birth year: ";
cin >> birthyear;
cout << "What is the breed of the dog: ";
cin.ignore(numeric_limits<std::streamsize>::max(), '\n');
getline(cin, breed);
cout << "Has the dog been vaccinated (1 = Yes/ 0 = No): ";
cin >> vaccines;
// Output what you got.
cout << birthyear << " '" << breed << "' " << vaccines << '\n';
}
Вы также можете сделать так, чтобы ввод все был линейным (преобразование этих строк в правильный тип после их ввода), так как это, вероятно, облегчит вашу задачу по обеспечению того, чтобы указатели находились в нужном месте, и что ошибки при вводе (например, ввод xyzzy
для целого числа) могут быть лучше обработаны.
Что-то вроде этого должно быть хорошим началом:
#include <iostream>
#include <string>
#include <limits>
#include <set>
#include <cstdlib>
using namespace std;
// Get string, always valid. Optionally strip leading and
// trailing white-space.
bool getResp(const string &prompt, string &val, bool strip = false) {
cout << prompt;
getline(cin, val);
if (strip) {
val.erase(0, val.find_first_not_of(" \t"));
val.erase(val.find_last_not_of(" \t") + 1);
}
return true;
}
// Get unsigned, must ONLY have digits (other than
// leading or trailing space).
bool getResp(const string &prompt, unsigned long &val) {
string str;
if (! getResp(prompt, str, true)) return false;
for (const char &ch: str)
if (! isdigit(ch)) return false;
val = strtoul(str.c_str(), nullptr, 10);
return true;
}
// Get truth value (ignoring leading/trailing space),
// and allow multiple languages.
bool getResp(const string &prompt, bool &val) {
string str;
if (! getResp(prompt, str, true)) return false;
const set<string> yes = {"yes", "y", "1", "si"};
const set<string> no = {"no", "n", "0", "nyet"};
if (yes.find(str) != yes.end()) {
val = true;
return true;
}
if (no.find(str) != no.end()) {
val = false;
return true;
}
return false;
}
// Test driver for your situation.
int main() {
unsigned long birthYear;
std::string dogBreed;
bool isVaccinated;
if (! getResp("What year was the dog born? ", birthYear)) {
std::cout << "** ERROR, invalid value\n";
return 1;
}
if (! getResp("What is the breed of the dog? ", dogBreed, true)) {
std::cout << "** ERROR, invalid value\n";
return 1;
}
if (! getResp("Has the dog been vaccinated? ", isVaccinated)) {
std::cout << "** ERROR, invalid value\n";
return 1;
}
std::cout
<< birthYear
<< " '" << dogBreed << "' "
<< (isVaccinated ? "yes" : "no") << '\n';
}
person
paxdiablo
schedule
13.06.2019
std::getline(cin, breed);
может быть полезно. en.cppreference.com/w/cpp/string/basic_string/getline - person Eljay   schedule 13.06.2019ignore
принадлежит после инструкций, которые оставляют данные в потоке, который вы хотите удалить. Не размещайте их перед другими инструкциями или случайным образом по всему коду на всякий случай. - person user4581301   schedule 13.06.2019