printf("Input an integer");
scanf("%d",&int);

i want my int to accept integer only..
how can i do that?

tnx in advance :)

Recommended Answers

All 2 Replies

You'll have to investigate the stream character by character using isdigit().

scanf() will only accept a valid integer using that code, and return a value other than 1 if the input string isn't a valid integer. It's your job to check the return value for success and handle errors:

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

void clear_stream(FILE *in)
{
    int ch;
    
    clearerr(in);
    
    do
        ch = getc(in);
    while (ch != '\n' && ch != EOF);
    
    clearerr(in);
}

int main(void)
{
    int value;
    
    printf("Enter an integer: ");
    fflush(stdout);
    
    while (scanf("%d", &value) != 1) {
        clear_stream(stdin);
        printf("Invalid integer. Please try again: ");
        fflush(stdout);
    }
    
    printf("You entered %d\n", value);
    
    return 0;
}

One problem you may encounter is a partial match, such as if the stream contains "123abc". scanf() will treat that as a valid integer, read the "123" part, and leave the rest in the stream. If you want to treat that as an error case, one of the two most common options is checking for the next character:

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

void clear_stream(FILE *in)
{
    int ch;
    
    clearerr(in);
    
    do
        ch = getc(in);
    while (ch != '\n' && ch != EOF);
    
    clearerr(in);
}

int main(void)
{
    int value, peek;
    
    printf("Enter an integer: ");
    fflush(stdout);
    
    while (scanf("%d", &value) != 1 || 
           ((peek = getchar()) != EOF && !isspace(peek)))
    {
        clear_stream(stdin);
        printf("Invalid integer. Please try again: ");
        fflush(stdout);
    }
    
    /* Return the peeked character if there was one */
    if (peek != EOF) {
        clearerr(stdin); /* Clear any error state peek may have caused */
        ungetc(peek, stdin);
    }
    
    printf("You entered %d\n", value);
    
    return 0;
}

The idea behind this option is that scanf() will stop reading at whitespace, so if the next character after a successful conversion is not whitespace, the conversion was partial.

Obviously checking the next character is awkward, so most of the time the recommendation is to eschew scanf() altogether in favor of a combination of fgets() and sscanf(). This gives you more control over the contents of the stream because fgets() extracts a whole line that can then can be parsed in memory at your leisure:

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

int main(void)
{
    char buf[BUFSIZ];
    int value, end;
    
    printf("Enter an integer: ");
    fflush(stdout);
    
    while (fgets(buf, sizeof buf, stdin) == NULL ||
           sscanf(buf, "%d%n", &value, &end) != 1 || 
           !isspace(buf[end]))
    {
        printf("Invalid integer. Please try again: ");
        fflush(stdout);
    }
    
    printf("You entered %d\n", value);
    
    return 0;
}

This has the distinct benefit of not requiring you to manage extraneous characters in the stream, but it does introduce potential issues in managing multiple items on a single line.

Now, usually when people ask your question they want to fully control what the user types, which isn't possible using the standard I/O functions. To do this you'd need to inspect each typed character before it's pushed into the stream, and that basically means taking over the job of the system's shell:

#include <conio.h> /* Non-portable library */
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>

int keyboard_int(int radix)
{
    const unsigned limit = UINT_MAX / radix;
    const unsigned top_digit = UINT_MAX % radix;

    unsigned overflow = 0; /* True if integer overflow occurs */
    unsigned sign = 0;     /* Final sign of the converted value */
    unsigned temp = 0;     /* The intermediate converted value */
    int ch = getch();      /* The current character being processed */

    if (ch == '-' || ch == '+') {
        /* Save and skip a valid sign character */
        sign = ch == '-';
        
        /* Echo the current character and grab another */
        putch(ch);
        ch = getch();
    }

    while (1) {
        if (ch == '\r' || ch == '\n') {
            putch('\n');
            break;
        }
        else if (!isdigit(ch)) {
            /* Don't echo an invalid integer character */
            ch = getch();
            continue;
        }
        else {
            unsigned digit = ch - '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;

            temp = temp * radix + digit;
            
            /* Echo the current character and grab another */
            putch(ch);
            ch = getch();
        }
    }
    
    if (overflow ||
        (sign && temp > -(unsigned)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 ? -(unsigned)INT_MIN : INT_MAX;
    }

    return sign ? -(int)temp : (int)temp;
}

int main(void)
{
    int value;
    
    printf("Enter an integer: ");
    fflush(stdout);
    value = keyboard_int(10);
    printf("You entered %d\n", value);

    return 0;
}

Bear with me because that implementation of keyboard_int() is very robust. It can be simplified at the cost of removing overflow protection, but I wouldn't recommend it because that introduces tremendous risk:

int keyboard_int(int radix)
{
    unsigned sign = 0;     /* Final sign of the converted value */
    unsigned temp = 0;     /* The intermediate converted value */
    int ch = getch();      /* The current character being processed */

    if (ch == '-' || ch == '+') {
        sign = ch == '-';
        putch(ch);
        ch = getch();
    }

    while (1) {
        if (ch == '\r' || ch == '\n') {
            putch('\n');
            break;
        }
        else if (!isdigit(ch)) {
            ch = getch();
            continue;
        }
        else {
            temp = temp * radix + (ch - '0');
            putch(ch);
            ch = getch();
        }
    }
    
    return sign ? -(int)temp : (int)temp;
}
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.