如何追加到 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 字符串时让他们失败。
- 除非它是
sizeof
或一元 &
运算符的操作数,或者是用于在声明中初始化字符类型数组的字符串文字,否则 表达式类型 "N-element array of T
" 的 将被转换或 "decay" 为类型 "pointer to T
" 的表达式,表达式的值将是数组第一个元素的地址.
假设我有一个将用字符串填充的空数组,我该如何在需要时向其附加字符串?
这是我目前所拥有的
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 字符串时让他们失败。
- 除非它是
sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化字符类型数组的字符串文字,否则 表达式类型 "N-element array ofT
" 的 将被转换或 "decay" 为类型 "pointer toT
" 的表达式,表达式的值将是数组第一个元素的地址.