C语言 sscanf 或 atoi 将字符串转换为整数有什么区别?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3420629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the difference between sscanf or atoi to convert a string to an integer?
提问by ant2009
gcc 4.4.4 c89
海湾合作委员会 4.4.4 c89
What is better to convert a string to an integer value.
最好将字符串转换为整数值。
I have tried 2 different methods atoi and sscanf. Both work as expected.
我尝试了 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;
}
or using atoi
或使用 atoi
device_num = atoi(digits);
I was thinking that the sscanf would be better as you can check for errors. However, atoi doesn't doing any checking.
我在想 sscanf 会更好,因为您可以检查错误。但是,atoi 不做任何检查。
回答by R.. GitHub STOP HELPING ICE
You have 3 choices:
你有3个选择:
atoi
atoi
This is probably the fastest if you're using it in performance-critical code, but it does no error reporting. If the string does not begin with an integer, it will return 0. If the string contains junk after the integer, it will convert the initial part and ignore the rest. If the number is too big to fit in int, the behaviour is unspecified.
如果您在性能关键代码中使用它,这可能是最快的,但它不会报告错误。如果字符串不是以整数开头,则返回0。如果字符串在整数后包含垃圾,则将转换初始部分并忽略其余部分。如果数字太大而无法放入int,则行为未指定。
sscanf
sscanf
Some error reporting, and you have a lot of flexibility for what type to store (signed/unsigned versions of char/short/int/long/long long/size_t/ptrdiff_t/intmax_t).
一些错误报告,并且您可以灵活地存储什么类型( 的签名/未签名版本char/short/int/long/long long/size_t/ptrdiff_t/intmax_t)。
The return value is the number of conversions that succeed, so scanning for "%d"will return 0 if the string does not begin with an integer. You can use "%d%n"to store the index of the first character after the integer that's read in another variable, and thereby check to see if the entire string was converted or if there's junk afterwards. However, like atoi, behaviour on integer overflow is unspecified.
返回值是成功的转换次数,因此"%d"如果字符串不是以整数开头,则扫描将返回 0。您可以使用"%d%n"存储在另一个变量中读取的整数之后的第一个字符的索引,从而检查整个字符串是否已转换或之后是否有垃圾。然而,像atoi,整数溢出的行为是未指定的。
strtoland family
strtol和家人
Robust error reporting, provided you set errnoto 0 before making the call. Return values are specified on overflow and errnowill be set. You can choose any number base from 2 to 36, or specify 0 as the base to auto-interpret leading 0xand 0as hex and octal, respectively. Choices of type to convert to are signed/unsigned versions of long/long long/intmax_t.
强大的错误报告,前提是您errno在拨打电话之前设置为 0。返回值在溢出时指定errno并将被设置。您可以选择 2 到 36 之间的任何数字基数,或指定 0 作为基数以分别自动解释前导0x以及0十六进制和八进制。要转换为的类型选择是long/long long/intmax_t.
If you need a smaller type you can always store the result in a temporary longor unsigned longvariable and check for overflow yourself.
如果您需要较小的类型,您可以随时将结果存储在临时long或unsigned long变量中并自己检查溢出。
Since these functions take a pointer to pointer argument, you also get a pointer to the first character following the converted integer, for free, so you can tell if the entire string was an integer or parse subsequent data in the string if needed.
由于这些函数采用指向指针参数的指针,您还可以免费获得指向转换后的整数后第一个字符的指针,因此您可以判断整个字符串是否为整数或在需要时解析字符串中的后续数据。
Personally, I would recommend the strtolfamily for mostpurposes. If you're doing something quick-and-dirty, atoi might meet your needs.
就个人而言,我会推荐strtol家庭用于大多数目的。如果您正在做一些快速而肮脏的事情,atoi 可能会满足您的需求。
As an aside, sometimes I find I need to parse numbers where leading whitespace, sign, etc. are not supposed to be accepted. In this case it's pretty damn easy to roll your own for loop, eg.,
顺便说一句,有时我发现我需要解析不应该接受前导空格、符号等的数字。在这种情况下,滚动自己的 for 循环非常容易,例如,
for (x=0; (unsigned)*s-'0'<10; s++)
x=10*x+(*s-'0');
Or you can use (for robustness):
或者您可以使用(为了健壮性):
if (isdigit(*s))
x=strtol(s, &s, 10);
else /* error */
回答by Alok Singhal
*scanf()family of functions return the number of values converted. So you should check to make sure sscanf()returns 1 in your case. EOFis returned for "input failure", which means that ssacnf()will never return EOF.
*scanf()函数族返回转换的值的数量。因此,您应该检查以确保sscanf()在您的情况下返回 1。 EOF为“输入失败”返回,这意味着ssacnf()永远不会返回EOF。
For sscanf(), the function has to parse the format string, and then decode an integer. atoi()doesn't have that overhead. Both suffer from the problem that out-of-range values result in undefined behavior.
对于sscanf(),该函数必须解析格式字符串,然后解码一个整数。 atoi()没有那个开销。两者都存在超出范围值导致未定义行为的问题。
You should use strtol()or strtoul()functions, which provide much better error-detection and checking. They also let you know if the whole string was consumed.
您应该使用strtol()orstrtoul()函数,它提供更好的错误检测和检查。他们还会让您知道整个字符串是否已被消耗。
If you want an int, you can always use strtol(), and then check the returned value to see if it lies between INT_MINand INT_MAX.
如果你想要int,你总是可以使用strtol(),然后检查返回的值,看它是否在INT_MIN和之间INT_MAX。
回答by PickBoy
To @R.. I think it's not enough to check errnofor error detection in strtolcall.
对于@R .. 我认为检查调用中的errno错误检测是不够的strtol。
long strtol (const char *String, char **EndPointer, int Base)
You'll also need to check EndPointerfor errors.
您还需要检查EndPointer错误。
回答by Steven Penny
Combining R.. and PickBoy answers for brevity
为简洁起见,结合 R.. 和 PickBoy 答案
long strtol (const char *String, char **EndPointer, int Base)
// examples
strtol(s, NULL, 10);
strtol(s, &s, 10);
回答by chux - Reinstate Monica
When there is no concern about invalid string input or range issues, use the simplest: atoi()
当不担心无效字符串输入或范围问题时,使用最简单的: atoi()
Otherwise, the method with best error/range detection is neither atoi(), nor sscanf().
This good answerall ready details the lack of error checking with atoi()and someerror checking with sscanf().
否则,具有最佳错误/范围检测的方法既不是 也不atoi()是sscanf()。
这个很好的答案已经准备好了,详细说明了缺少错误检查atoi()和一些错误检查sscanf()。
strtol()is the most stringent function in converting a string to int. Yet it is only a start. Below are detailed examples to show proper usage and so the reason for this answer after the accepted one.
strtol()是将字符串转换为int. 然而这只是一个开始。以下是显示正确用法的详细示例,以及在接受此答案后的原因。
// Over-simplified use
int strtoi(const char *nptr) {
int i = (int) strtol(nptr, (char **)NULL, 10);
return i;
}
This is the like atoi()and neglects to use the error detection features of strtol().
这是类似的atoi()并且忽略了使用 的错误检测功能strtol()。
To fully use strtol(), there are various features to consider:
要充分利用strtol(),需要考虑各种功能:
Detection of no conversion: Examples:
"xyz", or""or"--0"? In these cases,endptrwill matchnptr.char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (nptr == endptr) return FAIL_NO_CONVERT;Should the whole string convert or just the leading portion: Is
"123xyz"OK?char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (*endptr != '
') return FAIL_EXTRA_JUNK;errno = 0; long L = strtol(nptr, &endptr, 10); if (errno == ERANGE) return FAIL_OVERFLOW;Detect if value was so big, the the result is not representable as a
longlike"999999999999999999999999999999".long L = strtol(nptr, &endptr, 10); if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW;Detect if the value was outside the range of than
int, but notlong. Ifintandlonghave the same range, this test is not needed.char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (nptr == endptr) return FAIL_NO_CONVERT;Some implementations go beyond the C standard and set
errnofor additional reasons such as errno to EINVAL in case no conversion was performedorEINVALThe value of the Base parameter is not valid.. The best time to test for theseerrnovalues is implementation dependent.
检测没有转换: 示例:
"xyz", or""or"--0"? 在这些情况下,endptr将匹配nptr.char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (*endptr != '
') return FAIL_EXTRA_JUNK;errno = 0; long L = strtol(nptr, &endptr, 10); if (errno == ERANGE) return FAIL_OVERFLOW;应该转换整个字符串还是只转换前导部分:
"123xyz"可以吗?long L = strtol(nptr, &endptr, 10); if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW;检测值是否太大,结果无法表示为
longlike"999999999999999999999999999999"。#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 != '##代码##') { *error_code = FAIL_EXTRA_JUNK; } else if (errno) { *error_code = FAIL_IMPLEMENTATION_REASON; } return (int) i; }检测值是否在 than 的范围之外
##代码##int,但不是long。如果int和long具有相同的范围,则不需要此测试。某些实现超出了 C 标准并
errno出于其他原因进行设置,例如errno 到 EINVAL,以防未执行转换或EINVALBase 参数的值无效。. 测试这些errno值的最佳时间取决于实现。
Putting this all together: (Adjust to your needs)
把这一切放在一起:(根据你的需要调整)
##代码##Note: All functions mentioned allow leading spaces, an optional leading signcharacter and are affected by localechange. Additional code is required for a more restrictive conversion.
注意:提到的所有函数都允许使用前导空格,一个可选的前导符号字符,并且受区域设置更改的影响。更严格的转换需要额外的代码。
Note: Non-OP title change skewed emphasis. This answer applies better to original title "convert string to integer sscanf or atoi"
注意:非 OP 标题更改偏斜了重点。此答案更适用于原始标题“将字符串转换为整数 sscanf 或 atoi”
回答by Raghuram
If user enters 34abc and you pass them to atoi it will return 34. If you want to validate the value entered then you have to use isdigit on the entered string iteratively
如果用户输入 34abc 并将它们传递给 atoi,它将返回 34。如果要验证输入的值,则必须在输入的字符串上迭代使用 isdigit

![C语言 我的代码有什么问题?什么是 argv[1]?](/res/img/loading.gif)