C Function to Enforce to accept Number only

prvnkmr194 -1 Tallied Votes 283 Views Share

Get_Number function is a function to get input from keyboard, this function restrict the user to pass wrong input...........
How to use
->
For example we need to take input in any integer variable n call Get_Number()
like this

n=Get_Number();

With Full Back Space support

Please comments on my code

Get_Number()
{
char ch=NULL;
int num1=0,x,y,x1;
x=wherex();
y=wherey();
x1=x;
gotoxy(x1,y);
	while(ch!=13)
	{
	ch=getch();
	if(ch>=48 && ch<=57)
		{
		x1++;
		printf("%c",ch);
		num1=num1*10+(ch-'0');
		}
	else if(ch==8 && x1>x)
		{
		x1--;
		gotoxy(x1,y);
		puts(" ");
		gotoxy(x1,y);
			if(num1>0) num1/=10;
		}
	}
return num1;
}
Narue 5,707 Bad Cop Team Colleague

The code uses outdated and potentially dangerous techniques, and isn't robust at all. You can easily invoke undefined behavior by typing enough digits to overflow the signed int type. Further, it doesn't properly handle negative values.

To improve the code I'd offer three pieces of advice:

  1. Support the full range of int
  2. Pre-check for integer overflow
  3. Ditch the gotoxy stuff (the most you need for interactive control is a getch clone, everything else can be done with standard C)
  4. For maximum portability, use an intersection of the C89 and C99 standards
prvnkmr194 0 Posting Whiz in Training

Thanks For your great advice.......
ya this code in turbo c so its not standard, if going to change this code in visual studio 2005 i got some problem
1. How to move the cursor.
2. How to get current cursor position.
3. Size of integer variable is also compiler dependent.
Any advice.........
Thanks

prvnkmr194 0 Posting Whiz in Training

Sorry Actually I know howto get the size of integer jst help on first two point

Narue 5,707 Bad Cop Team Colleague

Thanks For your great advice.......
ya this code in turbo c so its not standard, if going to change this code in visual studio 2005 i got some problem
1. How to move the cursor.
2. How to get current cursor position.
3. Size of integer variable is also compiler dependent.
Any advice.........
Thanks

First and foremost, you can write standard C89 in Turbo C. Second, all of the cursor positioning is completely unnecessary. Since you're working on a single line at all times, you can get the same effect by writing backspace characters.

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

char *get_digits(char buf[], size_t size)
{
    size_t i = 0;
    int c;

    while (i < size - 1) {
        c = getch();

        if (c == '\r') {
            putchar('\n');
            break;
        }
        else if (c == '\b') {
            if (i > 0) {
                printf("\b \b");
                fflush(stdout);
                --i;
            }
        }
        else if (isdigit(c)) {
            putchar(c);
            fflush(stdout);
            buf[i++] = (char)c;
        }
    }

    buf[i] = '\0';

    return buf;
}

int main(void)
{
    char buf[BUFSIZ];

    printf(">%s<\n", get_digits(buf, sizeof buf));

    return 0;
}

To check an integer for overflow as you're building it, <limits.h> is critical. Here's a related example (parsing a string into an int) that you an use for ideas:

#include <ctype.h>
#include <errno.h>
#include <limits.h>

const char *parse_int(const char *s, int *value)
{
    /* Base of the final converted value */
    const unsigned base = 10;

    /* Largest possible value without the least significant digit */
    const unsigned limit = UINT_MAX / base;

    /* Least significant digit from the largest possible value */
    const unsigned top_digit = UINT_MAX % base;

    unsigned overflow = 0; /* True if integer overflow occurs */
    unsigned sign = 0;     /* Final sign of the converted value */

    unsigned temp = 0;     /* The intermediate converted value */
    unsigned n = 0;        /* Count of converted digits */

    /* Save and skip over the sign if present */
    if (*s == '-' || *s == '+')
        sign = *s++ == '-';

    /* Build the intermediate value */
    for (; isdigit(*s); s++, n++) {
        unsigned digit = *s - '0';

        /*
            This protects *only* the intermediate value
            from overflow. Overflow of the final value
            requires further checks
        */
        overflow =  temp > limit || (temp == limit && digit > top_digit);

        if (overflow)
            break;

        /* Shift-add by the base */
        temp = temp * base + digit;
    }

    if (n > 0) {
        /*
            A conversion was made, so now we need to
            deal with overflow and set the final value
        */
        if (overflow ||
            (sign && temp > -INT_MIN) ||
            (!sign && temp > INT_MAX))
        {
            /*
                The intermediate actually overflowed,
                or converting it to int would overflow.
                Either way it's an error to the caller
            */
            errno = ERANGE;
            temp = sign ? -INT_MIN : INT_MAX;
        }

        *value = sign ? -(int)temp : (int)temp;
    }
    else if (sign) {
        /*
            We found a sign and skipped over it. But
            because no conversion was made, we need
            to "unskip" the sign
        */
        --s;
    }

    return s;
}
prvnkmr194 0 Posting Whiz in Training

Thanks alot............

yashsaxena -1 Light Poster

My code used to hang after entering chars.

hey nice thread
and nice replies
thanks for sharing.

TrustyTony 888 ex-Moderator Team Colleague Featured Poster

After graduating to GUI, it looks worthwhile to check patterns from http://ui-patterns.com/

WaltP commented: What does that website have to do with numeric input? -3
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.