Char **的用法和打印

9

在 C 语言中,我使用 char ** 来存储一系列字符串。

这是我的代码:

char ** c;
//now to fill c with data ????

//cannot change:
printf ("%*s%s", 0, "", *c);
while (*++w)
    printf (" %s", *c);

我不知道如何填充c的数据。什么是正确的方法?我不能更改这3个打印行,因为它们在一个外部函数中。


适当的方法取决于您想要放入其中的数据。您期望的输入和输出是什么? - Carl Norum
我已经找到了答案,但由于我是新用户,无法在8小时内回复:char ** c; int row = 3; int col = 10; c = calloc(row, sizeof (char[col])); c[0] = "cat\0"; c[1] = "dog\0"; c[2] = "mouse\0";//不能更改: printf ("%*s%s", 0, "", c); while (++w) printf (" %s", *c);free(c); - user1483511
3个回答

8
术语在这里非常重要。与高级语言中的容器对象不同,char **根本不“持有”一系列字符串。变量c只是一个指向字符指针的指针,而该字符将成为以空字符结尾的字符串中的第一个字符。
这种思路直接导致解决方案:如果c是指向字符指针的指针,那么我们必须分配一些内存来实际保存字符串数组。
@DB_Monkey在评论中发布的解决方案试图做到这一点,但并不完全正确,因为它意味着像c[0] =“cat”这样的代码会将“cat”复制到c[0]中,这并不是这样——赋值应用于指针,而不是字符串。更好的方法是:
int rows = 3;
char **c = calloc (rows,sizeof(char*));
c[0] = "cat";
c[1] = "dog";
c[2] = "mouse";

这也表明每个字符串的显式零终止并不是必需的。

4
您的字符**实际上是一个数字,该数字认为它是指向有效字符地址的数字地址...简而言之:
// I am a number that has undefined value, but I pretend to point to a character.
char *myCharPointer;
// | The statement below will access arbitrary memory
// |   (which will cause a crash if this memory is not allowed to be accessed).
char myChar = *myCharPointer; 

为了使用这个指针,你需要对它进行初始化。
char *myCharPointer = (char *)malloc(10 * sizeof(char));

现在,您可以像处理数组一样使用该指针,或者使用指针算术运算(如果需要的话)。
请注意,malloc不会将“数组”中的所有值都设置为0,它们的默认值是未定义的。
为了实现您想要的功能,您需要执行以下操作:
// I can store 10 "strings"
char **myArrayOfStrings = (char **)malloc(10 * sizeof(char *));
char *str0 = "Hello, world0";
char *str1 = "Hello, World1";
char *str2 = "Hello, World2";
char *str3 = "Hello, world3";
char *str4 = "Hello, world4";
char *str5 = "Hello, world5";
char *str6 = "Hello, world6";
char *str7 = "Hello, world7";
char *str8 = "Hello, world8";
char *str9 = "Hello, world9";
myArrayOfStrings[0] = str0;
myArrayOfStrings[1] = str1;
myArrayOfStrings[2] = str2;
myArrayOfStrings[3] = str3;
myArrayOfStrings[4] = str4;
myArrayOfStrings[5] = str5;
myArrayOfStrings[6] = str6;
myArrayOfStrings[7] = str7;
myArrayOfStrings[8] = str8;
myArrayOfStrings[9] = str9;
// the above is the same as
// *(myArrayOfStrings + 9) = str9

您不必要求任何字符串具有相同的长度, 假设 str [0 .. 9] 实际上是存储这些字符串第一个字符在内存中位置的地址的数字,例如

str0 = (char *)&9993039;
str1 = (char *)&9993089;

myArrayOfStrings实际上也是一个数字,它存储了第一个字符串位置的地址,特别地:myArrayOfStrings = (char **)&str0;

很显然,你不会像我展示的那样明确地这样做,但可以在运行时轻松执行此操作,只需将用户的字符串存储到缓冲区中,然后将其附加到列表中,希望它不会用完空间(有避免这种情况的技术)。

希望这能有所帮助。


2
你所拥有的是一个指向指针的指针,指向的是字符。这意味着你已经预留了足够的空间来引用可能(更多地是必须)是另一个指针的变量。在为这些字符预留空间之前,这并不允许你保存实际的字符。
因此,现在,你需要进行两步内存分配,以便在你的变量“c”中拥有你的字符或字符串(如果你愿意)。
你可以使用mallocsizeof和一个for循环来实现这一点。
首先,你需要为你的字符串向量分配空间(在C语言中,它们只是字符向量的向量,因此,实际上,你将为指向字符向量的指针向量分配空间)。
char **c = malloc(NUMBER_OF_STRINGS * sizeof(char*));

这会使您的变量c指向整数NUMBER_OF_STRINGS,指针指向char。
现在,您可以选择为字符串选择最大大小并分配所有所需的空间,也可以在每次需要放置新字符串时执行此操作:
/*All the space with MAX_STR= maximum string size*/
 for(i=0;i<NUMBER_OF_STRINGS;i++){
    c[i] = malloc(MAX_STR * sizeof(char));
 }

现在你可以将字符串复制到 c [i] 中,它保存有MAX_STR大小的字符串,甚至可以通过执行 c [i] [j] 来从字符串中获取实际的char,这会给你第i个字符串的第j个字符。
/*Alloc when you have the string*/
  while(fgets(buff, BUFFSIZE, stdin) != NULL){   //This is just an example of an input reading from the keyboard
       c[i] = malloc(strlen(buff) * sizeof(char));
       i++;
  }

我使用了函数strlen来获取buff(一个字符串)的大小。请查看string.h以获取有关字符串操作函数的信息。
所以我希望这解决了你的问题。还有一件事,在每次调用malloc之后,您应该检查malloc是否返回了NULL,如果返回NULL,则表示您已经用尽了进程虚拟内存。
希望这可以帮助到您。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接