C 将 Char* 的二维数组展平为一维
C Flatten 2-D Array of Char* to 1-D
假设我有以下代码:
char* array[1000]; // An array containing 1000 char*
// So, array[2] could be 'cat', array[400] could be 'space', etc.
现在,我如何将这个数组展平为一维?是否可以这样做使得 new_1D_array[2] 仍然是 'cat',new_1D_array[400] 仍然是 'space',等等?
您有一个 pointer-to-char
类型的一维数组,其中包含 1000 个这样的元素。就数组而言,它已经是一维的了,尽管它可以被解释为 "jagged 2D array"。如果你想把它转换成一个巨大的字符数组,你可以这样做,这需要计算你需要存储它的缓冲区的大小,然后展平数组。
请注意,如果您选择使用 malloc
而不是 calloc
,则必须手动将最后一个字符设置为 '[=15=]'
或 0
,以便最终结果是一个 NULL 分隔的 C 风格字符串,而不仅仅是一个字符数组,因为两者中的后者不适用于 C 字符串操作,而前者可以。
代码清单
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
const char* array[] = { "one", "two", "three", "four" };
size_t length = sizeof(array) / sizeof(char*);
int i;
int sum = 0;
int count = 0;
for (i=0; i<length; i++) {
printf("Element #%d - %s\n", i, array[i]);
sum += strlen(array[i]) + 1;
}
sum++; // Make room for terminating null character
char* buf;
if ((buf = calloc(sum, sizeof(char))) != NULL) {
for (i=0; i<length; i++) {
memcpy(buf+count, array[i], strlen(array[i]));
count += strlen(array[i]) + 1;
buf[count-1] = '#';
}
printf("Output Buffer: %s\n", buf);
printf("Buffer size:%d - String Length:%d\n", sum, strlen(buf));
free(buf);
buf = NULL;
}
return 0;
}
示例输出
Element #0 - one
Element #1 - two
Element #2 - three
Element #3 - four
Output Buffer: one#two#three#four#
Buffer size:20 - String Length:19
上面的答案让我大吃一惊,看起来不错,但我会在这里完成我的想法。
在这个版本中,flatArray 的每个第 11 个字节都将包含原始数组中字符串的开头,这使得从之前的字符串中找到原始字符串变得非常容易 - 即字符串索引 2 将从 2*11 == index 22
和字符串 400 将从 400 * 11 == index 4400
开始。这样,您就不需要遍历平面数组计数终止符来查找旧字符串。这样做的代价是平面阵列比原来的阵列占用更多的内存。
char* array[1000];
// Malloc new buffer
char *flatArray = malloc(length * 1100);
for(i=0; i<1000; i++)
{
strncpy(&flatArray[i * 11], array[i], 10);
flatArray[i * 11 + 10] = '[=10=]';
}
假设我有以下代码:
char* array[1000]; // An array containing 1000 char*
// So, array[2] could be 'cat', array[400] could be 'space', etc.
现在,我如何将这个数组展平为一维?是否可以这样做使得 new_1D_array[2] 仍然是 'cat',new_1D_array[400] 仍然是 'space',等等?
您有一个 pointer-to-char
类型的一维数组,其中包含 1000 个这样的元素。就数组而言,它已经是一维的了,尽管它可以被解释为 "jagged 2D array"。如果你想把它转换成一个巨大的字符数组,你可以这样做,这需要计算你需要存储它的缓冲区的大小,然后展平数组。
请注意,如果您选择使用 malloc
而不是 calloc
,则必须手动将最后一个字符设置为 '[=15=]'
或 0
,以便最终结果是一个 NULL 分隔的 C 风格字符串,而不仅仅是一个字符数组,因为两者中的后者不适用于 C 字符串操作,而前者可以。
代码清单
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
const char* array[] = { "one", "two", "three", "four" };
size_t length = sizeof(array) / sizeof(char*);
int i;
int sum = 0;
int count = 0;
for (i=0; i<length; i++) {
printf("Element #%d - %s\n", i, array[i]);
sum += strlen(array[i]) + 1;
}
sum++; // Make room for terminating null character
char* buf;
if ((buf = calloc(sum, sizeof(char))) != NULL) {
for (i=0; i<length; i++) {
memcpy(buf+count, array[i], strlen(array[i]));
count += strlen(array[i]) + 1;
buf[count-1] = '#';
}
printf("Output Buffer: %s\n", buf);
printf("Buffer size:%d - String Length:%d\n", sum, strlen(buf));
free(buf);
buf = NULL;
}
return 0;
}
示例输出
Element #0 - one
Element #1 - two
Element #2 - three
Element #3 - four
Output Buffer: one#two#three#four#
Buffer size:20 - String Length:19
上面的答案让我大吃一惊,看起来不错,但我会在这里完成我的想法。
在这个版本中,flatArray 的每个第 11 个字节都将包含原始数组中字符串的开头,这使得从之前的字符串中找到原始字符串变得非常容易 - 即字符串索引 2 将从 2*11 == index 22
和字符串 400 将从 400 * 11 == index 4400
开始。这样,您就不需要遍历平面数组计数终止符来查找旧字符串。这样做的代价是平面阵列比原来的阵列占用更多的内存。
char* array[1000];
// Malloc new buffer
char *flatArray = malloc(length * 1100);
for(i=0; i<1000; i++)
{
strncpy(&flatArray[i * 11], array[i], 10);
flatArray[i * 11 + 10] = '[=10=]';
}