将字符串转换为整数的sscanf或atoi有什么区别?

ant*_*009 64 c scanf atoi

gcc 4.4.4 c89

将字符串转换为整数值更好.

我尝试了两种不同的方法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;
}
Run Code Online (Sandbox Code Playgroud)

或使用atoi

device_num = atoi(digits);
Run Code Online (Sandbox Code Playgroud)

我认为sscanf会更好,因为你可以检查错误.但是,atoi没有做任何检查.

R..*_*R.. 109

你有3个选择:

  1. atoi

如果您在性能关键代码中使用它,这可能是最快的,但它没有错误报告.如果字符串不是以整数开头,则返回0.如果字符串在整数后面包含垃圾,它将转换初始部分并忽略其余部分.如果数字太大而无法容纳int,则行为未指定.

  1. sscanf

一些错误报告,您可以灵活地存储哪种类型(签名/未签名版本char/short/int/long/long long/size_t/ptrdiff_t/intmax_t).

返回值是成功的转换次数,因此"%d"如果字符串不以整数开头,则scan将返回0.您可以使用"%d%n"存储在另一个变量中读取的整数之后的第一个字符的索引,从而检查整个字符串是否已转换或之后是否有垃圾.但是,类似atoi,未指定整数溢出的行为.

  1. strtol 和家人

强大的错误报告,前提是您errno在拨打电话前设置为0.返回值在溢出时指定errno并将被设置.您可以选择任意数量的基地从2到36,或指定0为基数,以自动解释领先0x,并0分别十六进制和八进制.要转换为的类型的选择是签名/未签名版本long/long long/intmax_t.

如果您需要较小的类型,您始终可以将结果存储在临时longunsigned long变量中,并自行检查溢出.

由于这些函数采用指向指针参数的指针,因此您还可以获得指向转换后整数后面的第一个字符的指针,这样您就可以判断整个字符串是整数还是解析字符串中的后续数据(如果需要).


就个人而言,我会推荐这个strtol家庭用于大多数目的.如果您正在做一些快速和肮脏的事情,atoi可能会满足您的需求.

顺便说一下,有时我发现我需要解析前导空格,符号等不被接受的数字.在这种情况下,很容易推出自己的循环,例如,

for (x=0; (unsigned)*s-'0'<10; s++) 
    x=10*x+(*s-'0');
Run Code Online (Sandbox Code Playgroud)

或者你可以使用(为了健壮性):

if (isdigit(*s))
    x=strtol(s, &s, 10);
else /* error */ 
Run Code Online (Sandbox Code Playgroud)


Alo*_*hal 10

*scanf()函数族返回转换的值的数量.因此,您应该检查以确保sscanf()在您的情况下返回1. EOF返回"输入失败",这意味着ssacnf()永远不会返回EOF.

因为sscanf(),函数必须解析格式字符串,然后解码整数. atoi()没有那个开销.两者都存在超出范围值导致未定义行为的问题.

您应该使用strtol()strtoul()功能,它们提供更好的错误检测和检查.它们还会让您知道整个字符串是否已被消耗.

如果你想要一个int,你可以随时使用strtol(),然后检查返回的值,看它是否在INT_MIN和之间INT_MAX.