Getting an integer from a string

138 views Asked by At

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.

5

There are 5 answers

3
Vlad from Moscow On BEST ANSWER

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;
}
2
0___________ On
  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
White Eagle On

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.

1
Namal Sanjaya On

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;
}
0
chqrlie On

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