Search code examples
carraysmemsetfflush

Array is not reseting correctly, when using memset


When I take a vale from stdin that is to large for c the reset is not behaving as expected. The user will be re-prompted to input the code but after inputing an additional new line is presented where input is needed, than the length check is failed.

void clear(void) {    
    while (getchar() != '\n')
        ;
}

int add_flight(code_t codes[], int lf) {
    char c[MAX_CODE_LEN + 1];
    int s = 0;
    while (s == 0) {
        printf("Enter code>\n");
        if (fgets(c, sizeof c, stdin)) {
            printf("%s", c);
            if ('\n' == c[0]) {
                printf("Invalid input\n");
            } else if (c[sizeof c - 1] == '\0' && c[sizeof c - 2] != '\n') {
                clear();
                printf("Invalid input\n");
                memset(c, 0, sizeof c);
            } else {
                strcpy(codes[lf].id, c);
                s = 1;
                break;
            }
        }
    }
    return 0;
}

Any help would be greatly appreciated.


Solution

  • There are several problems in your code:

    • the clear function does not test for end of file, causing an infinite loop if standard input is closed without a trailing newline, as would be the case when redirecting input from an empty file.
    • the test for overlong input lines is incorrect: the last character of the array is undefined if the input does not fill the array. You should test if strlen(c) == sizeof(c) - 1 after stripping the trailing newline.
    • c is a very confusing name for a char array. This name is commonly used for an int to receive a byte value. Name the array buf for better readability.
    • the memset is useless as you are going to read a new line into the array.
    • the definition of code_t is missing. If the size of its id member array is not at least MAX_CODE_LEN + 1, the behavior would be undefined.
    • Furthermore, you copy the trailing newline to codes[lf].id which is probably incorrect.
    • if id is defined to hold MAX_CODE_LEN characters, ie char id[MAX_CODE_LEN + 1]; for the extra null terminator, buf should have one extra byte for the newline typed by the user, hence char buf[MAX_CODE_LEN + 2];

    Here is a modified version:

    int clear(void) {
        int c;   
        while ((c = getchar()) != EOF && c != '\n')
            continue;
        return c;
    }
    
    int add_flight(code_t codes[], int lf) {
        char buf[MAX_CODE_LEN + 2];
    
        for (;;) {
            printf("Enter code>\n");
            if (fgets(buf, sizeof buf, stdin)) {
                printf("%s", buf);
                /* remove the trailing newline if present */
                size_t len = strlen(buf);
                if (len > 0 && buf[len - 1] == '\n')
                    buf[--len] = '\0';
                if (len == sizeof(buf) - 1) {
                    /* line too long: consume the rest of the input line */
                    printf("Invalid input\n");
                    if (clear() == EOF)
                        break;
                } else if (len == 0) {
                    /* empty line */
                    printf("Invalid input\n");
                } else {
                    strcpy(codes[lf].id, buf);
                    return 1;  // return success
                }
            } else {
                break;
            }
        }
        return 0;  // premature end of file: return failure
    }