Breaking an if statement inside a for-loop - c

How to get loop display to end after execution where gallons < 100 and hours < 24. I'm able to get the "The fish died after ... hours" but unsure how to stop the first printf() in the for loop from executing.
I've tried using a break statement indented in the if statement, but that only affects the for loop.
#include <stdio.h>
int main()
{
double add, vol = 500;
int hour;
printf("Please enter additional water added per hour: ");
scanf("%lf", &add);
for (hour = 1; hour <= 24; hour++)
{
vol = (vol * 0.90) + add;
printf("The volume is %.2f gallons after %d hours.\n", vol, hour);
if (hour <= 23 && vol < 100)
printf("The fish died after %d hours.", hour);
else if (hour == 24 && vol >= 100)
printf("Alas, The fish who lived.");
}
return 0;
}
Expected result:
Please enter additional water added per hour: 6
The volume is 456.00 gallons after 1 hours.
The volume is 416.40 gallons after 2 hours.
The volume is 380.76 gallons after 3 hours.
...
The volume is 103.33 gallons after 22 hours.
The volume is 99.00 gallons after 23 hours.
The fish died after 23 hours.
Actual result:
Please enter additional water added per hour: 6
The volume is 456.00 gallons after 1 hours.
The volume is 416.40 gallons after 2 hours.
The volume is 380.76 gallons after 3 hours.
...
The volume is 103.33 gallons after 22 hours.
The volume is 99.00 gallons after 23 hours.
The fish died after 23 hours. The volume is 95.10 gallons after 24 hours.

C is not Python, indentation is not significant syntactically. Compound statements must be enclosed in {..}:
if (hour <= 23 && vol < 100)
{
printf("The fish died after %d hours.", hour);
break ;
}
else if (hour == 24 && vol >= 100)
{
printf("Alas, The fish who lived.");
}
I suggest you always use {..} for conditional or loop blocks, even for single statements. It makes maintenance simpler.
However, break; is arguably a rather inelegant and poorly structured way of exiting a loop (along with continue). A better structured solution is to terminate the loop by the loop constraint alone. In this case this can be done by:
for( hour = 1;
vol > 100 && hour <= 24;
hour++)
There is the overhead of an additional test but in more complex code than this, with perhaps multiple breaks, it can become difficult to maintain, debug and comprehend.

