我编写了一个程序来接收用户输入并将其打印到屏幕上。
示例输入为abc 12 34
。
示例输出为abc 12 34
,但12
和34
应输入为整数。
通过示例输入,我的程序始终输出为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;
}
答案 0 :(得分:3)
您不应该使用atoi
:它会将字符串转换为int
,而不是char
。
接下来会发生什么:当您看到一个两位数的数字,例如34
时,第一次迭代将两个数字都归为atoi
,得到34
,并将其乘以十,制作340
。以下迭代选择4
,并愉快地将其添加到340
,以获得344
的累积结果。
如果您想将代表数字的单个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;
}
答案 1 :(得分:2)
两个快速更改。
首先,如前所述,atoi()
取一个字符串并返回一个int。因为你刚刚做了1个字符(0-9),只需从字符'0'中减去它。
digit=10*(digit+(*(str+index)-'0')); //instead of atoi(str+index)
为什么减去'0'?它归结为ASCII value个数字。
字符'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
/ if else
/ else
检查a-z,0-9,然后是其他任何内容。
因为您的第一个if
和您的else
是相同的代码,这意味着可以在那里进行简化。只需移除整个第一个if
并将else if
更改为if
,就可以获得与您正在执行的操作完全相同的操作。
答案 2 :(得分:1)
如果只使用sscanf
呢?像这样:
sscanf(str, "%s %d %d", str1, &num1, &num2);
如果由于某种原因无法使用sscanf
,则至少应使用isalpha()
和isdigit()
分别检查字符和数字。
所以不要使用它:
if((*(str+index)>='a') &&( *(str+index)<='z')) {
.....
}
使用此:
if (isalpha(*str+index)) {
.....
}
答案 3 :(得分:0)
您的代码的一个问题是数字+ = atoi(str + index);这将采取,例如,“12”将转换为int,并打印12比在下一次迭代它将采取“2”并再次打印,因此打印“122”。一个简单的解决方案是替换此digit = str[index] - '0';
的代码行,现在它将通过char转换char。
不要使用if / else这么多,最好使用一个条件来检查它是否是数字,如下面的代码所示:
#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 (isdigit(*(str+index)))
{
while (isdigit(*(str+index)))
{
digit = str[index] - '0';
fprintf(stdout,"%d",digit); fflush(stdout);
digit = 0;
index++;
}
index--;
}
else{
fprintf(stdout,"%c",*(str+index)); fflush(stdout);
}
}
printf("\n");
free(str);
return 0;
}