Finding the interpolation with user input - c

I made some revisions to the algorithm, and get a value (though it is incorrect) in the function, but the return value refuses to send it back to the main function. Also, I cannot get they yes no portion of the code that ask for the program to rerun to function.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
/*Prototype for functions used*/
float getdistance(float[], float[], float, int);
float printvalue(float);
int main()
{
int maxtime = 18;
float usertime = 0;
char reiteration;
char y, n;
int reit_choice = 0;
float interpolation = 0.0;
float time_arr[]={0,3,5,8,10,12,15,18};
float distance_arr[]={2,5.2,6,10,10.4,13.4,14.8,18};
do
{
printf("Please enter a number between 0 and 18 for the starting time:");
scanf("%f", &usertime, "\b");
while(usertime <0 || usertime >18)
{
printf("The value you have entered is not valid, please enter a value between 1 and 18");
scanf("%f", &usertime, "\b");
}/*End of data verification loop*/
getdistance(time_arr, distance_arr, usertime, maxtime);
printf("%f", interpolation);
printvalue(interpolation);
system("pause");
printf("would you like to check another time?(y/n)");
scanf("%c[y n]", &reiteration, "\b");
while(reiteration!='y' || reiteration!='n')
{
printf("Please enter either y for yes or n for no");
scanf("%c", &reiteration, "\b");
}/*End of choice verification loop*/
if(reiteration = 'y')
{
reit_choice = 1;
}
else
{
reit_choice = 0;
}
}/*End of do loop*/
while(reit_choice);
}/*End of main loop*/
float getdistance(float time_arr[], float distance_arr[], float usertime, int maxtime)
{
int index=0;
float interpolation = 0;
for(index; usertime > time_arr[index]; index++)
{
if(usertime<3)
{
break;
}
}/*End of value assignment for loop*/
interpolation = (time_arr[index]) + (((time_arr[index +1] - time_arr[index])/(distance_arr[index +1] - distance_arr[index])) * (usertime - distance_arr[index]));
printf("%f", interpolation);
return interpolation;
}/*End of distance calculation loop*/
float printvalue(float interpolation)
{
printf("The interpolation was %f", interpolation);
}/*End of screen print loop*/

The reason for 0 output is
getdistance(time_arr, distance_arr, usertime, maxtime);
in int main() function you're calling the function getdistance which calculates the interpolation value and returns the value, But in main function the returned value is not assigned to the variable interpolation . so you've to modify the code as
interpolation = getdistance(time_arr, distance_arr, usertime, maxtime);
printvalue(interpolation);
Which will print the output

Related

Not able to find my segmentation fault in this code of t-test

