【问题标题】:Initializing two dimensional string dynamic array and passing by reference初始化二维字符串动态数组并通过引用传递
【发布时间】:2021-12-27 16:23:51
【问题描述】:

我正在尝试学习 C 指针传递。所以请原谅我的无知。

我想在函数中分配一个二维动态分配的字符串数组。 函数签名是无效的,所以参数是引用的。

测试文件包含这两行。

I am testing.
This is not an empty file.

这是我到目前为止所做的。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void read_lines(FILE *fp, char** lines, int *num_lines) {
  ssize_t read;
  char * line = NULL;
  size_t len = 0;
  *num_lines = 0;


  while ((read = getline(&line, &len, fp)) != -1) {
    if (*num_lines == 0) {
      // For the first time it holds only one char pointer
      *lines = malloc(sizeof(char *));
    } else {
      // Every time a line is read, space for next pointer is allocated
      *lines = realloc(*lines, (*num_lines) * sizeof(char *));
    }
    // allocate space where the current line can be stored
    *(lines + (*num_lines)) = malloc(len * sizeof(char));
    // Copy data
    strcpy(*(lines + (*num_lines)), line);
    printf("Retrieved line of length %zu:\n", read);
    printf("%s\n", line);
    (*num_lines)++;
    // After first line subsequent lines get truncated if I free
    // the storage here, then subsequent lines are not read completely
    //if (line) {
    //  free(line);
    //}
  }  
  if (line) {
    free(line);
  }

}
int main(void)
{
    FILE * fp;
    char *array;
    int num_lines;
    fp = fopen("file.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);
    read_lines(fp, &array, &num_lines);
    printf("After returning\n");
    // Intend to access as array[0], array[1] etc
    // That's not working
    // If I access this way then I get seg violation after first line
    printf("%s\n", &array[0]);
    fclose(fp);
}

我的问题与代码一致:

  • 为什么我不能在 while 循环中为 line 释放存储空间?
  • 如何访问main 中返回的二维数组? array[0] array[1] 似乎不起作用?我想做类似的事情。
  • 为什么我现在这样做会产生段错误?

更正的代码将帮助我理解。此外,任何人都可以提供任何好的参考来澄清 C 的这些概念,我们将不胜感激。

【问题讨论】:

  • line 在第一个 *line = ... 上为 NULL。期待问题!

标签: arrays c pointers memory


【解决方案1】:

如果您在 while 循环中 free(line),则必须在下一次调用 getline 之前将 line 重置为 NULL 并将 len 重置为 0。否则,getline 会认为line 是大小为len 的有效缓冲区,并可能会尝试写入它,这实际上是现在所谓的“悬空指针”。

realloc 行中,大小应为(*num_lines + 1) * sizeof(char *),需要再分配一个元素来容纳刚刚读取的行。

array变量是char*,它的地址被分配给read_lines的参数lines。所以linesarray的地址,而*lines就是array本身。

但是

// allocate `char*[1]`
*lines = malloc(sizeof(char *));

// allocate `char*[N]` with N=`*num_lines`
*lines = realloc(*lines, (*num_lines) * sizeof(char *));

您将char*[] 分配给array,实际上是char*

因此,如果您希望函数通过参数返回一个字符串数组(即char*[]char**),则必须使参数成为指向字符串数组(即char***)的指针。

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

void read_lines(FILE * fp, char*** lines, int* num_lines) {
    ssize_t read;
    char* buffer = NULL;
    size_t buffer_len = 0;
    *num_lines = 0;

    while ((read = getline(&buffer, &buffer_len, fp)) != -1) {
        // `*lines` is actually `array`,
        // modify `*lines` will effectively modify `array`
        if (*num_lines == 0) {
            // `array` now is `char*[1]`
            *lines = (char**)malloc(sizeof(char*)); // A
        }
        else {
            // `array` now is `char*[(*num_lines) + 1]`
            *lines = (char**)realloc(*lines, (*num_lines + 1) * sizeof(char*)); // B
        }

        // *(x+n) is the same as x[n], this line is actually doing:
        // `array[*num_lines] = malloc...
        *(*lines + (*num_lines)) = (char*)malloc((read + 1) * sizeof(char)); // C
        strcpy(*(*lines + (*num_lines)), buffer);
        (*num_lines)++;

        printf("Retrieved line of length %zu:\n", read);
        printf("%s\n", buffer);
    }
    if (buffer) {
        // `line` is `malloc`ed or `realloc`ed by `getline`,
        // have to be `free`ed
        free(buffer);
    }
}
int main(void)
{
    FILE* fp;
    char** array;
    int num_lines;
    fp = fopen("file.txt", "r");
    if (fp == NULL)
        exit(EXIT_FAILURE);
    read_lines(fp, &array, &num_lines);
    printf("After returning\n");
    for (int i = 0; i < *num_lines; i++) {
        printf("%s\n", array[i]);
        free(array[i]); // corresponding to C
    }
    free(array); // corresponding to A or B
    fclose(fp);
}

【讨论】:

    猜你喜欢
    • 2018-06-30
    • 2016-11-12
    • 2011-06-04
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 2017-01-04
    • 2014-05-14
    • 2010-10-06
    相关资源
    最近更新 更多