For/while loop doesn't update value properly - c

I'm trying to write a program which finds the weighted average (for grades and such).
Through user input, I create two arrays of the same size, one carrying the weights for each grading category, and the other holding the users score in the corressponding category. For example, if a student has a score of 92% in category 1, which is worth 30% of the total grade, then weights[1] = .3 and scores[1] = .92. This way, the average in each category can be found through (weights[i] * scores[i]) where i is an instance variable initialized in a for loop to go through each array entirely. The problem here is in finding the cumulative average- my program is written to compound the values of each average it handles for example I have tried code like average = average + (weights[i] * scores[i]) to obtain the final cumulative average. However through print statements I've found the value of average is set to the last (weights[i] * scores[i]) operation performed, ignoring the previous value of average (or taking it to be 0). For example, if weights[]={.3, .3, .4} and scores[] = {.4, .4 , .4}. The cumulative average should be .4, but my program tells me .32, which is the last value of weights times the last value of scores.
methods.c:
#include <stdio.h>
#include "methods.h"
int howManyCategories()
{
int categories = 0;
int firstTime = 0;
while(1)
{
if(firstTime == 0)
{
fprintf(stdout, "\nHow many categories are you currently graded on? ");
scanf("%d", &categories);
}
else
{
fprintf(stdout, "\nThat's not a valid value, try a positive integer. ");
scanf("%d", &categories);
}
firstTime++;
if(categories > 0)
{
return categories;
}
}
}
double howMuchWeight(int categories)
{
double weight = 0;
while(1)
{
if(categories == 1)
{
fprintf(stdout,
"\nThis %d category accounts for how much of your grade? (.1, .85, 1 etc.) ",
categories);
scanf("%lf", &weight);
}
else
{
fprintf(stdout,
"\nThese %d categories account for how much of your grade? (.1, .85, 1 etc.) ",
categories);
scanf("%lf", &weight);
}
if(weight > 1 || weight <= 0)
{
fprintf(stdout,
"\nRemember, total weighting must be positive and no larger than 1"
" (100 percent). \nTry Again.\n");
}
else
{
return weight;
}
}
}
double findWeightsAndScores(int i, double categories,
double checkWeights, double totalWeight,
double scores[])
{
while(1)
{
double piece = 0;
int count = i + 1;
fprintf(stdout, "\nWeight for category %d: ", count);
scanf("%lf",&piece);
if(piece > 0 && piece < 1)
{
findScores(i, &scores[i]);
return piece;
}
else
{
fprintf(stdout, "\nRemember, weights must be positive and less than 1!\n");
}
}
}
void findScores(int i, double scores[])
{
int validScore = 0;
while(validScore == 0)
{
int count = i + 1;
double score = 0;
fprintf(stdout, "Please enter your percentage score in category %d: ", count);
scanf("%lf", &score);
if(score >= 0 && score <= 1)
{
scores[i] = score;
validScore = 1;
}
else
{
fprintf(stdout, "\nRemember, scores in each category must be positive, no greater "
"than 1 (100 percent) and no less than 0, try again.\n\n");
}
}
}
double findAverage(int categories, double weights[], double scores[])
{
double average = 0;
for(int i = 0; i <= categories - 1; i++)
{
average += (weights[i] * scores[i]);
fprintf(stdout, "%lf", average);
}
return average;
}
methods.h:
#ifndef METHODS_H_
#define METHODS_H_
int howManyCategories();
double howMuchWeight(int categories);
double findWeightsAndScores(int i, double categories,
double checkWeights, double totalWeight, double scores[]);
void findScores(int i, double scores[]);
double findAverage(int categories, double weights[], double scores[]);
#endif
whatsmyGrade.c:
#include <stdio.h>
#include "methods.h"
int main()
{
while(1)
{
/*Prompts for categories*/
int categories = howManyCategories();
int dataProvided = 1;
double checkWeights = 0;
double grade = 0;
double average = 0;
/*Prompts for total weight*/
double totalWeight = howMuchWeight(categories);
double category[categories];
double weights[categories];
double scores[categories];
/*Assign weights to each category and score in each category*/
for(int i = 0; i <= categories - 1; i++)
{
/*Fill array for weights*/
weights[i] = findWeightsAndScores(i, categories, checkWeights, totalWeight,
scores);
checkWeights = checkWeights + weights[i];
if(checkWeights != totalWeight && i == categories - 1)
{
fprintf(stdout, "\nYour weight distribution is invalid! Try again.\n");
dataProvided = 0;
break;
}
}
/*Calculate total grade*/
if(dataProvided == 1)
{
average = findAverage(categories, weights, scores);
grade = (average / totalWeight) * 100;
fprintf(stdout, "Your cumulative average is %.2lf percent\n\n", grade);
return 1;
}
}/*End of parent while loop*/
}/*End of main*/
Thank you in advance

