C 中的字符串数组
我需要保存一个 C 字符串数组。现在我知道 C 字符串只是一个字符数组,所以本质上我想要的是一个二维字符数组。我尝试存储的字符串也不会超过 6 个字符。我的计划是用 50 个“字符串槽”初始化一个 char 数组,然后如果我达到 50 个字符串,则重新分配数组的内存以将其容量加倍。我尝试过一些简单的方法,例如:
int main() {
char strings[50][6];
strings[0] = "test";
printf("The string is: %s", strings[0]);
return(0);
}
但是,当我编译它时,出现以下错误:
test.c:在函数“main”中:test.c:3: 错误:不兼容的类型 从类型分配给类型“char[6]” 'char *' test.c:4:警告: 不兼容的隐式声明 内置函数“printf”
有人能指出我正确的方向吗?
I need to hold an array of C strings. Now I know C strings are just an array of chars so essentially what I want is a 2d array of chars. The strings I'm trying to store will also never exceed 6 characters. My plan is to initialize a char array with 50 "string slots" and then if I hit 50 strings reallocate the array's memory to double it's capacity. I've tried something simple like:
int main() {
char strings[50][6];
strings[0] = "test";
printf("The string is: %s", strings[0]);
return(0);
}
But, when I go to compile it I get the following error:
test.c: In function ‘main’: test.c:3:
error: incompatible types when
assigning to type ‘char[6]’ from type
‘char *’ test.c:4: warning:
incompatible implicit declaration of
built-in function ‘printf’
Can anyone point in me in the right direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

发布评论
评论(6)
首先是简单的部分。您确实需要
#include <stdio.h>
消除不兼容的 printf 警告。这与标准所说的 C 工作方式有关,即允许您创建一些与标准 printf 不同的函数,该函数的隐式声明及其签名由编译器(错误地)猜测,并且编译器知道虽然你可以定义一个不同的 printf 但你可能实际上并不是故意的。
好的,现在是更复杂的部分。 C 中的数组有点特殊。可以计算为指针文字(无法分配给它,这类似于尝试 6 = 4;
),或者它们可以计算为整个数组,具体取决于上下文。通常它们是指针文字,但在这种情况下,strings[0]
被视为一个数组,这就是为什么您会收到错误,而不是指出strings[0]
code> 是无效的左值(左值,表示可以位于 =
左侧的内容)。无论哪种方式,您都无法将字符指针文字(这就是“test”的计算结果)复制到数组。但是,当您在声明字符串(字符数组)的行上执行此操作时,编译器会以不同的方式对待它,这可能会导致一些混乱。无论如何,您需要使用 strcpy
复制组成“test”的字符,或者将 strings[0] 初始化为“test”,如下所示:
char strings[50][6] = { "test" }; // only initializes the first member of the array
您无法使用 =
运算符分配数组内容。首先,数组对象不能成为赋值运算符的目标(在线 C 标准,草案 n1256,第 6.5.16.1 节,第 1 段)。 strings[0]
是 char[6]
类型的数组对象,因此它不能出现在 =
运算符的 LHS 上。
其次,当数组表达式不是 sizeof
或 address-of &
运算符的操作数并且不是用于初始化内容的字符串文字时另一个数组,表达式的类型从“T 的 N 元素数组”隐式转换(“衰减”)为“指向 T 的指针”,并且表达式的值是数组中第一个元素的地址(节6.3.2.1,第 3 段)。
字符串文字“test”是一个 5 元素的 char
数组(C++ 中的 const char
),具有静态范围(意味着它的内存在程序启动时分配并保存)直到程序退出)。但是,当它出现在表达式中时,
strings[0] = "test";
其类型从“5 元素 char 数组”转换为“指向 char 的指针”,并且其值是第一个元素的地址,因此您最终要做的是尝试分配 < em>指向数组对象的指针值,该对象不是兼容类型;坏juju,无论如何都无法分配数组对象。
如果要将一个数组的内容复制到另一个数组,则需要单独分配每个数组元素,例如
strings[0][0] = 't';
strings[0][1] = 'e';
strings[0][2] = 's';
strings[0][3] = 't';
strings[0][4] = 0;
或 甚至
size_t len = strlen("test");
size_t i;
for (i = 0; i < sizeof strings[0] - 1 && i < len; i++)
strings[0][i] = "test"[i]; // yes, you can subscript a string literal
strings[0][i] = 0;
,或者使用库函数,例如 memcpy()
、strcpy ()
、strncpy()
、strcat()
、sprintf()
等:
strcpy(strings[0], "test");
或
strncpy(strings[0], "test", sizeof strings[0] - 1); // -1 to leave room
// for 0 terminator
// if necessary
或
sprintf(strings[0], "%*s", (int) sizeof strings[0] - 1, "test");
请注意,您可以在声明数组时初始化数组的内容,如下所示:
char foo[] = "test"; // foo is implicitly sized to 5 (+1 for 0 terminator)
int bar[] = {1,2,3,4,5}; // again, size is implied from initializer
float f[3] = {1.0, 2.0, 3.0}; // Initializer cannot contain more items than
// array is sized for
我看到关于使用 strcpy()
与 strncpy()
的使用存在着一场愉快的战争在另一个答案的评论中;我的立场是使用适合特定情况的任何一种。如果您知道缓冲区足够大,可以处理尽可能大的输入,请使用 strcpy()
。如果没有,请使用 strncpy()
,但请注意,您可能需要手动添加 0 终止符。
您遇到的问题在于编译器解释语句 char strings[50][6];
的方式,
而不是您希望的那样,而是一个具有 50 个插槽的 char
数组6 个 char
字符串,您得到了一个由尺寸为 50x6 的单个 char
组成的 char
数组。
您想要初始化数组的方式不是 char strings[50][6];,而是如下(我只知道如何在堆上执行此操作,抱歉):
char ** strings[50] = malloc(50 * sizeof(char *));
for(int i = 0; i < 50; ++i)
{
strings[i] = malloc(50 * 6 * sizeof(char *));
}
不要忘记之后用frees清理。
编辑:如上所述。在你的 main 方法之前。包含行 #include
。这是 printf()
函数所在的位置。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
strncpy(strings[0], "test", 6);
除非您的 C 库具有strlcpy()
。但是,如果您需要改变存储的大小,最好将char **
与malloc()
、realloc() 一起使用
和free()
。strncpy(strings[0], "test", 6);
unless your C library hasstrlcpy()
. However if you are going to need to vary the size of the storage, you're better off using achar **
withmalloc()
,realloc()
andfree()
.