I have written this program for t-test. I'll add other functions as well, but first, I need to find my error. Here's my code
# include <stdio.h>
# include <math.h>
float mean(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += x[i];
return sum/size;
}
float sumsq(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += pow(x[i]-mean(x,size),2);
return sum;
}
int input(n)
{
float x[n];
printf("Enter the values one by one");
for (int i = 0; i<n;i++)
scanf("%f", &x[i]);
return x;
}
void t_check(float x)// Make sure to write this function before each of the t-tests. That is because it is of void type. If the t-test is done before the checking function is declared, then it assumes it's datatype to be "int", and we get an error. So either write the t-check function before those functions, or just define it at the beginning of the program
{
float t_tab;
printf("Enter the tabulated value of t");
scanf("%f",&t_tab);
if (x<t_tab)
printf("We do not have enough evidence to reject the null hypothesis");
else
printf("Reject the null hypothesis");
}
float t_diff_of_means()
{
float x=0.0,y=0.0,s1=0.0,s2=0.0,S=0.0,t=0.0,tcal;
int n,m,a,b;
printf("Enter the number of variables in population 1");
scanf("%d", &n);
a = input(n);
printf("Enter the number of variables in population 2");
scanf("%d", &m);
b = input(m);
x = mean(a,n);
y = mean(b,m);
s1 = sumsq(a, n);
s2 = sumsq(b, m);
S = sqrt((s1+s2)/(n+m-2));
t = (x-y)/(S*sqrt(1.0/n+1.0/m));
t_check(t);
}
int main(void)
{
t_diff_of_means();
return 0;
}
It gives segmentation fault as an error. I'm not able to understand where my code uses any memory uses a part of memory that is not allocated to it
The main issue is you expect input() to read an array floats but you return an int. You should declare the type of the argument n. You cannot return an address to a local variable as it out of scope for caller. The easiest option is to the declare the array variable in main() then pass it to input to populate (pun). (not fixed) Check that return value of scanf() otherwise the variable you expect to be initialized may not be.
t_diff_of_means() is declared to return a float but nothing is returned. Not sure what you want to return so I changed the return type to void.
Tweaked various prompts to make it more them more readable.
#include <stdio.h>
#include <math.h>
float mean(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += x[i];
return sum/size;
}
float sumsq(float x[], int size)
{
float sum = 0.0;
for (int i=0; i<size;i++)
sum += pow(x[i]-mean(x,size),2);
return sum;
}
void input(size_t n, float a[n])
{
printf("Enter the values one by one: ");
for (int i = 0; i<n;i++)
scanf("%f", a+i);
}
void t_check(float x)
{
float t_tab;
printf("Enter the tabulated value of t: ");
scanf("%f",&t_tab);
if (x<t_tab)
printf("We do not have enough evidence to reject the null hypothesis\n");
else
printf("Reject the null hypothesis\n");
}
void t_diff_of_means()
{
float x=0.0,y=0.0,s1=0.0,s2=0.0,S=0.0,t=0.0;
int n,m;
printf("Enter the number of variables in population 1: ");
scanf("%d", &n);
float a[n];
input(n, a);
printf("Enter the number of variables in population 2: ");
scanf("%d", &m);
float b[m];
input(m, b);
x = mean(a,n);
y = mean(b,m);
s1 = sumsq(a, n);
s2 = sumsq(b, m);
S = sqrt((s1+s2)/(n+m-2));
t = (x-y)/(S*sqrt(1.0/n+1.0/m));
t_check(t);
}
int main(void)
{
t_diff_of_means();
return 0;
}
and example run:
Enter the number of variables in population 1: 2
Enter the values one by one: 1
2
Enter the number of variables in population 2: 2
Enter the values one by one: 2
3
Enter the tabulated value of t: 0.05
We do not have enough evidence to reject the null hypothesis
Consider eliminating the variables you only use once (x, y, s1, s2, S, t and t_cal):
t_check(
(mean(a, n) - mean(b, m)) / (sqrt((sumsq(a, n)+sumsq(b, m))/(n+m-2))*sqrt(1.0/n+1.0/m))
);
then I observed that this only depends on variables a, n, b and m so push that calculation into t_check():
void t_check(size_t a_len, float a[a_len], size_t b_len, float b[b_len]) {
float t = (mean(a, a_len) - mean(b, b_len)) / (sqrt((sumsq(a, a_len)+sumsq(b, b_len))/(a_len+b_len-2))*sqrt(1.0/a_len+1.0/b_len));
// ...
}
Then I changed the length types to size_t and used the clearer variable names in t_diff_of_means():
void t_diff_of_means()
{
printf("Enter the number of variables in population 1: ");
size_t a_len;
scanf("%zu", &a_len);
float a[a_len];
input(a_len, a);
printf("Enter the number of variables in population 2: ");
size_t b_len;
scanf("%zu", &b_len);
float b[b_len];
input(b_len, b);
t_check(a_len, a, b_len, b);
}
We could take this another step by observing the two first sections in t_diff_of_means() are very similar, so we could have input() take a prompt and a pointer to an array of floats along with elements read. input() would then need to dynamically allocate the array of floats. This means most of our functions take a array of float and length argument. Let's create a type for that and refactor our functions to use it:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct array {
size_t len;
float *data;
};
float mean(struct array *a)
{
float sum = 0;
for (int i=0; i<a->len;i++)
sum += a->data[i];
return sum/a->len;
}
float sumsq(struct array *a)
{
float sum = 0;
for (int i=0; i<a->len;i++)
sum += pow(a->data[i] - mean(a), 2);
return sum;
}
void input(int prompt, struct array *a)
{
printf("Enter the number of variables in population %d: ", prompt);
scanf("%zu", &a->len);
a->data = malloc(a->len * sizeof(a->data[0]));
//if(!a->data) ...
printf("Enter the values one by one: ");
for (int i = 0; i<a->len;i++)
scanf("%f", &a->data[i]);
}
void t_check(struct array a[2])
{
float t = (mean(a) - mean(a+1)) / (
sqrt(
(sumsq(a) + sumsq(a+1)) / (a[0].len + a[1].len-2)
) * sqrt(1.0/a[0].len + 1.0/a[1].len)
);
printf("Enter the tabulated value of t: ");
float t_tab;
scanf("%f",&t_tab);
if (t<t_tab)
printf("We do not have enough evidence to reject the null hypothesis\n");
else
printf("Reject the null hypothesis\n");
}
int main(void)
{
struct array a[2];
input(1, a);
input(2, a+1);
t_check(a);
}
This would be a good base to add additional functions to.

