如何在C中添加数组

ukdjmx9f  于 2023-06-21  发布在  其他
关注(0)|答案(2)|浏览(124)

假设我有一个空数组,它将被字符串填充,当我想的时候,我如何向它附加一个字符串?
这是我目前所知道的。

string people[20] = {};

string name = "james";

strcpy(people[0], name);
c0vxltue

c0vxltue1#

CS50再次出击。
请注意,在使C更易于使用的过程中,CS50库 * 严重 * 歪曲了字符串和字符串处理在C中的实际工作方式。string类型不是原生C类型-它是类型“指向char的指针”(char *)的typedef名称(别名)。CS50 string实际上并不存储 * string *(字符序列),它存储字符串第一个字符的 * address *。这意味着

string people[20];

它实际上不是一个 * string * 的数组,而是一个 * points * 的数组:

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

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

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 |
                              +---+
                               ...

请注意,字符串文字可能是不可写的-试图修改字符串文字内容的行为是 * undefined *。你的代码可能会崩溃,它可能会像预期的那样运行,它可能会破坏其他数据,或者它可能会完全做其他事情。如果你有类似

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

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

strings[0] = "bob";

但是如果你试图修改strings[0]指向的文字的 * contents *:

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或一元&运算符的操作数,或者是用于在声明中初始化字符类型数组的字符串文字,否则类型为“T的N元素数组”的 * expression * 将被转换,或“decay”,指向类型为“指向T的指针”的表达式,表达式的值将是数组第一个元素的地址。

omhiaaxx

omhiaaxx2#

考虑到你的代码片段

string people[20] = {};

string name = "james";

strcpy(people[0], name);

类型string的定义似乎如下:

typedef char * string;

所以这个宣言

string people[20] = {};

声明一个char *类型的元素数组。
不能使用空大括号作为初始化器。你至少要写得像

string people[20] = { NULL };

所以要向数组中添加一个元素,你应该写

people[0] = name;

或者不使用中间变量

people[0] = "james";

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

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

相关问题