【问题标题】:Can't print char** outside of getline() while loop无法在 getline() while 循环之外打印 char**
【发布时间】:2018-10-17 02:45:40
【问题描述】:

尝试使用 getline() 从命令行参数读取文件并存储到 char** 中,但是当我尝试使用 printf() 访问内部数据时,它什么也没打印。尽管 printf() 在每个 getline() 之后的 while 循环中都能正常工作。

非常感谢任何帮助!

int main (int argc, char* argv[])
{
    //open file
    FILE *stream = NULL;
    char *line = NULL;
    size_t len = 0;
    ssize_t nread;
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    stream = fopen(argv[1], "r");
    if (stream == NULL)
    {
        perror("fopen");
        exit(EXIT_FAILURE);
    }

    //read file line by line
    char ** input = NULL;
    int i = 0;
    int j = 0;
    while ((nread = getline(&line, &len, stream)) != -1)
    {
        j++;
        input = (char **)realloc(input, sizeof(char*) * j);
        input[i] = (char *)malloc(sizeof(char) * strlen(line));
        input[i] = line;

        //print each line (PRINTS FINE)
        printf("%s",input[i]);
        i++;
    }

    //print each line outside of while loop (PRINTS NOTHING)
    for (int z = 0; z < j ; z++)
    {
        printf("%s",input[z]);
    }
}

欢迎尝试任何这样的 .txt 文件

./a.out input.txt

【问题讨论】:

  • 已编辑以增加 j,仍然不打印任何内容
  • OT:当调用任何堆分配函数时:malloccallocrealloc, 1) 始终检查 (!=NULL) 返回值以确保操作成功。 2)返回的类型是void*,可以分配给任何指针。强制转换只会使代码混乱,使其更难以理解、调试等
  • input[i] = line; 没有意义,你删除了你之前的分配!
  • 关于:input[i] = line; 在下一次调用 getline() 之后,char * 将指向不再属于您的程序的内存。建议:strcpy( input[i], line);
  • 感谢您的提示!使用 strcpy(input[i], line) 似乎可以解决问题!

标签: c string pointers malloc double-pointer


【解决方案1】:

您的问题不是打印。它在读取和存储中。

  1. sizeof(char) * strlen(line) 必须是 sizeof(char) * (strlen(line) + 1)(您没有为 NULL 终止符分配空间)。事实上,(strlen(line) + 1) 就足够了(参见@user3629249 的评论),甚至(len + 1)(因为len 保存了读取字符串的长度)。

  2. input[i] = line; 不会创建字符串的副本。您必须使用strcpy(input[i], line);

  3. 最后,你必须在最后free(line)

【讨论】:

  • 谢谢,使用 strcpy(input[i],line) 解决了这个问题! :D
  • 表达式:sizeof( char ) 在 C 标准中定义为 1。任何东西乘以 1 都没有效果(只会使代码混乱)
  • @user3629249 我知道并同意,但这也无妨。
  • 实际上,这种无用的代码确实很痛苦。它使代码更难理解、调试等
  • “最后,你必须在每次迭代结束时释放(line)并将其设置为NULL。否则,getline可能无法分配足够的空间,你会发生内存泄漏。”什么 ? getline 的目的不是每次都释放行,而只是在解析结束时!
猜你喜欢
  • 1970-01-01
  • 2016-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 2015-03-19
相关资源
最近更新 更多