Program Variance and Standard Deviation Using Pointer Function

So i'm trying to make a standard deviation and variance function and I can't really figure out why it doesn't work. I'm suppose to call variance in case 3 and SD in case 4. everything else works in the program. If you see anything that doesn't look right let me know.
#include <stdio.h>
#include <math.h>
#define Max_Nums 20
void sortNums(float nums[], int size);
float meanValue(float nums[],int size);
float medianValue(float nums[], int size);
void var_stdDev(float nums[],int size,float *var,float *stdDev);
float sqrtf(float);
int main (void)
{
int NumValue = 0;
float array[Max_Nums];
int i=0;
int choice=0;
float avg=0;
float median=0;
printf("How many numbers do you wish to enter (Max of 20): ");
scanf("%d",&NumValue);
while (NumValue<1 || NumValue>Max_Nums)
{
printf("Invalid response. You must enter a value between 1 and 20.\n");
scanf("%d",&NumValue);
}
printf("Enter %d real numbers: ",NumValue);
for (i=0;i<NumValue;i++)
{
scanf("%f", &array[i]);
}
do
{
sortNums(array,NumValue);
printf("-----Menu-----\n\a");
printf("Enter 1 for mean value\n");
printf("Enter 2 for median value\n");
printf("Enter 3 for variance\n");
printf("Enter 4 for standard deviation\n");
printf("Enter 5 to exit the program\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
avg=meanValue(array,NumValue);
printf("The mean is:%.2f\n",avg);
break;
case 2:
median=medianValue(array,NumValue);
printf("The median is:%.2f\n",median);
break;
case 3:
//printf("The variance is:%.2f",variance);
//break;
case 4:
//printf("The standard deviation is:%.2f\n");
//break;
case 5:
printf("Exiting the program\n");
break;
default:
printf("\nInvalid, try again");
break;
}
}while (choice!=5);
return 0;
}
void sortNums(float nums[], int size)
{
int x;
int y;
float z;
for(x=0;x<(size-1);x++)
{
for(y=0;y<size-x-1;y++)
{
if(nums[y]>nums[y+1])
{
z=nums[y];
nums[y]=nums[y+1];
nums[y+1]=z;
}
}
}
}
float meanValue(float nums[],int size)
{
int i;
float avg;
float sum;
for(i=0;i<size;i++)
{
sum+=nums[i];
}
avg = (sum/size);
return avg;
}
float medianValue(float nums[], int size)
{
float EvenMed;
float Med;
void sortNums(float nums[], int size);
if (size%2==0)
{
EvenMed=(nums[size/2]+nums[size/2-1])/2;
return EvenMed;
}
else
{
Med=nums[size/2];
return Med;
}
}
void var_stdDev(float nums[],int size,float *var,float *stdDev)
{
int i;
float sum;
float meanValue(float nums[],int size);
for(i=0;i<size;i++)
{
sum+=pow((nums[i]-meanValue,2);
}
*var=sum/(float)size;
*stdDev=sqrt(*var);
}
This line is wrong:
sum+=pow((nums[i]-meanValue,2);
This is trying to subtract a function pointer from a number, which makes no sense. You need to call the meanValue function to get the mean, and then subtract that.
Also, you didn't initialize sum before adding to it.
void var_stdDev(float nums[],int size,float *var,float *stdDev)
{
int i;
float sum = 0;
float mean = meanValue(nums, size);
for(i=0;i<size;i++)
{
sum+=pow((nums[i]-mean,2);
}
*var=sum/(float)size;
*stdDev=sqrt(*var);
}
There's no need to have a declaration of meanValue inside var_stdDev, the declaration at the top of the file serves that purpose throughout.
In medianValue(), you have a declaration of sortNums(), but you never call it, so the numbers aren't sorted (it seems like you don't understand the difference between a prototype and a call).
float medianValue(float nums[], int size)
{
float EvenMed;
float Med;
sortNums(nums, size);
if (size%2==0)
{
EvenMed=(nums[size/2]+nums[size/2-1])/2;
return EvenMed;
}
else
{
Med=nums[size/2];
return Med;
}
}
As well explained by #Barmar , OP's code has a number of problems:
void var_stdDev(float nums[],int size,float *var,float *stdDev) {
int i;
// sum not initialize
float sum;
// unneeded function declaration
float meanValue(float nums[],int size);
// missing code to find the mean
for(i=0;i<size;i++) {
// improper call to accumulate the average derivation from the mean
sum+=pow((nums[i]-meanValue,2);
}
...
Recommend a new approach to standard deviation calculation
from here
std = sqrt(n*sum_of_squares - sum_of_x*sum_of_x)/n
Suggested improvements:
Use double for intermediate calculation. float is fine to reduce storage and sometimes for speed. Yet statistics often subtract values leading to significant lost of precision. Use double.
Due to rounding, select data sets could result in a tiny negative number - even if mathematically the result should be >= 0.0. So good to check sign before sqrt().
Handle case when size == 0 and do not perform a run-time division by 0.
void var_stdDev2(const float x[], size_t size, float *var, float *stdDev) {
double sumx = 0.0;
double sumxx = 0.0;
double std = 0.0; // Used when size == 0.0 - or set to NaN
if (size > 0) {
for (size_t i = 0; i < size; i++) {
sumx += x[i];
sumxx += 1.0 * x[i] * x[i];
}
double std = sumxx * size - sumx * sumx;
std = std >= 0.0 ? sqrt(std) : 0.0;
std /= size;
}
if (stdDev) *stdDev = (float) std;
if (var) *var = (float) sqrt(std);
}
Minor bits:
Use a const in the signature as function does not modify nums[].
Array are best indexed with size_t rather than int.

How to make compiler repeat until the number 0 is presed

I'm wondering how to make the compiler repeat itself if the user presses a random button at the end. But if the user presses "0" the compiler exits.
My code:
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
#include <float.h>
struct mystruct
{
float startnummer;
float hoppnummer;
float svarighetsgrad;
float domarpoangs[7];
};
int main(void)
{
struct mystruct data;
float max = 0;
float min = FLT_MAX;
float sum = 0;
float avg = 0;
int i = 0;
float resultat = 0;
printf("Startnummer: \n");
scanf_s("%f", &data.startnummer);
printf("Hoppnummer:\n");
scanf_s("%f", &data.hoppnummer);
printf("Svarighetsgrad:\n");
scanf_s("%f", &data.svarighetsgrad);
for (i = 0; i < 7; i++)
{
printf("domarpoang %d\n", i + 1);
float f;
if (scanf_s("%f", &f) == 1)
{
if (f < min) min = f;
if (f > max) max = f;
data.domarpoangs[i] = f;
}
else
{
printf("error parsing float\n");
exit(0);
}
}
system("cls");
printf("Startnummer: %.1f \n", data.startnummer);
printf("Hoppnummer: %.1f\n", data.hoppnummer);
printf("Svarighetsgrad: %.1f\n", data.svarighetsgrad);
for (i = 0; i < 7; i++)
{
printf("Domarpoang %d: %.1f\n", (i + 1), data.domarpoangs[i]);
}
for (i = 0; i < 7; i++)
{
sum += data.domarpoangs[i];
}
sum = sum - (max + min);
avg = sum/5;
resultat = avg * 3 * data.svarighetsgrad;
printf("Hoppoang:%.2f \n", resultat);
printf("Tryck tangent for nytt hopp!");
getchar();
getchar();
return 0;
}
*If the user presses random button, the compiler repeat itself from the beginning
*If the user presses 0, the compiler exits.
Any help is appreciated, thank you.
This answer puts a loop around the body of your main() code, taking care to re-initialise some of the variables for the next iteration.
There are many SO questions about getting keyboard input and clearing the debris. I know of no simple standard ways of testing for keyboard input such as kbhit(), for taking a single key input such as getch() or for flushing the input. Even getchar() is horrible - it won't return until you have pressed "Enter" which it leaves in the input buffer. This has resulted in many SO answers with impenetrable (to me) formats for scanf() to flush the input, or testing if (getchar() == EOF) - which does not respond to the "Enter" key.
So I have put a simple wrapper around the main() code, which terminates when '0' is entered followed by a control char (because fgets() appends the newline) or terminator. This removes the need to clean up the input - except in the case where the user inputs some silly typing. GIGO!
#include <stdio.h>
#include <float.h>
#define BUFFSIZE 10
struct mystruct {
float startnummer;
float hoppnummer;
float svarighetsgrad;
float domarpoangs[7];
};
int main(void)
{
char kbuff [BUFFSIZE+1];
struct mystruct data;
float max;
float min;
float sum;
float avg;
int i;
float resultat;
do {
max = 0; // initialise for each loop
min = FLT_MAX;
sum = 0;
printf ("Body of your main loop\n");
fgets(kbuff, BUFFSIZE, stdin);
} while (kbuff[0] != '0' || kbuff[1] >= ' ');
return 0;
}

Custom average function with array input does not return value in C

I made a program which accepts input for 30 users (About their age)
and then the array was supposed to be an input in a custom function made by me (avg_age)
However the average printed on screen is 0.0000 (for 30 non-zero values)
That is why I think it does not return anything.
#include <stdio.h>
float avg_age(int age[]);
main()
{
int i=0,age[30]={0},intemp;
do{
printf("Input age for 30 users: ");
scanf("%d",&intemp);
if(intemp>0 && intemp<100)
intemp=age[i];
else i--;
i++;
}while(i<30 || intemp<0 || intemp>100);
printf("\nAverage age of 30 users: %f\n",avg_age(age));
float avg_age(int age[]){
int i,avg=0;
for(i=0;i<30;i++)
avg+=age[i];
avg=(float)avg/30;
return avg;
}
}
Take out the function definition of avg_age out of the main. You declared avg as int but it should be declared float to store float values.
float avg = 0.0;
In main intemp=age[i]; is not storing the inputs to the array age instead assigning 0 each time to intemp. Change it to
age[i] = intemp;
Your modified code: (for 5 users)
#include <stdio.h>
#define N 5
float avg_age(int age[]);
int main(void)
{
int i=0,age[N]={0},intemp;
do{
printf("Input age for %d users: ", N);
scanf("%d",&intemp);
if(intemp>0 && intemp<100)
age[i] = intemp;
else i--;
i++;
}while(i<N || intemp<0 || intemp>100);
printf("\nAverage age of %d users: %f\n",N, avg_age(age));
return 0;
}
float avg_age(int age[]){
int i;
float avg=0.0;
for(i=0;i<N;i++)
avg+=age[i];
avg=(float)avg/N;
return avg;
}
Here is the tested code.
Your avg inside avg_age should be a float
float avg_age(int age[]){
int i; float sum=0.0;
for(i=0;i<30;i++)
sum += age[i];
return sum/30;
}
and of course the above function should be outside of main (preferably before it).
BTW, you should have compiled with all warnings and debugging info (e.g. with gcc -Wall -g). The compiler certainly would have warned you! Also, learn how to use the debugger (e.g. gdb)

Segmentation fault with no pointers?

Here is my code and problem. The code compiles fine. But when I run it. After I enter the menu option in getMenuOption() "Segmentation Fault (core dumped)" pops up. What is wrong?
I'm new to programming in general. Thanks for the help if its provided.
#include <stdio.h>
#include<math.h>
#define CALCULATE_PI 'a'
#define CALCULATE_GEOMEAN 'b'
#define CALCULATE_HARMMEAN 'c'
void printInstructions (void);
void printMenuOptions (void);
int runMenuOption ();
int getMenuOption ();
int getLimit ();
int calculatePi ();
int calculateGeoMean ();
int calculateHarmonicMean ();
int main(void)
{
printInstructions();
printMenuOptions();
runMenuOption(getMenuOption());
return 0;
}
void printInstructions (void)
{
printf("======================================================\n");
printf("= PI, Geometric Mean, and Harmonic Mean Calculator =\n");
printf("= Please refer to the menu to choose calucaltion =\n");
printf("=Choose desired menu option and press enter to begin =\n");
printf("= Proceed to follow on-screen instructions =\n");
printf("======================================================\n\n\n");
return;
}
void printMenuOptions (void)
{
printf("3 choices: Please enter a VALID letter.\n");
printf("Choice 'a' = Calcualtes PI\n");
printf("Choice 'b' = Calculates Geometric Mean\n");
printf("Choice 'c' = Calculates Harmonic Mean\n\n");
return;
}
int runMenuOption (int getMenuOption())
{
char option;
double answer,
Pi = 0.0,
geoMean = 0.0;
option = getMenuOption();
switch (option)
{
case CALCULATE_PI:
calculatePi(getLimit());
answer = Pi;
break;
case CALCULATE_GEOMEAN:
calculateGeoMean(getLimit());
answer = geoMean;
case CALCULATE_HARMMEAN:
printf("Harmonic Mean");
break;
default:
printf("Incorrect Character!\n");
printf("Try again");
break;
}
printf("Your answer is %5p", &answer);
return 0;
}
int getMenuOption (void)
{
char option;
printf("Please enter choice: ");
scanf("%c", &option);
return option;
}
int getLimit ()
{
int limit;
scanf("%d", &limit);
return limit;
}
int calculatePi (void)
{
int limit,
count = 0,
Pi = 0;
printf("Please enter the PI limit: ");
limit = getLimit();
for (count = 1; count <= limit; count++)
{
Pi += 1 / count;
}
return sqrt(Pi * 6);
}
int calculateGeoMean()
{
int limit,
userValue = 0,
count = 0;
double geoMean = 0;
limit = getLimit();
while(count <= limit)
{
if (userValue <= 0)
printf("Incorrect. Try again");
else
{
count++;
userValue *= userValue;
}
}
geoMean = userValue;
return sqrt(userValue);
}
int calculateHarmonicMean()
{
int limit,
userValue = 0,
count = 0;
double harmMean = 0;
limit = getLimit();
while(count <= limit)
{
if (userValue <= 0)
printf("Incorrect. Try again");
else
{
count++;
userValue *= 1 / userValue;
}
}
harmMean = userValue;
return limit / userValue;
}
This function definition is totally wrong.
int runMenuOption (int getMenuOption())
either you can pass the return value of getMenuOption like this
int runMenuOption (int option)
or
you shouldn't pass any value to this function and call getMenuOption inside runMenuOption. You are doing both, which is incorrect.
int runMenuOption (int getMenuOption())
Here's your problem.
That should be:
int runMenuOption (int opt)
Also, you shouldn't be calling getMenuOption() within runMenuOption since you're calling getMenuOption() as you pass it to runMenuOption as a parameter. runMenuOption should only have a switch statement.
You need to modify the definition of your function from int runMenuOption (int getMenuOption()) to int runMenuOption (int option). In the call, getMenuOption() will be invoked and the output placed into the stack frame of the called function.
According to your declaration of the runMenuOption function, it takes a pointer to a function which returns an integer as its first argument:
int runMenuOption (int getMenuOption())
The function is then called in this line:
option = getMenuOption();
This is perfectly fine. However, the problem lies in this line:
runMenuOption(getMenuOption());
Here you are calling the getMenuOption function and passing the return value into the runMenuOption function. But what you should be doing is passing the function itself as the argument:
runMenuOption(getMenuOption);
The reason you are getting a Segmentation Fault error is because the return value from the getMenuOption function is being treated as a function pointer, and your program is attempting to call a function at that address, which is of course invalid.

Resources