Your problem is somewhere else because it works like a charm for me:
#include <stdio.h>
double findAverage(int categories, double weights[], double scores[])
{
double average = 0;
int i;
for(i = 0; i <= categories - 1; i++) {
average += (weights[i] * scores[i]);
fprintf(stdout, "%lf ", average);
}
return average;
}
int main(void) {
// your code goes here
double average;
double grade;
int categories = 3;
double totalWeight = .3 + .3 + .4;
double weights[] = {.3, .3, .4};
double scores[] = {.4, .4, .4};
average = findAverage(categories, weights, scores);
grade = (average / totalWeight) * 100;
fprintf(stdout, "\nYour cumulative average is %.2lf percent\n\n", grade);
return 0;
}

Got it, when I call the findScores function in the findWeightsAndScores function I was passing it &scores[i] when I should have been passing it scores. Thanks guys

Related

Get evenly spaced numbers in a range, in C

I am trying to perform an easy calculation without beeing able to figure out the right approach to it: I am trying to obtain a specific amount of N values, reading the step number from user input, within a certain range included between min and max also read from the user input. Those N values must be evenly spaced between themselves.
For instance, this should be able to produce a set of N numbers including the lower range limit and the upper one. I need to use decimal min and max and integer number of step.
This is the code I am trying to use:
#include <stdio.h>
int main()
{
double min;
double max;
int step;
double table_array[step];
table_array[0] = min;
printf("Enter the minimum value: ");
scanf("%lf", &min );
printf("Enter the maximum value: ");
scanf("%lf", &max );
printf("Enter the evenly spaced step value: ");
scanf("%d", &step );
printf("\n----------------------------------\n");
int i;
int increment;
for (i = 0; i <= step; i++){
increment = (max - min) / step;
table_array[i+1] = table_array[i] + increment;
while (table_array[i] < max){
printf("%i %lf\n",i, table_array[i]);
}
}
return 0;
}
I need to improve the for cycle for sure. Any suggestions? I assume it can be even totally wrong since it is not running, or better yet it is running but not showing the right result
First of all, you need declare an array with specific size. Initially the array size is not valid as step will initially have garbage value. then you are trying to print i with %i need to change that one with %d. with your step you need to calculate the increment only once. and as your increment can be double number then just make sure that you are using a double type for increment. now how i calculate the increment as 2 number must be min and max then there must be step >= 2 . suppose max =20 min =10 and step=3 so the numbers will be 10,15,20. so increment = (max -min )/(step-1) = 5. now make some complex case . if step = 1 then min must be equal to max. we need to check this case explicitly. another case if max < min then just need to swap them.
here is the code:
#include <stdio.h>
int
main ()
{
double min;
double max;
int step;
printf ("Enter the minimum value: ");
scanf ("%lf", &min);
printf ("Enter the maximum value: ");
scanf ("%lf", &max);
printf ("Enter the evenly spaced step value: ");
scanf ("%d", &step);
double table_array[step + 5];
table_array[0] = min;
printf ("\n----------------------------------\n");
int i;
double increment;
if (max < min){
double temp;
temp = min;
min = max;
max = temp;
}
if (step == 1 && max == min) {
i = 0;
printf ("%d %.18lf\n", i, table_array[i]);
} else {
increment = (max - min) / (step - 1);
i = 0;
printf ("%d %.18lf\n", i, table_array[i]);
for (i = 1; i < step; i++){
table_array[i] = table_array[i - 1] + increment;
printf ("%d %.18lf\n", i, table_array[i]);
}
}
return 0;
}
#include <stdio.h>
#define SWAPI(min,max,type) do{type tmp; if(min > max) {tmp = max; max = min; min = tmp;}}while(0)
double *getnumbers(double *table, size_t nelements, double max, double min)
{
double step;
if(table && nelements > 1 )
{
SWAPI(min,max, double);
step = (max - min) / (nelements - 1);
for(size_t element = 0; element < nelements; element++, min += step)
{
table[element] = min;
}
}
else
{
table = NULL;
}
return table;
}
void printtable(double *table, size_t num)
{
for(size_t i = 0; i < num; i++)
{
printf("[%zu] = %f\n", i, table[i]);
}
}
int main(int argc, char* argv[])
{
double numbers[25];
if(getnumbers(numbers,2,3,6)) printtable(numbers, 2);
printf("\n");
if(getnumbers(numbers,15,3,6)) printtable(numbers, 15);
}
https://godbolt.org/z/odscs6
#include <stdio.h> // printf, scanf, putchar
#include <float.h> // FLT_EPSILON
#include <math.h> // fabs
int isequal(double, double);
int main(void) {
double min, max, step, nnum;
printf("Maximum: "), scanf("%lf", &max); // Get maximum
printf("Minimum: "), scanf("%lf", &min); // Get minimum
if (min > max) { // If invalid maximum, handle error
puts("Maximum cannot be over minimum");
return 1; // Returning 1 indicates program failure
}
printf("Step: "), scanf("%lf", &step); // Get step
nnum = (max - min)/step;
if (!isequal(nnum, (int) nnum) || step <= 0) { // If invalid step, handle error
puts("Invalid step");
return 1;
}
putchar('\n'); // Separate input from output
for (int i = 0; i <= nnum; i++) {
printf("%d. %lf\n", i + 1, min);
min += step; // We already know it will go into maximum evenly
}
return 0; // Returning 0 indicates program success
}
int isequal(double x, double y) { // fabs() = Float absolute value
return fabs(x - y) < FLT_EPSILON; // FLT_EPSILON = Smallest comparable float value
}

