By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,959 Members | 1,139 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,959 IT Pros & Developers. It's quick & easy.

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

Bangonkali
P: 7
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.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <math.h>
  3. int main()
  4. {
  5.     long double r = 0;
  6.     long double p = 0;
  7.  
  8.     printf ("Enter a number: ");
  9.     scanf ("%lf", &r);
  10.     printf ("Enter its power: ");
  11.     scanf ("%lf", &p);
  12.     printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p));
  13.  
  14.     printf ("7 ^ 3 = %lf\n", pow (7.0,3.0));
  15.     printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0));
  16.     printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));
  17.     return 0;
  18. }
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)
Expand|Select|Wrap|Line Numbers
  1. Enter a number: 5
  2. Enter its power: 3
  3. 5.000000 to the power of 0.000000 = 0.000000
  4. 7 ^ 3 = 343.000000
  5. 4.73 ^ 12 = 125410439.217423
  6. 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.
Expand|Select|Wrap|Line Numbers
  1. Enter a number: 5
  2. Enter its power: 3
  3. 5.000000 to the power of 3.000000 = 125.000000
  4. 7 ^ 3 = 343.000000
  5. 4.73 ^ 12 = 125410439.217423
  6. 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.
Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <math.h>
  3. int main()
  4. {
  5.     char line[100];
  6.     long double r = 0;
  7.     long double p = 0;
  8.  
  9.     printf ("Enter a number: ");
  10.     fgets(line,sizeof(line),stdin);
  11.     sscanf(line,"%lf",&r);
  12.  
  13.     printf ("Enter its power: ");
  14.     fgets(line,sizeof(line),stdin);
  15.     sscanf(line,"%lf",&p);
  16.  
  17.     printf ("%lf to the power of %lf = %lf\n", r, p, pow(r, p));
  18.  
  19.     printf ("7 ^ 3 = %lf\n", pow (7.0,3.0));
  20.     printf ("4.73 ^ 12 = %lf\n", pow (4.73,12.0));
  21.     printf ("32.01 ^ 1.54 = %lf\n", pow (32.01,1.54));
  22.     return 0;
  23. }
Using the gcc compiler of MinGW this is the result: (MinGW gcc (GCC) 4.5.1)
Expand|Select|Wrap|Line Numbers
  1. Enter a number: 5
  2. Enter its power: 3
  3. 5.000000 to the power of 0.000000 = 0.000000
  4. 7 ^ 3 = 343.000000
  5. 4.73 ^ 12 = 125410439.217423
  6. 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:
Expand|Select|Wrap|Line Numbers
  1. Enter a number: 5
  2. Enter its power: 3
  3. 5.000000 to the power of 3.000000 = 125.000000
  4. 7 ^ 3 = 343.000000
  5. 4.73 ^ 12 = 125410439.217423
  6. 32.01 ^ 1.54 = 208.036691
Dec 11 '10 #1

✓ answered by AdrianH

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


A

Share this Question
Share on Google+
12 Replies


Expert 100+
P: 2,396
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.
Dec 12 '10 #2

AdrianH
Expert 100+
P: 1,251
No, looks like a bug. Submitting to gcc bugzilla. Bug 46908


A
Dec 12 '10 #3

Bangonkali
P: 7
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:

Expand|Select|Wrap|Line Numbers
  1. scanf( "%lf %lf", &r, &p );
I edited my original code to work like this:

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <math.h>
  3. int main()
  4. {
  5.     // my personal troubles with long double
  6.     // while using gcc under cygwin and mingw
  7.     long double r = 0;
  8.     long double p = 0;
  9.     long double a = 0;
  10.  
  11.     printf ("Enter a number <space> power: ");
  12.     scanf( "%Lf %Lf", &r, &p );
  13.  
  14.     // r to the power of p
  15.     a = pow(r,p);
  16.  
  17.     printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a);
  18.     printf ("7 ^ 3 = %.2Lf\n", (long double)pow(7.0,3.0));
  19.     printf ("4.73 ^ 12 = %.2Lf\n", (long double)pow(4.73,12.0));
  20.     printf ("32.01 ^ 1.54 = %.2Lf\n", (long double)pow(32.01,1.54));
  21.     return 0;
  22. }
Now it works perfectly fine with the following output when compiled with gcc both from MinGW and Cygwin.

Expand|Select|Wrap|Line Numbers
  1. 5.00 to the power of 3.00 = 125.00
  2. 7 ^ 3 = 343.00
  3. 4.73 ^ 12 = 125410439.22
  4. 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.
Dec 12 '10 #4

