Pelles C forum
Pelles C => Bug reports => Topic started by: LaVanTien on April 17, 2015, 10:19:52 AM
-
First, I wrote a program to calculate factorial of a natural number, I know the range of 64-bit integer can handle upto 20!, but the problem is when I run my program under Pelles C it gets wrong answer (very very wrong) for 20!, but others are well result (just 20! doesn't).
(http://i.imgur.com/spPHTmU.jpg)
------------------------------------------------------------------------------------------------------------------------------
I thaught I had a mistake in my code, but not, my code work very perfect on Visual Studio 2013, the program give exactly result for 20!.
(http://i.imgur.com/5ETJhkG.jpg)
------------------------------------------------------------------------------------------------------------------------------
Second, when I use scanf_s function, I get an error although I've already included stdio.h:
(http://i.imgur.com/DLGuPfG.jpg)
------------------------------------------------------------------------------------------------------------------------------
If two of these really are a bugs/errors/misstakes/... I hope two of these will be fixed.
If not, can someone tells me how to find reference to these points or suggest me how to fix this, thanks very much!
------------------------------------------------------------------------------------------------------------------------------
Here is my code:
#include<stdio.h>
#include<windows.h> //Windows enviroment
long long int table[20]; //Reuse previous values to improve performance
long long int fac(int);
void cls(HANDLE hConsole); //Clear screen function
int main(void) {
int n;
HANDLE hStdout;
hStdout=GetStdHandle(STD_OUTPUT_HANDLE);
for (;;) {
cls(hStdout);
fputs("n = ",stdout);
scanf_s("%d",&n); //C11
if (n<0||n>20) { //64-bit integer will only work with factorial of [0..20]
puts("The program has stopped working.");
while ((n=getchar())!=10);
getchar();
break;
}
if (table[n]==0)
table[n]=fac(n);
printf("%d! = %lld\n",n,table[n]);
while ((n=getchar())!=10);
getchar();
}
return 0;
}
long long int fac(int x) {
if (x<2)
return 1;
int i;
long long int t;
t=x;
for (i=2;i<x;i++)
t*=i;
return t;
}
void cls(HANDLE hConsole) {
COORD coordScreen={0,0};
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
if (!GetConsoleScreenBufferInfo(hConsole,&csbi)) {
return;
}
dwConSize=csbi.dwSize.X*csbi.dwSize.Y;
if (!FillConsoleOutputCharacter(hConsole,(TCHAR)' ',dwConSize,coordScreen,&cCharsWritten)) {
return;
}
if(!GetConsoleScreenBufferInfo(hConsole,&csbi)) {
return;
}
if (!FillConsoleOutputAttribute(hConsole,csbi.wAttributes,dwConSize,coordScreen,&cCharsWritten)) {
return;
}
SetConsoleCursorPosition(hConsole,coordScreen);
}
------------------------------------------------------------------------------------------------------------------------------
Ps: I really love Pelles C IDE and always do C projects on it. I find that the code generate by Pelles C fast at least twice if compare with VS, or 1.5 time faster if compare with Code::Blocks (of course on C mode).
-
for scanf_s use #define __STDC_WANT_LIB_EXT1__ 1
PellesC have _clrscr(); in <conio.h>
#include<stdio.h>
long long int fac(int x) {
if (x<2)
return 1;
int i;
long long int t;
t=x;
for (i=2;i<x;i++)
t*=i;
return t;
}
int main(void) {
long long x = fac(20);
printf("%lld\n", x);
return 0;
}
output2432902008176640000
Press any key to continue...
-
There is no problem with long long int.
Your bug is caused by the fact that you go out of bounds when using your long long int table[] array.
In C indexing starts from 0:
int arr[5];
arr[0] = 0; // OK
arr[1] = 0; // OK
arr[2] = 0; // OK
arr[3] = 0; // OK
arr[4] = 0; // OK
arr[5] = 0; // NOT OK, out of bounds!
arr[6] = 0; // NOT OK, out of bounds!
In your case, you save the result for factorial of 20 in table[20] which is not a valid position and may be overwritten (used by other variables). If your program is compiled by Visual Studio, you are lucky and the program doesn't touch that area which is why it seems like everything works fine.
Also a suggestion: why use long long int instead of UINT64 from windows.h or uint64_t from stdint.h?
https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx)
http://en.cppreference.com/w/c/types/integer (http://en.cppreference.com/w/c/types/integer)
-
Your bug is caused by the fact that you go out of bounds when using your long long int table[] array.
Thanks you Snowman, I have just realized how stupid I am.
And now the problem gone out long long int table[21];
8)
Also a suggestion: why use long long int instead of UINT64 from windows.h or uint64_t from stdint.h?
I used to use 'long long int' when need a 64-bit integer, because on my machine 'long long int' will exactly be 64 bit. I didn't know the differents between these 64-bit integer type, nor know about their impact to performance. I always use 'long long int' because of my habit.
for scanf_s use #define __STDC_WANT_LIB_EXT1__ 1
TimoVJL, It still doesn't work :(
(http://farm9.staticflickr.com/8721/17150068636_f1f76bdd75_o.jpg)
------------------------------------------------------------------------------------------------------------------------------
PellesC have _clrscr(); in <conio.h>
When I'm begin learning C, I always be told that I need to avoid conio.h, I know a part of this advice is about conio.h is not portable, nor standard, but I really don't know if I using it, then can I get any impact to performance? I really need performance, so I try to improve it everytime I can ::)
[EDIT] Now it work like a charm LOL, thanks you TimoVJL
#define __STDC_WANT_LIB_EXT1__ 1
#include<stdio.h>
#include<windows.h> //Windows enviroment