Gcc doesn't seem to get my scanf right, but Visual Studio does, what's wrong?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Bangonkali
    New Member
    • Dec 2010
    • 7

    #1

    Gcc doesn't seem to get my scanf right, but Visual Studio does, what's wrong?

    First I actually thought there was something wrong with my programming skills. But after I compiled the same code using Visual Studio, it worked. So here's the code that doesn't seem to be working right with gcc compilers, but they do compile. Note I'm using the Cygwin 3.4.4 version of gcc and 4.5.1 version of gcc from MinGW.

    Code:
    #include <stdio.h>
    #include <math.h>
    int main()
    {
        long double r = 0;
        long double p = 0;
    
        printf ("Enter a number: ");
        scanf ("%lf", &r);
        printf ("Enter its power: ");
        scanf ("%lf", &p);
        printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p));
    
        printf ("7 ^ 3 = %lf\n", pow (7.0,3.0));
        printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0));
        printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));
        return 0;
    }
    This is the first one. It compiles with GCC but the output doesn't seem to be what I'm expecting. (MinGW gcc (GCC) 4.5.1)
    Code:
    Enter a number: 5
    Enter its power: 3
    [B]5.000000 to the power of 0.000000 = 0.000000[/B]
    7 ^ 3 = 343.000000
    4.73 ^ 12 = 125410439.217423
    32.01 ^ 1.54 = 208.036691
    The part "5.000000 to the power of 0.000000 = 0.000000" doesn't seem to be right. But on the other hand, when I compiled it using Visual Studio, it worked very well.
    Code:
    Enter a number: 5
    Enter its power: 3
    5.000000 to the power of 3.000000 = 125.000000
    7 ^ 3 = 343.000000
    4.73 ^ 12 = 125410439.217423
    32.01 ^ 1.54 = 208.036691
    I looked for a solution in the internet and I found sscanf. I tried to modified the code, it still compiles with gcc but yielding the same results.
    Code:
    #include <stdio.h>
    #include <math.h>
    int main()
    {
        char line[100];
        long double r = 0;
        long double p = 0;
       
        printf ("Enter a number: ");
        fgets(line,sizeof(line),stdin);
        sscanf(line,"%lf",&r);
        
        printf ("Enter its power: ");
        fgets(line,sizeof(line),stdin);
        sscanf(line,"%lf",&p);
        
        printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p));
    
        printf ("7 ^ 3 = %lf\n", pow (7.0,3.0));
        printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0));
        printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));
        return 0;
    }
    Using the gcc compiler of MinGW this is the result: (MinGW gcc (GCC) 4.5.1)
    Code:
    Enter a number: 5
    Enter its power: 3
    5.000000 to the power of 0.000000 = 0.000000
    7 ^ 3 = 343.000000
    4.73 ^ 12 = 125410439.217423
    32.01 ^ 1.54 = 208.036691
    The previous yields the same result as before where the part "5.000000 to the power of 0.000000 = 0.000000" is not working as intended. If I use the compiler from Visual Studio 2008 C++, this is the result:
    Code:
    Enter a number: 5
    Enter its power: 3
    5.000000 to the power of 3.000000 = 125.000000
    7 ^ 3 = 343.000000
    4.73 ^ 12 = 125410439.217423
    32.01 ^ 1.54 = 208.036691
    Last edited by Bangonkali; Dec 11 '10, 07:47 AM. Reason: Revised Formatting
  • donbock
    Recognized Expert Top Contributor
    • Mar 2008
    • 2427

    #2
    Perhaps the difference in line termination (LF vs CR-LF) between unix [Cygwin] and DOS [Visual Studio] is catching you. You should be testing the return code from scanf.

    Comment

    • AdrianH
      Recognized Expert Top Contributor
      • Feb 2007
      • 1251

      #3
      No, looks like a bug. Submitting to gcc bugzilla. Bug 46908


      A

      Comment

      • Bangonkali
        New Member
        • Dec 2010
        • 7

        #4
        Case Resolved

        Thanks guys! But I think I have found the answer to my problem now. According to someone who replied to my email it was because gcc was keeping a space in the keyboard buffer. And you can tell if the same thing's happening again if the second input is always 0. He said I should try to use the following code separated by a space instead:

        Code:
        scanf( "%lf %lf", &r, &p );
        I edited my original code to work like this:

        Code:
        #include <stdio.h>
        #include <math.h>
        int main()
        {
            // my personal troubles with long double
            // while using gcc under cygwin and mingw
            long double r = 0;
            long double p = 0;
            long double a = 0;
            
            printf ("Enter a number <space> power: ");
            scanf( "%Lf %Lf", &r, &p );
        	
            // r to the power of p
            a = pow(r,p);
        
            printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a);
            printf ("7 ^ 3 = %.2Lf\n", (long double)pow(7.0,3.0));
            printf ("4.73 ^ 12 = %.2Lf\n", (long double)pow(4.73,12.0));
            printf ("32.01 ^ 1.54 = %.2Lf\n", (long double)pow(32.01,1.54));
            return 0;
        }
        Now it works perfectly fine with the following output when compiled with gcc both from MinGW and Cygwin.

        Code:
        5.00 to the power of 3.00 = 125.00
        7 ^ 3 = 343.00
        4.73 ^ 12 = 125410439.22
        32.01 ^ 1.54 = 208.04
        I still don't know how accept value from a second scanf though. If anyone of you who knows how to circumvent this issue please help. I need to accept the second input only after the return has been pressed from the first input and not separated by space.

        Comment

        • Bangonkali
          New Member
          • Dec 2010
          • 7

          #5
          Case SOLVED!

          THIS PROBLEM IS SOLVED! Thank you for everyone who replied. Not only from this forum but also from all the other forums which I sent this problem to.

          First let me summarize the problem. I'm using scanf to accept a long double value from the user. I used %Lf to accept this and used %.2Lf to printf it. The problem is that I can't do more than 2 scanf's because I can only read the first one if I used Cygwin's gcc compiler and MinGW's gcc compiler. The same code works with VSC++ though.

          However, if I use only double, and use %lf to scanf and printf data, the programs works quite well even if I have many scanf's.

          A person from one forum gave me an idea about keyboard caching. Which basically means, after I enter a value from the first %Lf (long double) another character is also received which totally messes up the next scanf. And thus when I run my initial code, I receive a 0 value for the next scanf.

          I found out that by putting getchar() from between the two scanf's I can circumvent the issue. Let me repeat, the problem only works on long double scanf's using %Lf, it doesn't occur on only doubles using %lf. The following is my final code that really works on gcc.

          Code:
          #include <stdio.h>
          #include <math.h>
          int main()
          {
              // my personal troubles with long double
              // while using gcc under cygwin and mingw
              long double r = 0;
              long double p = 0;
              long double a = 0;
              
              //printf ("Enter a number <space> power: ");
              //scanf( "%lf %lf", &r, &p );
              
              printf ("Enter a number: ");
          	scanf( "%Lf", &r);
              
              printf ("Enter a number: ");
          getchar();	
          	scanf( "%Lf", &p );
              
              // r to the powler of p
              a = pow(r,p);
          
              // put (long double) typecast before pow if you're
              // printing pow directly on printf and you're using
              // Cygwin's gcc (GCC) 3.4.4. You may not edit this 
              // code if you're compiling on VSC++ or MinGW's gcc 
              // (GCC) 4.5.1
              printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a);
              printf ("7 ^ 3 = %.2Lf\n", pow(7.0,3.0)); 
              printf ("4.73 ^ 12 = %.2Lf\n", pow(4.73,12.0));
              printf ("32.01 ^ 1.54 = %.2Lf\n", pow(32.01,1.54));
              return 0;
          }
          And also, because of the problem I learned something odd. If you are going to compile with Cygwin's gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125) make sure to add (long double) type casting before pow(4.73,12.0) if you are going to directly printf it using %Lf. But if you're going to use MinGW's gcc (GCC) 4.5.1, you must not put (long double) type casting before pow(4.73,12.0) if you are going to directly printf it using %Lf. But both ways work with VSC++. :D

          I'm just a newbie here and without the help of the many people who replied I could not have found the idea about the getchar() to solve this problem. I didn't know there really are a lot of good people around the internet. And seriously, I'm really sorry for those who I have annoyed because i sent the same thread to many forums. Thank you guys. THIS THREAD IS SOLVED. :D
          Last edited by Bangonkali; Dec 12 '10, 09:35 PM. Reason: Updated with the odd difference if found out.

          Comment

          • AdrianH
            Recognized Expert Top Contributor
            • Feb 2007
            • 1251

            #6
            Please look at the bug report with the test code I submitted. It is a bug. It should not be responding that way.


            A

            Comment

            • Bangonkali
              New Member
              • Dec 2010
              • 7

              #7
              This thread is solved

              THIS THREAD IS SOLVED You were using %lf for long double. It should be %Lf. As noted, the status of your bug report is RESOLVED INVALID, which basically means, it was a false report. Once again, for long double, use %Lf and not %lf. I commited that mistake in my first post, which lead me to believe it was a bug. I've learned a lot since then though. And bte, thank you so much for clarifying your point, I missed it out in the first post. THIS THREAD IS SOLVED

              Comment

              • AdrianH
                Recognized Expert Top Contributor
                • Feb 2007
                • 1251

                #8
                Well, I've retested with %Lf with the same results and resubmitted the bug. Looks like gcc 4.5.0 doesn't recognise %Lf for scanf, so it is either a bug or it hasn't been implemented yet. Also, to get printf to recognise %Lf, you need to change the standard settings with compiler flag -std=c99.

                Something else I forgot to do, but always did when I was using gcc is to use the -Wall switch. This will pick up many inadvertent errors in the code.


                A

                [edit]bug has been resubmitted.

                Comment

                • AdrianH
                  Recognized Expert Top Contributor
                  • Feb 2007
                  • 1251

                  #9
                  Also, IIRC, white spaces are ignored unless expressly stated not to be. I.e. use %[ a-zA-Z_0-9] as a format string. So, your solution is a workaround, not a code correct solution.


                  A

                  Comment

                  • Bangonkali
                    New Member
                    • Dec 2010
                    • 7

                    #10
                    Yes you do have a point there.

                    Comment

                    • Bangonkali
                      New Member
                      • Dec 2010
                      • 7

                      #11
                      This thread is solved

                      This thread is solved. Yes, I think this article explains things very clearly. Following is a quote from the article

                      After months of experimentation , I have settled on MinGW/MSYS as the best development environment for my purposes. Its advantages include the following:
                      Full support (for internal calculations) of 80-bit long doubles (including transcendentals ) and 64-bit integers; note, however, that the printf/scanf family produces erroneous results for long doubles, and uses peculiar syntax for 64-bit integers.
                      Disadvantages of the MinGW/MSYS environment include the following:
                      The printf/scanf family of functions is unable to correctly handle the 80-bit long double floating point variables native to the x86 Intel processors and FPUs (and compatible processors, such as AMD). Either the value must be cast to double and printed, with resulting loss of precision (16 digits rather than 19), or a custom function must be employed for the purpose.
                      I am only experiencing these problems because I'm using Cygwin and MinGW gcc versions when testing my code. And yes I think this is a bug, and very clearly needs fixing. Since they're offering long double datatype, they should at least make scanf and printf work with it. Anyway, thanks for the follow up.

                      And also, I found out the most efficient solution for my problem which is requiring very high precision mathematical calculations as suggested by the article. By using GMP 4.3.1 and MPFR 2.4.1 I was able to use very high precision datatypes from its libraries without problems with printf() and scanf(). I am posting an example below.

                      The following codes will be solving this series:
                      Code:
                      1 + (1 / 1!) + (1 / 2!) + ... + (1 /100!)
                      Solving the problem with stdio.h only:
                      Code:
                      #include <stdio.h>
                      int main (void)
                      {
                        unsigned int i;
                        double s, t, u;
                      
                        t = 1;
                        s = 1;
                        u = 1;
                      
                        for (i = 1; i <= 100; i++)
                          {
                              t = t * i;
                              u = 1;
                              u = u / t;
                              s = s + u;
                          }
                      
                        printf ("Sum is %lf \n", s);
                        return 0;
                      }
                      Solving the series using GMP 4.3.1 and MPFR 2.4.1 (CYGWIN):

                      Code:
                      #include <stdio.h>
                      
                      #include <gmp.h>
                      #include <mpfr.h>
                      
                      int main (void)
                      {
                        unsigned int i;
                        mpfr_t s, t, u;
                      
                        mpfr_init2 (t, 200);
                        mpfr_set_d (t, 1.0, GMP_RNDD);
                        mpfr_init2 (s, 200);
                        mpfr_set_d (s, 1.0, GMP_RNDD);
                        mpfr_init2 (u, 200);
                        for (i = 1; i <= 100; i++)
                          {
                            mpfr_mul_ui (t, t, i, GMP_RNDU);
                            mpfr_set_d (u, 1.0, GMP_RNDD);
                            mpfr_div (u, u, t, GMP_RNDD);
                            mpfr_add (s, s, u, GMP_RNDD);
                          }
                        printf ("Sum is ");
                        mpfr_out_str (stdout, 10, 0, s, GMP_RNDD);
                        putchar ('\n');
                        mpfr_clear (s);
                        mpfr_clear (t);
                        mpfr_clear (u);
                        return 0;
                      }
                      Output after compiling first code with gcc 3.4.4:
                      Code:
                      Sum is 2.718282
                      The second code:
                      Code:
                      Sum is 2.7182818284590452353602874713526624977572470936999595749669131
                      We can observe the sheer precision with 200 bit representation of double in this case compared to the standard double as shown in the first result from the first code.

                      I tried everything under Cygwin. But do note that you'll need to have the GMP ang MPFR libraries added during setup. Finally in order to compile the second code (the one using GMP and MPFR), if you've already installed GMP and MPFR use the following command:
                      Code:
                      gcc mpfr_sample.c -o mprfr_sample.exe -lmpfr -lgmp
                      For more information regarding the libraries visit MPFR Main Website and for the sample. I hope this will help everyone who are doing precision arithmetic for scientific research.
                      Last edited by Bangonkali; Dec 13 '10, 10:02 AM. Reason: Added GMP and MPFR finds for everyone to know about.

                      Comment

                      • AdrianH
                        Recognized Expert Top Contributor
                        • Feb 2007
                        • 1251

                        #12
                        Cool, so what sort of scientific research are you doing that requires this sort of precision?


                        A

                        Comment

                        • Bangonkali
                          New Member
                          • Dec 2010
                          • 7

                          #13
                          This is for my Math research. Mostly pure math. Calculating series and sequences. Taylor's, Maclaurin's and Binomial series. I need some way to verify calculation to the n'th decimal place without loss of integrity. I'm still testing this though.

                          Comment

                          Working...