Measurement with structure and searching for least, largest and average temperature - c

I have to write a program for recording the measured temperatures,
into which new measurements can be entered, or display statistics calculated from previous measurements. In the case of printing statistics, it is necessary to find and display the lowest and highest recorded temperature and calculate the average temperature.
#include <stdio.h>
int least_in_array(int array[], int n)
{
int i, least=array[0];
for(i=0; i<n; i++)
{
if(array[i]<least)
{
least=array[i];
}
}
return least;
}
int largest_in_array (int array[], int n)
{
int i, largest=array[0];
for(i=0; i<n; i++)
{
if(array[i]>largest)
{
largest=array[i];
}
}
return largest;
}
float average_array(int array[], int n)
{
int amount=0, i;
for(i=0; i<n; i++)
{
amount+=array[i];
}
return (1.0*amount)/n;
}
int main() {
int choose;
struct Data1 {
int dayInMonth;
int month;
float temperature;
} da;
printf("New measurement(1) or statistic(2)?\n");
scanf("%d", &choose);
if(choose==1) {
printf("Enter the day in month : ");
scanf("%d", &da.dayInMonth);
printf("Enter month : ");
scanf("%d", &da.month);
printf("Enter temperature (*C) : ");
scanf("%f", &da.temperature);
printf("Data saved!");
printf("-----------\n");
return 0;
}
if(choose==2) {
//printf("Least temperatures in quarter: %d", least_in_array(dayInMonth) );
return 0;
}
else {
printf("----------------\n");
printf("Wrong choose!\n");
}
return 0;
}
In case 2, I commented line where I get an error. Can anyone give me any advice to fix this problem?
|71|error: 'dayInMonth' undeclared (first use in this function)
|71|error: too few arguments to function 'least_in_array'

