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:Support the full range of int
Pre-check for integer overflow
Ditch the gotoxy stuff (the most you need for interactive control is a getch clone, everything else can be done with standard C)
For maximum portability, use an intersection of the C89 and C99 standards
Narue
Bad Cop
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
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, 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;
}
Narue
Bad Cop
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
pyTony
pyMod
5,358 posts since Apr 2010
Reputation Points: 782
Solved Threads: 852