c语言:大神最近写了一个关于匹配最长单词的程序。有点问题求指导
void match_lgest_word(char a[],char b[])
{
char c[20]; //一个单词不会超过20个字母吧
int i=0,j,m,n,maxlen=0,from;
for(;a[i]!='\0';)
{
for(j=0;a[i]!=' ';i++,j++) //将a中单词放到c中
{
c[j]=a[i];
}
c[j]='\0'; //c加上结束标识
for(m=0;b[m]!='\0';m++) //这个部分验证c是否为b的子串
{
for(n=0;b[m]==c[n]&&c[n]!='\0';m++,n++)
{
;
}
if(c[n]=='\0'&&maxlen<j-1)
{
maxlen=j-1;
from=i-j+1;
break;
}
}
for(;a[i]=' ';i++) //去掉单词之间一个或多个空格,继续循环
{
;
}
}
for(;a[from]!=' '&&a[from]!='\0';from++)
printf("%c",a[from]);
}
void main()
{
char str1[]="This is C programming text";
char str2[]="This is a text for C programming";
printf("两个字符串公共最长英文单词是:");
match_lgest_word(str1,str2);
}
具体问题时这段代码变异没问题,运行不起来,直接死掉。 展开
有两个主要修改点:
【修改点1】
尝试获取a中单词保存到c中时,注意最后一个单词可能不是空格结尾而是'\0'结尾。
【修改点2】
“去掉单词之间一个或多个空格,继续循环”这句话里的for中间
a[i]=' '改成a[i] == ' '。
另外为了预防,这类情况建议写成' ' == a[i],因为少写一个等号变成' ' = a[i]时编译器会帮你检测出来。
其他修改点见注释“修改点”。
#include <stdio.h>
void match_lgest_word(char a[],char b[])
{
char c[20]; //一个单词不会超过20个字母吧
int i=0,j,m,n,maxlen=0,from;
for(;a[i]!='\0';)
{
for(j=0;a[i]!=' ' && a[i] != '\0';i++,j++) //将a中单词放到c中 修改点:最后一个单词后面可能没有空格。
{
c[j]=a[i];
}
c[j]='\0'; //c加上结束标识
for(m=0;b[m]!='\0';m++) //这个部分验证c是否为b的子串
{
for(n=0;b[m]==c[n]&&c[n]!='\0';m++,n++)
{
;
}
if(c[n]=='\0'&&maxlen<j) // 修改点:j已经是单词长度,不用-1了
{
maxlen=j; // 修改点:j已经是单词长度,不用-1了
from=i-j; // 修改点:从下标角度考虑,由于j不-1,所以from也不用+1
break;
}
}
for(; ' ' == a[i];i++) //去掉单词之间一个或多个空格,继续循环 修改点:“=”改成“==”,颠倒比较顺序
{
;
}
}
for(;a[from]!=' '&&a[from]!='\0';from++)
printf("%c",a[from]);
}
void main()
{
char str1[]="This is C programming text";
char str2[]="This is a text for C programming";
printf("两个字符串公共最长英文单词是:");
match_lgest_word(str1,str2);
}
感谢!感谢!思虑不周啊!另外请问两个问题
1、代码还能优化么
2、你们回答的这种专门的代码block怎么调出来的啊
代码还能优化。比如“将a中单词放到c中”之后,由于a的单词长度已定(就是j),那么直接就能让j和maxlen比较。如果j小于maxlen,后面就不用比较了,反正肯定不会是“最长相同单词”。
再比如“这个部分验证c是否为b的子串”的地方,不一定要循环到b[m]是'\0'的地步,如果b后面只剩下3个字母,而c的长度(也就是当前的a中单词长度)是4,那么肯定匹配不到了。你可以在整个函数match_lgest_word的一开头先求出a和b的长度,对于每个单词,先求出c的长度,然后在这个地方的for的边界就改成m + “c的长度” > “a的长度”。
2.关于block,你在发帖时,右上方有个“代码语言”的下拉列表,点一下然后选择“C/C++”,就会看到灰色的底色,在那里输入的都会被视为代码。
你没有意识到应该先测试字符数组的结尾再测试该字符是否为空格。修改后的代码如下。
void match_lgest_word(char a[], char b[])
{
char c[20];
int i = 0, j, m, n, maxlen = 0, from;
for (; a[i] != '\0';) {
for (j = 0; a[i] != '\0' && a[i] != ' '; i++, j++) { // 这里不测试a[i]非零的话会出界
c[j] = a[i];
}
c[j] = '\0';
for (m = 0; b[m] != '\0'; m++) {
for (n = 0; c[n] != '\0' && b[m] == c[n]; m++, n++) { // 这里不先测试c[n]非零的话也会出界
;
}
if (c[n] == '\0' && maxlen < j) { // 之前这里字符串长度计算有误
maxlen = j;
from = i-j; // 尤其是这里
break;
}
}
for(; a[i] == ' '; i++) {
;
}
}
for(; a[from] != '\0' && a[from] != ' '; from++) // 这里类似
printf("%c", a[from]);
}