【问题标题】:C getline() read last line twiceC getline() 读取最后一行两次
【发布时间】:2021-12-05 01:55:13
【问题描述】:

只是想知道为什么我的函数 getline() 读取最后一行两次。

我应该从 tsv 文件中读取并将每一行打印到标准输出。但不知何故,最后一行读了两遍。

            char *line = NULL;
            size_t line_buf_size = 0;
            ssize_t line_size;
            line_size = getline(&line, &line_buf_size, stdin);
            int row = 0;
    
            while (line_size >= 0)
            {
                row++;
                line_size = getline(&line, &line_buf_size, stdin);
                printf("%s", line);

如果文件看起来像这样

A B C
D E F

打印出来

A B C
D E F
D E F

我该如何解决?

【问题讨论】:

  • 想想当 getline 失败时你的代码会发生什么。它是否打印一些东西?

标签: c getline


【解决方案1】:

getline 返回 -1 表示 EOF。下一步你要怎么做?你打印。哎呀!

char *line = NULL;
size_t line_buf_size = 0;
int row = 0;

while ( getline(&line, &line_buf_size, stdin) >= 0 ) {
   ++row;
   printf("%s", line);
}

if (ferror(stdin)) {
   perror("getline");
   exit(1);
}

【讨论】:

  • @Schwern 我一直忘记它与 Perl 不同。固定。
【解决方案2】:

你实际上跳过了第一行。

由于您从 STDIN 读取,因此您键入的内容没有文件。您的输出和输入混淆了。我们可以通过更改您的 printf 添加前缀 printf("output: %s", line); 来看到这一点。

A B C   <-- this is your input echoed to the screen
D E F   <-- and this
output: D E F
output: 

您的代码正在读取第一行,检查它的长度,然后读取下一行而不打印第一行。这就是为什么你错过了第一行。

我们在最后得到了额外的空白打印,因为您正在检查您是否从 previous 行中读取了任何内容。然后您无需检查即可立即阅读和打印。

// Read the first line.
line_size = getline(&line, &line_buf_size, stdin);
int row = 0;

// Check if you read anything from the *previous* line.
while (line_size >= 0)
{
    row++;

    // Read the next line overwriting the first line.
    line_size = getline(&line, &line_buf_size, stdin);

    // Print the second and subsequent lines without first checking
    // if you read anything.
    printf("%s", line);
}

相反,阅读、检查和打印。

#include <stdio.h>

int main() {
    char *line = NULL;
    size_t line_buf_size = 0;
    int row = 0;

    // Read and check.
    while (getline(&line, &line_buf_size, stdin) > -1)
    {
        row++;
        // Print.
        printf("output: %s", line);
    }
}

我们得到交错的输入和输出。

A B C
output: A B C
D E F
output: D E F

您不需要存储行长度,但如果您在比较之前确实在分配周围放置了括号。这确保了 (line_size = getline(...)) &gt; -1 而不是 line_size = (getline(...) &gt; -1)。那就是将 getline 的返回值存储在 line_size 中,then 检查它是否为 -1。不检查 getline 是否返回 -1 并将真/假结果存储到 line_size。

    while((line_size = getline(&line, &line_buf_size, stdin)) > -1)

【讨论】:

  • 我故意跳过了第一行,第一行是标题行,我需要跳过标题行。
  • 谢谢,如果我在阅读时检查,最后一行将停止打印两次。
猜你喜欢
  • 2013-10-14
  • 1970-01-01
  • 2014-12-21
  • 2018-01-08
  • 1970-01-01
  • 2017-03-26
  • 2023-03-24
  • 1970-01-01
  • 2020-12-08
相关资源
最近更新 更多