初始代码(错误)
#include<stdio.h>
#include<string.h>
main()
{
char str[100]={0}; //存放字符串
char *a[32]; /指针数组,用于存放单词的首地址
printf("please input a sentence:\n:");
scanf("%s",str); //scanf输入字符串遇到'\0'就结束,与输入单个字符不同 《错0》
int i=0,j=0,k,count=0;
for(i=0;i<=strlen(str);i++) 《错1》
{
if(str[i]<65 && str[i]>90 && str[i]<97 && str[i]>122) //判断是否为英文单词 《可修改》
{
str[i]='\0'; //遇到非英文单词的,即空格,赋'\0',这样输出一个单词时从首地址到'\0'停止
a[j]=str+i-count; //定位单词首字母首地址
j++;
count=0 //记单词长度
}
count++; 《错2》
}
for(k=j;k>0;k--) //反顺输出 《错3》
{
printf("%s ",a[k]);
}
printf("\n");
}
这一题我的大概思路:句子的输入一般是输完一个单词后按下空格输入下一个单词,既然倒置输出,就把每个单词的首字母地址提取出来,在每个单词后面加上’\0’,这样输出时只要提供每个单词的首字母地址,遇到’\0’停止输出,就能把这个单词输出来。只需要把各个首字母地址存放在一个指针数组中,反向输出,就能实现单词位置倒置的功能。
具体做法:i变量是用来for循环的,一直循环到最后的’\0’结束。 count是记单词长度,遇到非字母就清零,重新记下一个单词的长度,a[j]用于存放首字母地址。 k是用于最后反序输出。
以下为需要修改的地方:
- 错0:scanf用于输入字符串时,遇到’\0’会结束,所以可以选择改用gets(),但是gets函数会无视掉定义的数组长度,有可能会溢出造成错误,在编译时候会警告。这里我们把数组长度设置长一点,暂且避免这一情况。
- 错1:for(i=0;i<=strlen(str);i++) ,这一行语句,strlen原本目的是为了得出字符串长度确定循环次数。但是我忽略了在for循环里面会不断给每个单词后面的空格赋值为’\0’,而每循环一次,strlen就会再调用一次。strlen的原理是遇到’\0’停止计数,导致得到的循环次数也是会变,造成矛盾。错误很致命。 可以先定义一个指针变量,把数组首地址给它,吧这个指针变量放进for循环语句中。
- 错2:count++ ,这个语句原本是想用来记单词上次,但是这样写的话,不管是不是英文字母它都会加一。也就是如果if判断是英文字母,它会加一,这没错;但如果判断这不是英文单词,把count清零,它还是会在下面加一,这样单词长度的起点就是1而不是零,导致单词长度计算错误,直接后果就是单词首字母定位错误。错误也很致命。
- 错3:for(k=j;k>0;k–) 上面的a[j]是从j=0开始接受地址,所以应该是k>=0.
而k=j这一起始位置也有错,因为在最后一步循环结束时,j++了,所以j值多加了一,在最后输出循环时,j应该把多加了的一减去。不然会出现,多出的是_libc_start_main,貌似是一个函数,不是很懂是啥。
- if(str[i]<65 && str[i]>90 && str[i]<97 && str[i]>122) 这一个判断语句我觉得改为 if( str[i] == ’ ’ || !str[i] )会更好一点。
修改后的代码
#include<stdio.h>
#include<string.h>
main()
{
char str[100]={0};
char *a[32];
printf("please input a sentence:\n:");
gets("%s",str);
int i=0,j=0,k,count=0;
int len;
len=strlen(str);
for(i=0;i<=len;i++)
{
if( str[i] == ' ' || !str[i] )
{
str[i]='\0';
a[j]=str+i-count;
j++;
count=0
}
else
{
count++;
}
}
for(k=j-1;k>=0;k--)
{
printf("%s ",a[k]);
}
printf("\n");
}