Thread: sscanf() function behavior! Issues

  1. #1
    Registered User
    Join Date
    Mar 2019
    Posts
    51

    sscanf() function behavior! Issues

    Code:
    #include<stdio.h>
    #include<conio.h>
    main()
    {
        char str[50];
        char n[40], name[] = "Javaid";
        int a, age = 37;
        float c, cgpa = 3.17;
        printf("%s %d %0.2f\n", name, age, cgpa);
        sprintf(str, "%s %d %0.1f", name, age, cgpa);
        printf("%s\n", str);    
        sscanf(str,"%s %d %f",n, a, c); 
        printf("%s %d %0.2f\n", n, a, c);
        system("pause");
    }
    In sscanf() function I have wrongly used a and c. Correct is &a, &c. But
    problem is that when I use name[] = "Javaid Malik", last printf() statement is executed. But with name[] = "Javaid", last printf() statement doesn't execute.
    I am curious about what is behind the scene.

  2. #2
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    What did you got? "segmenation fault"? Sorry: "Access Violation"? "General Protection Fault"?

    PS: Get rid of conio.h and system() call. The former is non-standardized, the later isn't secure (or portable). If you want to wait for user input, use getc().
    Last edited by flp1969; 03-18-2019 at 05:36 PM.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Answering your question: sscanf() requires pointers where the tokens scanned from the string will be converted and copied. Using:
    Code:
    sscanf(str,"%s %d %f",n, a, c);
    Will, probably raise a "segmentation fault" signal (or generate a GPF exception). Here sscanf() thinks a and c are pointers. But they point, probably, to an invalid address, hence the fault...

    The correct usage, in this case is:
    Code:
    sscanf(str,"%s %d %f",n, &a, &c);
    But, remember, the scanf() functions returns the number of converted items. You should do:
    Code:
    if ( sscanf(str,"%s %d %f",n, &a, &c) != 3 )
    {
      // ... error handling here ...
    }

  4. #4
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    As for using "Javaid Malik" as a single string, it's not possible for sscanf() to recognize this as a single string with '%s'.
    sscanf() scans the string converting the tokens available, separated by a space ('\n', '\r', '\t', \'v' and ' ' are considered "spaces" in this context).

    In this context, when using the sscanf() the way you did, "Javaid" will be copied to n[] array and tries do convert "Malik" to int (and fail)...

    But not all is lost... since ISO 9989:1999 (or 2011, i don't remember), there is a converter using "[". It is a kind of regular expression... The code could be writen like this:
    Code:
    #include <stdlib.h>
    #include<stdio.h>
    
    int main( void )
    {
      char str[50];
      char n[40], name[] = "Javaid Malik";
      int a, age = 37;
      float c, cgpa = 3.17;
    
      printf ( "%s %d %0.2f\n", name, age, cgpa );
    
      // You HAVE to mark the end of the string somehow...
      // Here i choose to put between ".
      sprintf ( str, "\"%s\" %d %0.1f", name, age, cgpa );
    
      printf ( "%s\n", str );
    
      // Notice the %[^\"] conversion? This will scan a string
      // accepting everything, except the " char.
      if ( sscanf ( str, "\"%[^\"]\" %d %f", n, &a, &c ) != 3 )
      {
        fputs( "ERROR scanning string.\n", stderr );
        return EXIT_FAILURE;
      }
    
      printf ( "%s %d %0.2f\n", n, a, c );
      getchar();
    
      return EXIT_SUCCESS;
    }
    Last edited by flp1969; 03-18-2019 at 06:09 PM.

  5. #5
    Registered User
    Join Date
    Mar 2019
    Posts
    51
    Your Suggestion: You HAVE to mark the end of the string somehow...
    *There is always NULL character at the end of string i.e. '\0' So, why should I mark end of the string?
    Further I said that if name[] = "Javaid Malik" last printf() statement get executed. And you are saying that Javaid is converted and Malik is tried to convert into int and failed. If it is the case i.e. failed then last printf() statement in my program must not be executed. But case is opposite. In case of name[] = "Javaid Malik" last printf() statement still get executed.
    But when there is name[] = "Javaid" then last printf() statement didn't get executed. However In case of just "Javid", it must be converted because there is no space and next %d and %f should give nothing because I have not used them &a and &c. But case is opposite.
    What is happening with in case of "Javiad", I was expecting should happen with "Javaid Malik".
    Did you get my point?


    Last edited by rm82co; 03-19-2019 at 07:57 AM.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    Don't use color for your post. It just makes it harder to read.

    If a scanf call "fails" at some point, it doesn't cause the program to stop. The return value of the scanf can be used to see how many fields were converted. In your case, if it doesn't return 3 then it has failed to convert at least one of the parameters.

    When name is "Javaid Malik" the %s converts the "Javaid" and then the %d trys to convert the "Malik" to an integer and fails. sscanf will return 1 and execution continues at the printf statement.

    When name is "Javaid", the %s converts the "Javaid" and then the %d trys to convert the 37 to an integer, which would succeed except that you didn't use a pointer for the receiving parameter, and when the program tries to store the result at that "address" you get a segmentation fault, so the final printf doesn't execute.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    To "mark the end of the string somehow" was not about the NUL char, but to be possible to scan a string with spaces. For "Javaid 10 37.2", the "%s %d %f" will get the 3 parts and assign them to the char buffer, integer and float... If you do "Javaid Malik 10 37.2" with "%s %d %f", "Javaid" will be copied to n array and sscanf() will try to covert "Malik" do int...

    If you try, with the last string, using "%[^"] %d %f", the entire string will be copied to the array, and the other 2 argumentos will be undefined. So... If you use ""Javaid Malik" 10 37.2" and ""%[^"]" %d %f" you will get what you want...

    Running your code as it is you will get an segmentation fault:
    Code:
    $ cc -o test test.c
    test.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
     main()
     ^~~~
    test.c: In function ‘main’:
    test.c:13:22: warning: format ‘%d’ expects argument of type ‘int *’, but argument 4 has type ‘int’ [-Wformat=]
       sscanf ( str, "%s %d %f", n, a, c );
                         ~^
    test.c:13:25: warning: format ‘%f’ expects argument of type ‘float *’, but argument 5 has type ‘double’ [-Wformat=]
       sscanf ( str, "%s %d %f", n, a, c );
                            ~^
    $ ./test
    Javaid 37 3.17
    Javaid 37 3.2
    Segmentation fault (core dumped)
    And the warnings are self explanatory... Changing the string you will get:
    Code:
    $ sed -i 's/Javaid/Javaid Malik' test.c
    $ cc -o test test.c
    test.c:3:1: warning: return type defaults to ‘int’ [-Wimplicit-int]
     main()
     ^~~~
    test.c: In function ‘main’:
    test.c:13:22: warning: format ‘%d’ expects argument of type ‘int *’, but argument 4 has type ‘int’ [-Wformat=]
       sscanf ( str, "%s %d %f", n, a, c );
                         ~^
    test.c:13:25: warning: format ‘%f’ expects argument of type ‘float *’, but argument 5 has type ‘double’ [-Wformat=]
       sscanf ( str, "%s %d %f", n, a, c );
                            ~^
    $ ./test
    Javaid Malik 37 3.17
    Javaid Malik 37 3.2
    Javaid 32758 15610336269040904490120578005030928384.00
    Ok... This seems to be an unexpected result, but remember sscanf() is failing when trying to convert "Malik" to int...
    What you see here is the garbage from local variables b and c. Let's see on gdb, shall we?
    Code:
    $ cc -g -o test test.c
    $ gdb test
    Reading symbols from test...done.
    (gdb) l
    1    #include<stdio.h>
    2    
    3    main()
    4    {
    5      char str[50];
    6      char n[40], name[] = "Javaid Malik";
    7      int a, age = 37;
    8      float c, cgpa = 3.17;
    9    
    10      printf ( "%s %d %0.2f\n", name, age, cgpa );
    (gdb) b 10
    Breakpoint 1 at 0x837: file test.c, line 10.
    (gdb) r
    Starting program: /home/frederico/MyStuff/tmp/test 
    
    Breakpoint 1, main () at test.c:10
    10      printf ( "%s %d %0.2f\n", name, age, cgpa );
    (gdb) p a
    $1 = 32767
    (gdb) p c
    $2 = -1.03806422e+34
    (gdb) b 14
    Breakpoint 2 at 0x5555555548bd: file test.c, line 14.
    (gdb) c
    Continuing.
    Javaid Malik 37 3.17
    Javaid Malik 37 3.2
    
    Breakpoint 2, main () at test.c:14
    14      printf ( "%s %d %0.2f\n", n, a, c );
    (gdb) p a
    $3 = 32767
    (gdb) p c
    $4 = -1.03806422e+34
    (gdb) c
    Continuing.
    Javaid 32767 -10380642212464256323223514653917184.00
    
    [Inferior 1 (process 1273) exited normally]
    Now you known from where that 32758 comes from (the values are a little bit different here because of debugging code)... The other value is garbage as well...

    Did YOU get my point?
    Last edited by flp1969; 03-19-2019 at 09:29 AM.

  8. #8
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    The name scanf() should give a hint of what the function does. It scans the string and tries to convert its parts to the specified formats... When a conversion fails, it stops the scanning and returns the number of itens successfully converted.

    That's why the function name isn't called readf() or inputf().

  9. #9
    Registered User
    Join Date
    Mar 2019
    Posts
    51
    Thank you Sir! I have understood this point and sorry for, to use colors. It was just by mistake.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Another example of sscanf function
    By lsatenstein in forum C Programming
    Replies: 2
    Last Post: 01-26-2016, 02:22 PM
  2. understanding sscanf() function
    By ak47 in forum C Programming
    Replies: 6
    Last Post: 01-03-2014, 11:50 PM
  3. Sscanf Issues and getting rid of quotes
    By Ramkiller1 in forum C Programming
    Replies: 5
    Last Post: 10-27-2012, 10:34 PM
  4. strange behavior with array in function
    By pater in forum C Programming
    Replies: 4
    Last Post: 01-24-2012, 07:02 AM
  5. sscanf() issues
    By Stiletto in forum C Programming
    Replies: 11
    Last Post: 12-19-2011, 02:59 PM

Tags for this Thread