0
votes

I am trying to write a simple C program that loads a text-file, prints the first line to screen, waits for the user to press enter and then prints the next line, and so on.

As only argument it accepts a text-file that is loaded as a stream "database". I use the getline()-function for this, according to this example. It compiles fine, successfully loads the text-file, but the program never enters the while-loop and then exits.

#include <stdio.h>
#include <stdlib.h>

FILE *database = NULL; // input file

int main(int argc, char *argv[])
{
    /* assuming the user obeyed syntax and gave input-file as first argument*/  
    char *input = argv[1];

    /* Initializing input/database file */
    database = fopen(input, "r");
    if(database == NULL)
    {
        fprintf(stderr, "Something went wrong with reading the database/input file. Does it exist?\n");
        exit(EXIT_FAILURE);
    }

    printf("INFO: database file %s loaded.\n", input);

    /* Crucial part printing line after line */
    char *line = NULL;
    size_t len = 0;
    ssize_t read;

    while((read = getline(&line, &len, database)) != -1)
    {
        printf("INFO: Retrieved line of length %zu :\n", read);
        printf("%s \n", line);
        char confirm; // wait for user keystroke to proceed
        scanf("%c", &confirm);
        // no need to do anything with "confirm"
    }

    /* tidy up */
    free(line);
    fclose(database);
    exit(EXIT_SUCCESS);
}

I tried it with fgets() -- I can also post that code --, but same thing there: it never enters the while-loop.

It might be something very obvious; I am new to programming.

I use the gcc-compiler on Kali Linux.

2
What does a debugger tell you when you step through the code? - Ken White
Thank you for your answers; I found my mistake. This is really embarrassing, because the code works, only my text-file somehow got eaten up; maybe I did not close it properly and all its content got deleted, so of course the value of getline() was EOF/-1. - c2ethanol
I would also check return of scanf() here, - RoadRunner
My idea with this scanf() was to wait for the user to press enter before proceeding to print the next line. Probably that is no good style... - c2ethanol
Note that when reporting an error about being unable to open a file (especially if the message asks if it exists), you should include the file name in the message. The user may be confused about the meaning of arguments and have provided --help or something, and to be told that some file doesn't exist isn't a help, but being told "failed to open file '--help' for reading; does it exist?\n" would be a lot more meaningful. - Jonathan Leffler

2 Answers

1
votes

Change your scanf with fgetline using stdin as your file parameter.

1
votes

You should step through this in a debugger, to make sure your claim that it never enters the while loop is correct.

If it truly never enters the while loop, it is necessarily because getline() has returned -1. Either the file is truly empty, or you have an error reading the file.

man getline says:

On success, getline() and getdelim() return the number of characters read, including the delimiter character, but not including the termi‐ nating null byte ('\0'). This value can be used to handle embedded null bytes in the line read.

Both functions return -1 on failure to read a line (including end-of- file condition). In the event of an error, errno is set to indicate the cause.

Therefore, you should enhance your code to check for stream errors and deal with errno -- you should do this even when your code works, because EOF is not the only reason for the function to return -1.

  int len = getline(&line, &len, database);
  if(len == -1 && ferror(database)) {
        perror("Error reading database");
  }

You can write more detailed code to deal with errno in more explicit ways.

Unfortunately handling this thoroughly can make your code a bit more verbose -- welcome to C!