如何在C中制作动态大小的数组?

Rob*_*Rob 15 c arrays loops file multidimensional-array

我已经习惯了PHP,但我开始学习C.我正在尝试创建一个逐行读取文件并将每行存储到数组的程序.

到目前为止,我有一个逐行读取文件的程序,甚至可以打印每行,但现在我只需要将每行添加到数组中.

我昨晚的朋友告诉了我一些关于它的事.他说我必须在C中使用多维数组,所以基本上array[x][y].该[y]部分本身很简单,因为我知道每行的最大字节数.但是,我不知道该文件有多少.

我想我可以让它循环遍历文件,每次只增加一个整数并使用它,但我觉得可能有一种更简单的方法.

任何想法甚至暗示正确的方向?我感谢任何帮助.

pho*_*xis 12

要动态分配2D数组:

char **p;
int i, dim1, dim2;


/* Allocate the first dimension, which is actually a pointer to pointer to char   */
p = malloc (sizeof (char *) * dim1);

/* Then allocate each of the pointers allocated in previous step arrays of pointer to chars
 * within each of these arrays are chars
 */
for (i = 0; i < dim1; i++)
  {
    *(p + i) = malloc (sizeof (char) * dim2);
   /* or p[i] =  malloc (sizeof (char) * dim2); */
  }

 /* Do work */

/* Deallocate the allocated array. Start deallocation from the lowest level.
 * that is in the reverse order of which we did the allocation
 */
for (i = 0; i < dim1; i++)
{
  free (p[i]);
}
free (p);
Run Code Online (Sandbox Code Playgroud)

修改上面的方法.当您需要添加另一行时,请执行*(p + i) = malloc (sizeof (char) * dim2);并更新i.在这种情况下,您需要预测文件中由dim1变量指示的最大行数,我们p首次为其分配数组.这只会分配(sizeof (int *) * dim1)字节,因此比char p[dim1][dim2](在c99中)更好.

我认为还有另一种方式.在块中分配数组并在出现溢出时将它们链接起来.

struct _lines {
   char **line;
   int n;
   struct _lines *next;
} *file;

file = malloc (sizeof (struct _lines));
file->line = malloc (sizeof (char *) * LINE_MAX);
file->n = 0;
head = file;
Run Code Online (Sandbox Code Playgroud)

在此之后,第一个块就可以使用了.当你需要插入一行时,只需:

/* get line into buffer */
file.line[n] = malloc (sizeof (char) * (strlen (buffer) + 1));
n++;
Run Code Online (Sandbox Code Playgroud)

如果nLINE_MAX分配另一个块,并将其链接到了这里.

struct _lines *temp;

temp = malloc (sizeof (struct _lines));
temp->line = malloc (sizeof (char *) * LINE_MAX);
temp->n = 0;
file->next = temp;
file = file->next;
Run Code Online (Sandbox Code Playgroud)

像这样的东西.

当一个块n变为时0,取消分配它,并将当前块指针更新file为前一个块.您可以从开始单链表遍历并从一开始遍历或使用双链接.


Ada*_*eld 7

C中没有标准的可调整大小的数组类型.您必须自己实现它,或使用第三方库.这是一个简单的简单示例:

typedef struct int_array
{
    int *array;
    size_t length;
    size_t capacity;
} int_array;

void int_array_init(int_array *array)
{
    array->array = NULL;
    array->length = 0;
    array->capacity = 0;
}

void int_array_free(int_array *array)
{
    free(array->array);
    array->array = NULL;
    array->length = 0;
    array->capacity = 0;
}

void int_array_push_back(int_array *array, int value)
{
    if(array->length == array->capacity)
    {
        // Not enough space, reallocate.  Also, watch out for overflow.
        int new_capacity = array->capacity * 2;
        if(new_capacity > array->capacity && new_capacity < SIZE_T_MAX / sizeof(int))
        {
            int *new_array = realloc(array->array, new_capacity * sizeof(int));
            if(new_array != NULL)
            {
               array->array = new_array;
               array->capacity = new_capacity;
            }
            else
                ; // Handle out-of-memory
        }
        else
            ; // Handle overflow error
    }

    // Now that we have space, add the value to the array
    array->array[array->length] = value;
    array->length++;
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

int_array a;
int_array_init(&a);

int i;
for(i = 0; i < 10; i++)
    int_array_push_back(&a, i);
for(i = 0; i < a.length; i++)
    printf("a[%d] = %d\n", i, a.array[i]);

int_array_free(&a);
Run Code Online (Sandbox Code Playgroud)

当然,这仅适用于一系列ints.由于C没有模板,因此您必须将所有这些代码放在宏中,以用于每种不同类型的数组(或使用不同的预处理器,如GNU m4).或者,您可以使用一个通用数组容器,该容器使用void*指针(要求所有数组元素都是malloc'ed)或不透明的内存blob,这需要使用每个元素访问的转换和memcpy每个元素的获取/设置.

无论如何,它并不漂亮.二维阵列甚至更加丑陋.