【问题标题】:Tokenizing string from dynamic array into multiple lines in static 2D char array将动态数组中的字符串标记为静态二维字符数组中的多行
【发布时间】:2020-03-22 06:17:01
【问题描述】:

我有一个动态数组,其中包含一个包含“\n”字符的字符串,因此该字符串由多行组成。我正在尝试提取线条并将它们全部放入 2D char 数组中,但出现分段错误。

这是我的代码:

    char *input_lines = malloc(MAX_LINE_LEN*sizeof(char)); 
    input_lines = extractInput(MAX_LINE_LEN, input_file);
    char inputLines_counted[lineCount_input][MAX_LINE_LEN];


    char *t = strtok(input_lines, "\n");
    for(i = 0; i < lineCount_input; i++) {
        strcpy(inputLines_counted[i], t);
        // printf("%s\n", inputLines_counted[i]);
        t = strtok(NULL, "\n");
    }

创建动态数组后,我使用extractInput(MAX_LINE_LEN, input_file) 函数用包含多行的字符串填充input_lines 数组。

这里是提取函数:

char *extractInput(int len, FILE *file) {
    char tmp[len];
    char *pos;
    char *input_lines = malloc(len*sizeof(char)); 
    char *lines;
    while(fgets(tmp, len, file)) {
        // if((pos = strchr(tmp, '\n')) != NULL) {
        //     *pos = ' ';
        // }
        input_lines = realloc(input_lines, (strlen(input_lines) + len)*sizeof(char));
        strcat(input_lines, tmp);
    }
    return input_lines;
}

为什么会出现段错误?

【问题讨论】:

  • 计算 \n 之间的字符数,以确保 MAX_LINE_LEN 足够大并记住结尾 \0 需要空间
  • @AndersK 我的作业,最大行长是一个给定的值,我已经在代码中声明了它。
  • 是的,但 was 是您在 input_lines 中的实际长度
  • @AndersK 好吧,每行都会有所不同
  • 但我猜你检查了你没有显示的代码(extractInput)

标签: c arrays tokenize dynamic-arrays strtok


【解决方案1】:

函数调用

    input_lines = realloc(input_lines, (strlen(input_lines) + len)*sizeof(char));

如果可以的话,获取您当前分配的内存块并扩展它。你应该检查realloc的返回值,它可能会失败。

顺便说一句,当你在 C 中分配内存时,你总是需要为结尾的 \0 留出空间。

看看这个文件会发生什么

hello\n
world\n

第一个 fget 将 hello\n 读入 tmp。

你现在做 realloc 即使它是不必要的,input_lines 已经指向一个可以保存字符串的缓冲区

char *input_lines = malloc(MAX_LINE_LEN*sizeof(char)); 

现在使用你的 realloc

input_lines = realloc(input_lines, (strlen(input_lines) + len)*sizeof(char));

你做 strlen(input_lines) + len 所以你使缓冲区 strlen("hello\n") + len 长。

但您需要注意的重要一点是以下行

strcat(input_lines, tmp);

您还没有初始化 input_lines 所指向的内存,它可以包含任何甚至 \0 的内容,因此您的 strcat 可能会将字符串放在缓冲区中的任何位置并导致您描述的错误。

在分配缓冲区时,要么执行 memset,要么使用 calloc。

如果您使用 realloc,您应该跟踪已分配的总大小以及您使用了多少,然后再复制到缓冲区检查是否有足够的空间。如果不是,则向缓冲区添加一定数量的字节。

我还注意到您逐行读取文件,然后将这些行连接在一起,以便稍后使用 strtok 再次划分它们。返回一个行数组会更有效。

【讨论】:

  • 我的目标是尽可能将文件中的行和单词捕获到 2D 数组中,但我不允许声明足够大以容纳所有行/单词的静态 2D 数组,所以我需要用动态数组来解决这个问题。您可以在这里建议一种更简单的方法吗?
猜你喜欢
  • 2021-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-07-03
  • 2021-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多