C语言 为什么我在 C 中使用 atoi() 会得到这个意想不到的结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2729460/
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
Why do I get this unexpected result using atoi() in C?
提问by maddy
I don't understand the results of the following C code.
我不明白以下 C 代码的结果。
main()
{
char s[] = "AAA";
advanceString(s);
}
void advanceString(p[3])
{
int val = atoi(p);
printf("The atoi val is %d\n",val);
}
Here the atoivalue is shown as 0, but I could not figure out the exact reason.
As per my understanding, it should be the summation of decimal equivalent of each values in the array? Please correct me if I am wrong.
此处该atoi值显示为 0,但我无法弄清楚确切原因。根据我的理解,它应该是数组中每个值的十进制等值的总和?如果我错了,请纠正我。
回答by Tim Post
atoi()converts a string representation of an integer into its value. It will not convert arbitrary characters into their decimal value. For instance:
atoi()将整数的字符串表示形式转换为其值。它不会将任意字符转换为其十进制值。例如:
int main(void)
{
const char *string="12345";
printf("The value of %s is %d\n", string, atoi(string));
return 0;
}
There's nothing in the standard C library that will convert "A" to 65 or "Z" to 90, you'd need to write that yourself, specifically for whatever charset you're expecting as input.
标准 C 库中没有任何内容可以将“A”转换为 65 或将“Z”转换为 90,您需要自己编写,特别是对于您期望作为输入的任何字符集。
Now that you know what atoi()does, please don't use itto deal with numeric input in whatever you come up with. You really should deal with input not being what you expect. Hmm, what happens when I enter 65 instead of A?Teachers love to break things.
既然您知道是什么atoi(),请不要用它来处理您想出的任何数字输入。你真的应该处理不是你期望的输入。嗯,当我输入 65 而不是 A 时会发生什么?老师喜欢破坏东西。
atoi()doesn't do any error checking whatsoever, which makes anything relying on it to convert arbitrary input fragile, at best. Instead, use strtol()(POSIX centric example):
atoi()不做任何错误检查,这使得任何依赖它来转换任意输入的东西充其量都是脆弱的。相反,请使用strtol()(以 POSIX 为中心的示例):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
static const char *input ="123abc";
char *garbage = NULL;
long value = 0;
errno = 0;
value = strtol(input, &garbage, 0);
switch (errno) {
case ERANGE:
printf("The data could not be represented.\n");
return 1;
// host-specific (GNU/Linux in my case)
case EINVAL:
printf("Unsupported base / radix.\n");
return 1;
}
printf("The value is %ld, leftover garbage in the string is %s\n",
// Again, host-specific, avoid trying to print NULL.
value, garbage == NULL ? "N/A" : garbage);
return 0;
}
When run, this gives:
运行时,这给出:
The value is 123, leftover garbage in the string is abc
值为123,字符串中剩余的垃圾为abc
If you don't care about saving / examining the garbage, you can set the second argument to NULL. There is no need to free(garbage). Also note, if you pass 0 as the third argument, it's assumed the input is the desired value of a decimal, hex or octal representation. If you need a radix of 10, use 10 - it will fail if the input is not as you expect.
如果您不关心保存/检查垃圾,则可以将第二个参数设置为NULL. 没有必要free(garbage)。另请注意,如果您将 0 作为第三个参数传递,则假定输入是所需的十进制、十六进制或八进制表示值。如果您需要 10 的基数,请使用 10 - 如果输入不符合您的预期,它将失败。
You'd also check the return value for the maximum and minimum value a long intcan handle. However, if either are returned to indicate an error, errnois set. An exercise for the reader is to change *inputfrom 123abcto abc123.
您还将检查 along int可以处理的最大值和最小值的返回值。但是,如果返回任何一个以指示错误,errno则设置。对于读者的练习是改变*input从123abc到abc123。
It's important to check the return, as your example shows what happens if you don't. AbcDeFg is not a string representation of an integer, and you need to deal with that in your function.
检查回报很重要,因为您的示例显示了如果不这样做会发生什么。AbcDeFg 不是整数的字符串表示形式,您需要在函数中处理它。
For your implementation, the most basic advice I can give you would be a series of switches, something like:
对于你的实现,我能给你的最基本的建议是一系列的开关,比如:
// signed, since a return value of 0 is acceptable (NULL), -1
// means failure
int ascii_to_ascii_val(const char *in)
{
switch(in) {
// 64 other cases before 'A'
case 'A':
return 65;
// keep going from here
default:
return -1; // failure
}
.. then just run that in a loop.
.. 然后循环运行。
Or, pre-populate a dictionary that a lookup function could scope (better). You wouldn't need hashes, just a key -> value store since you know what it's going to contain in advance, where the standard ASCII characters are keys, and their corresponding identifiers are values.
或者,预先填充一个查找函数可以确定范围的字典(更好)。您不需要散列,只需要一个键 -> 值存储,因为您事先知道它将包含什么,其中标准 ASCII 字符是键,它们对应的标识符是值。
回答by Snake
It tries to convert the string into an integer. Since AAA cannot be converted into an integer the value is 0. Try giving it 42 or something.
它尝试将字符串转换为整数。由于 AAA 无法转换为整数,因此值为 0。尝试给它 42 或其他值。
If no valid conversion could be performed, a zero value is returned.
如果无法执行有效的转换,则返回零值。
See http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
回答by Deep
Read atoi()as a to i (ASCII to integer).
读取atoi()为 a 到 i(ASCII 到整数)。
atoi()converts a string representing a decimal number, to integer.
atoi()将表示十进制数的字符串转换为整数。
char s[] = "42";
int num = atoi(s); //The value of num is 42.
回答by John Bode
atoiexpects its argument to be a string representation of a decimal (base-10) integer constant; AAAis not a valid decimal integer constant, so atoireturns 0 because it has no other way to indicate that the input is invalid.
atoi期望它的参数是十进制(基数为 10)整数常量的字符串表示;AAA不是有效的十进制整数常量,因此atoi返回 0,因为它没有其他方法来指示输入无效。
Note that atoiwill convert up to the first character that isn't part of a valid integer constant; in other words, "123" and "123w" will both be converted to 123.
请注意,atoi将转换为不属于有效整数常量的第一个字符;换句话说,“123”和“123w”都将转换为 123。
Like everyone else is saying, don't use atoi; use strtolinstead.
就像其他人说的那样,不要使用atoi; 使用strtol来代替。

