EOF handling on user input

I am writing a small program that allows the user to enter dimensions m

and n

matrices and then fill that matrix to their liking. To read in numbers, I use fgets()

to read user input as a string and then convert it through strtol()

. I also remove the newline fgets()

adds through strcspn()

and does some error handling when the user enters a

, 12a

or just a newline \n

. But the program is giving me a headache when entering EOF

through Ctrl + D

. I have read several stackoverflow threads about this and I know that in some cases it needs to be entered EOF

twice. But when I post EOF

to my first call fgets()

reading inm

-size, I will be redirected to the next call fgets()

that reads in n

-dimensions and from there it will go to the actual input of the array and there it seems to be stuck, or I go into an infinite loop. I currently don't know the reason, and I don't know how to handle EOF

in this scenario. I would be glad if someone could give some hints. Here is the code:

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

int main(int argc, char *argv[]) {

    /* We use "m_row" and "n_col" to keep track of the matrix dimensions and "m"
     * and "n" to keep track of the size of dynamically allocated memory.  */
    unsigned long int m_row;
    unsigned long int n_col;
    unsigned long int element;

    /* Initializing at dummy value to silence compiler. */
    m_row = 1;
    n_col = 1;

    /* The largest integer that can fit into unsigned long int is a 20-digit 
     * number. */
    char save[20];
    char *ptr_save;
    printf("Enter number of rows:\n");
    if (fgets(save, sizeof(save), stdin) != NULL) {
        save[strcspn(save, "\n")] = 0;
        if (save[0] == '\0') {
            fprintf(stderr, "Wrong input\n");
            exit(EXIT_FAILURE);
        }

        m_row = strtol(save, &ptr_save, 10);

        if (*ptr_save != '\0') {
            fprintf(stderr, "Wrong input\n");
            exit(EXIT_FAILURE);
        }
    }

    printf("Enter number of columns:\n");
    if (fgets(save, sizeof(save), stdin) != NULL) {
        save[strcspn(save, "\n")] = 0;
        if (save[0] == '\0') {
            fprintf(stderr, "Wrong input\n");
            exit(EXIT_FAILURE);
        }

        n_col = strtol(save, &ptr_save, 10);

        if (*ptr_save != '\0') {
            fprintf(stderr, "Wrong input\n");
            exit(EXIT_FAILURE);
        }
    }

    errno = 0;
    unsigned long int **arr = calloc(m_row, sizeof(unsigned long int *));
    if (arr == NULL) {
            fprintf(stderr, "%s", strerror(errno));
            exit(EXIT_FAILURE);
    }


    int i;
    errno = 0;
    for(i = 0; i < m_row; i++) {
        arr[i] = calloc(m_row, sizeof(unsigned long int));
        if (arr[i] == NULL) {
                fprintf(stderr, "%s", strerror(errno));
                exit(EXIT_FAILURE);
        }

    }

    int j;
    for(i = 0; i < m_row; i++) {
        for(j = 0; j < n_col; j++) {
            if (fgets(save, sizeof(save), stdin) != NULL) {
                save[strcspn(save, "\n")] = 0;
                if (save[0] == '\0') {
                    fprintf(stderr, "Wrong input\n");
                    exit(EXIT_FAILURE);
                }

                element = strtol(save, &ptr_save, 10);

                if (*ptr_save != '\0') {
                    fprintf(stderr, "Wrong input\n");
                    exit(EXIT_FAILURE);
                }
                arr[i][j] = element;
            }
            printf("\n");
        }
    }

    for (i = 0; i < m_row; i++) {
        for(j = 0; j < n_col; j++) {
            printf("%lu\t", arr[i][j]);
        }
        printf("\n");
    }

    free(arr);
    return 0;
}

      

+3


source to share


1 answer


An incorrect allocation size: m_row

vs n_col

. This might not be a problem EOF

.

for (i = 0; i < m_row; i++) {
  // arr[i] = calloc(m_row, sizeof(unsigned long int));
  arr[i] = calloc(n_col, sizeof(unsigned long int));
}

      

Suggest initialize m_row = 0; n_col = 0;

instead.

The code tries to print arr

even if arr

it was not completely filled out due to EOF

. This should be avoided.

If that doesn't fix the problem, suggest printing m_row

ands n_col

before reading the elements to check the matrix size as expected.




Minor: use integers of the same size

 // Rather than 
 unsigned long int m_row;
 ...
 int i;
 for(i = 0; i < m_row; i++) {

 // Use same type: recommend `size_t`
 size_t m_row;
 ...
 size_t i;
 for(i = 0; i < m_row; i++) {

      

Minor: use strtoul()

with unsigned long

, not strtol()

.

Minor: The largest integer that can fit into an unsigned long int is a 20-digit number "... char save[20];

mis-leads. 1) pow(2,64)

takes 20 char

, but must be taken into account for input '\n'

and '\0'

therefore should be used char save[20+2];

2) unsigned long int

can be greater than 64- bit - it should be at least 32 bit, but this is certainly not the main problem of this post.

+2


source







All Articles