如何在 C 中使用 POINTERS 创建一个二维字符数组?

How can I create a 2D array of chars with POINTERS in C?

我正在尝试创建一个程序,用户输入项目(行)的数量并为每个项目指定一个名称(scanf),最多 30 个字符。

我想用指针的指针创建这段代码,一旦我在 C 上学习它。

我在编写代码时遇到一些困难。

Draft of the 2D array.

代码片段:

PS: #define MAX 31


  char **items = NULL, *columns = NULL, name[MAX];
  int rows, aux_rows;

  printf("\nNumber of items:\n");
  scanf("%d", &rows);

  items = (char **) malloc(rows * sizeof(char*));

  for (aux_rows = 0; aux_rows < rows; aux_rows++){
    columns[aux_rows] = (char *) malloc(MAX * sizeof(char));
  }

  for (aux_rows = 0; aux_rows < rows; aux_rows++){
    printf("\nName of item %d:\n", (aux_rows + 1));
    scanf("%s", name);
    *items[aux_rows] = name;
  }

items 被分配而不是 columns。并使用strcpy复制字符。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 31

int main()
{
    char **items = NULL, *columns = NULL, name[MAX];
    int rows, aux_rows;

    printf("\nNumber of items:\n");
    scanf("%d", &rows);

    items = (char **)malloc(rows * sizeof(char *));

    for (aux_rows = 0; aux_rows < rows; aux_rows++)
    {
        items[aux_rows] = malloc(MAX * sizeof(char));
    }

    for (aux_rows = 0; aux_rows < rows; aux_rows++)
    {
        printf("\nName of item %d:\n", (aux_rows + 1));
        scanf("%s", name);
        strcpy(items[aux_rows], name);
    }
    return 0;
}
$ gcc array2d.c
$ ./a.out      

Number of items:
2

Name of item 1:
Hello 

Name of item 2:
World!
$ 
*items[aux_rows] = name;

有两点是错误的。

*[] 都取消引用它们的一元操作数。如果 itemschar **items[n]char **items[n]char

这会尝试将数组分配给每个缓冲区的第一个元素。

其次,不能通过赋值复制数组。使用 strcpy 将字符串从一个缓冲区复制到另一个缓冲区。

就是说,您可以直接将字符串读入 pre-allocated 缓冲区,并取消临时缓冲区。


这一行,

columns[aux_rows] = (char *) malloc(MAX * sizeof(char));

columns 应该是 items.


一些注意事项:

sizeof (char) 保证为 1。它的使用是多余的。

C中mallocshould not be castreturn

malloc 可能会失败。 scanf 可能会失败。您应该养成不忽略 return 值的习惯。

scanf("%s", ...) 等同于 dangerous as gets。至少,使用 field-width 说明符 来限制输入(应该是缓冲区的大小减一)。

char foo[128];
if (1 != scanf("%127s", foo))
    /* handle error */;

请注意,使用 %s 将输入限制为不包含任何空格。 scanf 通常是 terrible tool,考虑使用 fgets.

的基于行的方法

话虽如此,要使其合理安全的最小更改:

#include <stdio.h>
#include <stdlib.h>

#define MAX 31

void die(const char *msg)
{
    fprintf(stderr, "%s\n", msg);
    exit(EXIT_FAILURE);
}

int main(void)
{
    size_t rows;

    printf("Number of items: ");

    if (1 != scanf("%zu", &rows))
        die("Failed to read input.");

    char **items = malloc(sizeof *items * rows);

    if (!items)
        die("Failed to allocate memory.");


    for (size_t i = 0; i < rows; i++) {
        if (!(items[i] = malloc(MAX)))
            die("Failed to allocate row.");

        printf("Name of item %zu: ", i + 1);

        if (1 != scanf("%30s", items[i]))
            die("Failed to read item input.");
    }

    for (size_t i = 0; i < rows; i++) {
        puts(items[i]);
        free(items[i]);
    }
}