Pascal's Triangle returning nonsense values - c

This is a homework project I was assigned some time ago... I've been successful in getting this far on my own, and the only hiccup I have left is (I believe) an issue with data types and overflow.
I've tried changing over to unsigned and double, and the code complies and still accepts input in the terminal, but it seems to hang up after that... nothing is printed and it looks like it's caught in a loop.
Here is the code...
/* pascaltri.c
* A program that takes a single integer as input and returns the nth line of
* Pascal's Triangle. Uses factorial() function to help find items of
* individual entries on a given row.
*/
#include <stdio.h>
#include <stdlib.h>
long factorial(long i)
{
long fact = 1;
while(i > 1)
{
fact = fact * i;
i = i - 1;
}
return fact;
}
main(void)
{
long n;
long *nPtr;
nPtr = &n;
scanf(" %i", nPtr);
if (n >= 0)
{
long k;
long *kPtr;
kPtr = &k;
for(k = 0; k <= n; k++)
{
long ans;
long *ansPtr;
ansPtr = &ans;
ans = factorial(n) / (factorial(k) * factorial(n - k));
printf("\n %i", ans);
}
return 0;
}
return 0;
}
It's not perfect or pretty, but it works up to an input of 13 (that is, row 14) of the triangle. Beyond that I start getting gibberish and even negative values sprinkled throughout the returns... much larger values break the code and return nothing but an exit error message.
Any ideas on how I can correct this problem? I've been staring at the screen for much to long to really see anything myself. Also, it's not essential, but I would like to print my return values on one line, rather than having them separated by a newline character.
1 5 10 10 5 1
Would the easiest way be to load the values into an array as they are computed, and then print the array? Or is there a built-in way I can tell the print statement to occur on only one line?

You are suffering from integer overflow. You may need to find a different approach to the algorithm to avoid having to calculate the large numbers.
In answer to your other point about the newline, you are explicitly printing the newline with the \n in your print statement. Remove it, and you will get answers printed on one line. You probably want to inlucde a final printf("\n"); at the end so the whole line is terminated in a newline.
Some other observations:
You don't need the first return 0; - the control will drop out of
the bottom of the if block and on to the second (should be only)
return 0; and not cause any problems.
You're declaring kPtr but not using it anywhere
You don't need to declare a separate variable nPtr to pass to scanf; you can pass &n directly.

For the garbage, you are most likely running into an integer overflow, that is, your calculated values become too large for the long data type. You should correct it by calculating your factorial function without explicitely calculating n!.

Change scanf(" %i", nPtr); to
scanf(" %ld", nPtr);
and printf("\n %i", ans); to
printf("\n %ld", ans);
to get printout on one line, use:
printf(" %ld", ans);
If you are using gcc, turn on warnings, i.e. use -Wall.

Related

function declaration and call and definition in c

Why is this code not running after printing of array if I take value of n>=9?
#include <stdio.h>
#include <math.h>
float mean_function(float array[],int n);
int main() {
int i,n;
float array[n],mean,sum=0,s2,summation,deno,C[i],elements;
printf("Enter No of Elements\n");
scanf("%d",&n);
printf("Enter Elements\n");
for(i=0;i<n;i++){
scanf("%f",&array[i]);
printf("%f",array[i]);
}
printf("sample variance(s2) : (sum((x-mean)*(x-mean)))/(n-1) /n");
printf("population variance(sigma2) : (sum((x-u)*(x-u))/n");
mean_function(array,n);
for(i=0;i<n;i++) {
deno=((array[i]-mean)*(array[i]-mean));
C[i]=deno;
summation=summation+C[i];
}
s2=((summation)/(n-1));
printf("s2=%f \n",s2);
}
float mean_function(float array[],int n) {
int i;
float sum=0,mean;
for(i=0;i<n;i++){ sum=sum+array[i]; }
mean=(sum/n);
return mean;
}
Why is this code not running after printing of array if I take value
of n>=9?
Some thoughts about your code (and about building programs in steps):
Arrays in C don't change in size once defined. VLAs are out for a variety of reasons. malloc() is in.
Use double, unless there is a specific reason to use floats.
Define and initialize one variable per line. Uninit vars can only result in an error as mentioned by #Jens.
Function declarations at the top (which you have done)
During development, there is no need to complicate things with a scanf (at least initially). It only adds an unwarranted layer of complexity. If you are testing statistical functions (mean, variance), put numbers in a pre-defined static array and verify functionality first.
C[i] as been declared with uninitialized i.
For this initial phase of building this program, I include a basic program.
I am not a fan of zero space between tokens (but ignore that)
Consider calling your array something other than 'array'.
Calculating the size of the samples array allows you to change the number of elements without changing anything else in code; which adds another layer of complexity to an already difficult phase.
#include <stdio.h>
#include <math.h>
double sample_mean(double* p, int n);
int main()
{
double samples[] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 16.5, 2.3};
double mean = 0.0;
int size_samples = sizeof samples/sizeof(double);
printf("size_samples = %d\n", size_samples);
mean = sample_mean(samples, size_samples);
printf("Mean = %.2lf", mean);
}
// -------------------------------
double sample_mean(double* p, int n)
{
double mean = 0.0;
double total = 0.0;
for(int i = 0; i < n; i++)
total += *p++;
mean = total/n;
return mean;
}
Once this functionality is present (saved), you can start working on other stat functions. This way you can work step by step to get closer to the desired outcome.
Next up you can define sample_variance(double* p, int n) and work on that knowing that additional(new errors) are not coming from your code written so far.
Output:
size_samples = 8
Mean = 5.24
I hope it helps.
The code is likely not running because array[n] is declared with an uninitialized n. At the time you read n with scanf(), the array does not automatically "grow into the right size". You should either declare array big enough, or if you really want it to be user-defined, use malloc to allocate it (read the comp.lang.c FAQ) and all Stackoverflow questions tagged array...)
In addition, the scanf at some point fails. Note that when you enter numbers, you also have the "Enter" as a newline ('\n') in the input stream. You never read the newline so the next scanf fails.
This becomes obvious when you actually check the return value from scanf with code like this:
if (scanf("%f", &array[i]) == 1) {
/* successfully converted 1 item */
}
else {
/* scanf failed */
}
Usually what you want is to skip whitespace in the input. You do this by placing a space in the scanf format. Note that a single space tells scanf to skip any amount of white-space.
if (scanf(" %f", &array[i]) == 1) {

Why does c print a different array the second time it's printed?

My cousin has a school project and we can't figure out why is the array different the second time it's printed when there is no values changing in between?
Basically you enter a number which states how many rows/columns will the matrix have, and during first loop he assigns a number to every position and prints out the random number. However, the second time we go through the matrix the numbers are different and it seems that they are copied through the matrix from bottom left corner to top right corner for some reason. It seems strange to us because we never assign a different value to a position in the array after defining it for the first time.
int i,j,n,matrica[i][j],suma=0;
srand(time(NULL));
printf("\nunesi prirodan broj N[3,20] = \n");
scanf("%d",&n);
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
matrica[i][j]=rand()%100;
printf("%d, %d = %4d ",i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
printf("\n");
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d, %d = %4d ", i, j, matrica[i][j]);
if(j==n-1) {
printf("\n");
}
}
}
And here is the result of this (the code I pasted here has 2 prints, and in the image there is 3 but every time you go through the matrix after the first time it's going to be the same):
We need to use malloc to allocate the dynamic amount of memory.
After
scanf("%d",&n) // PS You should check the return value - read the manual page
Put
matrica = malloc(sizeof(int) * n * n);
And declare it as
int *matrica;
Then replace
matrica[i][j]
with
matrica[i * n + j]
And after you have finished with matrica - use free i.e.
free(matrica);
int i,j,n,matrica[i][j]
At this point I must ask, what value do you think i and j will have? Right there you're invoking undefined behaviour by referring to variables declared with automatic storage duration which you've not initialised. Anything after this point is... undefined behaviour.
Having said that, I noticed a few other parts that look strange. Which book are you reading? The reason I ask is that the people I know to be reading reputable textbooks don't have these problems, thus your textbook (or resource, whatever) mustn't be working for you...
I can't read the commentary inside of the string literals, which is a shame, since that's usually quite valuable contextual information to have in a question. Nonetheless, moving on, if this were me, I'd probably declare a pointer to an array n of int, after asking for n, like so:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t n;
printf("Enter n, please: ");
fflush(stdout);
if (scanf("%zu", &n) != 1 || n == 0 || SIZE_MAX / n < n) {
puts("Invalid input or arithmetic overflow...");
return -1;
}
int (*array)[n] = malloc(n * sizeof *array);
if (!array) {
puts("Allocation error...");
return -1;
}
/* now you can use array[0..(n-1)][0..(n-1)] as you might expect */
free(array);
}
This should work for quite high numbers, much higher than int array[n][n]; would in its place... and it gives you that option to tell the user it was an "Allocation error...", rather than just SIGSEGV, SIGILL, SIGBUS or something...
... but nothing would be more optimal than just saving the seed you use to generate the random numbers, and the user input; that's only two integers, no need for dynamic allocation. There's no point storing what rand generates, amd you realise this, right? rand can generate that output purely using register storage, the fastest memory commonly available in our processors. You won't beat it with arrays, not meaningfully, and not... just not.

Error when using array elements in conditional statements in C

I have done my fair share of studying the C language and came across this inconsistency for which I cannot account. I have searched everywhere and reviewed all data type definition and relational syntax, but it is beyond me.
From the book C How to Program, there is a question to make a binary to decimal converter where the input must be 5-digits. I developed the follow code to take in a number and, through division and remainder operations, split it into individual digits and assign each to an element in of an array. The trouble arises when I try to verify that the number entered was indeed binary by checking each array element to see whether it is a 1 or 0.
Here is the code:
#include <stdio.h>
int power (int x, int y); //prototype
int main(void)
{
int temp, bin[5], test;
int n=4, num=0;
//get input
printf("%s","Enter a 5-digit binary number: ");
scanf("%d", &temp);
//initialize array
while(n>=0){
bin[n]=temp/power(10,n);
temp %= power(10,n);
n--; }
//verify binary input
for (test=4; test>=0; test--){
if ((bin[n]!=0)&&(bin[n]!=1)){
printf("Error. Number entered is not binary.\n");
return 0; }
//convert to decimal
while(n<=4){
num+=bin[n]*power(2,n);
n++; }
printf("\n%s%d\n","The decimal equivalent of the number you entered is ",num);
return 0;
}
//function definition
int power(int x, int y)
{
int n, temp=x;
if(y==0) return 1;
for(n=1; n<y; n++){
temp*=x; }
return temp;
}
Could someone explain to me why regardless of input (whether: 00000, or 12345), I always get the error message? Everything else seems to work fine.
Thank you for your help.
Update: If the if statement is moved to the while loop before. This should still work right?
Update2: Never mind, I noticed my mistake. Moving the if statement to the while repetition before does work given the solution supplied by sps and Kunal Tyagi.
After this
while(n>=0){
bin[n]=temp/power(10,n);
temp %= power(10,n);
n--; }
n is set as -1 so when you try to convert to decimal the statement bin[n] is actually bin[-1] so it returns you error.
One issue is that, while checking if the number is binary or not, you are returning at wrong place. You need to return only if the number is not binary. But you are returning outside the if condition. So your program returns no matter what the input is.
for (test=4; test>=0; test--){
if ((bin[test]!=0)&&(bin[test]!=1))
printf("Error, numbered entered was not binary.\n");
// Issue here, you are returning outside if
return 0; } //exit program
You can change that to:
for (test=4; test>=0; test--){
if ((bin[test]!=0)&&(bin[test]!=1)) {
printf("Error, numbered entered was not binary.\n");
// Return inside the if
return 0; // exit program
}
}
There is one more issue. Before you convert your number to decimal, you need to set n = 0;
//convert to decimal
n = 0; /* need to set n to zero, because by now
n will be -1.
And initially when n is -1, accessing
bin[-1] will result in undefined behavior
*/
while(n<=4){
num+=bin[n]*power(2,n);
n++; }
This looks like a homework, but your issue is in the brackets. More specifically line 23. That line is not part of the logical if statement despite the indentation (since that doesn't matter in C).
No matter what, the program will exit on test=4 after checking the condition.
Solution:
if ((bin[test]!=0)&&(bin[test]!=1)) { // << this brace
printf("Error, number entered was not binary.\n");
return 0; } } //exit program // notice 2 braces here

why runtime error on online judge?

I am unable to understand why i am getting runtime error with this code. Problem is every number >=6 can be represented as sum of two prime numbers.
My code is ...... Thanks in advance problem link is http://poj.org/problem?id=2262
#include "stdio.h"
#include "stdlib.h"
#define N 1000000
int main()
{
long int i,j,k;
long int *cp = malloc(1000000*sizeof(long int));
long int *isprime = malloc(1000000*sizeof(long int));
//long int *isprime;
long int num,flag;
//isprime = malloc(2*sizeof(long int));
for(i=0;i<N;i++)
{
isprime[i]=1;
}
j=0;
for(i=2;i<N;i++)
{
if(isprime[i])
{
cp[j] = i;
j++;
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
}
}
//for(i=0;i<j;i++)
//{
// printf("%d ",cp[i]);
//}
//printf("\n");
while(1)
{
scanf("%ld",&num);
if(num==0) break;
flag = 0;
for(i=0;i<j&&num>cp[i];i++)
{
//printf("%d ",cp[i]);
if(isprime[num-cp[i]])
{
printf("%ld = %ld + %ld\n",num,cp[i],num-cp[i]);
flag = 1;
break;
}
}
if(flag==0)
{
printf("Goldbach's conjecture is wrong.\n");
}
}
free(cp);
free(isprime);
return 0;
}
Two possibilities immediately spring to mind. The first is that the user input may be failing if whatever test harness is being used does not provide any input. Without knowing more detail on the harness, this is a guess at best.
You could check that by hard-coding a value rather than accepting one from standard input.
The other possibility is the rather large memory allocations being done. It may be that you're in a constrained environment which doesn't allow that.
A simple test for that is to drop the value of N (and, by the way, use it rather than the multiple hardcoded 1000000 figures in your malloc calls). A better way would be to check the return value from malloc to ensure it's not NULL. That should be done anyway.
And, aside from that, you may want to check your Eratosthenes Sieve code. The first item that should be marked non-prime for the prime i is i + i rather than i * i as you have. I think it should be:
for (k = i + i; k < N; k += i)
The mathematical algorithm is actually okay since any multiple of N less than N * N will already have been marked non-prime by virtue of the fact it's a multiple of one of the primes previously checked.
Your problem lies with integer overflow. At the point where N becomes 46_349, N * N is 2_148_229_801 which, if you have a 32-bit two's complement integer (maximum value of 2_147_483_647), will wrap around to -2_146_737_495.
When that happens, the loop keeps going since that negative number is still less than your limit, but using it as an array index is, shall we say, inadvisable :-)
The reason it works with i + i is because your limit is well short of INT_MAX / 2 so no overflow happens there.
If you want to make sure that this won't be a problem if you get up near INT_MAX / 2, you can use something like:
for (k = i + i; (k < N) && (k > i); k += i)
That extra check on k should catch the wraparound event, provided your wrapping follows the "normal" behaviour - technically, I think it's undefined behaviour to wrap but most implementations simply wrap two positives back to a negative due to the two's complement nature. Be aware then that this is actually non-portable, but what that means in practice is that it will only work on 99.999% of machines out there :-)
But, if you're a stickler for portability, there are better ways to prevent overflow in the first place. I won't go into them here but to say they involve subtracting one of the terms being summed from MAX_INT and comparing it to the other term being summed.
The only way I can get this to give an error is if I enter a value greater than 1000000 or less than 1 to the scanf().
Like this:
ubuntu#amrith:/tmp$ ./x
183475666
Segmentation fault (core dumped)
ubuntu#amrith:/tmp$
But the reason for that should be obvious. Other than that, this code looks good.
Just trying to find what went wrong!
If the sizeof(long int) is 4 bytes for the OS that you are using, then it makes this problem.
In the code:
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
Here, when you do k = i*i, for large values if i, the value of k goes beyond 4 bytesand get truncated which may result in negative numbers and so, the condition k<N is satisfied but with a negative number :). So you get a segmentation fault there.
It's good that you need only i+i, but if you need to increase the limit, take care of this problem.

reversing a string of integers user enters (C)

What I want to do is reverse a string of numbers that the user enters. what happens is it compiles and runs till i hit enter after the scanf. then I get some Microsoft runtime error... what's going wrong???
NOTE: this is homework, but i've got the logic figured out. what baffles me is this error.
#include <stdio.h>
int main()
{
unsigned int giveStr = 0;
char* charIt;
printf("Enter a number to be reversed.\t");
scanf("%d", &giveStr);
fflush(stdin);
sprintf(charIt, "%d", giveStr);
revStr(giveStr);
getchar();
return 0;
}
revStr(unsigned int n)
{
char buffer[100];
int uselessvar, counter = 0;
for (; n > 0;)
{
uselessvar = sprintf(&buffer[counter], "%d", n);
counter++;
}
for (counter = 0; counter > 0;)
{
printf("%c", buffer[counter]);
counter--;
}
return 0;
}
EDIT: flushing stdin for newlines :/ and also image here just not with that program. with mine.
You are trying to access memory which is not allocated in:
sprintf(charIt, "%d", giveStr);
Change char* charIt; to char charIt[50]; and all should be well (well, at least the segmentation fault part)
Also... pass charIt to revStr, as charIt contains the string with our number.
Then, a simple for loop in revStr will do the trick (what was the purpose of the second one, anyway?)
void revStr(char *giveStr)
{
int counter;
for (counter = strlen(giveStr)-1; counter >= 0; counter--)
{
printf("%c", giveStr[counter]);
}
printf("\n");
}
This will print each char our char representation has from the last one till the first one. You should read more on for loops.
For your home work problem, if you have the K&R book, turn to section 3.5 and read it thoroughly.
Note the functions reverse() and itoa(). They should give you a pretty good idea on how to solve your problem.
How does your program get out of the for (; n > 0;) loop? Won't counter simply increase until you get a bus error?
ED:
Respectfully, I think the claim that "i've got the logic figured out" is a little optimistic. :^) Doubtless someone will post the way it should have been done
by the time I'm done writing this, but it's probably worth drawing attention to what went wrong (aside from the memory allocation problems noted elsewhere):
Your first loop, "for (; n > 0;)", is strange because you're printing the entire number n into the buffer at counter. So why would you need to do this more than once? If you were selecting individual digits you might, but you're not, and obviously you know how to do this because you already used "sprintf(charIt, "%d", giveStr);". [Aside: giveStr isn't a great name for an unsigned integer variable!]
Your second loop also has strange conditions: you set counter to 0, set the condition that counter > 0, and then decrease counter inside. This obviously isn't going to loop over the characters in the way you want. Assuming you thought the first loop was character-by-character, then maybe you were thinking to loop down from counter-1 to 0?

Resources