字符串[,]在C中等价的字符串数组的数组

本文关键字:字符串 数组 | 更新日期: 2023-09-27 18:29:18

在C#中,如果我要创建一个字符串数组数组,这很容易:

string[,] array = new string[50,7];

我该如何在C中做到这一点?我确实理解我应该利用指针,但我所想出的似乎并不奏效。

char *array[50][7];

请注意,我不想将元素设置为常数值,我需要能够通过使用scanf()函数或简单地使用=(如果可能)在程序中再次访问/设置它们。实现这一目标的最简单方法是什么?

编辑:我是不是做错什么了?以下非常简单的例子使程序崩溃:

char *username;
printf("Username: ");
scanf("%s", &username);
array[0][0] = malloc(strlen(username) + 1);
strcpy(array[0][0], username);

事实上,我已经添加了对stdlib.h 的引用

字符串[,]在C中等价的字符串数组的数组

没有简单的方法:)由于C没有高级字符串类,至少在不调用一些非标准库的情况下没有。

为了灵活起见,您确实需要一个指针char *array[50][7];的2D数组,其中每个指针都设置为指向实际字符串。在创建一个字符串时,您必须通过使用malloc()来分配足够的内存来容纳它,再加上null终止符。例如:

array[x][y] = malloc(strlen(the_string) + 1);
assert(array[x][y] != NULL);

使用=赋值运算符无法复制C中的字符串,因此在分配内存后,必须使用strcpy将字符串复制到分配的内存区域。

strcpy(array[x][y], the_string);

以下代码崩溃,因为代码试图将scanf()输入保存到username指向的位置,但username未初始化。

char *username;
scanf("%s", &username);  // bad

相反,可以使用

char username[100];
scanf("%99s", username);

或者更好的

char username[100];
fgets(username, sizeof username, stdin);
username[strcspn(username, "'n")] = ''0';  // lop off potential 'n

OP似乎想要一个50 x 7的指针数组,指向像string[,] array = new string[50,7]; 中那样分配的C字符串

回想一下,在C中,字符串本身就是一个以空字符结尾的字符数组

#include <stdlib.h>
typedef char *a50_7_T[50][7];
a50_7_T *a50_7_alloc(void) {
  a50_7_T *a = malloc(sizeof *a);
  for (int i=0; i<50; i++) {
    for (int j=0; j<7; j++) {
      (*a)[i][j] = NULL;  // or whatever OP wants as initial state
    }
  }
  return a;
}
void a50_7_free(a50_7_T *a) {
  for (int i=0; i<50; i++) {
    for (int j=0; j<7; j++) {
      free((*a)[i][j]);
    }
  }
  free(a);
}
// Sample usage code
#include <string.h>
void foo(void) {
  a50_7_T *a = a50_7_alloc();
  printf("Size %zu'n", sizeof *a);   // e.g. "Size 1400"
  (*a)[0][0] = strcpy(malloc(6), "Hello");
  a50_7_free(a);
}

OTOH如果OP想创建数组作为声明的一部分,那么OP的做法是正确的。

//                   Initialize all to zeros, (NULL)
char *array[50][7] = { 0 };
...
array[0][0] = strcpy(malloc(6), "Hello");
...
free(array[0][0]);

数组就是这样。问题可能来自字符串。C字符串是非常低级的,不能真正与C#字符串相比较。您将不得不手动为它们分配和取消分配空间。如果计划在它们上使用scanf,可以为每个字符串分配一个缓冲区,但如果发现字符串比缓冲区长,则会出现问题。您可以用"="分配它们,但前提是您处理旧值的解除分配。也许你可以去"glib"之类的图书馆帮你做一些工作。

好吧,在C#根本不给你选择的情况下,你必须决定两件事(或者至少,强烈建议使用标准的):

  1. 您希望如何表示您的二维数组?

    您可以在之间进行选择

    • 一维数组和显式指针算法
    • 指向具有一个固定维度的二维数组的指针
    • 指向指向一维数组的指针的一维数组的一个指针
  2. 你想如何表示你的字符串?

    • 决定代码单元:char(希望是8位)、wchar16_twchar32_twchar_t
    • 计数字符串还是0终止
    • 在固定大小的缓冲区中还是动态分配