0

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);
}
  • 1
    Please don't show images of text, copy-paste text *as text* into your question. That includes output from your programs. – Some programmer dude Nov 28 '21 at 17:14
  • 2
    Your `clearInputBuffer` function is invalid. The [`getchar`](https://en.cppreference.com/w/c/io/getchar) function returns an **`int`** which is rather important for the comparison agains the `int` value `EOF`. – Some programmer dude Nov 28 '21 at 17:17
  • and `buff` doesn't need to be `static` in that function, `int buff` will do. – Weather Vane Nov 28 '21 at 17:19
  • Don't forget that `fgets()` retains the newline (if there is one, and if there is room). So you need to [remove that](https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input/28462221#28462221) before reversing the string, or otherwise take account of it. – Weather Vane Nov 28 '21 at 17:22
  • @WeatherVane I made it static to avoid unnecessary memory leaks. Cause it just creates a new variable every time I call this function and it also allocates new piece of memory what I don't want to happen. – George Glebov Nov 28 '21 at 21:38
  • @GeorgeGlebov the local variable is allocated on the stack and removed automatically at the end of the function. There is no memory leak. – Weather Vane Nov 28 '21 at 21:39
  • You can still edit your question to remove the picture of text and add the plain text. You wouldn't even need to include all the unused space on the screen but only the relevant text. – Gerhardh Nov 29 '21 at 11:21

2 Answers2

2

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:

// strcspn will return the beginning index of the sub-string you search for
// Or the index of the null-terminator if the sub-string wasn't found
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();
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • THANK YOU. There was really a huge gap in my logic. So, I've done what you said and now it works absolutely correctly. I understand now why trying to flush the input when my enter is less than MAX is absurd and absolutely nonsense. Thanks for this clear explanation dude. I haven't learned yet so I had no chance to come up with the idea of using strcspn(). – George Glebov Nov 28 '21 at 21:11
1

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';
    }
}

user1280483
  • 470
  • 4
  • 11