C Programming - Collecting data in a function outside of main()

Write a program that asks the user to enter daily rainfall amounts. Your program will need to accept 5 daily rainfall inputs. Only allow non-negative rainfall amounts. When the user enters a negative number, tell them that the number is invalid, and that they should enter another, valid value.
Calculate the total rainfall and the average rainfall. Determine the largest daily rainfall and the smallest daily rainfall.
Output the total, average, largest, and smallest values using informative messages.
The following things cannot happen in main:
Accepting user input
Calculation of total or average
Determination of largest or smallest
Outputting results
=============================================
Right now i'm just trying to figure out how to enter the 5 numbers, I have this code so far but it's having me put it in an infinite amount of times. I've been working on this project for hours, so any advice would be amazing.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
double CollectRainfall() {
double amount;
double rainfall[SIZE];
int i;
printf("Enter a rainfall amount: \n"); // enter amount
scanf_s("%lf", &amount);
for (i = 0; i < SIZE; i++) {
rainfall[i] = CollectRainfall();
while (amount < 0.0) { // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter another rainfall amount: \n");
}
}
}
int main() {
CollectRainfall();
return 0;
}
As said the recursion as you have it will essentially create an infinite loop, and really, for this you dont need it either, you can do something like:
Running sample (commented changes)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
void CollectRainfall() { //no return needed
double rainfall[SIZE], sum = 0, max = 0, min = 0;
int i;
for (i = 0; i < SIZE; i++)
{
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &rainfall[i]); //save values into the array
while (rainfall[i] < 0.0)
{ // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter another rainfall amount: \n");
i--; // iterate back to replace negative number
}
}
printf("Values:");
for (i = 0, min = rainfall[i]; i < SIZE; i++)
{
printf(" %.2lf", rainfall[i]); // print all values
sum += rainfall[i]; // sum values
if(rainfall[i] > max){ //max value
max = rainfall[i];
}
if(min > rainfall[i]){ //min value
min = rainfall[i];
}
}
printf("\nSum: %.2lf", sum); // print sum
printf("\nMax: %.2lf", max); // print max
printf("\nMin: %.2lf", min); // print min
printf("\nAverage: %.2lf", sum / SIZE); //print average
}
int main() {
CollectRainfall();
return 0;
}
You can create a struct to store you data and do the operation.
Something like:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
typedef struct data {
double rainfall[SIZE];
double average;
double min;
double max;
} data_t;
static void collectRainfall(double rainfall[SIZE]) {
for (int i = 0; i < SIZE; i++) {
double amount;
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &amount);
while (amount < 0.0) { // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &amount);
}
rainfall[i] = amount;
}
}
static void compute(data_t *data) {
data->min = data->rainfall[0];
data->max = data->rainfall[0];
data->average = data->rainfall[0];
for (int i = 1; i < SIZE; i++) {
double rainfall = data->rainfall[i];
if (rainfall > data->max) {
data->max = rainfall;
}
if (rainfall < data->min) {
data->min = rainfall;
}
data->average += rainfall;
}
data->average /= SIZE;
}
static void display(data_t *data) {
printf("min %f, max %f, average %f\n",
data->min, data->max, data->average);
}
int main() {
data_t data;
collectRainfall(data.rainfall);
compute(&data);
display(&data);
return 0;
}
scanf is a pain in case of bad input best is to read a line then parse it, check if strtod is ok
static void collectRainfall(double rainfall[SIZE]) {
for (int i = 0; i < SIZE; i++) {
char str[32];
double amount = -1;
printf("Enter a rainfall amount [%d/%d]: \n", i , SIZE);
while (42) {
char *res = fgets(str, sizeof(str), stdin);
if (res && (amount = strtod(str, &res)) >= 0 && res != str)
break;
printf("The number is invalid.\n");
printf("Enter a rainfall amount [%d/%d]: \n", i , SIZE);
}
rainfall[i] = amount;
}
}

