简体   繁体   中英

Handling EOF in user input

I am writing a small program that allows a user to input the dimensions m and n of a matrix and then to fill that matrix as to her liking. To read in the numbers I use fgets() to read the user input as a string and then convert it via strtol() . I also remove the newline fgets() appends via strcspn() and do some error handling when the user types in a , 12a or simply a newline \\n . But the program gives me headache with EOF input via Ctrl + D . I read several stackoverflow threads about this and I know that one needs to type in EOF two times in some cases. But when I send EOF to my first call to fgets() reading in the m -dimension I will be forwarded to the next call to fgets() which reads in the n -dimensions and from there on it will jump to the actual array input and there it seems stuck or I goes into an infinite loop. I do currently not know the cause and I do not know how to handle EOF in this scenario. I would be happy 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;
}

Wrong allocation size: m_row vs n_col . This may not be an EOF issue.

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 initializing m_row = 0; n_col = 0; m_row = 0; n_col = 0; instead.

Code attempts to print out arr even if arr was not fully populated due to EOF . Should avoid that.

If these do not fix the issue, suggest printing the m_row ands n_col prior to reading the elements to verify the matrix size is as expected.


Minor: Use same size integers

 // 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: "largest integer that can fit into unsigned long int is a 20-digit number" ... char save[20]; mis-leads. 1) pow(2,64) takes 20 char , but the input needs to account for '\\n' and '\\0' , so should use char save[20+2]; 2) unsigned long int could be larger than 64-bit - it must be at least 32-bit. But this is certainly not the main problem of this post.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM