Определите, является ли строка целым числом или числом с плавающей запятой в ANSI C.

StackOverflow https://stackoverflow.com/questions/78474

  •  09-06-2019
  •  | 
  •  

Вопрос

Используя только ANSI C, каков наилучший способ с достаточной уверенностью определить, является ли строка стиля C целым или действительным числом (т. е. float/double)?

Это было полезно?

Решение

Не используйте atoi и atof, поскольку эти функции возвращают 0 в случае ошибки.В прошлый раз, когда я проверял, 0 является допустимым целым числом и числом с плавающей запятой, поэтому для определения типа оно не используется.

используйте функции strto{l,ul,ull,ll,d}, поскольку они устанавливают errno в случае сбоя, а также сообщают, где закончились преобразованные данные.

стртул: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

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

#include <errno.h>

char* to_convert = "some string";
char* p = to_convert;
errno = 0;
unsigned long val = strtoul(to_convert, &p, 10);
if (errno != 0)
    // conversion failed (EINVAL, ERANGE)
if (to_convert == p)
    // conversion failed (no characters consumed)
if (*p != 0)
    // conversion failed (trailing data)

Спасибо Джонатану Леффлеру за указание на то, что я забыл сначала установить для errno значение 0.

Другие советы

С использованием sscanf, вы можете быть уверены, что строка является числом с плавающей запятой, целым числом или чем-то еще, без необходимости использования специального случая 0, как в случае с решениями atoi и atof.

Вот пример кода:

int i;
float f;
if(sscanf(str, "%d", &i) != 0) //It's an int.
  ...
if(sscanf(str "%f", &f) != 0)  //It's a float.
  ...

atoi и atof преобразуют или возвращают 0, если это невозможно.

Я согласен с Патриком_О, что функции strto{l,ul,ull,ll,d} — лучший способ.Однако есть несколько моментов, на которые стоит обратить внимание.

  1. Установите errno в ноль перед вызовом функций;ни одна функция не сделает этого за вас.
  2. На странице открытой группы, на которую есть ссылка (на которую я зашел, прежде чем заметить, что Патрик тоже ссылался на нее), указано, что errno не может быть установлен.Ему присваивается значение ERANGE, если значение выходит за пределы диапазона;это может быть установлен (но в равной степени, может нет быть установлен) в EINVAL, если аргумент недействителен.

В зависимости от текущей задачи я иногда планирую пропускать конечные пробелы в конце возвращаемого указателя преобразования, а затем жаловаться (отклонять), если последний символ не является завершающим нулевым '\0'.Или я могу быть небрежным и позволить мусору появиться в конце, или я могу принять необязательные множители, такие как «K», «M», «G», «T» для килобайтов, мегабайтов, гигабайтов, терабайтов и т. д.или любое другое требование, основанное на контексте.

Я полагаю, вы могли бы просмотреть строку и проверить, есть ли какие-либо . персонажи в нем.Однако это только первое, что пришло мне в голову, поэтому я уверен, что есть другие (лучшие) способы быть более уверенным.

Используйте strtol/strtoll (не atoi) для проверки целых чисел.Используйте strtof/strtod (не atof) для проверки двойных значений.

atoi и atof преобразуют начальную часть строки, но не сообщают, использовали ли они всю строку.strtol/strtod сообщит вам, остался ли лишний мусор после преобразования символов.

Поэтому в обоих случаях не забудьте передать ненулевой параметр TAIL и убедиться, что он указывает на конец строки (то есть **TAIL == 0).Также проверьте возвращаемое значение на предмет отсутствия и переполнения (подробности см. на страницах руководства или в стандарте ANSI).

Также обратите внимание, что strod/strtol пропускает начальные пробелы, поэтому, если вы хотите рассматривать строки с начальными пробелами как плохо отформатированные, вам также необходимо проверить первый символ.

Это действительно зависит от того, почему вы спрашиваете в первую очередь.

Если вы просто хотите проанализировать число и не знаете, является ли оно числом с плавающей запятой или целым числом, просто проанализируйте число с плавающей запятой, оно также правильно проанализирует целое число.

Если вы действительно хотите узнать тип, возможно, для сортировки, вам действительно следует рассмотреть возможность тестирования типов в том порядке, который вы считаете наиболее подходящим.Например, попробуйте проанализировать целое число, а если не сможете, попробуйте проанализировать число с плавающей запятой.(Наоборот, будет просто создано немного больше поплавков...)

atoi и atof преобразуют число, даже если в конце есть нечисловые символы.Однако если вы используете strtol и strtod, он не только пропустит ведущие пробелы и необязательный знак, но и оставит указатель на первый символ, отсутствующий в числе.Затем вы можете проверить, что остальное — пробелы.

Что ж, если вам не хочется использовать новую функцию, такую ​​​​как strtoul, вы можете просто добавить еще один оператор strcmp, чтобы проверить, равна ли строка 0.

то есть

if(atof(token) != NULL || strcmp(token, "0") == 0)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top