2

I have some code that reads a string of the form name 1 in a while loop, and then I have to extract the integer value to print yes or no. But when I tried to do it with sscanf, it gives the destination integer the value only after the loop finishes.

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

int main() {
    char a[20];
    int p = 0;
    while (scanf("%s", a)) {
        sscanf(a, "%d", &p);
        if (p != 0) {
            printf("yes");
        } else {
            printf("no");
        }
    }
    return 0;
}

even though the string I introduce has the integer greater than 1, the program always prints no.

I tried to evaluate the output with printfs and I saw that when I execute it gives this output:

printf("%d", p);

For the input:

name 1

it prints:

0no1yes

As I said, it first gets the integer as 0 and after entering the if it becomes 1.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Please format your code (indentation), too. Also, since this is about input handling, you need to inform us about what input you provided that caused problems. As a new user, also take the [tour] and read [ask]. – Ulrich Eckhardt Apr 06 '23 at 20:49

5 Answers5

2
  1. ALways format your code. Not for us - for yourself
  2. Alays check the result of scanf
  3. Do not use scanf to read lines - always use fgets
int main(void)
{
    char a[20];
    int p=0;
    while(fgets(a, sizeof(a), stdin))
    {
        if(sscanf(a,"%d",&p) != 1) 
        {
            printf("\nNo no no!!!!\n");
            continue;
        }
        if(p!=0)
        {
            printf("yes\n");
        }
        else{
        printf("no\n");
        }
    }
    return 0;
}

https://godbolt.org/z/dcqc47vh1

0___________
  • 60,014
  • 4
  • 34
  • 74
2

In this call of scanf

while(scanf("%s",a)) {

the conversion specifier s allows to read only a text that is separated by spaces. That is if you will enter

name 1

then the first call of scanf will read only the text "name" and in the next iteration of the loop the call of scanf will read the text "1" that indeed can be converted to an integer.

You need to use another conversion specifier in the call of scanf.

And the condition in the while loop

while(scanf("%s",a)) {

In fact you have an infinite loop.

Also your program contains redundant include directive.

The program can look the following way.

#include <stdio.h>

int main( void ) 
{
    char a[20];

    while ( scanf(" %19[^\n]",a ) == 1 ) 
    {
        int p = 0;

        sscanf( a,"%*s%d", &p );

        if ( p ) 
        {
            puts( "yes" );
        }
        else 
        {
            puts( "no" );
        }
    }

    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

When you use scanf() to read input values from the standard input stream, it stores the input values in a buffer until it reads all the expected input values. If you do not consume all the input values in the buffer, they can remain in the buffer and can cause issues in your program. Therefore better to use fgets() method to read data from input stream.

#include <stdio.h>

int main(){
    char inpt[20];
    char str[20];
    int val=0;
    while(1){
        fgets(inpt, 20, stdin);
        sscanf(inpt, "%s %d", str, &val);
        if(val!=0){
            printf("yes\n");
        }
        else{
            printf("no\n");
        }
    }
    return 0;
}
  • You must clear `val` in the loop before the `sscanf()`. As coded, a missing value will fail to report `no` after a match. – chqrlie Apr 06 '23 at 22:48
0

You have almost the correct approach: you should read a line of input with fgets() and then parse it with sscanf() to extract the integer.

As coded, reading with scanf("%s", a) is both incorrect and risky:

  • incorrect because only a single word is read, name, then 1 in the next loop.
  • risky because any word longer than 19 characters will cause a buffer overflow.

Here is a simple alternative:

#include <stdio.h>

int main(void) {
    char a[100];

    while (fgets(a, sizeof a, stdin)) {
        int p;
        if (sscanf(a, "%*s%d", &p) == 1 && p != 0)
            puts("yes");
        else
            puts("no");
    }
    return 0;
}

Note however that the above code will accept potentially invalid lines such as Hello 1 world! and 1 2 3

chqrlie
  • 131,814
  • 10
  • 121
  • 189
-1

Your input is "name 1" so the first read of sscanf is not "successful", because it first reads "name" and it's not an integer, either, as suggested try to check how many successful reads you have or (if you trust the input) try with

sscanf("%s %d", a, &p);

and now the sscanf will know to skip the string and read the integer you want.