sscanf或atoi将string转换为整数有什么区别?

gcc 4.4.4 c89

将string转换为整数值更好。

我已经尝试了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没有做任何检查。

你有3个select:

  1. atoi

如果您在性能关键的代码中使用它,这可能是最快的,但它不会报告错误。 如果string不是以整数开始,则返回0.如果string在整数后面包含垃圾,它将转换初始部分,忽略其余部分。 如果这个数字太大而不能适应int ,那么这个行为是不确定的。

  1. sscanf

有一些错误报告,而且对于什么types的存储( char/short/int/long/long long/size_t/ptrdiff_t/intmax_t符号/无符号版本)有很大的灵活性。

返回值是成功的转换次数,所以如果string不是以整数开头的话,扫描"%d"将返回0。 您可以使用"%d%n"来存储在另一个variables中读取的整数之后的第一个字符的索引,从而检查整个string是否被转换或者之后是否有垃圾。 但是,像atoi一样,整数溢出的行为是未指定的。

  1. strtol和家庭

强大的错误报告,只要您在打电话之前将errno为0。 返回值在溢出时指定, errno将被设置。 您可以select从2到36的任意数字基数,或者指定0作为基数,以自动解释前导0x0分别为hex和八进制。 要转换的types的选项是long/long long/intmax_t有符号/无符号版本。

如果你需要一个较小的types,你总是可以把结果存储在一个临时的long或者unsigned longvariables中,然后检查溢出。

由于这些函数需要一个指向指针参数的指针,因此您还可以获得一个指向转换后的整数后的第一个字符的指针,因此您可以判断整个string是整数还是需要parsingstring中的后续数据。


就个人而言,我会为大多数目的推荐strtol家族。 如果你正在做一些快速而又肮脏的事情,atoi可能会满足你的需求。

顺便说一句,有时我觉得我需要parsing数字,领先的空白符号等不应该被接受。 在这种情况下,你可以很容易地打开自己的循环,例如,

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

或者你可以使用(为了鲁棒性):

 if (isdigit(*s)) x=strtol(s, &s, 10); else /* error */ 

*scanf()函数族返回转换值的数量。 所以你应该检查以确保sscanf()在你的情况下返回1。 EOF返回“input失败”,这意味着ssacnf()永远不会返回EOF

对于sscanf() ,函数必须parsing格式string,然后解码整数。 atoi()没有那个开销。 两者都遭遇到超出范围的值导致未定义行为的问题。

您应该使用strtol()strtoul()函数,它们提供更好的错误检测和检查。 他们也让你知道,如果整个string被消耗。

如果你想要一个int ,你总是可以使用strtol() ,然后检查返回值是否在INT_MININT_MAX之间。

对@R ..我认为这是不够的,以检查errnostrtol调用错误检测。

 long strtol (const char *String, char **EndPointer, int Base) 

您还需要检查EndPointer是否有错误。

结合R ..和PickBoy答案为简洁起见

 long strtol (const char *String, char **EndPointer, int Base) // examples strtol(s, NULL, 10); strtol(s, &s, 10); 

当不需要关心无效stringinput或范围问题时,使用最简单的方法: atoi()

否则,具有最佳误差/范围检测的方法既不是atoi()也不是sscanf() 。 这个好的答案都准备好了详细信息,缺less使用atoi()错误检查和使用sscanf() 一些错误检查。

strtol()是将string转换为int的最严格的函数。 但这只是一个开始。 下面是详细的例子,以显示正确的用法,所以这个答案的理由后, 接受 。

 // Over-simplified use int strtoi(const char *nptr) { int i = (int) strtol(nptr, (char **)NULL, 10); return i; } 

这就像atoi() ,忽略了使用strtol()的错误检测function。

要充分使用strtol() ,需要考虑各种function:

  1. 检测不转换 :例如: "xyz""""--0" ? 在这些情况下, endptr将匹配nptr

     char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (nptr == endptr) return FAIL_NO_CONVERT; 
  2. 如果整个string转换或只是领导部分:是"123xyz"好吗?

     char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (*endptr != '\0') return FAIL_EXTRA_JUNK; 
  3. 检测值是否如此之大,其结果不能像"999999999999999999999999999999"那样long

     errno = 0; long L = strtol(nptr, &endptr, 10); if (errno == ERANGE) return FAIL_OVERFLOW; 
  4. 检测值是否超出int的范围,但不会long 。 如果intlong具有相同的范围,则不需要此testing。

     long L = strtol(nptr, &endptr, 10); if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW; 
  5. 有些实现超出了C标准,并且由于其他原因而设置了errno ,例如在没有执行转换的情况下从errno到EINVAL,或者EINVAL Base参数的值无效。 。 testing这些errno值的最佳时间是与实现相关的。

把这一切放在一起:(调整你的需要)

 #include <errno.h> #include <stdlib.h> int strtoi(const char *nptr, int *error_code) { char *endptr; errno = 0; long i = strtol(nptr, &endptr, 10); #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX if (errno == ERANGE || i > INT_MAX || i < INT_MIN) { errno = ERANGE; i = i > 0 : INT_MAX : INT_MIN; *error_code = FAIL_INT_OVERFLOW; } #else if (errno == ERANGE) { *error_code = FAIL_OVERFLOW; } #endif else if (endptr == nptr) { *error_code = FAIL_NO_CONVERT; } else if (*endptr != '\0') { *error_code = FAIL_EXTRA_JUNK; } else if (errno) { *error_code = FAIL_IMPLEMENTATION_REASON; } return (int) i; } 

注意:提到的所有function都允许前导空格,一个可选的前导符号字符,并受到语言环境变化的影响。 更多限制的转换需要额外的代码。


注:非OP标题变更偏重。 这个答案更适用于原始标题“convert string to integer sscanf or atoi”

如果用户input34abc,并将它们传递给atoi,它将返回34.如果要validationinput的值,则必须迭代地在input的string上使用isdigit