Używanie getline (cin, s) po cin
Potrzebuję poniższego programu, aby pobrać całą linię danych wejściowych użytkownika i umieścić ją w nazwach łańcuchów:
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);
Z poleceniem cin >> number
przed poleceniem getline()
jednak (co chyba jest problemem), nie pozwoli mi to na wprowadzanie nazw. Dlaczego?
Słyszałem coś o cin.clear()
poleceniu, ale nie mam pojęcia, jak to działa i dlaczego jest to w ogóle konieczne.
12 answers
cout << "Enter the number: ";
int number;
if (cin >> number)
{
// throw away the rest of the line
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
cout << "Enter names: ";
string name;
// keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
while (getline(cin, name))
...use name...
}
else
{
std::cerr << "ERROR reading number\n";
exit(EXIT_FAILURE);
}
W powyższym kodzie, ten bit...
char c;
while (cin.get(c) && c != '\n')
if (!std::isspace(c))
{
std::cerr << "ERROR unexpected character '" << c << "' found\n";
exit(EXIT_FAILURE);
}
...sprawdza, czy reszta linii wejściowej po numerze zawiera tylko białe znaki.
Dlaczego po prostu nie użyć ignorować?
To dość gadatliwe, więc używanie ignore
w strumieniu po >> x
jest często zalecanym alternatywnym sposobem odrzucania zawartości do następnego znaku nowego wiersza, ale grozi wyrzuceniem zawartości nie zawierającej białych znaków, a tym samym pominięciem uszkodzonych danych w pliku. Może cię to obchodzić lub nie, w zależności od tego, czy zawartość pliku jest zaufana, jak ważne jest unikanie przetwarzania uszkodzonych danych itp..
Kiedy użyjesz clear I ignore?
Tak więc, std::cin.clear()
(i std::cin.igore()
) nie jest do tego konieczne, ale jest przydatne do usuwania stanu błędu. Na przykład, jeśli chcesz dać użytkownikowi wiele szans na wprowadzenie poprawnego numeru.
int x;
while (std::cout << "Enter a number: " &&
!(std::cin >> x))
{
if (std::cin.eof())
{
std::cerr << "ERROR unexpected EOF\n";
exit(EXIT_FAILURE);
}
std::cin.clear(); // clear bad/fail/eof flags
// have to ignore non-numeric character that caused cin >> x to
// fail or there's no chance of it working next time; for "cin" it's
// common to remove the entire suspect line and re-prompt the user for
// input.
std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}
Nie może być prostsze z skipws lub podobne?
Kolejną prostą, ale na wpół upieczoną alternatywą dla ignore
dla Twojego pierwotnego zapotrzebowania jest użycie std::skipws
aby pominąć dowolną ilość białych znaków przed odczytaniem linii...
if (std::cin >> number >> std::skipws)
{
while (getline(std::cin, name))
...
...ale jeśli Dane wejściowe będą takie jak" 1E6 " (np. jakiś Naukowiec próbuje wprowadzić 1,000,000, ale C++ obsługuje tylko ten zapis dla liczb zmiennoprzecinkowych) nie zaakceptuje tego, skończysz z number
ustawionym na 1
i E6
odczytanym jako pierwsza wartość name
. Oddzielnie, jeśli masz poprawny numer, po którym następuje jedna lub więcej pustych linii, linie te będą po cichu ignorowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 04:04:38
cout << "Enter the number: ";
int number;
cin >> number;
cin.ignore(256, '\n'); // remaining input characters up to the next newline character
// are ignored
cout << "Enter names: ";
string names;
getline(cin, names);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-08 19:11:47
Innym sposobem jest umieszczenie
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
Po cin>>number;
spłukać bufor wejściowy całkowicie (odrzucając wszystkie Dodatkowe znaki, dopóki nie zostanie znaleziony nowy wiersz). Musisz #include <limits>
, aby uzyskać metodę max()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 05:53:23
Try:
int number;
cin >> number;
char firstCharacterOfNames;
cin >> firstCharacterOfNames; // This will discard all leading white space.
// including new-line if there happen to be any.
cin.unget(); // Put back the first character of the name.
std::string names;
std::getline(cin, names); // Read the names;
Alternatywnie. Jeśli wiesz, że liczba i nazwiska będą zawsze na różnych liniach.
cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::getline(cin, names);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 08:47:58
Możesz użyć STD::ws do wyodrębnienia białych znaków w buforze wejściowym przed użyciem getline. Nagłówek dla STD:: ws to sstream.
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 17:50:21
Lub możesz spłukać bufor wejściowy, aby odczytać łańcuch
Fflush (stdin)
Jest zdefiniowany w nagłówku stdio.h .
Ten kod działa..
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
fflush(stdin); //FLUSHING STDIN
getline(cin, names);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 13:23:43
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
getline(cin, names);//works on the \n left behind
getline(cin, names);//continues and rewrites names
Jest całkiem samowystarczalny, w strumieniu, którego używa cin >> number
, który zostaje przypisany do nazw po raz pierwszy. Ponowne użycie linii get zapisuje teraz poprawną wartość.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 17:11:05
Możesz znaleźć żądaną odpowiedź w cppreference .
Gdy zostanie użyte bezpośrednio po wejściu rozdzielonym białymi znakami, np. po
int n; std::cin >> n;
, getline zużywa znak końcowy pozostawiony w strumieniu wejściowym przez operatora> > i natychmiast powraca. Powszechnym rozwiązaniem jest ignorowanie wszystkich pozostałych znaków w linii wejścia za pomocącin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
przed przełączeniem na wejście zorientowane liniowo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-20 02:17:39
Chcesz użyć cin.ignoruj () po poleceniach cin, ponieważ chcesz zignorować "\n " pozostawione w buforze po pobraniu zmiennej int z cin.
Mam podobny program, którego używałem z podobnym problemem:
#include <iostream>
#include <iomanip>
#include <limits>
using namespace std;
int main() {
int i = 4;
double d = 4.0;
string s = "HackerRank ";
// Declare second integer, double, and String variables.
int n;
double d2;
string str;
// Read and save an integer, double, and String to your variables.
cin >> n;
cin >> d2;
cin.ignore();
getline(cin, str);
// Print the sum of both integer variables on a new line.
cout << i + n << endl;
// Print the sum of the double variables on a new line.
cout << d + d2 << endl;
// Concatenate and print the String variables on a new line
cout << s << str << endl;
// The 's' variable above should be printed first.
return 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 18:49:15
Właśnie użyłem
getline(cin >> ws,lard.i_npute);
Ze standardem
#include <iostream>
Nagłówek w przypadkach, w których miałem problemy ze zwrotami karetki i manipulator ws działał. Prawdopodobnie zacznę osadzać funkcje pętli jako klasy i używać constructor i destructor conajmniej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 17:25:31
Koncepcyjnie, myślę, że chcesz, aby każda odpowiedź była starannie jedna linijka. Więc dlaczego nie spróbujesz tego?
cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);
cout << "Enter names: ";
string names;
getline(cin, names);
Kod poprawnie pobiera pierwszy znak nowej linii, podaje liczbę, jeśli linia jest poprawna, lub rzuca wyjątek, jeśli nie. Wszystko za darmo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-09 12:56:45
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
// USE peek() TO SOLVE IT! ;)
if (cin.peek() == '\n') {
cin.ignore(1 /*numeric_limits<streamsize>::max()*/, '\n');
}
getline(cin, names);
return 0;
}
Wystarczy zajrzeć do przodu używając cin.peek()
i sprawdzić, czy '\n'
jest nadal w wewnętrznym buforze cin
. Jeśli tak, to ignoruj (w zasadzie pomiń)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 09:55:03