如何追加到 C 中的数组

How to append to array in C

假设我有一个将用字符串填充的空数组,我该如何在需要时向其附加字符串?

这是我目前所拥有的

string people[20] = {};

string name = "james";

strcpy(people[0], name);

考虑到您的代码段

string people[20] = {};

string name = "james";

strcpy(people[0], name);

似乎类型 string 定义为

typedef char * string;

所以这个声明

string people[20] = {};

声明类型为 char * 的元素数组。

您不能将空大括号用作初始值设定项。你至少要写like

string people[20] = { NULL };

因此,要向数组中添加一个元素,您应该这样写

people[0] = name;

或者不使用中间变量

people[0] = "james"; 

另一种方法是为数组的元素动态分配内存,并在内存中复制一个字符串。例如

people[0] = malloc( strlen( name ) + 1 );
strcpy( people[0], name );

CS50 再次来袭。

请注意,在使 C 更易于使用的过程中,CS50 库 严重地 错误地描述了字符串和字符串处理在 C 中的实际工作方式。string类型不是本机 C 类型 - 它是类型“指向 char”(char *) 的类型定义名称(别名)。 CS50 string 实际上并不存储 string (字符序列),它存储 address 第一个字符的 address一个字符串。也就是说

string people[20];

实际上不是字符串的数组,而是指针:

的数组
char *people[20];

在 C 中,字符串是字符值的序列,包括一个 0 值终止符 - 字符串 "hello" 表示为序列 {'h', 'e', 'l', 'l', 'o', 0}。所有字符串(包括字符串文字)都存储为 数组 字符类型(char 用于 ASCII/EBCDIC/UTF-8,wchar_t 用于“宽”编码)。

在大多数情况下,数组表达式“退化”为指针表达式1,所以大多数时候当我们使用字符串时,我们使用的是指针表达式,但是指针不是字符串。

如果你想将多个字符串一起追加成一个字符串,比如

"foo" + "bar" == "foobar"

那么您需要执行以下操作:

/**
 * Create a target buffer large enough to store the final string. In
 * this case we need a buffer 7 elements wide - 6 for the characters
 * "foobar" plus 1 for the string terminator.  The initial contents of
 * this array are *indeterminate*:
 *
 * +---+---+---+---+---+---+---+
 * | ? | ? | ? | ? | ? | ? | ? |
 * +---+---+---+---+---+---+---+
 */
char target[7]; 

/**
 * Copy the string "foo" to the target buffer.  After this operation,
 * the target buffer will contain:
 *
 * +---+---+---+---+---+---+---+
 * |'f'|'o'|'o'| 0 | ? | ? | ? |
 * +---+---+---+---+---+---+---+
 */
strcpy( target, "foo" ); 

/**
 * Append "bar" to the end of the string in target - looks for the 
 * string terminator, and starts appending at that point.  After 
 * this operation the target array should contain:
 *
 * +---+---+---+---+---+---+---+
 * |'f'|'o'|'o'|'b'|'a'|'r'| 0 |
 * +---+---+---+---+---+---+---+
 */
strcat( target, "bar" ); 

如果你想创建一个 array 字符串(这就是你所要求的),那么你要么需要创建一个二维数组 char:

char strings[NUM_STRINGS][MAX_STRING_LENGTH+1];

然后使用strcpy复制字符串内容:

strcpy( strings[0], "foo" );
strcpy( strings[1], "bar" );
strcpy( strings[2], "bletch" );

给你类似的东西

           +---+---+---+---+---+---+---+     +---+
strings[0] |'f'|'o'|'o'| 0 | ? | ? | ? | ... | ? |
           +---+---+---+---+---+---+---+     +---+
strings[1] |'b'|'a'|'r'| 0 | ? | ? | ? | ... | ? |
           +---+---+---+---+---+---+---+     +---+
strings[2] |'b'|'l'|'e'|'t'|'c'|'h'| 0 | ... | ? |
           +---+---+---+---+---+---+---+     +---+

或者您需要创建一个指针数组(这是您代码中的内容),然后存储每个字符串的 地址

char *strings[NUM_STRINGS];

strings[0] = "foo";
strings[1] = "bar";
strings[2] = "bletch";

这给你类似的东西

            +---+                               +---+
strings[0]: |   | ----------------------------> |'f'|
            +---+                      +---+    +---+
strings[1]: |   | -------------------> |'b'|    |'o'|
            +---+             +---+    +---+    +---+
strings[2]: |   | ----------> |'b'|    |'a'|    |'o'|
            +---+             +---+    +---+    +---+
             ...              |'l'|    |'r'|    | 0 |
                              +---+    +---+    +---+
                              |'e'|    | 0 |     ...
                              +---+    +---+
                              |'t'|     ...
                              +---+
                              |'c'|
                              +---+
                              |'h'|
                              +---+
                              | 0 |
                              +---+
                               ...

请注意字符串文字可能不可写 - 尝试修改字符串文字内容的行为是 未定义。您的代码 可能 崩溃,它可能按预期运行,它可能破坏其他数据,或者它可能完全做其他事情。如果你有类似

char *strings[20];
...
strings[0] = "joe";

然后你可以设置 strings[0] 指向不同的字符串文字,像这样:

strings[0] = "bob";

但如果您尝试修改 strings[0] 指向的文字的 内容

strcpy( strings[0], "bob" );

那么您的代码可能不会按预期运行。但是,如果您创建一个数组并使用字符串对其进行初始化:

char *strings[20];
char name[] = "joe";

strings[0] = name; // assigning the *address* of name[0] to strings[0]
strcpy( strings[0], "bob" );

那么这将按预期工作,因为 strings[0] 指向 name,这是一个可写缓冲区。但是 name 最多只能存储 3 个字符长的名字,所以如果你尝试做类似

strcpy( strings[0], "aloysius" );

你将写过 names 数组的末尾并破坏它后面的任何内容。

是的,C 中的字符串处理是一个主要的 PITA,这就是 CS50 库试图掩盖它的原因。但同样,在这样做时,他们歪曲了事情的实际运作方式,并且在学生必须自己处理 C 字符串时让他们失败。


  1. 除非它是 sizeof 或一元 & 运算符的操作数,或者是用于在声明中初始化字符类型数组的字符串文字,否则 表达式类型 "N-element array of T" 的 将被转换或 "decay" 为类型 "pointer to T" 的表达式,表达式的值将是数组第一个元素的地址.