Since it is Christmas Eve, lets help out fellow man... who obviously is badly in need. For code that is supposed to pass an array to least_in_array, largest_in_array and average_array -- you have no array! That somewhat puts you behind the eight-ball from the word "Go!".
Your thought to use a stuct to capture and coordinate dayInMonth, month and temperature is 100% correct. (but note: C-style generally avoids camelCase variable names in favor of all lowercase). Also, defining struct Data1 within main() prevents your functions above that point from knowing what struct Data1 is, so you need to move your struct definition to the top of the file. (or provide a forward declaration, but we will save that for later) For now, let's just move your Data1 to the top (I used a typedef to alleviate having to prefix each use with stuct and renamed Data1 data:
#define NDAYS 365
typedef struct {
int day,
month;
double temperature;
} data;
Note the defined constant NDAYS. Since you are going to need an array, and since a dynamically allocated and reallocated approach seem well beyond your needs here, let's just define a constant, a maximum, for the number of elements we will have in our array.
Now, before we go further, let's think about our array. If we are going to use a struct to hold the associated date and temperature measurement, then we are going to need an array of... what?? An array of struct. And with our constant NDAYS, we will declare a maximum of 365 elements in our array. So how would this work? We have our stuct typedeffed to data, so if we want an array of data we need:
data da[NDAYS] = {{0, 0, 0.0}};
Note: the older initializer format initializing each field was used as it is unclear whether you could be using a C89 compiler. C99 and later added named initializers , e.g. {{.day = 0}} and any uninitialized elements are implicitly initialized to zero.
Now we have an array of data and can capture measurements. Of course you are responsible for keeping track of the indexes you fill. A simple counter, incremented each time a successful measurement in entered is all you need (ndx is used below)
How do we make least_in_array, largest_in_array and average_array work with an array of data? Recall, we moved the definition of the struct to the beginning of the source file, so now each function knows what data is. We simply need to pass our array of data as a parameter, e.g.
float least_in_array (data *array, int n)
{
int i;
float least = INT_MAX; /* sufficiently high temp */
for (i = 0; i < n; i++)
if (array[i].temperature < least)
least = array[i].temperature;
return least;
}
(note, each of the quantities of least_in_array, largest_in_array and average_array refer to the temperature values and therefore need to return type float.)
The remainder of putting together largest_in_array and average_array follows the same pattern.
The crux of your remaining problems relate to handling user input, and the particular pitfalls associated with taking user input with scanf. It can be done, but you must always validate the return, and test for user cancellation of input by testing for EOF (the result of the user pressing Ctrl+d (or Ctrl+z on windoze)).
You must validate that the number of expected conversions did in fact take place, or you must handle the error, and most importantly, you must account for any characters left in the input buffer (e.g. stdin), otherwise, if an invalid entry is made and you don't remove it from stdin, you will loop forever... (with scanf if a matching or input failure occurs -- no additional character are processed -- leaving them where? (oh, in stdin)
You can make this fairly easy on yourself if you declare a few helper functions to empty stdin, and make the normal process of getting an integer or float from the user relatively safe. For example, to empty stdin, you simply read all remaining characters until a '\n' or EOF is encountered, e.g.
/** simple function to empty all characters that remain
* in stdin. Needed when using scanf for user input.
*/
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
To ask the user for an int or float, you simply validate the return, check the number of successful conversion (what scanf returns), check whether EOF was generated by the user, and finally handle the error if invalid input was given and empty_stdin as required. You generally want to loop until the user either provides valid input, or cancels. (an invalid input does you no good).
For example, getting integer input can be handled as follows. (note: I put it in a function to keep from repeating this block of code for each input you take in the main body of your code...
/** abbreviated function to read integer value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
int getint ()
{
int n = 0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%d", &n);
if (rtn == 1) { /* we got an integer */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid integer input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return n;
}
(taking input for a float works the same way).
Lastly, you generally want to avoid using float in most cases, using double instead, just due to loss of precision and limitations for representing floating-point numbers with a 23-bit mantissa. However, here we are taking temperature, and float will suffice for this code.
Putting it altogether, you could do something like the following. Note, I have left your functions before main() as you had them, and added the helper function definitions after main(), but provided declarations before main() so they are visible to main() :
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define NDAYS 365
typedef struct {
int day,
month;
double temperature;
} data;
float least_in_array (data *array, int n)
{
int i;
float least = INT_MAX; /* sufficiently high temp */
for (i = 0; i < n; i++)
if (array[i].temperature < least)
least = array[i].temperature;
return least;
}
float largest_in_array (data *array, int n)
{
int i;
float largest = INT_MIN; /* sufficiently low temp */
for (i = 0; i < n; i++)
if (array[i].temperature > largest)
largest = array[i].temperature;
return largest;
}
float average_array (data *array, int n)
{
int i;
float sum = 0.0;
for (i = 0; i < n; i++)
sum += array[i].temperature;
return sum / (float)n;
}
void empty_stdin();
int getint();
float getfloat();
int main (void) {
int ndx = 0;
float max = 0.0, min = 0.0, avg = 0.0;
data da[NDAYS] = {{0, 0, 0.0}};
for (;;) {
int choose = 0;
printf ("\n (1) New measurement\n"
" (2) Statistics\n"
" (3) Exit\n\n"
" choice: ");
choose = getint();
putchar ('\n');
switch (choose) {
case 1: if (ndx == NDAYS) {
fprintf (stderr, "error: array full.\n");
break;
}
printf (" Enter day in month : ");
da[ndx].day = getint();
printf (" Enter month : ");
da[ndx].month = getint();
printf (" Enter temperature : ");
da[ndx].temperature = getfloat();
printf (" da[%3d] saved\n"
" ----------------------------\n", ndx++);
break;
case 2: if (ndx == 0) {
fprintf (stderr, "error: no measurements taken.\n");
break;
}
min = least_in_array (da, ndx);
max = largest_in_array (da, ndx);
avg = average_array (da, ndx);
printf (" minimum temp : %.2f\n"
" maximum temp : %.2f\n"
" average temp : %.2f\n"
" ----------------------------\n",
min, max, avg);
break;
case 3:
goto done;
break;
default:
fprintf (stderr, "error: invalid choice.\n");
empty_stdin();
break;
}
}
done:;
return 0;
}
/** simple function to empty all characters that remain
* in stdin. Needed when using scanf for user input.
*/
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
/** abbreviated function to read integer value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
int getint ()
{
int n = 0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%d", &n);
if (rtn == 1) { /* we got an integer */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid integer input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return n;
}
/** abbreviated function to read float value from user.
* returns value on success, exits if user cancels.
* empties stdin after call to scanf.
*/
float getfloat ()
{
float v = 0.0;
for (;;) { /* loop until valid input or EOF */
int rtn = 0; /* variable to capture return of scanf */
rtn = scanf ("%f", &v);
if (rtn == 1) { /* we got an float */
empty_stdin();
break;
}
else if (rtn == EOF) { /* if user cancels, exit */
fprintf (stderr, "user canceled input.\n");
exit (EXIT_FAILURE);
}
if (rtn == 0) /* handle error */
fprintf (stderr, "getint() error: invalid float input.\n");
empty_stdin(); /* empty all chars remaining in stdin */
}
return v;
}
Note: how the array bounds are limited to 365 or less in your take measurement part of the code, and how a check is made that there is at least one measurement present before any statistics can be provided. You always need to validate each step of the process. Look for corner-cases, think about what could go wrong with input (what if a cat stepped on the keyboard), and then go provide validations and checks to handle each case. The validations above are just the bare minimum, there are always more you can add to more fully report and handle each error condition.
Example Use/Output
$ ./bin/tempmxmnavg
(1) New measurement
(2) Statistics
(3) Exit
choice: 2
error: no measurements taken.
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 8
Enter month : 2
Enter temperature : 20.0
da[ 0] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 9
Enter month : 2
Enter temperature : 30.0
da[ 1] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 1
Enter day in month : 10
Enter month : 2
Enter temperature : 70.0
da[ 2] saved
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 2
minimum temp : 20.00
maximum temp : 70.00
average temp : 40.00
----------------------------
(1) New measurement
(2) Statistics
(3) Exit
choice: 3
Look things over and let me know if you have any further questions (although given the evening, I won't be here much longer...)

Related

Error with C code: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) when iterating through pointer of memory

