8

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?

2
  • Do you feed an EOF (by Ctrl+D in Linux or Ctrl+Z in Windows) in the end of your input? Commented Nov 11, 2013 at 17:08
  • @timrau feeding an EOF ends the input whilst the program is running but I would expect it to terminate on Enter as well. Commented Nov 11, 2013 at 17:19

4 Answers 4

21

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).

Sign up to request clarification or add additional context in comments.

7 Comments

This doesn't seem to work; adding a space hasn't changed anything. Any ideas?
@haccks I have written a program which reads some characters. printf("\n 1. Give a character : \n"); scanf(""%c", &ch); while(ch != '\0'){ ... printf("\n 2. Give a character : \n"); scanf("%c", &ch); } But running this program, the second printf is printed twice. After having added a space before %c , it worked correctly! Could you explain me why we have to add a spece before %c, so that the second printf is printed only once??
The reason is simple which I explained in the above answer. When you press "Enter" key then a newline character \n is go to the input buffer. If a is the input character then input buffer will contain a\n. First scanf will read a leaving \n in the buffer for next call of scanf. On entering the loop, your second scanf will read this leftover \n from input buffer and loop runs one more time without waiting for your input and that's why you are getting Give a character line twice.
A space before %c will eat up this \n (or any number of whitespaces) left behind by scanf.
Wow! @haccks you're amazing. I was facing the exact same issue and your post helped solve it.
|
3

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);
    }
}

Comments

1

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();
    }
  }
} 

Comments

0
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.