1

我需要保存一个 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 *'类型分配给'char [6]'类型时的类型不兼容test.c:4:警告:内置的不兼容隐式声明在函数'printf'中</p>

谁能指出我正确的方向?

4

6 回答 6

5

strncpy(strings[0], "test", 6);除非你的 C 库有strlcpy(). 但是,如果您需要改变存储的大小,最好使用char **withmalloc()和.realloc()free()

于 2010-09-16T20:39:31.167 回答
2

不能以这种方式直接分配数组。在您目前的情况下,您需要执行类似...

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

不过,使用指针数组会更惯用。看看 p111 和 K & R 以后的版本。

于 2010-09-16T20:39:31.277 回答
1

使用 strncpy (如果可能的话)或 strcpy 进行分配。

于 2010-09-16T20:40:01.430 回答
1

首先是简单的部分。你确实需要

#include <stdio.h>

摆脱不兼容的 printf 警告。这与标准所说的 C 工作方式有关,即允许您创建一些与标准 printf 不同的函数,该函数的隐式声明及其签名(错误地)被编译器猜到,并且编译器知道尽管您可以定义不同的 printf,但您可能实际上并不打算这样做。

好的,现在是更复杂的部分。C 中的数组有点特别。可以评估为指针文字(不能分配给,类似于尝试6 = 4;),或者它们可以评估为整个数组,具体取决于上下文。通常它们是指针文字,但在这种情况下strings[0]被视为一个数组,这就是为什么你会得到你得到的错误而不是一个说明strings[0]是无效的左值(左值,意味着可以在左侧的一个=)。无论哪种方式,您都不能将字符指针文字(这是“test”评估的内容)复制到数组中。但是,当您在声明字符串(char 数组)的行上执行此操作时,编译器会以不同的方式处理它,这可能会导致一些混乱。无论如何,您需要使用strcpy复制组成“test”的字符或将字符串[0]初始化为“test”,如下所示:

char strings[50][6] = { "test" };  // only initializes the first member of the array
于 2010-09-16T21:07:02.883 回答
1

您不能使用运算符分配数组内容=。首先,数组对象不能成为赋值运算符的目标(在线 C 标准,草案 n1256,第 6.5.16.1 节,第 1 段)。 strings[0]是一个类型的数组对象char [6],所以它不能出现在=操作符的 LHS 上。

其次,当一个数组表达式不是运算符sizeof或地址运算符的操作数,&也不是用于初始化另一个数组内容的字符串字面量时,表达式的类型将隐式转换(“衰减”) “T 的 N 元素数组”到“指向 T 的指针”,表达式的值是数组中第一个元素的地址(第 6.3.2.1 节,第 3 段)。

字符串文字“test”是charconst char在 C++ 中)的 5 元素数组,具有静态范围(意味着它的内存在程序启动时分配并保持到程序退出)。但是,当它出现在表达式中时

strings[0] = "test";

它的类型从“char 的 5 元素数组”转换为“char 指针”,它的值是第一个元素的地址,所以你最终要做的是尝试将指针值分配给数组对象,即不是兼容的类型;糟糕的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()vs.存在一场快乐的战争;strncpy()我的立场是使用适合特定情况的任何一种。如果您知道缓冲区足够大,可以处理最大可能的输入,请使用strcpy(). 如果没有,请使用strncpy(),但请注意,您可能必须手动添加 0 终止符。

于 2010-09-17T15:42:17.697 回答
0

您遇到的问题在于编译器解释语句的方式char strings[50][6];

而不是你希望的那样,一个包含 6 个字符串char的 50 个插槽的数组,你得到了一个尺寸为 50x6 的单个 s 数组。charcharchar

而不是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 *));
}

之后别忘了用免费清洁剂进行清洁。

编辑:如上所述。在你的主要方法之前。包括行#include <stdio.h>。这是printf()函数所在的位置。

于 2010-09-17T10:13:57.473 回答