【问题标题】:Facing problems with the atoi function if used repeatedly如果重复使用,将面临 atoi 功能的问题
【发布时间】:2018-12-12 13:53:46
【问题描述】:

我必须找到给定字符串中数字 {0,1,2,3,4,5,6,7,8,9} 的频率,我正在使用 atoi 函数将字符转换为整数,当输入字符串很大时,atoi 函数出现问题(尝试使用不同长度的不同测试用例),

例如,如果输入字符串是

1v88886l256338ar0ekk

我的代码运行正常,答案是

1 1 1 2 0 1 2 0 5 0

其中第一个数字表示0的频率,以此类推直到9,

但是如果输入字符串是

9139f793308o0lo66h6vc13lgc697h0f6c32lu84445972k0o0l033od17c083yn5051d6j319hyo8j939n28d913015ns6zx5653x01211x12ch2526o65sg7xw6302141q9203s22l336319ll9yx4b597mr318a7943906750j4u152067nq83ne9f24thu96yd05173l47c803roxci45615f0w53i1sz913jj6za733l73tw6r66mq6p44sfhjr26h8e801z8zlcx2l1e65r2879xj3w3acv216196uq158o663y7oz2i5378v0v5w17762451t424352m23026r9o202i9785382o159e4gu1c8561157z5f1vqs5755465b8u728u956434mv944885li456628a994u7j5278m269n1pk8e46940q834h06il6h447888tr7ig72z10fe09k5g98h9bgt6z40v42s16pt6k3l3v45i83i01b9448g554741w766f2q7v31i085488h060e710p53076c6nm98pi946g8j2n6j8x29qa1ad48172y0u4818121p686bud89741201p54087u56g8scerv9pvhuo09re477zfb224i2c1325bj58jx4bk7b009f6446j5i95474p266i503r670n631x6940gwl71ejbx47imx576129248901765rnpu6l80084t0j1839f5y3409w2n403fu6ogw1170jmb6o5l520vg0703e0

到达字符串末尾时,atoi 函数返回错误值

例如,

我的代码使用 atoichar text 转换为整数并将其存储到 int num

一开始功能正常,

text is 9 num is 9 
text is 1 num is 1 
text is 3 num is 3 
text is 9 num is 9 
text is 7 num is 7 
text is 9 num is 9 
text is 3 num is 3 
text is 3 num is 3 
text is 0 num is 0 
text is 8 num is 8 
text is 0 num is 0 
.
.
.

当接近字符串的末尾时,函数返回

.
.
. 
text is 2 num is 2 
text is 4 num is 4 
text is 0 num is 0 
text is 3 num is 30 
text is 6 num is 60 
text is 1 num is 10 
text is 1 num is 10 
text is 7 num is 70 
text is 0 num is 0 
text is 6 num is 61 
text is 5 num is 51 
text is 5 num is 51 
text is 2 num is 21 
text is 0 num is 1
text is 7 num is 71  
text is 0 num is 1 
text is 0 num is 1 
text is 3 num is 31 

如果我用int num = text - '0' 替换int num = atoi(&text),我的程序对所有测试用例都能完美运行,

所以有人可以告诉我出了什么问题以及我是否错误地使用了该功能。 请记住,我只是想知道为什么 atoi 不起作用,因此我不是在寻找该功能的替代品。

我在下面包含了我的代码的 sn-p

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>

int main() {
    int arr[10] = {0};
    char text;
   text = getchar();
   while(text != EOF)
   {
       if(isdigit(text))
       {
           printf("text is %c ",text);
           int num = atoi(&text);
           printf("num is %d\n ",num);
           for(int i =0; i<10;i++)
           {
               if(num==i)
               {
                   arr[i]++;
                   //printf("arr[%d] is %d\n", i,arr[i]);
                   break;
               }
           }
       }
       text = getchar();
   }
for(int i=0; i<10;i++)
{
    printf("%d ",arr[i]);
}  
    return 0;
}

提前感谢您花时间阅读并回答我的问题

【问题讨论】:

  • atoi() 函数需要一个以空字符结尾的字符串作为参数,而不是字符。
  • 我会用简单的arr[num]++;替换那个for循环
  • @MartinVerjans 为什么该功能最初可以正常工作?
  • @Curfew 字符串是一个以 NULL 终止符 (\0) 结尾的字符数组。您没有在 atoi() 调用中提供以 NULL 结尾的字符串,所以这充其量是未定义的行为。
  • char text; -->> int text;(或者EOF不能正常工作)

标签: c


【解决方案1】:

the atoi() documentation in the C standard:

atoi、atol 和 atoll 函数将 nptr 指向的字符串的初始部分 分别转换为 int、long int 和 long long int 表示形式。

注意粗体部分。

给定

char text;

此代码调用未定义的行为,因为传递给atoi() 的地址不是字符串的地址:

int num = atoi(&text);

一个解决方法是:

char text[2];
text[1] = '\0';

// getchar() returns int, not char, in order
// to handle EOF properly
int input = getchar();
while(input != EOF)
{
    text[0] = input;
    if(isdigit(text[0]))
    {
        printf("text is %s ",text);
        int num = atoi(text);

这可确保将 字符串(以 nul 结尾的一系列char)传递给atoi()

【讨论】:

  • 感谢您的回答,但我仍然不确定为什么它在某些情况下有效。
  • @Curfew char text 之后的第一个字节可能是 '\0' 或等效的非数字 char 值。未定义的行为是未定义的。还要注意正确处理getchar()返回int而不是char这一事实的更新。
  • 感谢您的澄清
  • @Curfew 如果此答案对您有所帮助,如果您可以通过单击灰色 复选标记接受它作为答案,将不胜感激i> 在计票下。
  • @Tau 抱歉不知道,现在将其标记为答案
【解决方案2】:
  • 您不需要atoi(),因为您处理的是单个字符,而不是字符串
  • getc() 返回一个 int [0 .. 255 表示实际字符,-1 表示 EOF]
  • 你可以通过使用breakcontinue来避免很多{}大括号

#include <stdio.h>
#include <ctype.h>

int main() {
    int arr[10] = {0};
    int text, num;
   while(1) {
        text = getchar();
        if (text == EOF) break;
        if (!isdigit(text)) continue;
        printf("text is %c ", text);
        num = text - '0'
        printf("num is %d\n ",num);
        arr[num]++;
        //printf("arr[%d] is %d\n", num, arr[num]);
    }
    for(int i=0; i<10;i++)
    {
        printf("%d ",arr[i]);
    }

    return 0;
}

【讨论】:

  • @wildpasser wow,没想到break,continue,用arr[num]++替换循环,谢谢
猜你喜欢
  • 1970-01-01
  • 2018-07-19
  • 2020-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多