I'm working on a C programming project for school and it was working fine but now all of a sudden when it's trying to access a number in a block of memory under numbers_array[j] it will not access index 2 of the array and keeps giving me the error in the title
I have been debugging for about an hour and cannot figure what is wrong. It will factor number at index 0 and index 1 fine but after that the program crashes. Any idea what is wrong?
The error can be found in the loop after the declaration of factor_struct under the comment Requirement 2.
My code for a number factoring program is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
/* Requirement 2:
Creating a struct with serveral pieces of data */
struct factor_struct {
int number, count;
clock_t start;
clock_t end;
double time_to_factor;
double times_array[];
};
/* Function header decleration */
void factor(struct factor_struct *fs);
/* The main program loop */
int main(int argc, const char * argv[]) {
/* Intializing the variables we'll be using during the run loop */
int input, number, continue_loop_one = TRUE, continue_loop_two = TRUE;
int *numbers_array;
/* Printing the welcome message to the screen */
printf("Welcome to Factor Factory!\n\n");
/* Asking how many numbers the user would like to factor*/
printf("How many different numbers would you like to factor?\n");
/* Start of LOOP_1: Ask user to input the amount of numbers to factor.
This will let us allocate the proper amount of memory */
LOOP_1: do {
printf("Please enter a number from 1 to 10: ");
scanf("%d", &input);
printf("\n");
/* Check if user input is between 1 and 10, if not return to start of LOOP_1 */
if(input < 1 || input > 10) {
printf("%d isn't a valid number...don't play games with me human. Try again! \n\n", input);
/* Need to flush the incorrect input from the buffer or else scanf will cause a continuous loop*/
fflush(stdin);
goto LOOP_1;
}
/* Break out of the loop and continue our program */
continue_loop_one = FALSE;
} while (continue_loop_one == TRUE);
/* Requirement 4:
Intialize our numbers array with the correct amount of memory */
numbers_array = (int*) calloc(input, sizeof(int));
/* Check if memory was allocated properly */
if (numbers_array == NULL) {
printf("Error: Memory not allocated. Closing program...\n");
exit(0);
}
/* Requirement 1:
Asking the user to enter the numbers that we will be using our algorithm for to get their factors */
LOOP_2: do {
printf("Excellent! Lets get started...");
printf("enter %d number(s) between 2 and 1,000,000,000.\n", input);
/* Variable to track how many numbers have been input just incase a user enters an invalid number*/
int entered_number_count = 0;
LOOP_3: for(int i = 0 + entered_number_count; i < input; i++) {
printf("Number %d: ", i + 1);
scanf("%d", &number);
if (number < 2 || number > 1000000000) {
printf("%d isn't a valid number...don't play games with me human. Try again! \n\n", number);
fflush(stdin);
goto LOOP_3;
}
/* Assinging a number to the value at the proper memory location in the numbers_array */
numbers_array[i] = number;
/* Incrementing the amount of entered numbers */
entered_number_count++;
}
/* Break out the loop and continue our program */
continue_loop_two = FALSE;
} while(continue_loop_two == TRUE);
printf("\n");
/* Requirement 2:
Declaring our factor_struct for use */
struct factor_struct fs;
fs.count = 0;
/* For each number in the array, assign it to fs.number and factor it by passing it to our factor function
Each pass over the array will reassign fs.number */
for(int j = 0; j < input; j++) {
fs.number = numbers_array[j]; // **ERROR APPEARS IF INDEX J > 1**
factor(&fs);
fs.count++;
}
/* Requirement 3:
Using a pointer to move through time_array which will calculate
the total time to factor all numbers */
double total_time = 0.0;
double *ptr = fs.times_array;
for(; *ptr; ++ptr) { total_time += *ptr; }
printf("Total computation time: %f seconds. \n\n", total_time);
/* Ask the user if they would like to continue or quit the program*/
printf("Would you like to continue factoring numbers?\n");
printf("Enter 'y' to continue or 'q' to quit: ");
/* Control loop that handles the continue or quit commands */
char c;
while(c != 'q') {
scanf("%c", &c);
if(c == 'y') {
printf("\n");
goto LOOP_1;
}
}
/* Thank the user and quit the program */
printf("\n");
printf("Thank you for using Factor Factory!\n");
printf("Closing program...\n\n");
/* Requirement 4:
Deallocating the memory for the numbers_array */
free(numbers_array);
return 0;
}
/* Requirement 5:
Taking data and passing it through the facotring algorithm */
void factor(struct factor_struct *fs) {
/* Marking the starting time of the function */
fs->start = clock();
printf("Factors of %d: ", fs->number);
/* Algorithm for finding all factors of our number */
for(int i = 1; i <= fs->number/2; i++) {
if (fs->number % i == 0) {
printf("%d ", i);
}
}
printf("%d\n", fs->number);
/* Marking the ending time of the function */
fs->end = clock();
/* Calculating the total time it took to find all factors*/
fs->time_to_factor = (double)(fs->end - fs->start) / CLOCKS_PER_SEC;
fs->times_array[fs->count] = fs->time_to_factor;
}

