Home > Enterprise >  Broken fgets input when underflow in C
Broken fgets input when underflow in C

Time:11-29

I'm trying to make a string reverse program. I'm trying to fix bugs with over/underflow. I fixed the first one, so now I've set MAX = 8 just to make it easier to debug. It works correctly. But when my input is shorter than MAX, the program breaks down.

enter image description here

So, as you can see, the string "QWERTY ASDFGH" is cut correctly and I have "QWERTY A" (which is exactly 8 characters), then the program reverses it and the output is "A YTREWQ". It does exactly what I want.

But if the actual length is less then 8, I press enter, and nothing happens. I have to press it twice and still have this broken input and output. The output goes to a new line, but it's not how it has to work.

There's my source code:

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define MAX 8 // not including '\0' symbol

void printAsterisks(uint8_t);
void clearInputBuffer(void);

int main(void) {

    char word[MAX   1], temp;
    int length, index;

    printAsterisks(46);
    printf("Please, type in any string. To exit give me #.\n");
    printAsterisks(46);

    while(1) {
        index = 0;
        printf("Your string : "); 

        fgets(word, MAX   1, stdin);
            
        if(word[0] == '#') {
                printAsterisks(39);
                printf("The program has been cancelled by User.\n");
                printAsterisks(39);
                break;
        }

        clearInputBuffer();

        length = strlen(word);
            
        for(index = 0; index < length / 2; index  ) {
                temp = word[index];
                word[index] = word[length - index - 1];
                word[length - index - 1] = temp;
        }

        printf("Reversed    : %s\n", word);
    }

    return 0;
}

void printAsterisks(uint8_t count) {
    for(uint8_t i = 0; i < count; i  ) {
            printf("*");
    }
    printf("\n");
}

void clearInputBuffer(void) {
    static char buff;
    while((buff = getchar()) != '\n' && buff != EOF);
}

CodePudding user response:

The problem is your attempt to flush the input buffer.

The fgets call reads and includes the newline in the buffer, if it fits.

When you enter less than MAX characters the fgets call will read the newline, but you still call clearInputBuffer which will attempt to read until the next newline.

You need to check if the buffer word includes the newline or not, and only call clearInputBuffer if there's no newline in it.

You can use the strcspn function to check for the newline, as well as use its returned position to set the null-terminator to "remove" the newline from the buffer:

size_t newline_pos = strcspn(word, "\n");
if (word[newline_pos] == '\n')
{
    // There's a newline in the input, remove it
    word[newline_pos] = '\0';
}
else
{
    // There's no newline, skip the remainder of the line
    clearInputBuffer();
}

CodePudding user response:

As @Some programmer dude said, the clearInputBuffer function was invalid, and I changed it a little bit. I assume you meant it to clear word. I also made word and temp global, and called clearInputBuffer after instead of before parsing the string and reversing it.

#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define MAX 8 // not including '\0' symbol

char word[MAX   1], temp;

void printAsterisks(uint8_t);
void clearInputBuffer(void);

int main(void) {
    int length, index;

    printAsterisks(46);
    printf("Please, type in any string. To exit give me #.\n");
    printAsterisks(46);

    while(1) {
        index = 0;
        

        fgets(word, MAX   1, stdin);
        
        if(word[0] == '#') {
                printAsterisks(39);
                printf("The program has been cancelled by User.\n");
                printAsterisks(39);
                break;
        }
        
        length = strlen(word);
        
        for(index = 0; index < length / 2; index  ) {
                temp = word[index];
                word[index] = word[length - index - 1];
                word[length - index - 1] = temp;
        }

        printf("Reversed    : %s\n", word);

        clearInputBuffer();
    }

    return 0;
}

void printAsterisks(uint8_t count) {
    for(uint8_t i = 0; i < count; i  ) {
            printf("*");
    }
    printf("\n");
}

void clearInputBuffer() {
    int i;
    for (i = 0; word[i] != '\0'; i   ) {
        word[i] = '\0';
    }
}

  • Related