Kundan Kumar
Kundan Kumar

Reputation: 2002

Understanding that scanf is doing in this code

Please help me in understanding the below code. The function get_digit takes a character argument by address. I am unable to get what scanf("%1[0123456789]", ch) does here.

If I give 1234 on the terminal then it takes only the first digit. Same is if I give 2345 it takes 2. I have never came across such usage of scanf. Please help me in understanding this feature.

int get_digit ( char *ch )
{
    int rc;

    printf ( "Enter a single digit: " );
    fflush ( stdout );

    if ( rc = scanf ( "%1[0123456789]", ch ) == 1 ) {
        jsw_flush();
    }
    return rc;
}

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

void fill_table ( char table[] )
{
    char ch;
    while ( get_digit ( &ch ) ) {
        unsigned i =  ch - '0';
        if ( table[i] != 0 ) {
            printf ( "That index has been filled\n" );
        }
        else {
            table[i] = ch;
        }
    }
}

void show_table ( const char table[], size_t size )
{
    size_t i;
    for ( i = 0; i < size; i++ ) {
        printf ( "%c\n", table[i] != 0 ? table[i] : '~' );
    }
}

Upvotes: 2

Views: 1312

Answers (1)

Daniel Fischer
Daniel Fischer

Reputation: 183883

scanf ( "%1[0123456789]", ch ) scans 1 character (%1) which is a decimal digit ([0123456789]) int the characer pointed to by ch.

The number immediately following the % is the field width, how many characters (maximally) to scan. The characters inside the square brackets are the characters scanf will accept. The scan ends when a character not listed is encountered.

An extremely simple example to scan two-digit numbers:

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

int main(void) {
    char chs[2] = {0};   // space for two digits, zero-initialized
    unsigned u = 0, i;
    if (scanf("%2[0123456789]",&chs[0]) == 1) {
        // parse the number
        for(i = 0; i < 2 && chs[i]; ++i) {
            u = 10*u + chs[i] - '0';
        }
        printf("Got %u\n",u);
    } else {
        puts("Scan failed.");
    }
    return EXIT_SUCCESS;
}

Of course, instead of parsing ourselves, we could make the character array one longer than we expect digits (zero-initialise!, scanf doesn't add a 0-terminator with that format) and leave the parsing to strtoul(chs,NULL,10).

Upvotes: 5

Related Questions