Why is my average not the correct answer? (C code program to find mean)

I am bashing my head because I cannot figure out why my C code keeps printing the wrong average of a set of n numbers!
This is my code below:
int main()
{
int i;
int n;
int sum = 0.0;
int lowest;
int highest;
float average;
int range;
int middle;
double median;
printf("\nEnter the amount of numbers you want?\n");
scanf("%d",&n);
int numbs[n];
int temp[n];
for(i = 0;i < n; i++)
{
printf("\nEnter a number from 0 to 15: ");
scanf("%d",&temp[i]);
}
while (temp[i] < 0 || temp[i] > 15) than 15
{
printf("This number is not from 0 to 15! Please re-enter another number: ");
scanf("%d",&temp[i]);
}
numbs[i] = temp[i];
sum += numbs[i];
}
int sortt = 0, j, x;
for (x = 1; x < n; x++) {
for (j = 0; j < n - x; j++) {
if (numbs[j] > numbs[j + 1]) {
sortt = numbs[j];
numbs[j] = numbs[j + 1];
numbs[j + 1] = sortt;
}
}
}
lowest = numbs[0];
highest = numbs[n-1];
middle = n/2;
if (n % 2)
{
median = numbs[middle];
}
else
{
median = (numbs[middle - 1] + numbs[middle]) / 2.0;
}
average = sum/n;
range = highest - lowest;
printf("\nSum: %d", sum);
printf("\nAverage: %.2f", average);
printf("\nMedian: %.2f", median);
printf("\nRange: %d\n", range);
return 0;
}
This is my input and output below. You can see that 8 divided by 3 is not 2, it is 2.67! I've tried using double and float.
Input & Output:
You need to correct the following line:
average = sum/n;
to
average = (float)sum/n;
You have to cast your return value into float. Think about it as a function with the following definition:
float divide(int x,int y){
return x/y; // returns an integer instead of float.
}
While this definition:
float divide(int x,int y){
return (float)x/y; // creates a temporary float variable and returns it immediately as the returned value of the function.
}
In addition, declaring int sum=0.0 is definitely going to show you a warning when compiling with -Wall. Try to follow warnings that you get from your compiler and fix all of them before you run your program.
8 divided by 3 is 2, remainder 2. 8 and 3 are integers, and when you divide two integers, you use integer division with integer rules.
Also, this line might be confusing you:
int sum = 0.0;
Since sum is an int, this just sets sum to zero.
And:
average = sum/n;
Since both sum and n are integers, this is integer division. What you do with a result does not affect how that result is computed -- C's rules are complex enough already.
/*Here see you can intake all values as float instead */
#include <stdio.h>
#include <stdlib.h>
void main()
{
float i,n,a,b,sum,ave;
printf("This is a program to calculate the average of 'n' numbers \n");
printf("Of How many numbers do you want to calculate average \n");
scanf("%f", &n);
printf("Enter the first number \n");
scanf("%f", &a);
sum = a;
for (i=1;i<n;i++)
{
printf("Enter another number \n");
scanf("%f", &b);
sum = sum + b;
}
ave = (sum/n);
printf("The average of the %f number is %f", n, ave);
getchar();
}

average function returning nan

