字符串[,]在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没有高级字符串类,至少在不调用一些非标准库的情况下没有。
为了灵活起见,您确实需要一个指针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#根本不给你选择的情况下,你必须决定两件事(或者至少,强烈建议使用标准的):
-
您希望如何表示您的二维数组?
您可以在之间进行选择
- 一维数组和显式指针算法
- 指向具有一个固定维度的二维数组的指针
- 指向指向一维数组的指针的一维数组的一个指针
-
你想如何表示你的字符串?
- 决定代码单元:
char
(希望是8位)、wchar16_t
、wchar32_t
、wchar_t
- 计数字符串还是0终止
- 在固定大小的缓冲区中还是动态分配
- 决定代码单元: