#c
Вопрос:
Вот код
double enter_number()
{
double number;
while(1)
{
cin>>number;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), 'n');
cout << "Invalid input " << endl;
}
else
break;
cout<<"Try again"<<endl;
}
return number;
}
Моя проблема в том, что когда я ввожу что-то вроде 1x, то 1 принимается в качестве входных данных, не замечая символа, который пропущен для другого запуска.
Есть ли способ заставить его работать с любым реальным числом, например 1,8?
Комментарии:
1. Прочитать все в строку и соответственно проанализировать входные данные?
2. Используйте cin.get (), а затем проверьте наличие символа EOF?
Ответ №1:
Когда cin обнаруживает входные данные, которые он не может правильно прочитать в указанной переменной (например, ввод символа в целочисленную переменную), он переходит в состояние ошибки и оставляет входные данные в своем буфере.
Вам нужно сделать несколько вещей, чтобы правильно справиться с этим сценарием.
- Вы должны проверить это состояние ошибки.
- Вы должны очистить состояние ошибки.
- Вы должны либо альтернативно обработать входные данные, которые породили состояние ошибки, либо удалить их и повторно ввести пользователя.
Следующий код предоставляет один из многочисленных методов выполнения этих трех вещей.
#include<iostream>
#include<limits>
using namespace std;
int main()
{
cout << "Enter an int: ";
int x = 0;
while(!(cin >> x)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), 'n');
cout << "Invalid input. Try again: ";
}
cout << "You enterd: " << x << endl;
}
Вы можете просто передать какое-то большое значение в cin.игнорируйте, например, 1000, и оно, скорее всего, будет вести себя точно так же для всех практических целей.
Вы также можете протестировать cin после попытки ввода и обработать его таким образом, что-то вроде if(!cin){//устранить ошибку} .
Проверьте ссылку на istream для других функций-членов для обработки состояния потока: http://cplusplus.com/reference/iostream/istream/
Комментарии:
1. @Джефф Да, это очищает буфер. Вы также можете использовать его при использовании cin с getline при приеме входных данных, поскольку cin оставляет ‘n’ в буфере и не удаляет (я полагаю, не совсем уверен, возможно, это был cin.get), поэтому getline просто разделяется в тот момент, когда он присоединяется к входному буферу, когда он сталкивается с оставшимся ‘n’.
2. Одна вещь, которую не удается остановить, — это когда пользователь вводит что-то подобное
5a
. С помощью этого вы не обнаружите ошибку до следующего раза, когда попытаетесь получить ввод.
Ответ №2:
Я бы использовал std::getline
и std::string
прочитал всю строку, а затем вырвался бы из цикла только тогда, когда вы сможете преобразовать всю строку в двойную.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
Ответ №3:
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
int get_int(void);
int main()
{
puts("Enter a number");
cout<<"The integer is "<<get_int()<<endl;
return 0;
}
int get_int(void)
{
char str[20];
char* end;
int num;
do{
fgets(str,20,stdin);
str[strlen(str)-1]='';
num=strtol(str,amp;end,10);
if(!(*end))
return num;
else
{
puts("Please enter a valid integer");
num=0;
}
}while(num==0);
}
Это прекрасно работает для любого целого числа. Он даже может проверить, вводите ли вы пробел или любой другой символ после целого числа. Единственная проблема в том, что он не используется std::cin
. Но проблема в std::cin
том, что он игнорирует любой пробел после целого числа и с радостью принимает целое число в качестве входных данных.
Комментарии:
1. Этот код действительно плохой. Он смешивает C и C без веской причины, накладывает жестко заданное ограничение на строку, строка, которая добавляет нулевой терминатор, неправильно работает с многобайтовыми новыми строками, и ее нельзя использовать для ввода 0.
2. что касается смешивания C и C , strtol() действительно существует в C .
3. и его можно использовать для ввода 0. Вы, должно быть, не пробовали этого.
4. о str[strlen(str)-1]=»; Мне это было нужно, потому что в противном случае str содержал бы символ новой строки в качестве последнего символа, и код не работал бы. Если вы думаете, что можете сделать лучше, пожалуйста, предложите лучшее решение.