Julian Laval
Julian Laval

Reputation: 1250

Using the scanf function in while loop

I am attempting to format a space-delimited user input for a programming assignment.

Essentially, the input consists of an arbitrary number of expressions

L integer integer integer integer and C integer integer integer.

For example: L 1 1 5 7 C 4 5 3.

So far, I've managed to extract the integers depending on the initial character, and can iterate through the string using the scanf function:

char a;
while(scanf("%c", &a) == 1){
    if(a == 'C'){
        int inputX, inputY, inputR;
        scanf("%d %d %d", &inputX, &inputY, &inputR);
        printf("%d %d %d\n", inputX, inputY, inputR);
    }
    else if(a == 'L'){
        int x1, y1, x2, y2;
        scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
        printf("%d %d %d %d\n", x1, y1, x2, y2);
    }
}

Unfortunately, although this outputs the desired integers, the loop (and user input prompt) doesn't terminate.

Could someone please enlighten me as to why this is happening?

Upvotes: 8

Views: 106569

Answers (4)

saint_sharan
saint_sharan

Reputation: 109

char a;
    while(scanf("%[LC]", &a) == 1){
    if(a == 'C'){
        int inputX, inputY, inputR;
        scanf("%d %d %d%*c", &inputX, &inputY, &inputR);
        printf("%d %d %d\n", inputX, inputY, inputR);
    }
    else if(a == 'L'){
        int x1, y1, x2, y2;
        scanf("%d %d %d %d%*c", &x1, &y1, &x2, &y2);
        printf("%d %d %d %d\n", x1, y1, x2, y2);
    }
}

"%[LC]" makes sure that only 'L' or 'C' will be scanned. After taking 3 or 4 of an integer input accordingly, both 'space' or 'enter' or 'any single character' will be discarded "%*c", after that, anything but 'L' or 'C' will break loop.

Upvotes: 0

haccks
haccks

Reputation: 105992

This is because \n is always there to make scanf("%c", &a) == 1 always true.
Change your

while(scanf("%c", &a) == 1) 

to

while(scanf(" %c", &a) == 1)  
     //      ^space before format specifier.  

A space before %c will eat up this \n left behind by scanf (on pressing Enter).

Upvotes: 21

chux
chux

Reputation: 153338

Combining some features of other posts and some additions.
Use fgets() and %n inside sscanf(). Be sure to check results of sscanf().

char line[1024];
while (fgets(line, sizeof line, stdin) != NULL)) {
  char *s = line; 
  char Type;
  int n;
  while(sscanf(s, " %c%n", &Type, &n) == 1) {
    s += n;
    if(Type == 'C') {
      int inputX, inputY, inputR;
      if (3 != sscanf(s, "%d %d %d%n", &inputX, &inputY, &inputR, &n)) {
        Handle_Syntax_Error();
      }
      s += n;
      printf("%d %d %d\n", inputX, inputY, inputR);
    }
    else if(Type == 'L') {
      int x1, y1, x2, y2;
      if (4 != sscanf(s, "%d %d %d %d%n", &x1, &y1, &x2, &y2, &n)) {
        Handle_Syntax_Error();
      }
      s += n;
      printf("%d %d %d %d\n", x1, y1, x2, y2);
    }
    else {
      Handle_Syntax_Error();
    }
  }
} 

Upvotes: 1

T.V.
T.V.

Reputation: 495

The reason is scanf reads directly from the standard input and which blocks and waits for user input after it has processed the line. What you need to do is read the line and process that line in your while loop. I've modified your code below.

char a;
char line[1024];

fgets(line, 1023, stdin);   // leave 1 character for null terminator
while(sscanf(line, "%c", &a) == 1){
    if(a == 'C'){
        int inputX, inputY, inputR;
        sscanf(line, "%d %d %d", &inputX, &inputY, &inputR);
        printf("%d %d %d\n", inputX, inputY, inputR);
    }
    else if(a == 'L'){
        int x1, y1, x2, y2;
        sscanf(line, "%d %d %d %d", &x1, &y1, &x2, &y2);
        printf("%d %d %d %d\n", x1, y1, x2, y2);
    }
}

Upvotes: 3

Related Questions