Home > Blockchain >  C getchar loop to get integer input from user - [how to improve]
C getchar loop to get integer input from user - [how to improve]

Time:08-04

Is there more elegant way to do this task?

Program asks user for integer and repeats if non-digital characters are entered. To exit loop two conditions expected: a) all entered characters are digits b) last character is '\n'

Short solutions like scanf don’t work properly, other approaches require lots of variables loops and if else conditions. User input is common task and I would like to have proper reusable template.

Subjective opinions are appreciated. Way to simplify this function or advice on another solution. Improve formatting. Reading for more systematic understanding.

#include <stdio.h>

int getIntOnly();

int main() {
    int x = 0;
    x = getIntOnly();
    printf("\nvalue entered is: %d \n", x);
}

int getIntOnly() {
    int ch, num, quit, abc;

    do {
        num = 0;
        ch = 0;
        quit = 0;
        abc = 0;
        printf("Enter the input: ");

        do {
            ch = getchar();
            if (ch >= 48 && ch <= 57) {
                num = num * 10   (ch - 48);
            }
            else if (ch == '\n') {
                quit = 1;
            }
            else {
                abc = 1;
            }

        }
        while (quit == 0);

    }
    while (quit == 0 || abc == 1);
    return (num);
}

CodePudding user response:

Using fgets() means you'll get the full text at once. You can then examine it (and convert it too) to suit your needs.

int getIntOnly( void ) {
    int value = 0, i = 0;
    char buf[ 64 ];

    do {
        printf( "Enter integer value: " );

        
        fgets( buf, sizeof( buf ), stdin );
        
        value = 0;
        for( i = 0; '0' <= buf[i] && buf[i] <= '9'; i   )
            value = value * 10   buf[i] - '0';

    } while( buf[i] != '\n' ); // good! reached end of line

    return value;
}

CodePudding user response:

May be better? Add some validity checks for the result of fgets() and strtol() according to your original code.

#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>

int getIntOnly();

int main() {
    int x = 0;
    x = getIntOnly();
    printf("\nvalue entered is: %d \n", x);
}

bool isDigit(char ch) {
    return (ch >= '0' && ch <= '9')? true : false;
}

bool isAllDigit(char *buf) {
    int i;

    for (i = 0; buf[i] != '\n'; i  ) {
        if (isDigit(buf[i]) == false) {
            return false;
        }
    }
    return true;
}

bool isVaildInt(long int number) {
    return (number >= INT_MIN && number <= INT_MAX)? true : false;
}

int getIntOnly() {
    char buf[100];
    long int num;
    bool done = false;

    do {
        /* read line-by-line */
        fgets(buf, 100, stdin);
        if (isAllDigit(buf) == false)
            continue;

        num = strtol(buf, NULL, 10);
        /* strtol() returns long int */
        if (isVaildInt(num) == false)
            continue;
        done = true;
    } while (done == false);
    return num;
}
  • Related