当前位置:  开发笔记 > 编程语言 > 正文

如何在C中创建字符串数组?

如何解决《如何在C中创建字符串数组?》经验,为你挑选了9个好方法。

我试图在C中创建一个字符串数组.如果我使用此代码:

char (*a[2])[14];
a[0]="blah";
a[1]="hmm";

gcc给我"警告:从不兼容的指针类型分配".这样做的正确方法是什么?

编辑:我很好奇为什么这应该给编译器警告,因为如果我这样做printf(a[1]);,它正确打印"嗯".



1> Mikael Auno..:

如果您不想更改字符串,那么您可以这样做

const char *a[2];
a[0] = "blah";
a[1] = "hmm";

当你这样做时,你将分配一个两个指针的数组const char.然后,这些指针将被设置为静态字符串的地址"blah""hmm".

如果您确实希望能够更改实际的字符串内容,则必须执行类似操作

char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");

这将分配两个连续的14s数组char,之后静态字符串的内容将被复制到它们中.



2> John Bode..:

有几种方法可以在C中创建字符串数组.如果所有字符串的长度相同(或者至少具有相同的最大长度),则只需声明一个二维char数组并根据需要进行分配:

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");

您也可以添加初始化程序列表:

char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};

这假定初始化程序中字符串的大小和数量与数组维度相匹配.在这种情况下,每个字符串文字的内容(它本身是一个以零结尾的char数组)被复制到分配给strs的内存中.这种方法的问题是内部碎片化的可能性; 如果您有99个字符串,不超过5个字符,但是1个字符串长度为20个字符,则99个字符串将至少包含15个未使用的字符; 这是浪费空间.

您可以存储指向char的1-d指针数组,而不是使用2-d char数组:

char *strs[NUMBER_OF_STRINGS];

请注意,在这种情况下,您只分配了内存来保存指向字符串的指针; 字符串本身的内存必须在别处分配(作为静态数组或使用malloc()或calloc()).您可以像前面的示例一样使用初始化列表:

char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};

您只需存储指向它们的指针,而不是复制字符串常量的内容.请注意,字符串常量可能不可写; 您可以重新分配指针,如下所示:

strs[i] = "bar";
strs[i] = "foo"; 

但是你可能无法改变字符串的内容; 即

strs[i] = "bar";
strcpy(strs[i], "foo");

可能不被允许.

您可以使用malloc()为每个字符串动态分配缓冲区并复制到该缓冲区:

strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");

顺便说一句,

char (*a[2])[14];

将a声明为指向14元素char数组的2元素指针数组.


那么当你完成它之后你必须释放strs [i]吗?
@AndrewS:完整的答案不适合评论,但基本上它是C如何处理数组表达式的工件; 在大多数情况下,类型为"T [N]"的表达式转换为类型为"T*"的表达式,表达式的值为第一个元素的地址.因此,如果您编写了`str ="foo"`,您将尝试将"foo"`的第一个字符的地址分配给数组`str`,这不起作用.有关详细信息,请参阅[此答案](http://stackoverflow.com/questions/21391685/returning-a-two-dimensional-array-in-c/21​​393651#21393651).
@Slater:是的,如果它是`malloc`调用的结果.

3> mpen..:

确认!常量字符串:

const char *strings[] = {"one","two","three"};

如果我没记错的话.

哦,你想使用strcpy进行赋值,而不是使用=运算符.strcpy_s更安全,但它既不是C89也不是C99标准.

char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE]; 
strcpy(arr[0], "blah");

更新: 托马斯说strlcpy是要走的路.


它可以在C89和C99中使用.它是无论是const还是没有它都没关系,尽管前者是首选.
strcpy_s是一个Microsoft功能.应该避免它,因为它不符合标准C.
strcpy_s和其他"安全功能"标准化为ISO/IEC TR 24731(它是ISO发布的标准,因此不能在线免费获取;最新的草案是http://www.open-std.org/jtc1 /sc22/wg14/www/docs/n1225.pdf)

4> Faisal Vali..:

以下是您的一些选择:

char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" };  // only since you brought up the syntax -

printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah

a2的优点是您可以使用字符串文字执行以下操作

a2[0] = "hmm";
a2[1] = "blah";

对于a3,您可以执行以下操作:

a3[0] = &"hmm";
a3[1] = &"blah";

对于a1,即使在分配字符串文字时也必须使用strcpy.原因是a2和a3是指针数组,你可以使它们的元素(即指针)指向任何存储,而a1是"字符数组"的数组,所以每个元素都是一个"拥有"它的数组自己的存储(这意味着当它超出范围时会被销毁) - 你只能将东西复制到它的存储中.

这也使我们处于使用a2和a3的缺点 - 因为它们指向静态存储(存储字符串文字),如果要分配非字符串文字,则其内容无法可靠地更改(即未定义的行为)对于a2或a3的元素 - 首先必须动态分配足够的内存,然后让它们的元素指向这个内存,然后将字符复制到其中 - 然后你必须确保在完成后释放内存.

Bah - 我已经错过了C++;)

ps如果您需要示例,请告诉我.



5> FutureSci..:

或者你可以声明一个结构类型,它包含一个字符arry(1个字符串),它们创建一个结构数组,从而创建一个多元素数组

typedef struct name
{
   char name[100]; // 100 character array
}name;

main()
{
   name yourString[10]; // 10 strings
   printf("Enter something\n:);
   scanf("%s",yourString[0].name);
   scanf("%s",yourString[1].name);
   // maybe put a for loop and a few print ststements to simplify code
   // this is just for example 
 }

与其他任何方法相比,这样做的一个优点是,它允许您直接扫描到字符串而无需使用strcpy;



6> Noldorin..:

在ANSI C中:

char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";


@Noldorin`char*foo,bar;``bar`的类型是什么?
对于其他读这篇文章的人,我想指出Bjarne Stroustrup按类型排列*
@Zifre:我完全不同意.它非常属于类型 - 在这种情况下是"char指针".无论如何你会说什么......它是变量名称的一部分?我见过许多有能力的程序员使用这种风格.
C由Dennis Ritchie于1972年开发,1988年他和Brian Kernighan发表了第二版K&R - C编程语言,这本书很多都是C语言的事实标准.他们把*放在标识符上.

7> dmckee..:

字符串文字是const char *s.

你使用括号是奇怪的.你可能意味着

const char *a[2] = {"blah", "hmm"};

它声明了一个指向常量字符的两个指针的数组,并将它们初始化为指向两个硬编码的字符串常量.



8> Sergey..:

如果您不想跟踪数组中的字符串数并希望迭代它们,只需在最后添加NULL字符串:

char *strings[]={ "one", "two", "three", NULL };

int i=0;
while(strings[i]) {
  printf("%s\n", strings[i]);
  //do something
  i++;
};


不知道:)如果你愿意,可以在while语句中与NULL进行比较.

9> Bryce..:

如果字符串是静态的,那么你最好用:

const char *my_array[] = {"eenie","meenie","miney"};

虽然不是基本ANSI C的一部分,但您的环境很可能支持语法.这些字符串是不可变的(只读),因此在许多环境中使用比动态构建字符串数组更少的开销.

例如,在小型微控制器项目中,此语法使用程序存储器而不是(通常)更珍贵的RAM内存.AVR-C是支持此语法的示例环境,但大多数其他语法也是如此.

推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有