字符串中的非整数数字并使用 atoi

Posted

技术标签:

【中文标题】字符串中的非整数数字并使用 atoi【英文标题】:Non-Integer numbers in an String and using atoi 【发布时间】:2010-07-09 17:00:13 【问题描述】:

如果字符串中有非数字字符并且您调用 atoi [我假设 wtoi 也会这样做]。 atoi 将如何处理字符串?

举个例子,我有以下字符串:

    “20234543” “232B” “B”

我确定 1 会返回整数 20234543。我很好奇 2 是否会返回“232”。 [这就是我需要解决我的问题]。 3也不应该返回一个值。这些信念是错误的吗?另外...如果 2 确实像我相信的那样,它如何处理字符串末尾的 e 字符? [通常以指数表示法使用]

【问题讨论】:

为什么不试试看呢? 我认为社区会比建立一个支持 unicode 的新项目更快。 “尝试和观察”有效,但它仅向您显示系统上的行为。如果想确保代码是可移植的,那么阅读标准是最好的方法。下面的大多数答案都属于“尝试和观察”,因此描述了atoi 在某些系统上的工作方式。 “3 不应返回值” - 非void 返回类型怎么可能? 有人否决了这个问题?有点傻。 【参考方案1】:

你可以自己测试这种东西。我从Cplusplus 参考站点复制了代码。看起来您对前两个示例的直觉是正确的,但第三个示例返回“0”。 'E' 和 'e' 的处理方式与第二个示例中的 'B' 一样。

所以规则是

成功时,函数将转换后的整数作为 int 值返回。 如果无法执行有效转换,则返回零值。 如果正确值超出可表示值的范围,则返回 INT_MAX 或 INT_MIN。

【讨论】:

–1。 atoi 在输入不能表示为整数时的行为是未定义的,所以不能自己测试;任何调用未定义行为的测试都是无效的。 Cplusplus.com 没有这么说,而是cplusplus.com is a notoriously unreliable reference。您引用的是strtol 的规则,但适用于int 而不是long(这意味着它们根本不适用于任何功能)。当您需要权威引用时,请使用标准。当您需要快速参考时,请使用 cppreference.com。 atoi() 在“abc123”的输入上返回 0。为什么它被视为 0,但是当输入“123abc”时,它显示“123”作为输出。有人可以解释一下吗? 因为 POSIX 将 atoi 定义为与 strtol 具有相似的行为,后者处理前导空格(如果有),然后是数字,然后是任何无法识别的字符(如果有)(pubs.opengroup.org/onlinepubs/009695399/functions/strtol.html)。在您的第二个示例中,strtol 命中无法识别的字符并放弃。【参考方案2】:

根据标准,“函数atofatoiatolatoll在出错时不需要影响整数表达式errno的值。如果结果的值不能被表示,行为是未定义的。” (7.20.1,C99 中的数值转换函数)。

所以,从技术上讲,任何事情都有可能发生。即使对于第一种情况,由于INT_MAX 保证至少为 32767,并且由于 20234543 大于该值,因此它也可能失败。

为了更好地检查错误,请使用strtol:

const char *s = "232B";
char *eptr;
long value = strtol(s, &eptr, 10); /* 10 is the base */
/* now, value is 232, eptr points to "B" */

s = "20234543";
value = strtol(s, &eptr, 10);

s = "123456789012345";
value = strtol(s, &eptr, 10);
/* If there was no overflow, value will contain 123456789012345,
   otherwise, value will contain LONG_MAX and errno will be ERANGE */

如果你需要解析带有“e”的数字(指数符号),那么你应该使用strtod。当然,这样的数字是浮点数,strtod 返回double。如果你想从中得到一个整数,你可以在检查正确的范围后进行转换。

【讨论】:

失败了,但根据 MSDN 整数是 32 位。 msdn.microsoft.com/en-us/library/296az74e.aspx @steven:它还在顶部显示“Microsoft 特定”。因此,如果您只关心 Microsoft 特定的代码,那么在第一种情况下您无需担心溢出是对的。但是,如果您想要可移植性,则需要这样做。您的问题没有标记任何特定于平台的标签,所以我假设您想要可移植性:-)。 很公平。我编写的大多数系统都是 32 位的,所以这就是我习惯看到的。 [嗯 16 位是很久以前的] POSIX 也需要sizeof(int)>=4 只是为了完成您对 strtol 的提及,我发现 base 0 的特殊参数最方便。这会自动转换通常基数的数字,特别是 普通十进制数的基数为 10,如果数字以 0x 开头,则从十六进制数转换。【参考方案3】:

atoi 从缓冲区中读取数字,直到不能再读取为止。它在遇到任何不是数字的字符时停止,除了空格(它跳过)或“+”或“-”在它看到任何数字之前(它用于为结果选择适当的符号) .如果没有看到数字,则返回 0。

所以要回答您的具体问题:1 返回 20234543。2 返回 232。3 返回 0。字符“e”不是空格、数字、“+”或“-”,因此 atoi 遇到该字符时会停止并返回字符。

另见here。

【讨论】:

【参考方案4】:

如果 atoi 遇到非数字字符,它会返回直到该点形成的数字。

【讨论】:

【参考方案5】:

我尝试在项目中使用 atoi(),但如果混合中有任何非数字字符并且它们出现在 数字字符之前,它将不起作用 - 它会返回零.无论出于何种原因,它们是否出现在 数字之后似乎并不介意。

这是我写的一个非常简单的字符串到 int 的转换器,它似乎没有这个问题(因为它不适用于负数并且它不包含任何错误处理,但它可能在特定情况下会有所帮助)。希望它可能会有所帮助。

int stringToInt(std::string newIntString)

    unsigned int dataElement = 0;
    unsigned int i = 0;

    while ( i < newIntString.length())
    
        if (newIntString[i]>=48 && newIntString[i]<=57)
        
         dataElement += static_cast<unsigned int>(newIntString[i]-'0')*(pow(10,newIntString.length()-(i+1)));
        
        i++;
    
    return dataElement;

【讨论】:

【参考方案6】:

当我在学习接近编码程序时,我将这种 atoi 函数行为归咎于自己,该程序通过启动命令行参数来计算给定输入参数的整数阶乘结果。

如果 value 不是数字值,则 atoi-function 返回 0,并且“3asdf”返回 3。众所周知,C 语言处理 char -array 指针变量中的命令行输入参数。

有人告诉我,在“Linux Hater 手册”一书中,有一些对计算机极客很有吸引力的讨论并不真正喜欢 atoi 函数,因为无法检查给定输入类型的有效性,这有点愚蠢。

有人问我为什么不使用位于 stdlib.h -library 上的 strtol -function,他给了我一个附加到我的阶乘计算递归方法的示例,但我不关心阶乘结果更大比整数主要类型值-范围,超出范围(基数太大)。它会在我的程序中产生负值。

我用 atoi-function 解决了我的问题,首先检查给定用户的输入参数是否是真正的数值,如果匹配,然后我计算阶乘值。

使用位于 chtype.h -library 上的 isdigit() -函数如下:

int checkInput(char *str[]) 
 for (int x = 0; x < strlen(*str); ++x)
    
        if (!isdigit(*str[x])) return 1;
    
    return 0;

我在其他 Linux 编程论坛中的朋友告诉我,如果我使用 strtol,我可以处理超出范围值的情况,甚至可以将有符号 int 解析为无符号长类型,这意味着 -0 和其他负值不是接受。

如果字符不是数值,则在我的代码检查中很重要。检查这个的协商方式,当第一个数值出现在检查字符串旁边时,函数返回失败的结果。 (或 C 中的 char 数组)

【讨论】:

【参考方案7】:

编写简单的代码并查看它的作用是神奇而富有启发性的。

在第 3 点,它不会返回“无”。它不能。它会返回一些东西,但这些东西对你没有用处。

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

成功时,函数将转换后的整数作为 int 值返回。

如果无法执行有效转换,则返回零值。

如果正确值超出可表示值的范围,则返回 INT_MAX 或 INT_MIN。

【讨论】:

我知道它会返回 0 [或设定值] 或 null。但我不确定。但我的问题是......它会转换为下一个非整数值还是什么? “下一个非整数值”是什么意思? 你是对的,它不能返回“无”,但这并不意味着它会返回“某物”。行为未定义,因此它可能根本不会返回。 @RobKennedy 以何种方式未定义行为?通过我粘贴在那里的参考,它似乎完全定义了。也就是说,如果你将垃圾传递给函数,那么你会得到垃圾。 您粘贴的参考来自一个臭名昭著的错误网站。检查标准,或检查网站今天所说的内容。

以上是关于字符串中的非整数数字并使用 atoi的主要内容,如果未能解决你的问题,请参考以下文章

简单算法17.字符串转整数(atoi)

leetcode-字符串转整数(atoi)

输入一个表示整数的字符串,把该字符串转换成整数并输出(实现atoi函数功能)

c语言中如何将字符串转化成整数型并输出?

c语言中如何将字符串转化成整数型并输出?

使用 byte[] 的 Java 快速 atoi