I have the following code in C :
#include <stdio.h>
// Global variables :
int i;
int x[10];
int Nmax;
int sum;
// Functions used :
void Summation();
int Average(float avg); // This function will return avg
int main()
{
float avg;
printf("Mention how many numbers to be added\n");
scanf("%d",&Nmax);
printf("Enter %d numbers\n",Nmax);
for (i=0; i<Nmax; i++){
scanf("%d",&x[i]);
}
Summation();
Average(avg);
printf("%d %d %f\n",Nmax,sum,avg);
printf("Average = %.2f\n",avg);
return 0;
}
// Summation :
void Summation()
{
sum=0;
for (i=0; i<Nmax; i++) {
sum=sum+x[i];
}
printf("Sum of them = %d\n",sum);
}
// Average
int Average(float avg)
{
avg=(float)sum/(float)Nmax;
return avg;
}
Somehow the function Average is not returning the expected average value.
Instead it's showing a garbage value.
A typical input/output :
Mention how many numbers to be added
4
Enter 4 numbers
1 2 3 4
Sum of them = 10
4 10 1637156136366093893632.000000
Average = 1637156136366093893632.00
What's going wrong here? Hope I don't require a pointer here or do I?
For the average function you are passing the argument as pass by value. Once you call the function your are not assigning the return value back to the avg variable inside the main function. So what you are printing is the garbage value inside the avg variable declared in main function. Change your code to
avg = Average(avg);
Also this is a very bad way of writing c programs. Please dont you use global variables if you dont need them.
You are mixing int and float and that can cause problems.
You are never initializing avg in main(), use parameters instead of global variables to avoid the confusion. You pass avg's value to Average() it has absolutely no use in this case.
In c parameters to functions are always passed by value so the value of avg is not being modified in Average(), you may think it is because you seem confused about how you can modify global variables everywhere. The truth is global variables are mean, of course they have their uses for example, a global state in a library could be stored in a global variable1 but generally they are not needed.
Try like this
#include <stdio.h>
// Functions used :
float Summation(float *data, int size);
float Average(float *data, int size); // This function will return avg
int
main(void)
{
int size;
printf("Mention how many numbers to be added\n");
if (scanf("%d", &size) == 1)
{
float data[size];
float sum;
float average;
int i;
printf("Enter %d numbers\n", size);
for (i = 0 ; ((i < size) && (scanf("%f", &data[i]) == 1)) ; i++)
;
size = i;
sum = Summation(data, size);
average = Average(data, size);
printf("%d %f %f\n", size, sum, average);
printf("Average = %.2f\n", average);
}
return 0;
}
// Summation :
float
Summation(float *data, int size)
{
float sum;
sum = 0;
for (int i = 0 ; i < size ; i++)
sum = sum + data[i];
return sum;
}
// Average
float
Average(float *data, int size)
{
return Summation(data, size) / (float) size;
}
Note that you "don't really need an Average() function.", although it could be useful to make the API clean.
1Although I don't like that either, it makes the library very limited in multithreaded environments. Still sometimes it makes senes, but you can always have a structure with all the needed data and pass it in every call to the library API. So global variables are very rarely good.
Related
I am new to the C language (I started to learn it a week ago). the program was having some random output so i wanted to see what was it storing in the variable. then the printf fixed it somehow.
#include <stdio.h>
int laske(float lista[]);
const int MAX = 3;
int main()
{
float lista[5], yhteispisteet;
int counter = 0;
do
{
printf("Anna %d. pisteet: \n", counter +1);
scanf("%f", &lista[counter++] );
printf("%d",lista[counter]); <-- if you remove this line it dosent work
}
while (counter < MAX);
yhteispisteet = laske(lista);
printf("\nYhteispisteet ovat: %.2f\n", yhteispisteet);
getchar();
return 0;
}
int laske(float lista[])
{
int rivi, tulos;
for (rivi=0; rivi< MAX; rivi++)
tulos = tulos + lista[rivi];
return tulos;
}
Three things to note from your code:
You are adding a float and an int when you do: tulos = tulos + lista[rivi];, without casting the input float to int like this: tulos = tulos + (int)lista[rivi]; Or better yet, just declare tulos as float, and return a float from your laske function, because the return value is again being assigned to a float yhteispisteet
You assign to lista[counter++] with the scanf, and then increment the counter (post-increment) and print the lista[counter](which is printing the incremented indexed value that did not take any assignments yet). It is better to increment counter++ after the printf function.
You did not initialize your variable tulos, and this gives you undefined behavior when your code is running, which is probably what you are seeing when you add and then remove the printf and then rerun
I am currently trying to take a sum from two different subroutine and pass it back to the main function, but every time I do this, it just comes up with a zero value and I am unsure why. I have tried putting my print statements in the main function and just doing calculations in the subroutines and that still didn't work, so I know that my variables aren't returning right and my sum is an actual number. How do I pass my variable sum back to my main function correctly?
Here is my code:
#include<stdio.h>
int X[2000];
int Y[2000];
int main()
{
FILE*fpdata1= NULL;
FILE*fpdata2 = NULL;
fpdata1=fopen("DataSet1.txt","r");
fpdata2=fopen("DataSet2.txt","r");
if(fpdata1==NULL || fpdata2 == NULL)
{
printf("file couldn't be found");
}
int i=0;
while(i<2000)
{
fscanf(fpdata1,"%d!",&X[i]);
fscanf(fpdata2,"%d!",&Y[i]);
// printf("This is X: %d\n",X[i]);
// printf("This is Y: %d\n",Y[i]);
i++;
}
fclose(fpdata1);
fclose(fpdata2);
avgX(X);
avgY(Y);
float sum;
float sumY;
float totalsum;
float totalavg;
totalsum= sum + sumY;
totalavg= totalsum/4000;
printf("Sum X: %f\n\n",sum);
printf("Total sum: %f\n\n",totalsum);
printf("The total average is: %0.3f\n\n",totalavg);
return 0;
}
int avgX(int X[])
{
int i=0;
float averageX;
float sum;
sum = 0;
while (i<2000)
{
sum += X[i];
i++;
}
averageX = sum/2000;
printf("Sum of X: %f\n\n",sum);
printf("The sum of Data Set 1 is: %0.3f\n\n",averageX);
return(sum);
}
int avgY(int Y[])
{
int i=0;
float averageY;
float sumY;
sumY = 0;
while (i<2000)
{
sumY += Y[i];
i++;
}
averageY = sumY/2000;
printf("Sum of Y: %f\n\n",sumY);
printf("The sum of Data Set 2 is: %0.3f\n\n",averageY);
return (sumY);
}
Firstly, it would appear you are expecting the lines
avgX(X);
avgY(Y);
to somehow update the sum and sumY variables in the main function. This is a fundamental misunderstanding of how memory is accessed.
Local variable declarations with the same identifier are not shared between functions. They can be accessed only from within the function in which they are declared (and only for the duration of the function call).
In this example, the apples variables in each of the functions have absolutely no correlation to one another. Expecting this program to print 15 is wrong. This program has undefined behavior because foo and bar read values from uninitialized variables.
void foo(void) {
int apples;
/* This is undefined behaviour,
* as apples was never initialized. Do not do this. */
apples += 5;
}
void bar(void) {
int apples;
/* This is undefined behaviour,
* as apples was never initialized. Do not do this. */
printf("%d\n", apples);
}
int main(void) {
int apples = 10;
foo();
bar();
return 0;
}
Instead of this, you'll want to utilize the arguments and return values of your functions. In this example, in main we pass the value of apples as an argument to foo, which adds 5 to this value and returns the result. We assign this return value, overwriting our previous value.
int foo(int val) {
return value + 5;
}
void bar(int val) {
printf("%d\n", val);
}
int main(void) {
int apples = 10;
apples = foo(apples);
bar(apples);
return 0;
}
Again note that the val parameters do not refer some "shared variable", they are local to both foo and bar individually.
As for the specifics of your program:
The functions avgX and avgY do the exact same thing, just with different identifiers.
It would be better to write a more generic summation function with an additional length parameter so that you are not hard-coding data sizes everywhere.
int sum_ints(int *values, size_t length) {
int result = 0;
for (size_t i = 0; i < length; i++)
result += values[i];
return result;
}
You can then easily write averaging logic utilizing this function.
You do check that your file pointers are not invalid, which is good, but you don't halt the program or otherwise remedy the issue.
It is potentially naive to assume a file will always contain exactly 2000 entries. You can use the return value of fscanf, which is the number of conversions that took place, to test if you've failed to read data. Its also used to signify errors.
Though the fact that global variables are zeroed-out saves you from potentially operating on unpopulated data (in the event the files contain less than 2000 entries), it would be best to avoid global variables when there is an alternative option.
It might be better to separate the reading of files to its own function, so that failures can be handled per-file, and reading limits can be untethered.
int main(void) or int main(int argc, char **argv) are the correct, valid signatures for main.
With all that said, here is a substantially refactored version of your code. Note that an implicit conversion takes place when we assign the integer return value of sum_ints to our floating point variables.
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 2000
int sum_ints(int *values, size_t length) {
int result = 0;
for (size_t i = 0; i < length; i++)
result += values[i];
return result;
}
size_t read_int_file(int *dest, size_t sz, const char *fname) {
FILE *file;
size_t i;
if ((file = fopen(fname, "r")) == NULL) {
fprintf(stderr, "Critical: Failed to open file: %s\n", fname);
exit(EXIT_FAILURE);
}
for (i = 0; i < sz; i++)
if (fscanf(file, "%d!", dest + i) != 1)
break;
fclose(file);
return i;
}
int main(void) {
int data_x[DATA_SIZE] = { 0 },
data_y[DATA_SIZE] = { 0 };
size_t data_x_len = read_int_file(data_x, DATA_SIZE, "DataSet1.txt");
size_t data_y_len = read_int_file(data_y, DATA_SIZE, "DataSet2.txt");
float sum_x = sum_ints(data_x, data_x_len),
sum_y = sum_ints(data_y, data_y_len);
float total_sum = sum_x + sum_y;
float total_average = total_sum / (data_x_len + data_y_len);
printf("Sums: [X = %.2f] [Y = %.2f] [Total = %.2f]\n"
"The total average is: %0.3f\n",
sum_x, sum_y, total_sum,
total_average);
}
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 added a few printf stantments to see if the information is being computer and passed correctly, and while is is being computed correctly in the calcMean function, I keep getting zeros in the main function. I am not sure where my mistake is.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void calcMean(int [], int, float);
void calcVariance(int [], int, float);
int main(void)
{
/*create array and initialize it with values*/
int mainArr [ ] = {71,1899,272,1694,1697,296,722,12,2726,1899,
.......
1652,488,1123,17,290,1324,2495,1221,2361,1244,
813,2716,1808,2328,2840,1059,2382,2391,2453,1672,
1469,778,2639,357,2691,1113,2131,23,2535,1514,
2317,45,1465,1799,2642,557,1846,1824,1144,1468,-1};
/*create initilized values for variables*/
float mean = 0.0;
int counter = 0;
calcMean(mainArr, counter, mean);
calcVariance(mainArr, counter, mean);
printf ("Mean: %10.2f\n", mean); /*gives the average number to one decimal place*/
printf ("counter: %10.0d\n", counter);
getchar();
}/*End of the program*/
void calcMean(int mainArr[], int counter, float mean)/*This function finds the Mean(average) of the function, and the size of the array*/
{
int sentinel = -1;
float sum = 0.0;
int index = 0;
for (index; mainArr[index] != sentinel; index++) /*gets the total numbers in the function and the sum*/
{
counter++;
sum = sum + mainArr[index];
} /*end of the sumation and counting of integers*/
printf ("%0.0d\n", counter);
mean = ((float) sum / counter); /*Divides the sum by the total number of numbers to find the mean*/
printf ("mean: %10.2f\n", mean);
}
void calcVariance(int mainArr[], int counter, float mean)
{
int varindex = 0;
int numerator =0;
int square = 0;
int variance = 0;
int sumation = 0;
for(varindex; varindex<counter; varindex++)
{
numerator = (mainArr[varindex] - mean);
square = (numerator * numerator);
sumation = sumation + square;
variance = sumation / (counter-1);
}
printf ("variance %10.2f\n", variance);
}
You're assuming your function changes the value of outer variables. It won't.
calcMean(mainArr, counter, mean);
^ ^ pass by value
void calcMean(int mainArr[], int counter, float mean)
^ ^ receive by value
Modifying counter inside the function changes only the local variable.
Function parameters are copied into functions. So the variables inside a function will not change the parameters in the outer function.
You will need to do something like the following to any function which you wish to pass back more than one value from a function. (If you only need to pass back one value that can be returned with the function return statement).
// declare the parameters you wish to pass back to calling function as pointers
void calcMean(int [], *int, *float);
// pass the address of the variables:
calcMean(mainArr, &counter, &mean);
// obtain the values of the pointers in your calcMean using derefence operator *
printf ("%0.0d\n", *counter);
*mean = ((float) sum / *counter);
OP later requested an answer with little use of pointers.
As others (#suspectus, #Karoly Horvath, #Carl Norum) correctly pointed out the problem that passing into a function mean does not change it.
main() has an object named mean. That object's value was used to initialize the object called mean in the argument list of calcMean(). calcMean() proceeded to set its mean to some value. At the end of the function, the original mean in main() is not affected.
Instead, use the return value of function calcMean() to set mean in main().
// void calcMean(int mainArr[], int counter, float mean)
float calcMean(int mainArr[], int counter) {
float mean;
...
mean = ((float) sum / counter);
return mean;
}
int main(void) {
...
float mean = 0.0;
...
// calcMean(mainArr, counter, mean);
mean = calcMean(mainArr, counter);
...
}
Do the same for calcVariance
C is a pass-by-value language. Modifying mean and counter in the other functions doesn't affect their values in main().