Bangonkali
P: 7
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.

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. #include <math.h>
  3. int main()
  4. {
  5.     // my personal troubles with long double
  6.     // while using gcc under cygwin and mingw
  7.     long double r = 0;
  8.     long double p = 0;
  9.     long double a = 0;
  10.  
  11.     //printf ("Enter a number <space> power: ");
  12.     //scanf( "%lf %lf", &r, &p );
  13.  
  14.     printf ("Enter a number: ");
  15.     scanf( "%Lf", &r);
  16.  
  17.     printf ("Enter a number: ");
  18. getchar();    
  19.     scanf( "%Lf", &p );
  20.  
  21.     // r to the powler of p
  22.     a = pow(r,p);
  23.  
  24.     // put (long double) typecast before pow if you're
  25.     // printing pow directly on printf and you're using
  26.     // Cygwin's gcc (GCC) 3.4.4. You may not edit this 
  27.     // code if you're compiling on VSC++ or MinGW's gcc 
  28.     // (GCC) 4.5.1
  29.     printf ("%.2Lf to the power of %.2Lf = %.2Lf\n", r, p, a);
  30.     printf ("7 ^ 3 = %.2Lf\n", pow(7.0,3.0)); 
  31.     printf ("4.73 ^ 12 = %.2Lf\n", pow(4.73,12.0));
  32.     printf ("32.01 ^ 1.54 = %.2Lf\n", pow(32.01,1.54));
  33.     return 0;
  34. }
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
Dec 12 '10 #5

AdrianH
Expert 100+
P: 1,251
Please look at the bug report with the test code I submitted. It is a bug. It should not be responding that way.


A
Dec 12 '10 #6

Bangonkali
P: 7
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
Dec 12 '10 #7

AdrianH
Expert 100+
P: 1,251
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.
Dec 12 '10 #8

AdrianH
Expert 100+
P: 1,251
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
Dec 12 '10 #9

Bangonkali
P: 7
Yes you do have a point there.
Dec 12 '10 #10

Bangonkali
P: 7
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:
Expand|Select|Wrap|Line Numbers
  1. 1 + (1 / 1!) + (1 / 2!) + ... + (1 /100!) 
Solving the problem with stdio.h only:
Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2. int main (void)
  3. {
  4.   unsigned int i;
  5.   double s, t, u;
  6.  
  7.   t = 1;
  8.   s = 1;
  9.   u = 1;
  10.  
  11.   for (i = 1; i <= 100; i++)
  12.     {
  13.         t = t * i;
  14.         u = 1;
  15.         u = u / t;
  16.         s = s + u;
  17.     }
  18.  
  19.   printf ("Sum is %lf \n", s);
  20.   return 0;
  21. }
Solving the series using GMP 4.3.1 and MPFR 2.4.1 (CYGWIN):

Expand|Select|Wrap|Line Numbers
  1. #include <stdio.h>
  2.  
  3. #include <gmp.h>
  4. #include <mpfr.h>
  5.  
  6. int main (void)
  7. {
  8.   unsigned int i;
  9.   mpfr_t s, t, u;
  10.  
  11.   mpfr_init2 (t, 200);
  12.   mpfr_set_d (t, 1.0, GMP_RNDD);
  13.   mpfr_init2 (s, 200);
  14.   mpfr_set_d (s, 1.0, GMP_RNDD);
  15.   mpfr_init2 (u, 200);
  16.   for (i = 1; i <= 100; i++)
  17.     {
  18.       mpfr_mul_ui (t, t, i, GMP_RNDU);
  19.       mpfr_set_d (u, 1.0, GMP_RNDD);
  20.       mpfr_div (u, u, t, GMP_RNDD);
  21.       mpfr_add (s, s, u, GMP_RNDD);
  22.     }
  23.   printf ("Sum is ");
  24.   mpfr_out_str (stdout, 10, 0, s, GMP_RNDD);
  25.   putchar ('\n');
  26.   mpfr_clear (s);
  27.   mpfr_clear (t);
  28.   mpfr_clear (u);
  29.   return 0;
  30. }
Output after compiling first code with gcc 3.4.4:
Expand|Select|Wrap|Line Numbers
  1. Sum is 2.718282
The second code:
Expand|Select|Wrap|Line Numbers
  1. 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:
Expand|Select|Wrap|Line Numbers
  1. 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.
Dec 13 '10 #11

AdrianH
Expert 100+
P: 1,251
Cool, so what sort of scientific research are you doing that requires this sort of precision?


A
Dec 13 '10 #12

Bangonkali
P: 7
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.
Dec 13 '10 #13

Post your reply

Sign in to post your reply or Sign up for a free account.