在C中将字符从一个字符串参数复制到另一个

问题描述

以下程序在尝试用 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))))

至少没有意义,因为 tpreT 指向的字符串具有不同的长度。所以这个表达式 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