2017-08-10 46 views
4

我正在做一个练习,其中一个字符指针数组作为存储单词的一种方式。我不明白为什么我不能使用'strcpy'将单词'hoi'复制到主函数中数组的第二个元素。当我编译代码时,我在CodeBlocks中收到'程序已停止工作'的消息。不能从C中的strcpy指针数组中复制字符串?

函数'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

'快译通[1]'指向一个字符串的第一个字符。修改'strcpy(dict [1],newWord1)'这样的字符串文字会导致未定义的行为。 – Peter

+0

非常感谢大家! –

+0

这是一个令人难以置信的常见问题。如果您在“字符串”下面查看[Stack Overflow C FAQ](https://stackoverflow.com/tags/c/info),有几个规范的帖子可用于进一步阅读/重复关闭。 – Lundin

回答

0

存储器中的指针指向是只读作为"string"是文字的字符串。

0

据我的理解,写入字符串文字是不可能的。

+2

写入_string literal_不是不可能的。试图这样做是_undefined行为_ - 它_might_“工作”,它可能不会。 – chux

+0

@chux感谢您的评论;这就是我的意思。 – Codor

1

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

当您使用strcpy(dict[1]), ...时,您试图修改dict[1]指向的东西。但它指向一个常数。所以你试图修改一个常量。

常量不能修改。

+0

C有各种_constants_,但没有指定_string常量_。 _string literals_不是真正的常量,但试图改变他们是UB像'的strcpy(字典[1]),...' – chux

2

数组dict是一个指向字符串文字的指针数组。

在这份声明中

strcpy(dict[1],newWord1); 

你要复制一个字符串中另一个字符串字面直译。

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

从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) 
+0

详细内容:C不指定“字符串文字是不可修改的。” UB试图这样做。很好,你已经强调了这个UB。 – chux

+0

@Vlad来自莫斯科,你的代码是UB。 '炭字典[10] [9] = { “AAP”, “兄弟”, “乔乔”, “千奥斯特”, “千磅”, “哈哈”, “杭德”, “降” };'然后你迭代'的size_t numberOfWordsInDict(字符字典[] [N]) { 为size_t N = 0; while(* dict [n])++ n; return n; “你很幸运,你在表格的最后一个元素之后有某种零值。 –

+0

@PeterJ你错了。我不幸运。我只是一个合格的失业者。:)这个数组被声明为有10个元素。但只明确提供了8个初始化器。其余两个元素用零初始化。那是他们包含空字符串。代码格式正确。 –

0

您需要在RW存储和复制的文字有保留的存储空间。你不必做手工:)

#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]); 
     } 
    } 
} 

和地方()

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]));