问题描述
以下程序在尝试用 t 替换 s 中的第一个字符后崩溃,没有错误消息。该程序的目的是测试两个字符串 s 和 t 是否同构:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isIsomorphic(char *s,char *t);
int main()
{
isIsomorphic("egg","add");
}
bool isIsomorphic(char *s,char *t)
{
//create two other char pointers for the characters one position before s and t.
char *preS = s;
char *preT = t;
//replace first character in s with t.
*s = *t //CRASHES HERE
//increment both pointers to their second character.
s ++;
t ++;
//run through t
while(t != NULL)
{
//if the characters in both strings are either a. both equal to their prevIoUs or b. both different to their prevIoUs:
if(((strcmp(t,preT) == 0) && (strcmp(s,preS) == 0)) || (((strcmp(t,preT) != 0) && (strcmp(s,preS) != 0))))
{
//copy t into s and shift both pointers along.
*s = *t;
s ++;
t ++;
}
else
{
printf("not isomorphic\n");
return false;
}
}
printf("isomorphic\n");
return true;
}
为什么会这样?任何帮助将不胜感激。
解决方法
禁止修改字符串文字。尝试这样做会引发未定义行为。
在这种情况下,指针在赋值后递增,而在调用 isIsomorphic
函数后不引用字符串,因此您应该删除无意义和有害的赋值(*s = *t;
)。
如果您想稍后引用修改后的字符串,您应该将要修改的字符串存储在一个可修改的数组中,如下所示:
int main(void)
{
char str[] = "egg";
isIsomorphic(str,"add");
}
,
您正在使用字符串文字
isIsomorphic("egg","add");
您正在函数 isIsomorphic
*s = *t //CRASHES HERE
您不能更改字符串文字。任何更改字符串文字的尝试都会导致未定义的行为。
来自 C 标准(6.4.5 字符串文字)
7 未指定这些数组是否不同,只要它们 元素具有适当的值。 如果程序试图 修改这样的数组,行为未定义。
但无论如何这个函数是不正确的。
首先,函数不应改变传递给它的字符串。也就是说它应该被声明为
bool isIsomorphic( const char *s,const char *t);
还有这些 if 语句中函数 strcmp
的调用
if(((strcmp(t,preT) == 0) && (strcmp(s,preS) == 0)) || (((strcmp(t,preT) != 0) && (strcmp(s,preS) != 0))))
至少没有意义,因为 t
和 preT
指向的字符串具有不同的长度。所以这个表达式 strcmp(t,preT) == 0
的计算结果总是逻辑假。
我可以建议以下演示程序中显示的以下函数定义。
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isIsomorphic( const char *s,const char *t )
{
size_t n = strlen( s );
bool isomorphic = n == strlen( t );
while ( isomorphic && n-- )
{
const char *p1 = strchr( s + n + 1,s[n] );
const char *p2 = strchr( t + n + 1,t[n] );
isomorphic = ( !p1 && !p2 ) || ( p1 && p2 && p1 - s == p2 - t );
}
return isomorphic;
}
int main(void)
{
const char *s = "egg";
const char *t = "add";
printf( "\"%s\" is isomorphic with \"%s\" is %s\n",s,t,isIsomorphic( s,t ) ? "true" : "false" );
s = "foo";
t = "bar";
printf( "\"%s\" is isomorphic with \"%s\" is %s\n",t ) ? "true" : "false" );
s = "paper";
t = "title";
printf( "\"%s\" is isomorphic with \"%s\" is %s\n",t ) ? "true" : "false" );
s = "0123456789";
t = "9876543210";
printf( "\"%s\" is isomorphic with \"%s\" is %s\n",t ) ? "true" : "false" );
return 0;
}
程序输出为
"egg" is isomorphic with "add" is true
"foo" is isomorphic with "bar" is false
"paper" is isomorphic with "title" is true
"0123456789" is isomorphic with "9876543210" is true