You are still having a bit of problem figuring out your loop control. You are also inviting an Endless Loop if a matching failure occurs during input because you fail to check the return of scanf (probably one of the biggest pitfalls that new C programmers fall into). Try it. Type "one gallon" at your prompt for input and see what happens. Further, after checking the return, you have to handle 3-cases:
scanf can be used, if used correctly. This means you are responsible for checking the return of scanf every time.
(return == EOF) the user canceled input by generating a manual EOF by pressing Ctrl+d (or on windows Ctrl+z, but see CTRL+Z does not generate EOF in Windows 10 (early versions));
(return < expected No. of conversions) a matching or input failure occurred. For a matching failure you must account for every character left in your input buffer. (scan forward in the input buffer reading and discarding characters until a '\n' or EOF is found); and finally
(return == expected No. of conversions) indicating a successful read -- it is then up to you to check whether the input meets any additional criteria (e.g. positive integer, positive floating-point, within a needed range, etc..).
Onto your loop logic. Given your example and your question "Breaking an if statement inside a for-loop", I think I know where you want to go -- and you can get there with one of the simplest, least used and frankly, mandatory, expressions for nested loop control. The good ole goto statement. It still has a place in programming, and while it should not be overly used, there are a few circumstances, such as those above, and in fact you circumstance, where it is fine to use the goto to jump out of a loop and pass control a few lines down. (the limitation is a longjmp -- you don't want to use it to jump out of a function)
For example, if I understand what you are going for in fish-survival, you can clean up your logic and incorporate the scanf validations by putting the pieces together similar to the following:
#include <stdio.h>
int main (void) {
double add, vol = 500;
int hour;
for (;;) { /* loop continually until valid input is received */
int rtn; /* varible for scanf return - EVERY TIME */
/* there is no conversion taking place, fputs will do */
fputs ("Please enter additional water added per hour: ", stdout);
if ((rtn = scanf ("%lf", &add)) == EOF) { /* handle EOF case */
fputs ("(user canceled input)\n", stderr);
return 1;
}
else if (rtn == 0) { /* handle matching failure */
fputs ("error: invalid double input.\n", stderr);
/* empty all characters from stdin before next input */
for (int c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
}
else /* handle good input */
break;
}
for (hour = 0; hour < 24; hour++) { /* loop 0 < 24 */
vol = (vol * 0.90) + add; /* adjust output hour + 1 below */
printf ("The volume is %.2f gallons after %d hours.\n", vol, hour+1);
if (vol < 100) { /* don't forget the '\n' */
printf ("The fish died after %d hours.\n", hour + 1);
goto deadfish; /* jump to deadfish label */
}
}
puts ("Alas, The fish who lived."); /* again, no conversion */
deadfish:; /* good ole goto label */
return 0;
}
(note: generally loop in C will run 0 < n and you adjust the output as required above. While this is not mandatory, it is very much by convention, and accommodates arrays being zero-indexed in C, as well as the hours on a clock that run 0 -> 23, not 1 - > 24. The title of the movie "Zero Dark Thirty" is a good analogy (e.g. zero hour thirty minutes or 12:30 am.) You can't get there looping 1 <= 24, so those limits fail to model the concept of time correctly)
Notice above the use of the goto. It is used in conjunction with the vol < 100 check. If vol < 100 tests TRUE, then control is passed to the label associated with the goto statement. (the label being deadfish:; here). This provides several benefits here. Your for loop can simply track time -- the hours the tank is leaking up to 24. Note how the volume falling below 100 causes control to jump over the living fish output which would execute on normal loop exit.
While you may be able to get your desired dead fish output by incorporating the if (vol < 100) /* print dead fish */; break; else if ... it becomes very difficult to get your /* print live fish */ method on normal loop exit that way without checking the loop counter again as part of the else if clause. The goto provides an elegant solution to just that problem by allowing you to pass control over the /* print live fish */ case when the volume falls below the limit, while at the same time preserving the normal loop exit without having to test your loop counter variable a second time within the loop itself.
Example Use/Output
Make sure your program can handle a cat stepping on the keyboard for every user input. You must Validate every time, e.g.
$ ./bin/deadfish
Please enter additional water added per hour: one gallon
error: invalid double input.
Please enter additional water added per hour: 1
The volume is 451.00 gallons after 1 hours.
The volume is 406.90 gallons after 2 hours.
The volume is 367.21 gallons after 3 hours.
The volume is 331.49 gallons after 4 hours.
The volume is 299.34 gallons after 5 hours.
The volume is 270.41 gallons after 6 hours.
The volume is 244.37 gallons after 7 hours.
The volume is 220.93 gallons after 8 hours.
The volume is 199.84 gallons after 9 hours.
The volume is 180.85 gallons after 10 hours.
The volume is 163.77 gallons after 11 hours.
The volume is 148.39 gallons after 12 hours.
The volume is 134.55 gallons after 13 hours.
The volume is 122.10 gallons after 14 hours.
The volume is 110.89 gallons after 15 hours.
The volume is 100.80 gallons after 16 hours.
The volume is 91.72 gallons after 17 hours.
The fish died after 17 hours.
(cat on keyboard test passed...)
The closest dead fish to 100 gallons:
$ ./bin/deadfish
Please enter additional water added per hour: 6.53
The volume is 456.53 gallons after 1 hours.
The volume is 417.41 gallons after 2 hours.
The volume is 382.20 gallons after 3 hours.
The volume is 350.51 gallons after 4 hours.
The volume is 321.99 gallons after 5 hours.
The volume is 296.32 gallons after 6 hours.
The volume is 273.22 gallons after 7 hours.
The volume is 252.42 gallons after 8 hours.
The volume is 233.71 gallons after 9 hours.
The volume is 216.87 gallons after 10 hours.
The volume is 201.71 gallons after 11 hours.
The volume is 188.07 gallons after 12 hours.
The volume is 175.79 gallons after 13 hours.
The volume is 164.75 gallons after 14 hours.
The volume is 154.80 gallons after 15 hours.
The volume is 145.85 gallons after 16 hours.
The volume is 137.80 gallons after 17 hours.
The volume is 130.55 gallons after 18 hours.
The volume is 124.02 gallons after 19 hours.
The volume is 118.15 gallons after 20 hours.
The volume is 112.86 gallons after 21 hours.
The volume is 108.11 gallons after 22 hours.
The volume is 103.83 gallons after 23 hours.
The volume is 99.97 gallons after 24 hours.
The fish died after 24 hours.
(3 - 100th of a gallon dead)
The first live fish:
$ ./bin/deadfish
Please enter additional water added per hour: 6.54
The volume is 456.54 gallons after 1 hours.
The volume is 417.43 gallons after 2 hours.
The volume is 382.22 gallons after 3 hours.
The volume is 350.54 gallons after 4 hours.
The volume is 322.03 gallons after 5 hours.
The volume is 296.36 gallons after 6 hours.
The volume is 273.27 gallons after 7 hours.
The volume is 252.48 gallons after 8 hours.
The volume is 233.77 gallons after 9 hours.
The volume is 216.94 gallons after 10 hours.
The volume is 201.78 gallons after 11 hours.
The volume is 188.14 gallons after 12 hours.
The volume is 175.87 gallons after 13 hours.
The volume is 164.82 gallons after 14 hours.
The volume is 154.88 gallons after 15 hours.
The volume is 145.93 gallons after 16 hours.
The volume is 137.88 gallons after 17 hours.
The volume is 130.63 gallons after 18 hours.
The volume is 124.11 gallons after 19 hours.
The volume is 118.24 gallons after 20 hours.
The volume is 112.95 gallons after 21 hours.
The volume is 108.20 gallons after 22 hours.
The volume is 103.92 gallons after 23 hours.
The volume is 100.07 gallons after 24 hours.
Alas, The fish who lived.
(saved by 7 - 100th of a gallon -- I'll leave it to you to bisect further into the 1000th of a gallon if you need to)
Look things over and let me know if you have further questions. Put the goto into you C toolbox knowing it should not be over-used, but that it has a few uses where it can provide the optimal solution, and in the case of breaking nested loop, is the only tool in your toolbox that can do it.

Related

Round-Robin Scheduling Algorithm in OS

I have been trying to understand how the round robin concept and how the algorithm works. I have tried running this code in ubuntu, and i'm unable to get the answer that i wanted.
So based on the Round Robin Scheduling Algorithm; Let's say there are 3 processes. Where Processor 1 - Burst Time is 24, Processor 2 - Burst time is 3 and Processor 3 - Burst time is 3. and the Time Quantum is 3.
Based on this information, the waiting time for P1 is 6, P2 is 4 and P3 is 7. So the Turn Around Time is P1 is 30, P2 is 7 and P3 is 10.
Average Turn Around time is 15.6667 and The average waiting time is 5.667
Based on the code below, if i run it, it would return me; for waiting time - P1 is 6, P2 is 3 and P3 is 6, Turn around time P1 is 30, P2 is 6, P3 is 9.
And the Average Turn Around time is 15.0000 and The average waiting time is 5.000
I'm unable to figure out the error. Can any one help me with this problem and provide an explanation to error and solution?
#include<stdio.h>
#include<curses.h>
int main()
{
int i,j,n,bu[10],wa[10],tat[10],t,ct[10],max;
float awt=0,att=0,temp=0;
clear();
printf("Enter the no of processes -- ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\nEnter Burst Time for process %d -- ", i+1);
scanf("%d",&bu[i]);
ct[i]=bu[i];
}
printf("\nEnter the size of time slice -- ");
scanf("%d",&t);
max=bu[0];
for(i=1;i<n;i++)
if(max<bu[i])
max=bu[i];
for(j=0;j<(max/t)+1;j++)
for(i=0;i<n;i++)
if(bu[i]!=0)
if(bu[i]<=t)
{
tat[i]=temp+bu[i];
temp=temp+bu[i];
bu[i]=0;
}
else
{
bu[i]=bu[i]-t;
temp=temp+t;
}
for(i=0;i<n;i++)
{
wa[i]=tat[i]-ct[i];
att+=tat[i];
awt+=wa[i];
}
printf("\n\tPROCESS\t BURST TIME \t WAITING TIME\tTURNAROUND TIME\n");
for(i=0;i<n;i++)
{
printf("\t%d \t %d \t\t %d \t\t %d \n",i+1,ct[i],wa[i],tat[i]);
}
printf("\nThe Average Turnaround time is -- %f",att/n);
printf("\nThe Average Waiting time is -- %f ",awt/n);
getch();
}
The code is returning the right answer.
All the processes arrived at time 0.
P1 - 0-3 21 units remaining
P2 - 3-6 0 units remaining
P3 - 6-9 0 units remaining
P1 - 9-30 0 units remaining
P1 waited 6 units, P2 waited 3 units and P3 waited 6 units.
Note that Waiting time is the amount of time a process is waiting without being executed after given to the scheduler. Turnaround time is the total time a process took to complete its execution (Waiting time + Burst time).
Avg waiting time: (6+3+6) / 3 = 15
Average Turnaround time = (30+6+9) / 3 = 15

Calculate average sea level change

This the assignment I'm trying to do.
Download the sea level data from http://climate.nasa.gov/vital-signs/sea-level (Links to an external site.). Create a program that does the following:
a. Tell the user that the program uses data from NASA to predict sea level from the years 2020 to 2050.
b. Store the sea level data in an array. You only need to use one data point for each year from 1993 to the present year. Use the last column for each row (the Global Mean Sea Level GMSL with annual and semi-annual signal removed).
c. Find the average annual change in sea level over all the years specified in the data. (Hint - use a loop to store the annual change in an array over the years, and then use a loop to compute the average annual change).
d. Assume a linear increase and compute the predicted sea level rise for the years 2020, 2025, 2030, 2035, 2040, 2045, and 2050. Store these results in their own array. (Hint - just use the average you computed in part c as the annual change for the future years).
e. Display the results for the user and be sure to reference the data set as specified in the data file so the user knows where the data came from.
Sample output:
The predicted Global Mean Sea Level is
2020 64.32
2025 68.98
2030 73.51
2035 78.12
2040 83.43
2045 88.12
2050 93.04
These predictions were made using data provided by XXXXXXXXXX
This is the code so far. However It seems to not use all of the data in the array to find the average change in sea level.
#include <stdio.h>
#include <stdlib.h>
int main()
{
//creates a file object to read data
FILE* infile = fopen("nasa.txt","r");
//checks if file exists
if(infile == NULL)
{
printf("File does not exist.\n");
return -1;
}
//create 2d array to store years and their sea levels
int level[50][2];
//number of elements in array
int n = 0,i;
char word[5];
//read data from file word by word
while(fscanf(infile, "%s", word) != EOF)
{
if(word != ' ' && word != '\n')
{
//convert string to int and store in array
level[n][0] = atoi(word);
//store sea level
fscanf(infile, "%s", word);
level[n][1] = atoi(word);
//increment n
n++;
}
}
//store avg change
float avg=0;
for(i=1;i<n;i++)
{
//add difference of consecutive elements
avg += level[i][1] - level[i-1][1];
}
//calculate mean
avg = (float)avg/n;
int c = 7; //number of predictions
//array to store results
float predictions[][2] = {{2020,0},{2025,0},{2030,0},{2035,0},
{2040,0},{2045,0},{2050,0}};
//predict future sea levels
for(i=0;i<c;i++)
{
//multiply avg change by number of years
predictions[i][1] = level[n-1][1] +
(predictions[i][0] - level[n-1][0])*avg;
}
//print avg change
printf("Average change in sea level year over year is: %f mm\n",avg);
//print predictions
for(i = 0;i<c;i++)
{
printf("Predicted sea level change since 1993 for the year %.0f: %.2f mm\n",
predictions[i][0],predictions[i][1]);
}
printf("These predictions were made using data provided by the National Aeronautics and Space Administration.");
return 0;
}
Sea level change data
1993 4
1994 7
1995 11
1996 14
1997 21
1998 20
1999 19
2000 22
2001 27
2002 31
2003 34
2004 36
2005 40
2006 42
2007 43
2008 47
2009 48
2010 54
2011 53
2012 59
2013 65
2014 68
2015 75
2016 83
2017 85
2018 88
2019 94
However It seems to not use all of the data in the array to find the average change in sea level.
avg = (float)avg/n; is same as avg = (float)(level[n-1][1] - level[0][1])/n.
Only the end-points matter.
The loop that accumulates the differences is canceling out the in-between year's values.
In a mid-year, if you add +100, it makes one year difference +100 more, and the next year difference 100 less. The running sum of the differences is not affect by that +100 in the end.
All the mid-year values could be 0 and one would get the same average.

Shipping calculator not returning correct results

The assignment is to write a shipping calculator using the following information.
Packages above 50 pounds will not be shipped. You need to write a program in C that calculates the shipping charge.
The shipping rates are based on per 500 miles shipped. They are not pro-rated, i.e., 600 miles is the same rate as 900 miles or 1000 miles.
Here are the shipping charges -
Package Weight Rate per 500 miles shipped
Less than or equal to 10 pounds $3.00
More than 10 pounds but less than or equal to 50 pounds $5.00
If the shipping distance is more than 1000 miles, there is an additional charge of $10 per package shipped.
I originally started writing the program using double but wanted to used a trick I had seen on here to always force the program to round up for the shipping charges by adding 499 to distance then dividing by 500.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int Shipping, packageWeight, packageDistance, packagePrice;
printf("Enter the weight of the package: \n");
scanf("%d", &packageWeight);
printf("The weight you have entered is %.2d\n", packageWeight);
if (packageWeight <= 10 )
Shipping = 3.00;
if (packageWeight <= 50 && packageWeight > 10 )
Shipping = 5.00;
if (packageWeight > 50.0) {
puts("Sorry, we only ship packages of 50 pounds or less.");
return 0;
}
printf("How far are you sending the package? \n");
scanf("%d", &packageDistance);
printf("The distance you entered is %.2d\n", packageDistance);
if (packageDistance <= 1000){
packagePrice = (packageDistance + 499 / 500) * Shipping;
printf("The shipping charge is %.2d \n", packagePrice);
system("pause");
}
if (packageDistance > 1000) {
packagePrice = (packageDistance + 499 / 500) * Shipping + 10.00;
printf("The shipping charge is %.2d \n", packagePrice);
system("PAUSE");
}
}
With a weight of 10 and distance of 501 the output should be a shipping charge of 6 but was 1503
Based on a a weight of 20 and a distance of 1001 the program should output a shipping charge of 25 but was 5000
You have mess with integers / doubles, output, expressions, etc.
Let me show you why you get 1503:
if (packageDistance <= 1000){
packagePrice = (packageDistance + 499 / 500) * Shipping;
printf("The shipping charge is %.2d \n", packagePrice);
system("pause");
}
Your packageDistance is 501 then if statement is true and you get inside.
Then you setup package price. First you get packageDistance which is 501. Then you add it with 499/500 which is 0 since 499 < 500 and you attempt to get integer part of division (as per C/C++ standard). The sum of 501 and 0 is 501.
Now, you multiply it with Shipping. The value you set is 3.0, but smart C convert it to integer 3. 501 * 3 is 1503 and you get the result.
Finally, you try to sent output as %.2d. This is nonsense and I am surprised C shows something at all, but I believe it just see d and ignores .2
This is what you have to do:
Understand your business logic (you do)
Be careful with integers and floating point numbers, read C documentation or send questions here if you do not understand something.
Make sure you use brackets when needed: a + b / c is not the same as (a + b) / c
Make sure you do not use integer division if you mean to use "regular" division.
Make sure you use %d for integers and %.2f for floating point numbers when appropriate.

Code is ignoring IF command in C, Issues with FOR

I had posted on here before, but I was never able to get the help I needed.
I'm working on a school project and I can not get my program to work properly.
The program should prompt the user to enter the number of gallons used and
the number of miles driven for each of the 3 tanks of gas. The program should
then calculate and display the miles per gallon obtained for each tank. Once
processing is complete for the 3 tanks, the program will calculate the overall
mileage(total gallons / total miles) and display a friendly "Goodbye" message.
The issue i am having is that I can not get it to display to OVERALL Millage. it ends after looping 3 times.
I know different loop statements need conditions to be met, but I cant get the FOR loop to work properly. Im getting really frustrated, cause I know this should not be this hard.
Code
#include <stdio.h>
int main(void)
{
int miles,i=3;
float gallons, mg, overall = 0, avg = 0;
while(i>0)
{
printf("Enter the gallons used: ");
scanf("%f", &gallons);
printf("Enter miles driven: ");
scanf("%d", &miles);
mg = miles/gallons;
printf("The miles/gallon for this tank was : %f\n", mg);
overall += miles;
avg += gallons;i--;
}
if(gallons == 0)
{
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
exit(0);
}
return 0;
}
If I read your code correctly, then what is preventing the overall mileage from being printed is the following final if statement:
if (gallons == 0)
If you remove it, then the overall mileage should print. Use this pattern:
while (i > 0)
{
// your while loop here
}
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
exit(0);
This if (if (gallons == 0) {})block is out of while loop.
First, you need to move the if loop inside while loop.
and this if condition should be for variable i as follow and not for gallons.
if (i == 0)
{
printf("\n\n The overall miles/gallon was: %f\n", overall/avg);
}
In this case, after 3 iteration, value of i will be 0 so it will enter into the if block and calculate and print the overall miles/gallon.
Adding to Tim Biegeleisen's answer:
mg = miles/gallons;
What if gallons equals to 0? e.g. 0 miles for 0 gallons
This will lead to floating point exception.
A simple if-else can solve this problem!
if(!gallons)
mg = 0;
else
mg = miles/gallons;

remove trailing zeros from output

So my program works and compiles it does what I ask.
But my program's output has these trailing zeros that I would like to eliminate.
It's not like it bothers me but I definitely would like to have it cleaned up a little.
If anyone could give me a little insight on how to eliminate the trailing zeros your help,
would be greatly appreciated.
#include "stdafx.h"
#include "stdio.h"
#define BPR 10 // Basic Pay Rate is $10.00/hr.
#define OTPR 15 // Over Time is time and a half.
#define OT 40 // Overtime is after 40 hours.
#define RATE1 .15 // Tax Rate 15%.
#define RATE2 .20 // Tax Rate 20%.
#define RATE3 .25 // Tax Rate 25%.
#define LIMIT1 300.00 // The first 300.00.
#define LIMIT2 200.00 // 200 after the first 300.
int main(void)
{
int hours;
double tax;
double gross;
double taxes1=0,taxes2=0,taxes3=0;
double net;
double hold1=0,hold2=0,hold3=0;
printf("Please enter hours worked: ");
scanf_s("%i", &hours);
if(hours < OT)
gross=hours*BPR;
else
gross=((hours-OT)*OTPR+(OT*BPR));
if(gross > LIMIT2 && gross < LIMIT1)
taxes1=gross*RATE2, hold1=gross-taxes1;
if(gross > LIMIT1)
taxes2=gross*RATE1, hold2=gross-taxes2;
if(gross < LIMIT2)
taxes3=gross*RATE3, hold3=gross-taxes3;
if(gross > 0)
{
net=(hold1+hold2+hold3);
tax=(taxes1+taxes2+taxes3);
}
printf("Your Net Pay is %f\n", net);
printf("Your Gross Pay was %f\n", gross);
printf("Your Taxes paid are %f\n", tax);
return 0;
}
if 65 was put in for the hours variable the output would read:
Your Net pay is 828.750000
Your Gross Pay was 975.000000
Your Taxes paid are 146.250000
as you can see there are a lot of zeros I would love to have disappear please help ?
Use %.2f as the output format.
You can specify how many positions you want to display after the decimal point using . followed by the number of positions between % and f like so: printf("Your Net Pay is %.2f\n", net);. There are other formatting options that can be used with format specifiers and you can read more on them in the man pages by doing man printf since printf is not just a C function.

Resources