Is there a way to transfer a value from one function to the main function for a loop?

I am writing a banking program for an assignment. I made a base program that has no functions. Now I need to add two functions to replace to parts of the code. I am choosing to replace the user input loops for deposit and withdrawal amounts. I can make the function work fine with asking for the number, but when I attempt to use a loop asking for deposit amounts it is not working properly. I think my loop limiting variable does not transfer due to it coming from another function. Is there a way to get that limiting variable. I have included the portions of code that is involved.
int deposit_message (void)
{
int d;
do
{
printf("\nEnter the number of deposits (0-5): ");
scanf("%i", &d);
/* Define rules for invalid answers */
/* -------------------------------- */
if( d < 0 || d > 5)
{
printf("*** Invalid number of deposits, please re-enter.");
}
}while( d < 0 || d > 5); /* end of loop */
return d;
} /* end of function */
/* Prompt user for positive deposits, if invalid re-prompt. */
/* -------------------------------------------------------- */
for( i=0; i < d; i++)
{
/* Create array for deposits */
do
{
printf("Enter the amount of deposit #%i: ", i +1);
scanf("%f", &deposit[i]);
/* Define rules for invalid answers */
/* -------------------------------- */
if(deposit[i] < 0.00)
{
printf("*** Deposit amount must be greater than zero, please re-enter.\n");
}
}while(deposit[i] < 0.00);
Revised code after attempting to pass the variable d.
void deposit_message (int d)
{
do
{
printf("\nEnter the number of deposits (0-5): ");
scanf("%i", &d);
/* Define rules for invalid answers */
/* -------------------------------- */
if( d < 0 || d > 5)
{
printf("*** Invalid number of deposits, please re-enter.");
}
}while( d < 0 || d > 5); /* end of loop */
return d;
} /* end of function */
/* Prompt user for number of deposits between 0 and 5 with function, if invalid re-prompt with loop. */
/* ----------------------------------------------------------------------------------- */
deposit_message(&d);
/* Prompt user for positive deposits, if invalid re-prompt. */
/* -------------------------------------------------------- */
for( i=0; i < d; i++)
{
/* Create array for deposits */
do
{
printf("Enter the amount of deposit #%i: ", i +1);
scanf("%f", &deposit[i]);
/* Define rules for invalid answers */
/* -------------------------------- */
if(deposit[i] < 0.00)
{
printf("*** Deposit amount must be greater than zero, please re-enter.\n");
}
}while(deposit[i] < 0.00);
The loop should ask for a deposit amount X times based on the number of deposits chosen by the user. When used, it would either not stop, or just once. (After attempting to revise it, the loop does not stop.
You should pass reference of variable d defined in main() method to deposit_message(), like shown below.
void deposit_message(int* d){
// take value of deposits from user
scanf("%d",d);
}
int main(){
int d;
deposit_message(&d);
// your code here...
// your loop
for(int i=0;i<d;i++){
// logic here
}
}

Having a hard time adding results together in C (For Loop)

I wrote this code in C. What it basically do is it takes an input (number) for the user and, depending the number the user chose, it will run a for loop. The for loop will asks the user to input more numbers depending on the statement that it is asking. The code will then take those input from the user and apply it to the formula.
Let say the user inputs 2 at first. What it is supposed to do is go to through the loop twice and take the sum from the first and second time and added them together. Unfortunately, it doesn't do that and will only give back the first result from the loop separated by the second result.
This is the code:
#include <stdio.h>
int main(){
int i = 0;
int robotMany = 0;
int enginePower = 0;
int resistance = 0;
int weight = 0;
int height = 0;
printf("Depending the numbers of robot that you enter.You will need to do the following\n");
printf("Engine power\nResistance\nWeight\nHeight\n");
printf("Enter the amount of robots\n");
scanf("%d",&robotMany);
printf("You chose %d robot\n", robotMany);
//Depending the user input, it will run # of times.
for(i = 0; i < robotMany; i++){
//for loop begins
printf("Enter the engine power.(1-20)\n");
scanf("%d", &enginePower);
printf("Enter the resistance.(1-3)\n");
scanf("%d", &resistance);
printf("Enter the weight of the robot\n");
scanf("%d", &weight);
printf("Enter the height of Robot.\n");
scanf("%d", &height);
int product;
//take the user inputs and apply it to the formual.
product = (enginePower + resistance) * (weight - height);
printf("This is your total power\n");
printf("%d\n", product);
}
return 0;
}
You have a fundamental logic error in failing to keep a running total for the product calculated within each loop iteration.
However you have a larger problem in failing to validate the return of scanf (or any function you use for user-input). It is critical you validate EVERY user input, and even more so when using scanf to avoid invoking Undefined Behavior in your code. Why? If the user enters a stray character that does not match the conversion specifier in the format string, a matching failure occurs and character extraction from stdin ceases at that point leaving the offending character in the input buffer unread. In your case this would result in the same matching failure occurring for every call to scanf throughout the remainder of your program.
Take for example the user reaches for the '2' key but accidentally taps the 'w' key instead when entering robotMany. Not only does the input for robotMany fail, but since the 'w' is left in stdin unread, it causes input for enginePower, resistance, weight & height to fail as well. (if this occurs within a loop, your loop will likely go spinning out of control until the process is manually terminated)
That is why it is critical to always validate the return of any input function, but especially the scanf family of functions. To catch and handle any input failure (matching failure, input failure, or manually generated EOF), just check the return, e.g.
if (scanf ("%d", &robotMany) != 1) { /* VALIDATE EVERY USER INPUT! */
fputs ("error: invalid input, or user canceled - robotMany\n", stderr);
return 1;
}
On to your logic errors. First, you need a variable to track the sum of each product calculated on each trip through the loop. Since it appears this will be a total power, just add a totalpwr variable and initialize it to zero (as you have done a good job doing with all your variables), e.g.
int i = 0,
robotMany = 0,
enginePower = 0,
resistance = 0,
weight = 0,
height = 0,
totalpwr = 0; /* sum of product from each iteration */
Now within your loop, you want to add product to totalpwr each time it is computed, e.g.
/* Depending the user input, it will run # of times. */
for (i = 0; i < robotMany; i++) {
...
/* take the user inputs and apply it to the formula. */
int product = (enginePower + resistance) * (weight - height);
totalpwr += product; /* add product to total power */
}
To output the totalpwr, you will output the value after you exit the loop, e.g.
...
}
/* you output the total power required outside the loop */
printf ("\ntotal power required: %d\n", totalpwr);
return 0;
}
Putting it altogether in an example (without passing on the correctness of the product calculation or the range of values needed) you can do something similar to the following:
#include <stdio.h>
int main (void) {
int i = 0,
robotMany = 0,
enginePower = 0,
resistance = 0,
weight = 0,
height = 0,
totalpwr = 0; /* sum of product from each iteration */
/* you only need a single printf (fputs would do due to no conversion) */
printf ("Depending the numbers of robot that you enter, you will need "
"to enter:\n\n"
" Engine power | Resistance | Weight | Height\n\n"
"Enter the amount of robots: ");
if (scanf ("%d", &robotMany) != 1) { /* VALIDATE EVERY USER INPUT! */
fputs ("error: invalid input, or user canceled - robotMany\n", stderr);
return 1;
}
printf ("\nYou chose: %d robots\n\n", robotMany);
/* Depending the user input, it will run # of times. */
for (i = 0; i < robotMany; i++) {
printf ("Enter the engine power.(1-20): ");
if (scanf("%d", &enginePower) != 1) { /* validate! */
fputs ("error: invalid input - enginePower\n", stderr);
return 1;
}
printf ("Enter the resistance.(1-3): ");
if (scanf("%d", &resistance) != 1) { /* validate! */
fputs ("error: invalid input - resistance\n", stderr);
return 1;
}
printf ("Enter the weight of the robot: ");
if (scanf("%d", &weight) != 1) { /* validate! */
fputs ("error: invalid input - weight\n", stderr);
return 1;
}
printf ("Enter the height of Robot: ");
if (scanf("%d", &height) != 1) { /* validate! */
fputs ("error: invalid input - height\n", stderr);
return 1;
}
/* take the user inputs and apply it to the formula. */
int product = (enginePower + resistance) * (weight - height);
/* the following outputs the per-loop/per-robot product (you can remove) */
printf (" iteration %d product: %d\n\n", i+1, product);
totalpwr += product; /* add product to total power */
}
/* you output the total power required outside the loop */
printf ("\ntotal power required: %d\n", totalpwr);
return 0;
}
(note: only one printf is required to output multiple lines of output. There is no need to make repeated calls one after the other just to output separate lines. All sequential strings will be concatenated by the compiler)
Example Use/Output
$ ./bin/robotmany
Depending the numbers of robot that you enter, you will need to enter:
Engine power | Resistance | Weight | Height
Enter the amount of robots: 3
You chose: 3 robots
Enter the engine power.(1-20): 4
Enter the resistance.(1-3): 2
Enter the weight of the robot: 10
Enter the height of Robot: 31
iteration 1 product: -126
Enter the engine power.(1-20): 5
Enter the resistance.(1-3): 3
Enter the weight of the robot: 9
Enter the height of Robot: 31
iteration 2 product: -176
Enter the engine power.(1-20): 3
Enter the resistance.(1-3): 1
Enter the weight of the robot: 8
Enter the height of Robot: 31
iteration 3 product: -92
total power required: -394
You may want to add constraints on the weight and height entry to prevent a negative power-required result -- but that is left to you. Look things over and let me know if you have further questions.

Calculate GPA of a student without arrays [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
whats wrong in my code? it doesn't give the values properly and when i insert q it doesn't execute properly....
#include<stdio.h>
void main()
{
double a=0, x, ctot;
double y, stot;
char b, c='q';
double score=x*y;
while(a<200){
printf("Enter no of Credits of the subject = ");
scanf("%lf\n",&x);
printf("Enter the score for the subject = ");
scanf("%lf\n",&y);
scanf("%c\n",&b);
if(b=='q'){
break;
}else{
ctot+=x;
stot+=score;
a++;
}
}
printf("GPA of the student = %f\n", stot/ctot);
}
An attempt to access a variable with indeterminate value (meaning uninitialized) invokes Undefined Behavior and the valid operation of your code ceases at that point. It can appear to work properly or SegFault or anything in between.
To avoid uninitialized values, always initialize them -- especially when you are just beginning to program. (it will save you from yourself...), e.g.
int a = 0; /* always initialize all variables - good practice */
double ctot = 0.0,
stot = 0.0,
score = 0.0,
x = 0.0,
y = 0.0;
char c = 0;
The proper declarations for main are int main (void) and int main (int argc, char **argv) (which you will see written with the equivalent char *argv[]). note: main is a function of type int and it returns a value. See: C11 Standard ยง5.1.2.2.1 Program startup p1 (draft n1570). See also: See What should main() return in C and C++?
While there are some ancient compilers, and some micro-controllers that allow void main(), it is a non-standard invocation, and any worthwhile compiler will warn. (you are compiling with compiler-warning enabled right?, e.g. -Wall -Wextra for gcc/clang or /W3 for VS (cl.exe))
You must check the return of scanf every time and validate the return is equal to the number of conversions you have requested -- otherwise a matching or input failure has occurred (or the user canceled by generating a manual EOF). This is the only way you can insure you are processing valid data and not further invoking Undefined Behavior (or throwing yourself into an endless input loop). You must always empty stdin after each input. Your '\n' gimick in the format string will not work. A simple way to empty stdin is to define a helper-function to call after each input to remove any extraneous or additional characters that remain unread, e.g.
/* simple function to empty remaining chars in stdin */
void empty_stdin (void) /* if no parameter - spcecify 'void' explicitly */
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
...
printf ("Enter no of Credits of the subject = ");
if (scanf ("%lf", &x) != 1) { /* validate EVERY input */
fprintf (stderr, "error: invalid input for 'x'.\n");
return 1;
}
empty_stdin(); /* empty stdin, your \n gimick doesn't work */
Putting it altogether, you could do something similar to the following:
#include <stdio.h>
/* simple function to empty remaining chars in stdin */
void empty_stdin (void) /* if no parameter - spcecify 'void' explicitly */
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int a = 0; /* always initialize all variables - good practice */
double ctot = 0.0,
stot = 0.0,
score = 0.0,
x = 0.0,
y = 0.0;
char c = 0;
for (; a < 200; a++) { /* loop however you like */
printf ("Enter no of Credits of the subject = ");
if (scanf ("%lf", &x) != 1) { /* validate EVERY input */
fprintf (stderr, "error: invalid input for 'x'.\n");
return 1;
}
empty_stdin(); /* empty stdin, your \n gimick doesn't work */
printf ("Enter the score for the subject = ");
if (scanf ("%lf", &y) != 1) {
fprintf (stderr, "error: invalid input for 'y'.\n");
return 1;
}
empty_stdin();
score = x * y; /* compute values each iteration */
ctot += x;
stot += score;
/* prompt for additional credits? */
printf ("add additional credits? (y/n): ");
if (scanf (" %c", &c) != 1) {
fprintf (stderr, "error: user canceled input.\n");
return 1;
}
empty_stdin();
if (c == 'n' || c == 'N') /* you can use 'q', but (y/n) is fine */
break;
}
printf ("\nGPA of the student = %f\n", stot/ctot);
return 0;
}
(can you figure out why if (scanf (" %c", &c) != 1) can only mean that the user canceled input?)
Example Use/Output
note: there are extraneous characters intentionally input below to provide example of how the simple additions to your code handle them safely. (try the input below with your original code and see what happens)
$ ./bin/credits_grades
Enter no of Credits of the subject = 3
Enter the score for the subject = 90
add additional credits? (y/n): y
Enter no of Credits of the subject = 4 (seemed like 40)
Enter the score for the subject = 80 (thank god!)
add additional credits? (y/n): y
Enter no of Credits of the subject = 3
Enter the score for the subject = 85
add additional credits? (y/n): n
GPA of the student = 84.500000
Look things over and let me know if you have further questions.
Initializing ctot and stot and re-positioning score=x*y your code will work . Try this edited code this works fine :-
#include <stdio.h>
void main()
{
double a = 0, x, ctot;
double y, stot;
char b, c = 'q';
double score;
ctot = 0; // initialize ctot and stot #ERROR1
stot = 0;
while (a < 200)
{
printf("\n Enter no of Credits of the subject = ");
scanf("%lf", &x);
printf("\n Enter the score for the subject = ");
scanf("%lf", &y);
getchar(); // to manage the addtional \n from scanf()
score = x * y; // computing score #ERROR2
scanf("%c", &b);
if (b == 'q')
{
break;
}
else
{
ctot += x;
stot += score;
a++;
}
}
printf("\n GPA of the student = %f", stot / ctot);
}
based on comments of #mch and #David C. Rankin
should modify the slot+=score to slot+=x*y
#include<stdio.h>
void main()
{
double a=0, x, ctot;
double y, stot;
char b, c='q';
double score=x*y;
while(a<200){
printf("Enter no of Credits of the subject = ");
scanf("%lf\n",&x);
printf("Enter the score for the subject = ");
scanf("%lf\n",&y);
scanf("%c\n",&b);
if(b=='q'){
break;
}else{
ctot+=x;
stot+=x*y;
a++;
}
}
printf("GPA of the student = %f\n", stot/ctot);
}

How to pass arrays into functions in C ( on Fedora )?

Since I am a beginner have been practicing passing arrays as parameters to functions. Could someone explain why this program I wrote works fine on codeblox, but doesn't work in Fedora terminal (on Fedora it doesn't work for any number of scores). I'm using the GCC compiler.
#include<stdio.h>
int num,scores[]={},count,max,sum;
void input(int scores[]);
int findmax(int scores[]);
int findsum(int scores[]);
void display(int max,int sum);
int main()
{
printf("Enter number of scores\n");
scanf("%d",&num);
input(scores);
max=findmax(scores);
sum=findsum(scores);
display(max,sum);
return 0;
}
void input(int scores[])
{
for(count=0; count<num; count ++)
{
printf("Enter score #%d:\n",count);
scanf("%d",&scores[count]);
}
}
int findmax(int scores[])
{
for(count=0; count<num ; count ++)
{
if(scores[count]>max)
{
max=scores[count];
}
}
return max;
}
int findsum(int scores[])
{ sum=0;
for(count=0; count<num ; count++ )
{
sum=sum+scores[count];
}
return sum;
}
void display(int max,int sum)
{
printf("The max score is :%d\nThe total score is:%d\n",max,sum);
}
You should avoid using global variables unless they are absolutely required. None are required here. All values should be declared local to main and should be passed to each function as a parameter, as required.
You must validate ALL input by, at minimum, checking the return of scanf (or whatever input function you are using). If a user simply pressed Enter (generating a '\n') or enters words instead of numbers causing the conversion to fail, you are dead in the water and may well be watching an infinite loop scroll by until you kill the process. (a cat might step on the keyboard, etc.)
When using the scanf family of functions, if a failure occurs, you must account for any characters left in the input buffer (e.g. stdin with scanf). If scanf is called within a loop, you risk an infinite loop where the conversion fails, leaving the same characters in the input buffer only to be read again, and fail, over-and-over again.
If you do not validate your input, you can have no confidence that you are processing a valid input from that point forward, and may in fact be well off into Undefined Behavior. The scanf family of functions returns the number of valid conversions based on the number of format-specifiers contained within the format-string. So with "%d", you have one format-specifier (e.g. %d), so upon successful conversion the return will be 1 (you should also check for EOF if the user manually cancels input with Ctrl + d, or Ctrl + z on windoze -- which is left to you)
Putting those pieces together, you could do something like the following:
#include <stdio.h>
#include <limits.h> /* for INT_MIN */
#define MAX 512
void input (int *scores, int num);
int findmax (int *scores, int num);
int findsum (int *scores, int num);
void display (int max, int sum);
int main (void)
{
int num, scores[MAX] = { 0 }, max, sum;
printf ("Enter number of scores: ");
if (scanf ("%d", &num) != 1) { /* VALIDATE ALL input */
fprintf (stderr, "error: invalid integer input.\n");
return 1;
}
input (scores, num);
max = findmax (scores, num);
sum = findsum (scores, num);
display (max, sum);
return 0;
}
void input (int *scores, int num)
{
int count = 0;
while (count < MAX && count < num) { /* always protect array bounds */
printf ("Enter score [%d]: ", count);
while (scanf ("%d", &scores[count]) != 1) { /* VALIDATE input */
fprintf (stderr, "error: invalid input, try again.\n");
/* remove invalid chars from input buffer */
for (int c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
goto badval;
}
count++;
badval:;
}
}
int findmax (int *scores, int num)
{
int max = INT_MIN, count;
for (count = 0; count < num; count++)
if (scores[count] > max)
max = scores[count];
return max;
}
int findsum (int *scores, int num)
{
int sum = 0, count;
for (count = 0; count < num; count++)
sum = sum + scores[count];
return sum;
}
void display (int max, int sum)
{
printf ("\nThe max score is :%d\nThe total score is:%d\n", max, sum);
}
Example Use/Output
$ ./bin/maxminsum
Enter number of scores: 5
Enter score [0]: 9
Enter score [1]: 3
Enter score [2]: 7
Enter score [3]: 8
Enter score [4]: 2
The max score is :9
The total score is:29
With Error Correction
$ ./bin/maxminsum
Enter number of scores: 5
Enter score [0]: 9
Enter score [1]: 3
Enter score [2]: foo
error: invalid input, try again.
Enter score [2]: 7
Enter score [3]: 8
Enter score [4]: bar
error: invalid input, try again.
Enter score [4]: 2
The max score is :9
The total score is:29
Leave a comment if you have further questions.

Resources