在C语言中使用strcpy无法从指针数组复制字符串?

5
我正在做一项练习,其中一个字符指针数组被用作存储单词的方式。我不明白为什么我不能在主函数中使用'strcpy'将单词“hoi”复制到数组的第二个元素中。当我编译代码时,在CodeBlocks中会收到“程序已停止工作”的消息。
'numberOfWordsInDict'和'printDict'函数正常工作。
提前感谢。
int numberOfWordsInDict(char **dict)
{
    int i, cnt = 0;
    for(i = 0; i < 10; i++)
    {
        if(dict[i] != NULL)
        {
            cnt++;
        }
    }
    return cnt;
}

void printDict(char **dict)
{
    int i = 0;
    printf("Dictionary:\n");
    if(numberOfWordsInDict(dict) == 0)
    {
        printf("The dictionary is empty.\n");
    } else
    {
        for(i = 0; i < 10; i++)
        {
            printf("- %s\n", dict[i]);
        }
    }
}

int main()
{
    char *dict[10] = {
            "aap", "bro ", "jojo", "koe", "kip", 
            "haha", "hond", "    drop", NULL,NULL};

    char *newWord1 = "hoi";
    printDict(dict);
    strcpy(dict[1], newWord1);
    printDict(dict);

    return 0;
}

1
dict[1] 指向字符串字面量的第一个字符。修改字符串字面量,例如 strcpy(dict[1], newWord1),会产生未定义的行为。 - Peter
非常感谢大家! - blabla444
这是一个非常常见的FAQ。如果您查看下面“字符串”部分的Stack Overflow C FAQ,那里有几篇经典文章可供进一步阅读/关闭为重复。 - Lundin
5个回答

2
数组dict是一个指向字符串字面量的指针数组。
在这个语句中:
strcpy(dict[1],newWord1);

您正在尝试将一个字符串字面量复制到另一个字符串字面量中。

C和C ++中的字符串字面量是不可修改的。任何尝试修改字符串字面量的操作都会导致程序行为未定义。

来自C标准(6.4.5字符串字面量)

7未指定这些数组是否不同,只要它们的元素具有适当的值即可。如果程序尝试修改这样的数组,则行为是未定义的。

如果您要在其元素中复制字符串字面量,则应声明二维字符数组或动态分配字符数组的一维数组。

程序可以如下所示:

#include <stdio.h>
#include <string.h>

#define N   9

size_t numberOfWordsInDict( char dict[][N] )
{
    size_t n = 0;

    while ( *dict[n] ) ++n;

    return n;
}

void printDict( char dict[][N] )
{
    printf("Dictionary:\n");

    size_t n = numberOfWordsInDict( dict );
    if ( n == 0 )
    {
        printf("The dictionary is empty.\n");
    } 
    else
    {
        for ( size_t i = 0; i < n; i++ )
        {
            printf( "- %s\n", dict[i] );
        }
    }
}

int main(void) 
{
    char dict[10][9] = 
    {
        "aap", "bro ", "jojo", "koe", "kip", "haha", "hond", "    drop"
    };
    char *newWord1 = "hoi";

    printDict(dict);
    strcpy(dict[1], newWord1);
    printDict(dict);

    return 0;
}

程序的输出为:
Dictionary:
- aap
- bro 
- jojo
- koe
- kip
- haha
- hond
-     drop
Dictionary:
- aap
- hoi
- jojo
- koe
- kip
- haha
- hond
-     drop

你可以使用可变长度数组。
请记住,根据C标准,没有参数的main函数应该声明为
int main( void )

@PeterJ 你错了。我不是幸运的,我只是一名合格的失业者。:) 这个数组被声明为有10个元素。但只提供了8个初始化程序。剩下的两个元素将被初始化为零。也就是说,它们包含空字符串。这段代码是良好形成和正确的。 - Vlad from Moscow
@Vlad来自莫斯科,那么你的函数对以下代码做了什么:char dict[10][9] = { "aap", "bro ", "jojo", "koe", "kip", "haha", "hond", " drop", "mod", "bod" }; 它会产生未定义行为吗? - 0___________
@PeterJ,这里没有未定义行为。该数组被声明为具有10个元素,但只提供了8个初始化程序。在这种情况下,其他两个元素将被零初始化。也就是说,它们将包含空字符串。至于你的数组示例,则应追加一个带有空字符串的元素。 - Vlad from Moscow
@来自莫斯科的Vlad没有填充任何内容,也没有将它们视为终止值。他只是不知道如何正确检测它(他正在检查strlen并认为NULL的strlen为零。而解引用NULL会导致UBs)。 - 0___________
@PeterJ 在这种情况下,他还必须跳过输出数组元素的这些插槽。然而,他按顺序输出元素,无论它是真实字符串还是插槽。因此,无论如何,它的解决方案都是错误的。 - Vlad from Moscow
显示剩余8条评论

1

由于"bro"是一个字符串常量并且dict[1]指向它,所以dict[1]指向一个字符串常量。

当你使用strcpy(dict[1]), ...时,你试图修改dict[1]指向的内容。但是它指向一个常量。因此你试图修改一个常量。

常量不能被修改。


C语言有各种常量,但没有指定字符串常量。字符串字面值不是真正的常量,但试图更改它们会导致未定义行为,例如strcpy(dict[1])等。 - chux - Reinstate Monica

0
指针所指向的内存是只读的,因为 "string" 是一个字符串常量。

0
据我所知,无法向字符串字面量写入内容。

2
在字符串字面值上进行写操作并非“不可能”。尝试这样做是未定义的行为——它可能会“起作用”,也可能不会。 - chux - Reinstate Monica
@chux 感谢您的评论;这正是我想表达的意思。 - Codor

0
您需要在可读写内存中保留存储空间,并将文字直接复制到其中。您无需手动执行此操作 :)
#define MAXDICTSIZE 25

int numberOfWordsInDict(char dict[][MAXDICTSIZE], int dictsize)
{
    int i, cnt = 0;
    for (i = 0; i < dictsize; i++)
    {
        if (strlen(dict[i]))
        {
            cnt++;
        }
    }
    return cnt;
}

void printDict(char dict[][MAXDICTSIZE], int dictsize)
{
    int i = 0;
    printf("Dictionary:\n");
    if (numberOfWordsInDict(dict, dictsize) == 0)
    {
        printf("The dictionary is empty.\n");
    }
    else
    {
        for (i = 0; i < dictsize; i++)
        {
            if(strlen(dict[i]))printf("- %s\n", dict[i]);
        }
    }
}

而在main()的某个地方

char dict[10][MAXDICTSIZE] = {
    "aap", "bro ", "jojo", "koe", "kip",
    "haha", "hond", "    drop", "","" };

char *newWord1 = "hoi";
printDict(dict, sizeof(dict)/sizeof(dict[1]));
strcpy(dict[1], newWord1);
printDict(dict, sizeof(dict) / sizeof(dict[1]));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接