Search code examples
cinputscanffgets

Read an input that is separated by spaces, parenthesis, and commas with scanf() and fgets()


I have the following input:

1 (2 ,3 ,4) lantern

The number of int inputs between the parenthesis is unknown, and could extend for a while.

My original thought was to scanf() the first int, then create a while loop to determine when the closed paranethsis is scanned. Then finally use fgets() to get the string at the end, something similar to this.

scanf("%d", &address);  //first input

scanf("%c", &paren);    //scan the '(' or ',' or ')'

int current_room = 0;   //index for array inside parenthsis

while(paren == '(' || paren == ','){

    scanf("%d,", adjoined_room[current_room]);  //scan am int

    scanf("%c", &paren);   //scan a ',' or ')'

    current_room++;        //increase the index

}

This however prints the following output when I print my address, array, and string:

Address: 1
Item: (2 ,3 ,4) lantern

The inputted ints between the parenthesis were never set to the array. Is there a better way to determine when ')' is inputted?


Solution

  • The problem is that scanf("%c", will read the very next character in the input, without skipping any whitespace. If you want to skip whitespace, you need a space in the format, eg scanf(" %c",. You should also check the scanf return value to make sure that you got an integer

    Adding that to your code gives you something like:

    if (scanf("%d", &address) != 1) {  //first input
        fprintf(stderr, "syntax error\n");
        return;  // not an integer -- do something else
    }
    scanf(" %c", &paren);    //scan the '(' or ',' or ')'
    int current_room = 0;   //index for array inside parenthsis
    while(paren == '(' || paren == ','){
        if (scanf("%d", adjoined_room[current_room]) == 1) {  //scan an int
            current_room++;        //increase the index
        }
        scanf(" %c", &paren);   //scan a ',' or ')'
        if (paren != ',' && paren != ')') {
            fprintf(stderr, "syntax error\m");
            return;
        }
    }
    

    If you want to do this with interactive input, you should probably use fgets or getline to read entire lines and sscanf to parse each line independently so you don't confuse your user when there's an error in the middle of a line. The "read line + sscanf" is also very useful if you have a number of different patterns that you want to try (sscanf on the same line with different formats to find the first one that matches).