У меня есть проблема с программой, я продолжаю работать в C++. Я прошу, чтобы пользователь ввел верный номер. Я принимаю его как строку, потому что особое присвоение, которое я делаю, это помогает в конечном счете. Для основной проверки ошибок я хочу проверить, чтобы видеть, является ли введенный номер верным номером. Пример:
Enter number: 3.14
This would be valid
Enter number: 3.1456.365.12
This shouldn't be valid
Я думаю, что Boost :: Lexical_Cast должен помочь вам здесь
Используйте Strtod, который преобразует строку в двойную и возвращает любые символы, которые он не мог интерпретировать как часть двойного.
double strtod(const char* nptr, char** endptr)
Мне нравится:
char* input = "3.1456.365.12";
char* end;
strtod(input, &end);
if (*input == '\0')
{
printf("fail due to empty string\n");
}
if (end == input || *end != '\0')
{
printf("fail - the following characters are not part of a double\n%s\n", end);
}
Возможно, библиотека ASIHTTPRequest может помочь в этом?
-121--4518536-Если у вас нет повышения, вы всегда можете использовать strtod
-121--3777345- Ах, я любил эти задания. Старая добрая рука, написанная лексером, - это путь, по которому можно идти (так как вы все еще находитесь в первые дни - не пытайтесь использовать boost
только что). Они быстрые, простые в написании и чрезвычайно весело играть. Если вы можете получить копию книги Ливайна о Lex/Yacc, найдите первые пару глав для идей.
Простая опция - использование функции sscanf:
const char * num_as_str = "3.1416";
double num;
if(std::sscanf(num_as_str, "%lg", &num) == 1)
{
std::cout << "You correctly entered the number " << num << "\n";
}
Если вы хотите получить фантазию, вы можете использовать istringstream:
std::istringstream iss(num_as_str);
if(iss >> num)
{
std::cout << "You correctly entered the number " << num << "\n";
}
Если вы хотите получить экстра-фантазию, вы можете использовать lexical_cast:
try
{
num = boost::lexical_cast<double>(num_as_str);
}
catch(boost::bad_lexical_cast &)
{
std::cout << "What you entered is not a proper number" << num << "\n";
}
Это мой быстрый взлом :)
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template <typename T>
bool fromStr(const std::string& str, T& var)
{
std::stringstream convertor;
convertor << str;
convertor >> var;
if( convertor.fail() )
return false;
char c = static_cast<char>( convertor.get() );
return convertor.eof() || c == '\n' || c == ' ' || c == '\t';
}
int main()
{
double d;
std::string str = "5.04146.55";
if( fromStr<double>(str, d) )
{
std::cout << "Valid conversion!, d = " << d;
}
else
{
std::cout << "Invalid conversion!";
}
}
Лучший способ - сделать фактическую попытку преобразовать вашу строку в Двойной
, используя любой из стандартных и / или идиоматических способов выполнения преобразования и проверки ошибок потом Отказ В C, который будет функционируют из STRTO ...
Группа (которые, конечно, отлично используются в C ++). В C ++ вы можете использовать преобразование на основе потока идиома.
Одним из них наблюдается, что общая конвенция в стандартных методах преобразования является преобразование «как можно больше», и не учитывает никаких дополнительных символов в качестве ошибки. Например, строка «123ABC» обычно считается действительным входом, причем только «123» часть преобразована. Все удобные методы предоставляют вам способ обнаружить тот факт, что после фактического номера есть что-то дополнительное, если вы хотите лечить эту ситуацию как ошибку. Но это зависит от вас, чтобы принять дополнительные шаги для выполнения этой проверки.
Если у вас нет повышения, вы всегда можете использовать Strtod
Пример использования только стандартной C++:
#include <sstream>
// ...
double dbl = 0.0;
std::istringstream num("3.1456.365.12");
num >> dbl;
if(!num.fail() &&
num.eof()) // This second test is important! This makes sure that the entire string was converted to a number
{
// success
}
else
{
// failure
}
Версия бонусной общей шаблонной функции:
#include <sstream>
#include <string>
#include <exception>
// Version that throws an exception on a bad parse:
template <typename T>
T parse(const std::string& str)
{
T value;
std::istringstream parser(str);
parser >> value;
if(!parser.fail() && parser.eof())
{
return value;
}
else
{
throw "bad lexical cast";
}
}
// usage:
double foo = parse<double>("3.14234");
// Non-exception, error code version
template <typename T>
bool parse(const std::string& str, T& value)
{
std::istringstream parser(str);
parser >> value;
return (!parser.fail() && parser.eof());
}
// usage:
double foo = 0.0;
bool success = parser<double>("3.11234", foo);
Как упоминал Андрей Т, лучший способ - это попытаться преобразовать строку в плавающий диск и проверить на ошибку. Лично я бы предпочел использовать std::istringstream, так как вы используете C++. Должно сработать что-то вроде следующего:
float ff;
std::istringstream istr;
std::string input("1234.5678");
// set the stream to have your string as its base
istr.str(input);
// now try to read the number:
istr >> ff;
if (istr.fail())
{
// some error in the parsing
}
istringstream является частью STL, так что дополнительные библиотеки вам не понадобятся, и будет с исключениями, если вы так решите. Дополнительную информацию можно найти здесь: http://www.cplusplus.com/reference/iostream/istringstream/
Можно использовать регулярные выражения. Так как у Вас уже есть строка, легко сравнить это с этим regex:
/^\d+(\.\d+)?$/
Библиотека regex.h может Вам помочь. Посмотрите на это: regex.h
Вы можете использовать STRTOX
(где x - f
f l
l ul
Для долгосрочных и т. Д.), Выбирая для того, что вы хотите. Один из параметров, которые вы даете, - это «конечный указатель», который указывает на первый символ в строке, которая может не , быть преобразован в тип целевого номера.
В вашем случае то, что вы, по-видимому, в том, что конечный указатель должен быть в конце строки, указывающую, что все символы в строке были преобразованы в тип целевого значения.
Править: Извините, не заметил, что вы упомянули «двойной» в названии (но не сам вопрос). Что касается случая, вы бы использовали Strtod
, как также посоветовали пару других.