Home > Back-end >  C getline() read last line twice
C getline() read last line twice

Time:10-18

just wondering why my function getline() read the last line twice.

I'm supposed to read from a tsv file and print each line to stdout. But somehow keep reading the last row twice.

            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);

if a file looks like this

A B C
D E F

it prints

A B C
D E F
D E F

How do i fix it?

CodePudding user response:

You're actually skipping the first line.

Since you're reading from STDIN, what you type, there is no file. Your output and input are mixed up. We can see this by changing your printf to add a prefix 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: 

Your code is reading the first line, checking how long it is, and then reading the next line without printing the first. That's why you're missing the first line.

We get the extra blank print at the end because you're checking if you read anything from the previous line. Then you're reading and printing immediately without checking.

// 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);
}

Instead, read, check, and print.

#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);
    }
}

And we get interleaved inputs and outputs.

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

You don't need to store the line length, but if you did put parens around the assignment before you compare it. That ensures doing (line_size = getline(...)) > -1 not line_size = (getline(...) > -1). That is storing the return value of getline in line_size and then checking if it's -1. Not checking if getline returned -1 and storing the true/false result into line_size.

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

CodePudding user response:

Say getline returns -1 signifying EOF. What do you do next? You print. oops!

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);
}
  • Related