В чем разница между sscanf или atoi для преобразования строки в целое число?

gcc 4.4.4 c89

Что лучше преобразовать строку в целочисленное значение.

Я пробовал 2 разных метода atoi и sscanf. Оба работают как положено.

char digits[3] = "34";
int device_num = 0;

if(sscanf(digits, "%d", &device_num) == EOF) {
    fprintf(stderr, "WARNING: Incorrect value for device\n");
    return FALSE;
}

или используя atoi

device_num = atoi(digits);

Я думал, что sscanf будет лучше, так как вы можете проверять ошибки. Однако atoi не выполняет никакой проверки.

64
задан Ciro Santilli 新疆改造中心法轮功六四事件 11 May 2016 в 18:08
поделиться

3 ответа

У вас есть 3 варианта:

  1. atoi

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

  1. sscanf

Некоторые отчеты об ошибках, и у вас есть большая гибкость в отношении того, какой тип хранить (подписанные / неподписанные версии char / short / int / long / long long / size_t / ptrdiff_t / intmax_t ]).

Возвращаемое значение - это количество успешных преобразований, поэтому сканирование «% d» вернет 0, если строка не начинается с целого числа. Вы можете использовать «% d% n» , чтобы сохранить индекс первого символа после целого числа, считанного в другой переменной, и тем самым проверить, была ли преобразована вся строка или нет ли впоследствии мусора. Однако, как и atoi , поведение при целочисленном переполнении не определено.

  1. strtol и семейство

Надежный отчет об ошибках при условии, что вы установили для errno значение 0 перед вызовом. Возвращаемые значения указываются при переполнении и устанавливается номер ошибки .Вы можете выбрать любое основание числа от 2 до 36 или указать 0 в качестве основания для автоматической интерпретации ведущих 0x и 0 как шестнадцатеричных и восьмеричных соответственно. Варианты преобразования типа - это подписанные / беззнаковые версии long / long long / intmax_t .

Если вам нужен меньший тип, вы всегда можете сохранить результат во временной переменной long или unsigned long и самостоятельно проверить переполнение.

Поскольку эти функции принимают указатель на аргумент указателя, вы также бесплатно получаете указатель на первый символ, следующий за преобразованным целым числом, так что вы можете определить, была ли вся строка целым числом, или при необходимости проанализировать последующие данные в строке. .


Лично я бы рекомендовал семейство strtol для большинства целей. Если вы делаете что-то поспешное и грязное, атой может удовлетворить ваши потребности.

Кстати, иногда мне нужно анализировать числа, в которых не допускается использование начальных пробелов, знаков и т. Д. В этом случае чертовски легко развернуть свой собственный цикл for, например,

for (x=0; (unsigned)*s-'0'<10; s++) 
    x=10*x+(*s-'0');

Или вы можете использовать (для надежности):

if (isdigit(*s))
    x=strtol(s, &s, 10);
else /* error */ 
109
ответ дан 24 November 2019 в 15:49
поделиться

Если пользователь введет 34abc, а вы передадите их atoi, он вернет 34. Если вы хотите проверить введенное значение, вы должны многократно использовать isdigit во введенной строке

0
ответ дан 24 November 2019 в 15:49
поделиться

*scanf() семейство функций возвращает количество преобразованных значений. Поэтому вам следует убедиться, что sscanf() возвращает 1 в вашем случае. EOF возвращается при "сбое ввода", что означает, что ssacnf() никогда не вернет EOF.

Для sscanf() функция должна разобрать строку формата, а затем декодировать целое число. atoi() не имеет таких накладных расходов. Обе функции страдают от того, что значения, выходящие за пределы диапазона, приводят к неопределенному поведению.

Вам следует использовать функции strtol() или strtoul(), которые обеспечивают гораздо лучшее обнаружение и проверку ошибок. Они также позволяют узнать, была ли использована вся строка.

Если вам нужно int, вы всегда можете использовать strtol(), а затем проверить возвращаемое значение, лежит ли оно между INT_MIN и INT_MAX.

10
ответ дан 24 November 2019 в 15:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: