At the moment I am coding a program in which I need a variable count that increments every time I call the function. In my case I have a recursive function and want to know how many iterations the program does.
I simplified the code by computing the factorial of a number.
My first approach does not work and ends up with warning messages:
#include <stdio.h>
int factorial(unsigned int i, int *count)
{
*count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, &count);
}
int main()
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, &count));
return 0;
}
warning: passing argument 2 of ‘factorial’ from incompatible pointer type
My second approach does not work either but also does not ends up with any warning messages.
#include <stdio.h>
int factorial(unsigned int i, int count)
{
count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main()
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, count));
return 0;
}
How can I make it run? Any ideas? I use Ubuntu and gcc.
There is no need for static variables, as other solutions suggest. The following is correct:
int factorial(unsigned int i, int *count)
{
*count += 1;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main(void)
{
int i = 10;
int count = 0;
printf("%d Iterations, Factorial of %d is %d\n", count, i, factorial(i, &count));
return 0;
}
One note: as the order of parameter evaluation in the printf statement is not guaranteed, as I understand it the value of count in the call to printf may either be zero (it is passed before factorial was called) or may be 10 (the value after factorial was called). Therefore, main could better be written as:
int main(void)
{
int i = 10;
int count = 0;
int fact= factorial(i, &count);
printf("%d Iterations, Factorial of %d is %d\n", count, i, fact);
return 0;
}
6.5.2.2 Function calls: 10 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
In your first case, factorial() function, count is of type int *. So, while calling the function recursively (in the return statement), do not pass address of count, just pass the count itself.
That said, as count is to be modified in the function call of factorial(), don't pass both of them (the variable and the function call which modifies the variable) in the same argument list as there is no sequence point in the elements passed as argument list, so you'll end up invoking undefined behavior.
Declare the count variable as static inside the factorial function itself.
static int count = 0;
There are two ways of solving this problem.
Declare a static variable in the recursive function to count the no of times it is called.
e.g.
int factorial(unsigned int i, int *count)
{
static int count2;
*count = ++count2;
if(i <= 1)
{
return 1;
}
return i * factorial(i - 1, count);
}
int main()
{
int i = 10;
int count = 0, fact;
fact = factorial(i, &count);
printf("%d Iterations, Factorial of %d is %d\n", count, i, fact);
return 0;
}
Have count as a pointer to integer, which can then be updated in each function to find the number of iterations.
e.g.
int factorial(unsigned int i, int *count)
{
(*count)++;
// Remaining lines the same as first solution.
}
The second solution will only work in some special types of recursive functions where the first function calls the second and the second calls the third, etc. It will not work for example in a recursive fibbonaci sequence algorithm.
The first solution is a more general one, and will work for all conditions.
Related
This is the question "Write a function which gets an integer array and number of elements as parameters and calculates and displays sum and average of all the integers of the array in C language"
Below is the code which I have done, it's running but consists of bugs which give false answers
#include <stdio.h>
void SumAvg(int x, int arr[x]) {
int i, sum = 0;
float avg = 0;
for (i = 0; i < x; ++i) {
sum += arr[i];
}
avg = (float)sum / x;
printf("The sum is %d", sum);
printf("\nThe average is %.2f", avg);
}
int main() {
int x, i;
printf("Enter number of elements");
scanf("%d", &x);
int arr[x];
for (i = 0; i < x; ++i) {
printf("Enter integers for array[%d]", i + 1);
scanf("%d", &arr[i]);
}
SumAvg(x, arr[x]);
return 0;
}
First , your function calling is wrong .It should be SumAvg(x,arr) instead of SumAvg(x, arr[x]);.
also in function declaration , in some compiler void SumAvg(int x, int arr[x]) might be problematic.
For starters the function should be declared the following way
void SumAvg( const int arr[], size_t n );
That is the parameter that declares the array shall have the qualifier const because the array is not changed in the function.
The number of elements of the array should have the type size_t.
The function definition can look the following way
void SumAvg( const int arr[], size_t n )
{
long long int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
sum += arr[i];
}
double avg = n == 0 ? 0 : ( double )sum / n;
printf( "The sum is %lld\n", sum );
printf( "The average is %.2f\n", avg );
}
That is within the function the variable sum should have the type long long int to decrease the risk of overflow.
In general the user can pass to the function the number of elements equal to 0. In this case if not to check this value the function will have undefined behavior.
This call of the function
SumAvg(x, arr[x]);
is invalid because instead of passing the array you are passing its non-existent element with the index x.
Taking into account the provided function definition above a valid call of the function will look like
SumAvg( arr, x );
Basically I have a function called MinSubTab that is supposed to calculate the sum of the array passed and also to change the value passed in the first argument from inside the function without using return. This is done with pointers. Anyway, I think it'd be easier if I just showed you the code so here it is:
maintab.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "tab.h"
int main(){
int *reftab;
int min;
reftab = (int *)malloc(sizeof(int) * NMAX);
InitTab(reftab,NMAX);
printf("\n Total: %d et min: %d", MinSumTab(&min, reftab, NMAX), min);
free(reftab);
return 0;
}
tab.c
void InitTab(int *tab, int size){
srand(time(NULL));
for (int i=0; i<size; i++){
*(tab+i) = rand() % 10;
}
}
int MinSumTab(int *min, int *tab, int size){
int total=0;
int minimum = NMAX;
int temp = *min;
for (int i=0; i<size; i++){
total += *(tab+i);
}
for (int i=0; i<size; i++){
if(*(tab+i)<minimum){
minimum = *(tab+i);
}
}
*min = minimum;
return total;
}
So the expected result here is that the sum is printed (which it is) and the minimum value of the array is printed (which it is not). Every single time the min variable equals 8 and I've no idea how to actually change the value of min from within that function.
Please help as my brain has no more capacity for rational thought, it's been 1.5 hrs and no solution in sight. Thanks
Looks like a small mistake:
You initialize minimum with NMAX, which I assume is 8 (the size of the array). 99.9% of the random numbers will be bigger. So 8 is chosen as the minimum.
What you really want is to initialize it with RAND_MAX – the maximum value rand() can return.
In C order of evaluation and argument passing is undefined.
You can of course the order yourself but it only to feed your curiosity.
#include <stdio.h>
volatile char *message[] = {
"fisrt", "second", "third", "fourth"
};
int print(size_t x)
{
printf("%s\n", message[x]);
return x;
}
int main()
{
printf("%d %d %d %d\n", print(0), print(1), print(2), print(3));
return 0;
}
Note. There is one exception from this rule.
Logical operators are evaluated form the left to the right.
if( x != NULL && *x == 5)is safe because x will not be dereferenced if it is NULL
I'm trying to do a program that will do a sum for an array. If i put a printf in the function, it returns right, but at the final the result is incorrect. Why?
#include <stdio.h>
int summ(int a[100],int n)
{
static int sum=0;
static int i=0;
if(i<n)
{
sum+=a[i];
++i;
return (summ(a,n)+sum);
}
}
int main()
{
int b[100];
int n,i,suma;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&b[i]);
}
suma=summ(b,n);
printf("Suma=%d",suma);
return 0;
}
Compiling your code with warnings enabled should yield the following output:
program.c:13:1: warning: control may reach end of non-void function [-Wreturn-type]
This means that your summ function lacks a base case - i.e. it does not specify what should be returned once n is reached.
Once you fix this problem, your code starts returning the correct value. However, your function would still need some fixing, because you should not be using static variables in it. Any static variable in a function makes the function non-reentrant, which is very bad. In particular, your function can be run only once; second invocation would yield an error, because neither i nor sum could be reset.
Here is a simple recursive implementation of what you are looking to build:
int summ_impl(int a[], size_t i, size_t n) {
return i != n ? a[i] + summ_impl(a, i+1, n) : 0;
}
int sum(int a[], size_t n) {
return summ_impl(a, 0, n);
}
With recursion:
int summ(int *a, int n) {
if (n-- > 0)//the n is equal to n-1 after check condition
return (summ(a,n) + a[n]);//return the n-1 sum (recursion) + current value
return (0);
}
This way, the function will call itself while it not equal to zero (so between n and 0)
So we got:
a = [1,2,3]
the function will return
3 + sum before
-> 2 + sum before
-> 1 + sum before
-> 0
When the function go back in the stack
0 + 1 + 2 + 3 -> 6
I've written a program for a class and am having a problem. The purpose of the program is to read a set of values into an array, calculate the average, and then find how many elements in that array are larger than that average. The function prototypes were provided so that cannot be changed. Also, we were instructed to initialize the array to size 10 and double the size whenever the number of read elements exceeds the current size, so that cannot be changed.
The problem I'm running into is returning a value from the aboveaverage function. It works properly within itself (I can put a printf to display count before return, but in the main function, the value being returned is 0. Is there anyone that can help with this please? It's getting frustrating.
Also, the commented printf line was to check the value being returned by the function. I commented it out instead of deleting it so I wouldn't have to retype it every time.
#include <stdio.h>
#include <stdlib.h>
double average(double *ptr, int size);
int aboveaverage(double *ptr, int size, double average);
int main(int argc, char* argv[])
{
double *ptr, avg, above, temp;
int size = 10, i, j;
void *tmp;
FILE *fp;
avg = above = 0;
if (argc != 2)
{
printf("Invalid number of arguments, 2 required\n");
return 1;
}
fp = fopen(argv[1], "r");
ptr = (double *)calloc(10, sizeof(double));
printf("Allocated 10 doubles\n");
for (i = 0;fscanf(fp, "%lf", &temp) != EOF; i++)
{
if (i >= size - 1)
{
size*=2;
tmp = realloc(ptr, size);
if (tmp == NULL)
{
printf("Error with realloc, exiting\n");
return 1;
}
printf("Reallocated to %d doubles\n", size);
}
ptr[i] = temp;
j = i;
}
size = j + 1;
avg = average(ptr, size);
above = aboveaverage(ptr, size, avg);
//printf("%d\n", above);
printf("%d elements are above average of %lf\n", above, avg);
free(ptr);
return 0;
}
double average(double *ptr, int size)
{
double sum;
int i;
while (i < size)
{
sum+=ptr[i];
i++;
}
return (sum / size);
}
int aboveaverage(double *ptr, int size, double avg)
{
int count=0, temp;
for (int i = 0; i < size; i++)
{
temp = (int)ptr[i];
if (temp > avg)
count++;
}
return count;
}
So other answers have already pointed out where the problem is and how exactly can it be fixed.
printf("%d elements are above average of %lf\n", above, avg);
You pass %d as the format string and then you pass a double.
This can be fixed by declaring above as int (since that is what your function returns too).
But I would like to add as to why it is wrong and why are you getting a zero.
So this is the issue with var args functions. Since the prototype says nothing about the types of the arguments, you call to printf assumes that the second argument is of type double.
Now the calling convention says that the second argument (if it is float or double) should be passed in the SSE register (on windows in the XMM1 register). But since the printf function sees that the format string is %d so it expects for the second argument to be int. Now int arguments are passed in the general purpose registers (on windows second is passed in rdx).
As a result it gets a garbage value.
I hope this helps you better understand the problem.
1 Important Mistake
You never use the value returned by realloc().
You need
ptr = tmp;
right after checking that realloc() did not return NULL.
The program above looks fine.
printf("%d elements are above average of %lf\n", above, avg);
Above line you are printing a double value with %d may be wrong. Otherwise I see everything fine.
I am passing in an array into a function straightflush. I use a counting loop so i can get to all of the elements but for some reason, even tho the counter i increases, i get the value and suit for the first element of the array. Therefore, only my spadesCount increases as it always shows 4 for the value and spade for the suit.
struct card{
int value;
char suit;
};
int straightflush(struct card hand[], int n)
{
int clubsCount = 0;
int diamondsCount = 0;
int heartCount = 0;
int spadesCount =0;
int i;
for(i=0; i<n; i++)
{
if (hand[i].suit == 'c')
{
clubsCount++;
}
else if (hand[i].suit == 'd')
{
diamondsCount++;
}
else if (hand[i].suit == 'h')
{
heartCount++;
}
else{
spadesCount++;
}
}
return 0;
}
here is my main:
int main(){
struct card hand1[] = {{4,'s'}, {9,'s'},{12,'c'},{11,'s'},{8,'s'},
{6,'d'}, {3,'d'},{7,'s'},{10,'s'},{12,'d'}};
printf ("%d\n", straightflush(hand1, 10));
}
I just run your code and the four count variables have correct values. I think it's because you are returning 0 at the end of your straightflush function, the output is always 0.
You can use a debugger or add the following line before the return statement in straightflush() to prove that your counts are actually accurate.
printf("%d %d %d %d\n", clubsCount, diamondsCount, heartCount, spadesCount);
Your return value has nothing to do with the values you read thus the printf statement in your main() function is not printing the count of any thing, it is just printing 0 no matter what.
If you want the counts accessible outside of striaghtflush() you need to either use global variables for those counts (a generally shunned idea) or pass some values in by reference. An example of this would be:
#include <stdio.h>
#include <stdlib.h>
void editValues( int *numDiamonds, int *numClubs, int *numHearts, int *numSpades ){
*numDiamonds = 3;
*numClubs = 5;
*numHearts = 7;
*numSpades = 11;
}
int main(int argc,char**argv)
{
int numD=0, numC=1, numH=2, numS=3;
printf("%d %d %d %d\n", numD, numC, numH, numS);
editValues(&numD, &numC, &numH, &numS);
printf("%d %d %d %d\n", numD, numC, numH, numS);
return 0;
}