I made this program to order data sets and display the max, min, average, and median. Originally I had everything in main, I decided to clean it up a bit by making functions. The average function was working fund but after adding a few more the value returned for average in 'nan. Any suggestions? Thanks in advance guys
#include <stdio.h>
int findSize();
double findAverage(int size, double num[]);
double findMedian(int size, double num[]);
void findLowtoHigh(int size, double num[]);
void findHightoLow(int size, double num[]);
int main()
{
while(1)
{
int size = findSize();
if(size <= 1)
{
return 0;
}
double num[size];
double holder;
double lowest;
double highest;
double average;
double median;
fprintf(stdout, "\n");
for(int i = 0; i <= size - 1; i++)
{
int j = i+1;
fprintf(stdout, "Please enter number %d: ", j);
fscanf(stdin, "%lf", &num[i]);
}
if(size > 1)
{
for(int y = 0; y < size - 1; y++)
{
for(int k = 0; k < size - 1; k++)
{
if(num[k] > num[k+1])
{
holder = num[k];
num[k] = num[k+1];
num[k+1] = holder;
}
}
}
}
findLowtoHigh(size, num);
findHightoLow(size, num);
average = findAverage(size, num);
median = findMedian(size, num);
fprintf(stdout, "\n\nLowest Value: %3.4f", num[0]);
fprintf(stdout, "\nHighest Value: %3.4f", num[size-1]);
fprintf(stdout, "\n\nAverage Value: %3.4f\n", average);
fprintf(stdout, "Median Value: %3.4f", median);
fprintf(stdout, "\n");
}
}
int findSize()
{
int size;
fprintf(stdout, "\nPlease enter size of the array: ");
scanf("%d", &size);
return size;
}
void findLowtoHigh(int size, double num[])
{
fprintf(stdout, "\nFrom least to greatest: ");
for(int x = 0; x <= size - 1; x++)
{
fprintf(stdout, "%3.2f ", num[x]);
}
}
void findHightoLow(int size, double num[])
{
fprintf(stdout, "\nFrom greatest to least: ");
int reverse = size - 1;
while(reverse != -1)
{
fprintf(stdout, "%3.2f ", num[reverse]);
reverse--;
}
}
double findAverage(int size, double num[])
{
double average;
for(int a = 0; a <= size - 1; a++)
{
average = average + num[a];
}
average = average / size;
return average;
}
double findMedian(int size, double num[])
{
double median;
if(size % 2 == 0)
{
median = (num[size/2 - 1] + num[size/2])/2;
}
else
{
median = num[size/2];
}
return median;
}
You have to initialize average. Change to
double average=0;
Compile your prrogram with (mild) optimization and all reasobnable warnings turned on (gcc -O -Wall is a starting point on Linux, clang is similar), and check (and fix!) all complaints by the compiler. Only then are you allowed to ask the 'net.

passing struct array to function for inputting value

Need to pass a struct array to 2 functions so that the user can input the values.
This is the structure needed:
struct Sale {
double quantity;
double unit_p;
char taxable;
};
Calling the function in the main functions as:
no_sales = enter(sales, MAX_SALES);
total(sales, no_sales);
and i am inputting values by:
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
printf("Unit Price : ");
scanf("%lf", &s[i].unit_p);
printf("Taxable(y/n) : ");
scanf("%*c%c%*c", &s[i].taxable);
It compiles fine in gcc compiler. When I ran the program I can enter the values but when I try to print the values it displays all values as 0. The values are not being stored in struct array
output I am getting:
Quantity : 2
Unit Price : 1.99
Taxable(y/n) : y
Quantity Unit Price
0.000000 0.000000
The whole code:
program accepts the values and calculates total price in 2 separate functions
#include <stdio.h>
const int MAX_SALES = 10;
struct Sale {
double quantity;
double unit_p;
char taxable;
};
void total(const struct Sale *s,int n);
int enter(struct Sale *s, int M);
int main()
{
int no_sales;
struct Sale sales[MAX_SALES];
printf("Sale Records \n");
printf("=============\n");
no_sales = enter(sales, MAX_SALES);
total(sales, no_sales);
}
int enter(struct Sale *s, int M)
{
int i = 0;
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
while(s[i].quantity != 0) {
printf("Unit Price : ");
scanf("%lf", &s[i].unit_p);
printf("Taxable(y/n) : ");
scanf("%*c%c%*c", &s[i].taxable);
i++;
if(i == M) {
printf("Maximum exceeded\n");
break;
}
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
}
int j;
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[i].quantity, s[i].unit_p, s[i].taxable);
}
return i;
}
void total(const struct Sale *s,int n)
{
int i, subtot = 0, hst = 0, tot = 0;
for(i = 0; i < n; i++) {
subtot = subtot + (s[i].quantity * s[i].unit_p);
if(s[i].taxable == 'y' || s[i].taxable == 'Y') {
hst = hst + (0.13 * s[i].quantity * s[i].unit_p);
}
}
tot = subtot + hst;
printf("\n%-12s%.2lf", "Subtotal", subtot);
printf("\n%-12s%.2lf", "HST (13%)", hst);
printf("\n%-12s%.2lf\n", "Total", tot);
}
In function enter() you are using the wrong index variable i to access the struct:
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[i].quantity, s[i].unit_p, s[i].taxable);
}
which should be
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[j].quantity, s[j].unit_p, s[j].taxable);
}
Second, in function total(), your variables for calculating the totals, should be of type double
int i;
double subtot = 0, hst = 0, tot = 0;
...

Resources