Clear fgets buffer

118 Views Asked by At

i have an issue with my code.

int startProg()
{
    char *method;
    method= malloc(30*sizeof(char));
    int isInteger=0;
    int num;
    do{

        printf("Seleziona il metodo \n");
        fgets(method,30,stdin);

        //it must be nothing more than 1 char inside 
        if (method[1]!= 10)
        {
            printf("Insert just one char  \n");
        }else{

            if (method[0]>='1'&&method[0]<='4'){

                 switch (method[0]){
                    case '1':
                        num=1;
                        break;
                    case '2':
                        num=2;
                        break;
                    case '3':
                        num=3;
                        break;
                    case '4':
                        num=4;        
                        break;
                }
                isInteger=1;
                //check the option choose
            }else{
                printf("Inserire un carattere valido\n");
            }
        }
    }while(isInteger==0);
    free (method);
    return num;
}

//terminal output
Seleziona il metodo 
123456789123456789123456781345646       
Inserire solo un carattere  
Seleziona il metodo 
Inserire solo un carattere  
Seleziona il metodo 

The idea is to recive a user input, check if is a number between 1 and 4, check witch value is and then return the value. The only issue is that when i insert a value with more than 30 digit. I have to clean the buffer and i need my code to be portable. Anyone as an idea? thanks

3

There are 3 best solutions below

3
pmg On

I think you want to clear all characters till the end of line if input was larger than the buffer reserved for fgets()

So, detect if that was the case

    if (!fgets(method, 30, stdin)) exit(EXIT_FAILURE);
    size_t len = strlen(method);
    if (len == 0) exit(EXIT_FAILURE); // input with '\0'????
    if (method[len - 1] != '\n') {
        // there is still data from the line in the input buffer
        clearEOL();
    }

and you can implement clearEOL() as one of these examples:

void clearEOL(void) {
    int ch;
    do {
        ch = getchar();
    } while ((ch != '\n') && (ch != EOF));
}

Some people may prefer a for loop :-)

void clearEOL(void) {
    for (int ch = getchar(); (ch != '\n') && (ch != EOF); ch = getchar()) /* void */;
}

or even an infinite loop with break inside

void clearEOL(void) {
    for (;;) {
        int ch = getchar();
        if (ch == '\n') break;
        if (ch == EOF) break;
    }
}
6
Anthony C Howe On

You're allocating an unnecessary buffer for a single character input. Also you should handle EOF (^D from terminal) in the event there is no more input. This code takes advantage of the ASCII property where the digits 0 to 9 are a contiguous range, which is also true for EBCDIC (IBM's character encoding system).

(revised to handle inputs like abc1abc and 41)

#include <ctype.h>
#include <stdio.h>

/*
 * Return a value between 1..4 inclusive or 0 for EOF.
 */
int
startprog()
{
    int ch, num;

    do {
        num = 0;
        (void) printf("\rchoice (1-4): ");
        while ((ch = getchar()) != EOF && isdigit(ch)) {
            num = num * 10 + (ch - '0');
        }
    } while (ch != EOF && (num < 1 || 4 < num));

    return num;
}

int
main(int argc, char **argv)
{
    (void) printf("your choice %d\n", startprog());

    return 0;
}
5
Riccardo Ricci On

I rewrite my code in the definitive way (OT) I know i don't need malloc and the rest, was just to try that i'm still learning lol. The code now is

void clearEOL() {
    int ch;
    do {
        ch = getchar();
    } while ((ch != '\n') && (ch != EOF));
}
int startprog()
{
    int num;
    char option[25];
    int isInt=0;
    do{

        printf("insert a numer (1/4)  \n");
        fgets(option,20,stdin);
        if(option[1]!='\n' || option[0]=='\n'){

             printf("Inserire solo un carattere  \n");
            clearEOL();
        }else
        {
            if ('1'<=option[0]&&option[0]<='4'){

                num=(option[0]-='0');
                isInt=1;
            }else{

                printf("Inserire 1 e 4\n");
                clearEOL();
            }

        }


    }while(isInt==0);
    return num;
}