c - 在 C 中制作二维字符串数组

标签 c arrays character

我正在为我的 CS1 类(class)做一个项目,我遇到了一些我以前从未想过的事情。我知道 C 中的所有数组本质上都是指向数组第一个元素的指针,而字符串实际上只是一个字符数组。但是,对于我的作业,我们必须读入一个文件,文件的一部分如下:

Brad Tim Rick (more man names separated by spaces)
Lucy Angela Tina (more women names separated by spaces)

This is a short example, but what I have to do is extract the names and store them into two separate arrays, one for men and one for females.

I have never worked with something like this, so of course I am confused. This is what I am trying to do, and of course its not working... oh yeah, and I'm trying to store them in dynamic allocation. The only spec says that the names will never exceed 19 characters (should I say twenty to allow the '/0' at the end of the string to still be there no matter what?) How can I tell the compiler, "hey I want an array of strings, and each string can hold 19 characters + 1 for the "string trailer '/0' "? And then how do I access those through pointers?

char **mens_names, **womens_names;

mens_names = malloc(number_of_couples * sizeof(char[19]));
womens_names = malloc(number_of_couples * sizeof(char[19]));

if(mens_names == NULL){
printf("Malloc failed! Memory could not be allocated to variable mens_names.");
return -1;
}

int i;
for(i = 0; i < number_of_couples; i++){
    fscanf(input_file, "%s", &mens_names[i]);
}


if(womens_names == NULL){
    printf("Malloc failed! Memory could not be allocated to variable womens_names.");
    return -1;
}

for(i = 0; i < number_of_couples; i++){
    fscanf(input_file, "%s", &womens_names[i]);
}

for(i = 0; i < number_of_couples; i++){
    printf("Man: %s ", mens_names[i]);
    printf("Woman: %s\n", womens_names[i]);
}

最佳答案

I know at all arrays in C are essentially pointer to the first element of an array

不完全是。数组和指针是完全不同的两个东西。除非它是 sizeof_Alignof 或一元 & 运算符的操作数,或者是用于初始化数组的字符串文字声明,类型为“T 的 N 元素数组”的表达式将被转换为“指向的指针”类型的表达式T”,它的值将是数组中第一个元素的地址。

给出声明

int a[10];

a 指定的对象 永远是 int 的 10 元素数组;但是,表达式 a 可能被视为指向第一个元素的指针。

如果您知道您的字符串的长度永远不会超过 19 个字符(包括终止符在内的 20 个元素),但事先不知道字符串的数量,您可以这样做:

char (*mens_names)[20];
char (*womens_names)[20];
...
mens_names = malloc(number_of_couples * sizeof *mens_names);
womens_names = malloc(number_of_couples * sizeof *womens_names);
...
fscanf(input_file, "%s", mens_names[i]);
...
free(mens_names);
free(womens_names);

在这种情况下,我们已将 mens_nameswomens_names 声明为指向 20 个元素的 char 数组的指针(括号很重要)。因此,sizeof *mens_names 等同于 sizeof (char [20])

您将像使用常规二维数组一样访问每个单独的字符:

char x = mens_names[i][j];

mens_names[i] 隐式取消引用 mens_names 指针(记住表达式 a[i] 被解释为 *( a + i)).

与 KBart 的方法相比,此方法有几个优点。首先,所有内存都作为一个 block 连续分配,如果缓存成为问题,这可能很重要。其次,每个数组只需要一个 malloc 和一个 free。当然,这假设每个名称数组的最大大小 a) 是固定的并且 b) 在编译时已知。

如果您直到运行时才知道名称的大小,并且您使用的是支持可变长度数组的 C99 编译器或 C2011 编译器,您可以这样做:

size_t name_len, number_of_couples;
// get name_len from the user or input file
// get number_of_couples
char (*mens_names)[name_len+1] = malloc(number_of_couples * sizeof *mens_names);
...

如果您直到运行时才知道名称的大小,并且您使用的编译器 支持 VLA,那么您将需要使用 KBart 的方法。

如果您想真正花哨,可以使用单个 3 维数组而不是两个 2 维数组:

#define MENS_NAMES 0
#define WOMENS_NAMES 1
...
char (*all_names)[2][20] = malloc(number_of_couples * sizeof *all_names);
...
fscanf(input_file, "%s", all_names[i][MENS_NAMES]);
...
free(all_names);

关于c - 在 C 中制作二维字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14583144/

相关文章:

c - 发生错误时如何在makefile中同时退出并记录文件中的数据

c - 为什么要定义一个函数原型(prototype),然后定义一个同名的预处理器宏?

改变矩阵列并得到所有元素都相等的子矩阵的行数

c - C语言数组计算时如何打印带符号的结果

javascript - 正则表达式模式不只验证一个字符

php - 如何在 php 中检查字符串是否包含 { 和 } 等特殊字符

c - tsp 使用动态规划

c - C 中的哪些对象声明导致存储被保留(即定义)?

arrays - 从 cURL 结果访问项目列表

jquery - 根据字符数动态更改字体大小