Ответ 1
Посмотрите на strtol(), он может рассказать вам о недопустимых частях строки по возврату указателя.
И будьте осторожны с восторженным примером кода.. см. страницу руководства для всесторонней обработки ошибок.
Мне нужно проверить, является ли строка C допустимым целым числом.
Я попробовал оба
int num=atoi(str);
и
int res=sscanf(str, "%d", &num);
Но посылка строки "8 -9 10"
в обе строки, возвращаемые просто 8, без указания недействительности этой строки.
Может ли кто-нибудь предложить альтернативу?
Посмотрите на strtol(), он может рассказать вам о недопустимых частях строки по возврату указателя.
И будьте осторожны с восторженным примером кода.. см. страницу руководства для всесторонней обработки ошибок.
Может быть, я получу пламя за то, что не использовал strtol
или подобные функции libc
, но рассуждать об этой проблеме не так сложно:
#include <stdbool.h> // if using C99... for C++ leave this out.
#include <ctype.h>
bool is_valid_int(const char *str)
{
// Handle negative numbers.
//
if (*str == '-')
++str;
// Handle empty string or just "-".
//
if (!*str)
return false;
// Check for non-digit chars in the rest of the stirng.
//
while (*str)
{
if (!isdigit(*str))
return false;
else
++str;
}
return true;
}
[NB: я мог бы сделать иначе isdigit(*str++)
вместо else
, чтобы сохранить его короче, но мое воспоминание о том, что стандарты говорят, что isdigit
является макросом.]
Я предполагаю, что одно ограничение состоит в том, что это не возвращает false, если число в строке не будет вписываться в целое число. Это может или не важно для вас.
Простым способом сделать это можно было бы прочитать int и убедиться, что строковое представление идентично входной строке, например, объединение atoi
и itoa
:
int is_int(char const* p)
{
return strcmp(itoa(atoi(p)), p) == 0;
}
Чтобы проверить, содержит ли строка допустимое число, вы можете использовать регулярное выражение. Например, для целых чисел используйте:
? [- +] [0-9] +
и общий регистр чисел с плавающей запятой:
[+ -] [0-9] + [0-9] * ([еЕ]? [- +], [0-9] +)? [.]?
В случае С++ 11 функции регулярного выражения доступны в библиотеке, например. "std:: regex_match (.....)" дает точное совпадение. Код должен выглядеть так:
#include <regex>
.....
std::string strnumber("-1.234e+01");
float number;
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?"))
number=std::stof(strnumber);
else
std::cout<<"error, string is not a valid number";
Извините за то, что вырыли тему, но ради полноты и потому, что этот поток является первым совпадением при выполнении поиска в google...
Можно использовать что-то вроде:
ret = sscanf(string, "%d%n", &number, &idx);
if (ret == 0 || string[idx] != '\0')
/* handle the error */
Директива %n
, которая, как представляется, является стандартным C в соответствии с man-страницей, подсчитывает количество обработанных символов.
[Изменить] sscanf, похоже, не дает возможности обнаруживать переполнения, поэтому семейство функций strtoX должно быть предпочтительным IMHO.