2

我编写了一个程序来接收用户输入并将其打印到屏幕上。

样本输入为abc 12 34

样本输出为abc 12 34,但1234应作为整数输入。

使用示例输入,我的程序始终输出为abc 122 344. 我已经研究了很长时间,但我仍然无法弄清楚。可以帮我检查我的代码吗?谢谢。

我的 gcc 版本是 4.1.2 。

#include<stdio.h>
#include<stdlib.h>
int main()
{
    char c;
    char *str = NULL;
    str = (char *)malloc(20*sizeof(char)); /*just sample code, not robust*/
    memset(str,'\0',20*sizeof(char)); 

    if(str == NULL)
    {
        fprintf(stderr,"Error: failed to allocate memory.\n"); fflush(stderr);
        return 0;
    }

    /*store user input*/
    int index = 0;
    while((c=getchar()) != '\n')
    {
        *(str+index) = c;
        index++;
    }

    int digit = 0;
    for(index = 0; *(str+index)>0; index++)
    {
        if((*(str+index)>='a') &&( *(str+index)<='z'))
        {
            fprintf(stdout,"%c",*(str+index)); fflush(stdout);
        }

        else if((*(str+index)>='0') &&( *(str+index)<='9'))
        {
            /*handling the case that a number with more than one digit*/
                    if(*(str+index+1)>='0' && *(str+index+1)<='9')
            {
                digit=10*(digit+atoi(str+index));
            }
            else
            {
                digit += atoi(str+index);   
                fprintf(stdout,"%d",digit); fflush(stdout);
                digit = 0;
            }           
        }

        else
        {   
            fprintf(stdout,"%c",*(str+index)); fflush(stdout);
        }
    }
    printf("\n");
    free(str);
    return 0;
}
4

3 回答 3

3

您不应该使用atoi:它将字符串转换为int,而不是单个char.

以下是发生的情况:当您看到一个两位数时,例如 ,34第一次迭代 pssses 两个数字到atoi,得到34,并将其乘以十,得到340。下面的迭代将提取4并愉快地将其添加340344.

如果您想将char表示数字的单个转换为int,请使用减法:

digit = *str - '0';

此外,您处理多位数字的代码是非正统的,因此难以理解。当您看到下一个字符是数字时,不要将当前值乘以 10,而应该在看到数字时将先前值乘以 10。这甚至适用于第一个数字,当先验值为 时0,因为十倍零仍然是零。

您应该消除if(((*str+index+1)>='0') && (*str+index+1)<='9')及其then分支,并修改其else分支如下:

digit = 10*digit + *(str+index) - '0';
if (((*str+index+1)<'0') || (*str+index+1)>'9') {
    fprintf(stdout,"%d",digit); fflush(stdout);
    digit = 0;
}
于 2012-10-26T15:40:37.320 回答
2

为您提供两个快速更改。

首先,如前所述,atoi()获取一个字符串并返回一个 int。由于您只是在做 1 个字符 (0-9),因此只需从字符 '0' 中减去它。

digit=10*(digit+(*(str+index)-'0')); //instead of atoi(str+index)

为什么要减去“0”?它归结为数字的ASCII 值

字符 '0' 的值是 30 10, '1' 的值是 31 10,所以:

int a = '0' - '0'; // that's  30-30, or 0 as an int
int b = '1' - '0'; // that's  31-30, or 1 as an int

如果您在当前使用的两个地方进行此调整atoi()

            ...
            digit=10*(digit+atoi(str+index));
        }
        else
        {
            digit += atoi(str+index); 
            ...

更改为:

            ...
            digit=10*(digit+(*(str+index)-'0'));
        }
        else
        {
            digit += *(str+index)-'0';   
            ...

您的代码现在将按照您希望的方式工作。还有一点,您有一个if//检查 az、0-9,然后是其他任何内容if elseelse

因为您的第一个if和您else的代码相同,这意味着可以在那里进行简化。只需删除整个 firstif并将您的更改else if为 just an 即可if为您提供与您正在做的完全相同的事情。

于 2012-10-26T16:21:06.083 回答
1

仅仅使用sscanf它怎么样?像这样:

sscanf(str, "%s %d %d", str1, &num1, &num2);

如果由于某种原因您不能使用sscanf,那么您至少应该使用isalpha()andisdigit()分别检查字符和数字。

所以不要使用这个:

if((*(str+index)>='a') &&( *(str+index)<='z')) {
    .....
}

用这个:

if (isalpha(*str+index)) {
    .....
}
于 2012-10-26T15:37:53.360 回答