Cin принимает неверный ввод

У меня есть программа, которая просто вычисляет функцию Аккермана:

#include <iostream>

// Ackermann function calculations
unsigned int ackermann(unsigned int m, unsigned int n){
if(m == 0)
return n+1;
if(n == 0)
return ackermann(m-1,1);
return ackermann(m-1,ackermann(m,n-1));
}

// Check for non-integer input
bool inputCheck(){
if(!std::cin.fail())
return false;

std::cout << "Invalid input!" << std::endl;
return true;
}

// Check for negative or overflow errors
bool numCheck(int i, char name){
if(i < 0){
std::cout << "Negative error!" << std::endl;
return true;
}

if(name == 'm' && i > 3){
std::cout << "Overflow error (m > 3)!" << std::endl;
return true;
}

if(name == 'n' && i > 12){
std::cout << "Overflow error (n > 12)!" << std::endl;
return true;
}

return false;
}

// Run input and num checks
bool check(int x, char y){
bool result = inputCheck() || numCheck(x, y);

std::cin.clear();
std::cin.ignore();

return result;
}

int main(){

int m, n;
bool valM, valN;

do{
std::cout << "m = ";
std::cin >> m;
valM = check(m, 'm');
} while(valM);

do{
std::cout << "n = ";
std::cin >> n;
valN = check(n, 'n');
} while(valN);

std::cout << "\nM = " << m << "\nN = " << n
<< "\n\nCALCULATING..." << std::endl;

std::cout << "A(" << m << ',' << n << ") = " << ackermann(m,n) << std::endl;

return 0;
}

Большая часть кода проверяет правильность ввода. По вычислительным причинам, m не может быть больше 3, и n не может быть больше 12. Он также проверяет, является ли вход отрицательным.

Известные проблемы:

  • Если пользователь вводит что-то вроде 3z, cin просто берет 3 и игнорирует z. Очевидно, что 3z отличается от 3и я хотел бы обнаружить такой неверный ввод.

  • Если пользователь вводит что-то вроде 1.2, cin принимает 1 для m, а затем 2 для n. Программа игнорирует период и принимает его как два входа, и я хотел бы обнаружить такой неверный ввод.

Как я могу изменить или исправить свой код, чтобы он только правильно вводил?

0

Решение

Этот пост может иметь отношение к тому, что вы спрашиваете:

Проверка входного значения является целым числом

Он показывает, как проверить, является ли только что прочитанное значение из cin в int действительным int.

0

Другие решения

Я бы порекомендовал прочитать строку и преобразовать строку в int. Нечто подобное будет работать.

#include <iostream>
#include <cctype>
#include <string>

// true is s is an int, false otherwise

bool is_number(const std::string& s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}

// Ackermann function calculations
unsigned int ackermann(unsigned int m, unsigned int n) {
if (m == 0)
return n + 1;
if (n == 0)
return ackermann(m - 1, 1);
return ackermann(m - 1, ackermann(m, n - 1));
}

// Check for non-integer input
bool inputCheck() {
if (!std::cin.fail())
return false;

std::cout << "Invalid input!" << std::endl;
return true;
}

// Check for negative or overflow errors
bool numCheck(int i, char name) {
if (i < 0) {
std::cout << "Negative error!" << std::endl;
return true;
}

if (name == 'm' && i > 3) {
std::cout << "Overflow error (m > 3)!" << std::endl;
return true;
}

if (name == 'n' && i > 12) {
std::cout << "Overflow error (n > 12)!" << std::endl;
return true;
}

return false;
}

// Run input and num checks
bool check(int x, char y) {
bool result = inputCheck() || numCheck(x, y);

std::cin.clear();
std::cin.ignore();

return result;
}

int main() {

std::string mstr, nstr; // parse int from string
int m, n;
bool valM, valN;

std::cout << "m = ";
std::getline(std::cin, mstr);

if (is_number(mstr))
{
m = atoi(mstr.c_str()); // now we have m as an int
}

valM = check(m, 'm');

std::cout << "n = ";
std::getline(std::cin, nstr);

if (is_number(nstr))
{
n = atoi(nstr.c_str()); // now we have n as an int
}

valN = check(n, 'n');

std::cout << "\nM = " << m << "\nN = " << n
<< "\n\nCALCULATING..." << std::endl;

std::cout << "A(" << m << ',' << n << ") = " << ackermann(m, n) << std::endl;

return 0;
}
0

Я нашел способ проверить, что-то вроде ввода 1.2,

Вместо инициализации m а также n как целые числа, я могу инициализировать их как двойные числа. Затем я могу проверить, совпадает ли округленный дубль с первоначальным двойным:

double x;

if(floor(x) != x){
// not an integer
}

Используя это я могу проверить, если что-то вроде 1.2 является целым числом или нет. Затем я могу преобразовать двойное в целое и продолжить в программе.

тем не мение, Я все еще не могу проверить наличие недопустимых входных данных, таких как 3z,

0
По вопросам рекламы [email protected]