2013-03-07 6 views
0

, поэтому я видел, как многие люди спрашивают об этом и не много твердых ответов, плавающих по сети. наиболее просто проверьте, что вместо строки было помещено целое число, но если был введен номер с плавающей запятой, он обрезает нижнюю половину или целые числа и символы пересекаются, он усекает символы. Мне нужна помощь в написании фрагмента кода, который проверяет ввод пользователя и просит пользователя повторить попытку, если его ввод недействителен или комбинация действительных/недействительных. Я думаю, что основная идея заключалась в том, чтобы создать строку, чтобы она принимала что-либо, а затем использовала sstream для управления, а затем возвращалась к int, если вход был законным, но я не могу действительно проверить другие части. если кто-то прогонит это или может помочь мне, напишите мне. я отправлю свой код, когда у меня будет хорошее представление о том, что делать.Проверка законного целочисленного ввода в C++

+1

Boost терпит неудачу при преобразовании двойные представления к целым числам. – chris

+0

Я избегал использования внешних библиотек, поскольку нам не разрешено устанавливать внешние библиотеки для назначений. Кстати, все еще студент. –

+0

В этом случае вы можете проверить, была ли конвертирована вся строка. Я знаю, что здесь есть хороший пример. – chris

ответ

2

Предполагая, что вы не можете использовать boost::lexical_cast, вы можете написать свою собственную версию:

#include <sstream> 
#include <iostream> 
#include <stdexcept> 
#include <cstdlib> 
template <class T1, class T2> 
T1 lexical_cast(const T2& t2) 
{ 
    std::stringstream s; 
    s << t2; 
    T1 t1; 
    if(s >> std::noskipws >> t1 && s.eof()) { 
    // it worked, return result 
    return t1; 
    } else { 
    // It failed, do something else: 
    // maybe throw an exception: 
    throw std::runtime_error("bad conversion"); 
    // maybe return zero: 
    return T1(); 
    // maybe do something drastic: 
    exit(1); 
    } 
} 



int main() { 
    std::string smin, smax; 
    int imin, imax; 

    while(std::cout << "Enter min and max: " && std::cin >> smin >> smax) { 
    try { 
     imin = lexical_cast<int>(smin); 
     imax = lexical_cast<int>(smax); 
     break; 
    } catch(std::runtime_error&) { 
     std::cout << "Try again: "; 
     continue; 
    } 
    } 

    if(std::cin) { 
    std::cout << "Thanks!\n"; 
    } else { 
    std::cout << "Sorry. Goodbye\n"; 
    exit(1); 
    } 
} 
+0

кажется, что это работает, но мое понимание того, что делает ваше дело. –

+0

, поэтому этот заголовок принимает шаблоны t2 и сохраняет это в строковом потоке с именем s. вы затем объявляете t1 и в хранилище операторов if в noskipws (не уверенный, что это делает, я думал, что это нужно считать пробелом) и, в свою очередь, сохраните это в t1, пока s имеет и заканчивается. –

+0

Нет заголовка. 'lexical_cast' - это шаблон функции, который, как вы сказали, сохраняет свой аргумент' t2' в 'stringstream', а затем извлекает его возвращаемое значение' t1' из того же строкового потока. Все остальное проверяет условия ошибок. –

1

Функция C strtol (и ее братьев и сестер) сможет рассказать вам, полностью ли поглощена строка, поданная на нее.

std::string str; 
char *endptr; 
std::cin >> str; 
long x = std::strtol(str.c_str(), &endptr, 0); 
if (*endptr != 0) 
    cout << "That's not a valid number..."; 
+0

Это говорит о том, что регулярные целые числа также не являются числами, также если введен символ или строка в виде сбоев. –

+0

Добавлен недостающий *, чтобы заставить его работать ... –

2

Вы можете использовать C++ 11 string conversion functions как Stol

try 
{ 
    std::string value = ...; 
    long number = std::stol(value); 
} 
catch (std::invalid_argument const& e) 
{ 
    // no conversion could be performed 
} 

Пост-комментарии обновление: Visual C++ 11, поставляемый с Visual Studio 2012, реализует std::stol в качестве удобной обертки вокруг strtol, объявленной в <cstdlib>. Я думаю, что можно с уверенностью предположить, что большинство реализаций на C++ 11 определяют его наиболее оптимальным образом, не достигая для std::stringstream машин.

+1

Если у вас возникли какие-либо шансы, то вы посмотрели, как это реализовано? У меня еще не было шанса. Надеюсь, это не поток строк, а нечто большее, чем 'strtol'. – 2013-03-14 03:03:09

+0

@ VladLazarenko хороший момент, я обновил свой ответ, основываясь на моих выводах. – mloskot

0

Я не знаю, есть ли какие-либо классы в стандартных C++ Lib, что encapsule примитивных типов, как и в Java, но здесь, как простая и очень простая реализация будет выглядеть как `lexical_cast`

class Integer { 
    private: 
     int value; 
     void parse(string); 
    public: 
     Integer(string); 
     int intValue(); 
}; 

Integer::Integer(string sint) { parse(sint); } 
int Integer::intValue() { return value; } 

void Integer::parse(string sint) { 
    string::iterator its = sint.begin(); 
    while(its != sint.end() && (! (*its < '0' || *its > '9'))) { 
     its++; 
    } 
    if(its != sint.end()) { 
     throw sint + ": Input is not a valid integer."; 
    } 
    value = atoi(sint.c_str()); 
} 
Смежные вопросы