cscanf

Behavior of scanset


There is a difference in the scansets %1[x+-/] and %1[x/+-]. The first will also accept , and . but the second rejects those characters.

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

char scanoperator ( ) {
    int scanned = 1;
    char operator[2] = "";
    char nl[2] = "";

    do {
        if ( ! scanned) {
            printf ( "try again\n");
        }
        scanned = scanf ( "%1[x+-/]", operator);
        if ( EOF == scanned) {
            fprintf ( stderr, "EOF\n");
            exit ( 1);
        }
        scanf ( "%*[^\n]"); // scan and discard everything not a newline
        scanf ( "%1[\n]", nl); // scan a newline
    } while ( ! scanned);
    return operator[0];
}

char scanop ( ) {
    int scanned = 1;
    char operator[2] = "";
    char nl[2] = "";

    do {
        if ( ! scanned) {
            printf ( "try again\n");
        }
        scanned = scanf ( "%1[x/+-]", operator);
        if ( EOF == scanned) {
            fprintf ( stderr, "EOF\n");
            exit ( 1);
        }
        scanf ( "%*[^\n]"); // scan and discard everything not a newline
        scanf ( "%1[\n]", nl); // scan a newline
    } while ( ! scanned);
    return operator[0];
}

int main ( void) {
    char op;

    printf ( "Select the operator((+ - x /)\n");
    op = scanoperator ( );
    printf ( "operator is %c\n", op);

    printf ( "Select the operator((+ - x /)\n");
    op = scanop ( );
    printf ( "operator is %c\n", op);

    return 0;
}

The output from the above code is:

Select the operator((+ - x /)
.
operator is .
Select the operator((+ - x /)
.
try again  

The call to scanoperator () accepts a ..
The call to scanop ( ) responds correctly with try again. Why is there any difference in these scansets?


Solution

  • C 2024 7.23.6.3 says:

    … If a - character is in the scanlist and is not the first, nor the second where the first character is a ^, nor the last character, the behavior is implementation-defined…

    In %1[x/+-], the - is the last character, so the characters x, /, +, and - are accepted.

    In %1[x+-/], the - is not the first, second, or last character, so the behavior is implementation-defined. Most commonly, the behavior is that a-b represents the set of characters from a to b in the execution character set, inclusive. If the execution character set is ASCII or an extension of it, then the characters from + to / are + (character code 43), , (44), - (45), . (46), and / (47). In such implementations, %1[x+-/] will accept those characters and x.