printf() with a function call arg sometimes incorrect - c

The C code at bottom usually operates as expected, using gcc on Ubuntu 20.04, but about 15% of the time I get a huge result for highest temp:
Normal:
Highest temp: 15.30
15% of the time:
Highest temp: 970363834813736688025683948382903403895871057............00
If I pull the the function out of the printf() call, things behave as expected 100% of the time:
double max = maxTemp(temperatures,7);
printf("Highest temp: %.2lf\n", max);
I'm assuming the error case is a huge number because there's a double with garbage data somewhere.
Any idea what's going on?
Thank you for your time.
#include <stdio.h>
double maxTemp(double *temps, int numOfTemps);
int main(void) {
double temperatures[7] = {6.9, 12.3, 9.0, 15.3, 9.8, 1.8, 0.3};
printf("Highest temp: %.2lf\n", maxTemp(temperatures, maxTemp(temperatures,7)));
return 0;
}
double maxTemp(double *temps, int numOfTemps) {
double max = temps[0];
for (int i = 0; i < numOfTemps; i++) {
if (max < temps[i]) {
max = temps[i];
}
}
return max;
}

This is your problem:
maxTemp(temperatures, maxTemp(temperatures,7)))
maxTemp expects its second argument to have type int and to be the number of elements in the temperatures array. In the outer call, you're passing the result of maxTemp, which is a double, and is a temperature, not a count of array elements.
The compiler should be yelling at you right there - if not, turn on all warnings and treat all warnings as errors (-Wall -Werror if you're using gcc).
Secondly, the max temperature in your array is 15.3 - assuming that gets converted to an int value of 15, you're iterating past the end of your array into garbage.
Are you sure you don't mean to call that as
maxTemp( temperatures, 7 );
?

as one comment pointed out, you're calling maxTemp(…) twice in main.
If you remove the "outer call" you'll be fine, i.e. changing main to:
int main(void) {
double temperatures[7] = {6.9, 12.3, 9.0, 15.3, 9.8, 1.8, 0.3};
printf("Highest temp: %.2lf\n", maxTemp(temperatures, 7));
return 0;
}
Reason being that maxTemp(temps, n) calculates the maximum of n temperatures. So it will only work properly (defined behavior) if n is the actual number of values. This does usually not apply to the max temp.
This means you were taking values into consideration that are outside of the temperatures-array.
why it worked sometimes (by accident)
Those values outside your array are undefined. Values outside of allocated space are often 0, but not by definition. This is why it worked most of the time.

Related

Why is this returning -nan?

#include <stdlib.h>
int main()
{
int i,j;
float averageyear;
float averagemonth;
float sumyear;
float rainny;
int year = 2020;
int rain[5][12];
const char* month[12] = {"jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"};
for (i=0;i<5;i++)
{ printf("*****Year %d*****\n",year+i);
for (j=0;j<12;j++)
{
printf("%s: ",month[j]);
scanf("%f",&rainny);
sumyear+=rainny;
averageyear=(float)sumyear/12;
}
printf("Total of %d is %.2f\n",year+i,sumyear);
//averageyear=(float)sumyear/12;
printf("Average of %d is %.2f\n",year+i, averageyear);
sumyear=0;
}
}
The code gives me the output
Total of 2020 is -nan
Average of 2020 is -nan
But when I switch averageyear=(float)sumyear/12; to outside the for loop (The commented line), it gives me the right output. I don't see any difference between those 2 positions of the code. Please help me clarify this. Thank you!
Without initializing variables declared in block-scope (like sumyear) they contain whatever the memory had present prior to the program running.
If this value was not a number, which is a special number in floating point representations to handle things that aren't rational numbers, then adding anything to it will also yield NAN (not a number).
Initialize the sumyear (and your other variables) to valid values, and your program will work correctly regardless of whatever memory it is assigned to use.

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) {

How to do simple average calculation using a function & calling it?

I need to learn how to use the function for the calculation and then a simple call in main. When I tried it didn't work. I have no idea what to do. It works but when I take out the code from main it gets funky.
this is simple simple scenario and code for that.
Write a function that takes an array of ints, and the size of the array - another int.
It also returns a double. Call this one 'average.' Return a double that is the average
of the values in the array. Demonstrate that it works by finding the average of an array
with these values {78, 90, 56, 99, 88, 68, 92}
#include <stdio.h>
#include <stdlib.h>
// Outside of main, a function will be declared that takes an array of ints.
double Function(int Array[7])
{
// int Array[7] = {78, 90, 56, 99, 88, 68, 92};
int sum = 0;
int i;
double average;
// This for loop allows us to use all 7 elements in the array.
for(i=0; i<7; i++)
{
// This takes all the array's elements and sums them up.
sum += Array[i];
}
// This prints the sum
printf("Sum = %d\n", sum);
// The double average is found by taking the sum found and dividing it by 7.
average = sum/7;
// This prints the average in a double.
printf("The resulting average is %lf \n", average);
return average;
} // Ends Function
// There will also be the size of the array(which is another int)
// The function will return a double called average. It is the average of the values in the array.
int main()
{
//int i; // Allows us to use the for loop and print each element in the corresponding array.
// int array numbers are declared and initialized.
int Array[7] = {78, 90, 56, 99, 88, 68, 92};
int sum = 0;
int i;
double average;
// This for loop allows us to use all 7 elements in the array.
for(i=0; i<7; i++)
{
// This takes all the array's elements and sums them up.
sum += Array[i];
}
// This prints the sum
printf("Sum = %d\n", sum);
// The double average is found by taking the sum found and dividing it by 7.
average = sum/7;
// This prints the average in a double.
printf("The resulting average is %lf \n", average);
Function(Array);
system("pause");
return 0;
}
Can any one give me a tips!
If you want to follow the instruction you were given, your function declaration should be
double average(int *array, int array_size)
Also, your solution should be general, not only for array with length of 7.
In general in C language - when you want to pass an array which its length is unknown, you pass the address of the array (here *array) and its size (here array_size). Then your function will iterate over the array from the given address, with jumps of the type (here jumps of sizeof(int) because it's an array of ints).
In C Program execution always starts from main.
So the stack will be like
main()-->Function()
You are almost right just you called the function which returns the average so to keep that average or to accept that average in main you need variable so just remove all the code shown below
for(i=0; i<7; i++)
{
// This takes all the array's elements and sums them up.
sum += Array[i];
}
// This prints the sum
printf("Sum = %d\n", sum);
// The double average is found by taking the sum found and dividing it by 7.
average = sum/7;
// This prints the average in a double.
printf("The resulting average is %lf \n", average);
Now take the results returned by the Function() in average variable shown below.
average=Function(Array);
Now print that value if you want to print or use in main if you need.
the posted code contains several misconceptions
no need to '#include' header files those contents are not needed.
only write code that is part of the solving of the problem. Other code that is added for 'debug' purposes should be eliminated from the final executable. Usually be surrounding the debug code with: #ifndef NDEBUG .... #endif Suggest learning how to work with NDEBUG
The problem only needs to solved once, not both in 'main()' and in 'Function()' BTW: function is a terrible function name suggest: calculateAverage(). Function names should indicate what they will perform, usually by starting the function with some active verb, like calculate
for ease of readability and understanding, consistently indent the code. Indent after every opening brace '{'. unindent before every closing brace '}'. Suggest each indent level be 4 spaces as that is wide enough to be visible even with variable width fonts. Remember, the compiler (in general) doesn't care about the 'style' of the code formatting. However, any human cares a lot, because the human wants to be able to read the code.
it is (almost always) a bad idea to hard code any values other than 0 and 1. Instead give them meaningful names via a enum statement or #define statements, then use those meaningful names throughout the code.
Please pay attention to these 3 details in the code:
how the size of the array is calculated
how the parameters are passed to the 'Function()'
how the average is calculated.
Note: when all the variables in a divide operation are integers, then a integer divide is performed. This can produce some surprising results.
For instance, 5/3 results in 1, not 1.66.
by wanting to keep the fraction, cast one of the elements (not the whole expression) to double or float
and now the code
#include <stdio.h> // printf()
//#include <stdlib.h>
double Function(int *pArray, int numElements );
int main( void )
{
// int array numbers are declared and initialized.
// note: usually best to let the compiler calculate array size
// rather than hardcoding the size
int Array[] = {78, 90, 56, 99, 88, 68, 92};
// number of elements in array
int sizeofArray = sizeof(Array)/sizeof(int);
// call Function to calculate and return as double,
// the average of the array elements
double average = Function( Array, sizeofArray );
// This prints the average as a 'double'.
printf("The resulting average is %lf \n", average);
//system("pause"); // not portable, suggest:
int ch;
while( (ch = getchar()) != EOF && '\n' != ch );
getchar();
//return 0; // <-- in modern C, if main to return 0 then this line not needed
} // end function: main
double Function(int *pArray, int numInts )
{
int sum = 0;
double average;
for(int i=0; i<numInts; i++)
{
sum += pArray[i];
}
// cast one of the values as a double so an integer divide is NOT performed
average = (double)sum / numInts;
return average;
} // end function: Function

Counter in a do while loop in C

I am trying to keep a count of how many times the operation inside the do-while loop is repeating, but the counter only shows 1 each time. Can anyone tell me where is my mistake? I have provided the code here.
#include <stdio.h>
#include <math.h>
int main(void)
{
double i = 84;
int counter = 0;
do {
counter++;
i = fmod(i, 25.0);
}
while(i > 25);
printf("Counter: %i\n %lf\n", counter, i);
}
fmod is floating point modulo.
It cannot return something higher than 25.0 since you've passed 25.0 as the modulo value.
That's why while(i>25) is false at the first iteration.
i = fmod(i, 25.0);
This takes the current value of i and finds the remainder of its division by 25. Following that, the remainder is reassigned to i.
double i = 84;
This sets the initial value of i to 84. If we do 84 % 25, we get 9.0. And since 9.0 < 25.0, the loop will terminate after the first operation. Therefore, counter is only incremented once in your loop.

Inexplicable computational error

I am writing a program that reads wavelength and intensity data from separate signal and background files (so each file is comprised of a number of pairs of wavelength and intensity). As you can see, I do this by creating a structure, and then assigning the values to the proper elements in the structure using fscanf in a loop. Once the data is read in, the program is supposed to plot it on the interval where the recorded wavelengths in each file overlap, that is, the common range of wavelengths. The wavelengths align perfectly where this overlap exist and are known to be spaced at a constant difference. Thus, my way of discerning which elements of the structure array were applicable was to determine which of the two files' minimum wavelength was higher, and maximum wavelength was lower. Then, for the file that had the lower minimum and higher maximum, I would find the difference between this and the higher minimum/lower maximum, and then divide it by the constant step to determine how many elements to offset. This works, except when the math is done, the program returns a wrong answer that is completely inexplicable.
In the code below, I define the constant step as lambdastep by calculating the difference between wavelengths of one element and the element before it. With my sample data, it is .002, which is confirmed by printf. However, when I run the program and divide by lambdastep, I get an incorrect answer. When I run the program dividing by .002, I get the correct answer. Why is this case? There is no explanation I can think of.
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include "plots.h"
struct spectrum{
double lambda;
double intensity;
};
main(){
double a=0,b=0,c=0,d=0,lambdastep,smin,smax,bmin,bmax,tmin,tmax,sintmin,bintmin,tintmin,sintmax,bintmax,tintmax,ymin,ymax;
int ns,nb,nt,i=0,sminel,smaxel,bminel,bmaxel,tminel,tmaxel;
double min(struct spectrum *a,int,int);
double max(struct spectrum *a,int,int);
FILE *Input;
Input = fopen("sig.dat","r");
FILE *InputII;
InputII = fopen("bck.dat","r");
fscanf(Input,"%d",&ns);
fscanf(InputII,"%d",&nb);
struct spectrum signal[ns];
struct spectrum background[nb];
struct spectrum *s = &signal[0];
struct spectrum *ba = &background[0];
s = malloc(ns*sizeof(struct spectrum));
ba = malloc(nb*sizeof(struct spectrum));
while( fscanf(Input,"%lf%lf",&a,&b) != EOF){
signal[i].lambda = a;
signal[i].intensity = b;
i++;
}
i = 0;
while( fscanf(InputII,"%lf%lf",&c,&d) != EOF){
background[i].lambda = c;
background[i].intensity = d;
i++;
}
for (i=0; i < ns ;i++){
printf("%.7lf %.7lf\n", signal[i].lambda,signal[i].intensity);
}
printf("\n");
for (i=0; i < nb ;i++){
printf("%.7lf %.7lf\n", background[i].lambda,background[i].intensity);
}
lambdastep = signal[1].lambda - signal[0].lambda; //this is where I define lambdastep as the interval between two measurements
smin = signal[0].lambda;
smax = signal[ns-1].lambda;
bmin = background[0].lambda;
bmax = background[nb-1].lambda;
if (smin > bmin)
tmin = smin;
else
tmin = bmin;
if (smax > bmax)
tmax = bmax;
else
tmax = smax;
printf("%lf %lf %lf %lf %lf %lf %lf\n",lambdastep,smin,smax,bmin,bmax,tmin,tmax); //here is where I confirm that it is .002, which is the expected value
sminel = (tmin-smin)/(lambdastep); //sminel should be 27, but it returns 26 when lamdastep is used. it works right when .002 is directly entered , but not with lambdastep, even though i already confirmed they are exactly the same. why?
sminel is an integer, so (tmin-smin)/lambdastep will be casted to an integer when the calculation concludes.
A very slight difference in lambdastep could be the difference between getting e.g. 27.00001 and 26.99999; the latter truncates down to 26 when cast to an int.
Try using floor, ceil, or round to get better control over the rounding of the returned value.
It almost certainly has to do with the inherent imprecision of floating-point calculations. Trying printing out lambdastep to many significant digits -- I bet you'll find that its exact value is slightly larger than you think it is.
With my sample data, it is .002, which is confirmed by printf.
Try printing out (lambdastep == .002).

Resources