2016-09-22 4 views
0

У меня есть программа, которая просто вычисляет функцию Аккермана: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

Можете ли вы объяснить, что вы должны делать для '' 3z''? Что представляет собой '' z''? – nathanesau

+0

@nathanesau Программа должна принимать только целые входы. Когда вводится '3z' (или аналогичный), он игнорирует' z' и принимает '3', так как z не существует. В некотором смысле я хочу, чтобы он обнаружил такой недопустимый ввод (например, '3z'). – esote

ответ

0

Я придумал способ, чтобы проверить, если вход что-то вроде 1.2.

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

double x; 

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

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

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

0

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

Checking input value is an integer

Он показывает, как проверить, если только что считанное значение из CIN в междунар был действительным внутр.

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; 
}