Program stops running after displaying result - c

I want to be able to take someones amount owed as the price, and then do some math from the amount received and print my result.
Below is the code I came up with. However, my program does not run after showing the amount tendered.
Any thoughts?
Note, it is my first time coding in C, and I'm from Java..
#include <stdio.h>
int main (void) {
double tendered;
double changeDue;
double price;
int hundred=0;
int twenty=0;
int ten=0;
int five=0;
int toonoe=0;
int loonie=0;
int quarter=0;
int dime=0;
int nickle=0;
int penny=0;
/* Statements to be executed */
printf("Total purchase price and tendered amount");
scanf("%lf%lf", &price, &tendered);
printf("The sum of %lf and %lf is ", tendered,price);
changeDue=tendered-price;
while(changeDue!=0.00){
if(changeDue<=100.00){
changeDue=changeDue-100.00;
hundred=hundred+1;
}
if(changeDue<=20.00){
changeDue=changeDue-20.00;
twenty=twenty+1;
}
if(changeDue<=10){
changeDue=changeDue-10.00;
ten=ten+1;
}
if(changeDue<=5){
changeDue=changeDue-5.00;
five=five+1;
}
if(changeDue<=2){
changeDue=changeDue-2.00;
toonoe=toonoe+1;
}
if(changeDue<=1){
changeDue=changeDue-1.00;
loonie=loonie+1;
}
if(changeDue>1){
for(int i=0;i<changeDue;i++){
if(i==0.25&&changeDue>=0.25){
changeDue=changeDue-0.25;
quarter=quarter+1;
}
if(i==0.10&&changeDue>=0.10){
changeDue=changeDue-0.10;
dime=dime+1;
}
if(i==0.05&&changeDue>=0.05){
changeDue=changeDue-0.05;
nickle=nickle+1;
}
if(i==0.01&&changeDue<0.05){
changeDue=changeDue-0.01;
penny=penny+1;
}
}
}
}
if(hundred!=0){
printf("%d hundred$ bills given as change",hundred);
}
if(twenty!=0){
printf("%d twenty$ bills given as change",twenty);
}
if(ten!=0){
printf("%d ten$ bills given as change",ten);
}
if(five!=0){
printf("%d five$ bills given as change",five);
}
if(toonoe!=0){
printf("%d toonie coins given as change",toonoe);
}
if(loonie!=0){
printf("%d loonie coins given as change",loonie);
}
if(quarter!=0){
printf("%d quarter coins given as change",quarter);
}
if(dime!=0){
printf("%d dime coins given as change",dime);
}
if(nickle!=0){
printf("%d nicke coins given as change",nickle);
}
if(penny!=0){
printf("%d penny coins given as change",penny);
}
return 0;
}
I have an alternative version of that code, which changes the first part of scanning and printing to
/* identical to start of first version ... */
/* Statements to be executed */
printf("Total purchase price");
scanf("%d", &price);
printf("Enter amount recieved by customer ");
scanf("%d", &tendered);
printf("%d", &tendered);
printf("%d",&tendered);
changeDue=tendered-price;
/* identical to end of first version ... */
And I have a third version, where first scanning and printing is like this.
/* identical to start of first version ... */
float tendered;
float changeDue;
float price;
int hundred=0;
int twenty=0;
int ten=0;
int five=0;
float toonoe=0;
float loonie=0;
float quarter=0;
float dime=0;
float nickle=0;
float penny=0;
/* Statements to be executed */
printf("Total purchase price");
scanf("%f", &price);
printf("Enter amount recieved by customer ");
scanf("%f", &tendered);
printf("%f tendered", tendered);
changeDue=tendered-price;
/* identical to end of first version ... */

You have the problem of comparing a floating point value for identity
(or for not being identical, same problem) here:
while(changeDue!=0.00){
See here for some background:
Is floating point math broken?
It creates an endless loop (at least if you are not "lucky"), which prevents all further printing. (Actually "lucky" is not a good description for hiding a bug...)
In order to verify this diagnose, insert a printf at the start of the loop.
while(changeDue!=0.00){
printf("Making change...\n");
You will see many more of that debug output line than you expect.
In order to solve that endless-loop problem, change to
while(changeDue>=0.01)
and the endless loop is solved, which currently prevents anything visible happen after printing the due amount.
This does not necessarily fix all the problems in your code, but the most prominent one described in your question is solved.
Note that one of the comments recommends to use int for currency.
I normally agree, but I have accepted your statement that you have to use float/double.
By the way, use the first version of the code.
In the second version you are printing the address of something instead of the value. I.e. the & is wrong here:
printf("%d", &tendered);
In the third version your types and the format string in printf do not match.

Related

How to get the total?

Good day, I am practicing about Arithmetic and started to experiment a bit and got confused. How can I total the liter, refueled, and tendered?
#include <stdio.h>
int main()
{
int liter, refueled, tendered, changed;
printf("Enter the price of the fuel per liter: ");
scanf("%f",&liter);
printf("Enter the number of liters the customer wants refueled: ");
scanf("%f",&refueled);
printf("Enter the amount tendered: ");
scanf("%f",&tendered);
printf("your change is %.2f pesos. Thank you and come again!", changed = liter * refueled - tendered);
return 0;
}
It seems like float is more appropriate for all your variables (liter, refueled, tendered, changed). There's no reason to allow only integer amounts of fuel etc. You also scanfed them using "%f" which is used for floats.
It's better to assign changed in a separate line, or alternatively get rid of it altogether and simply put the mathematical expression in the printf call.
You inverted the value of changed. Should be tendered - liter * refueled.
Better version:
#include <stdio.h>
int error_handler(/*error params*/)
{
int errCode{ 1 };
// Error handling based on the params, set errCode ...
return errCode;
}
float get_change(float liter, float refueled, float tendered)
{
return tendered - liter * refueled;
}
int main()
{
float liter{ 0 }, refueled{ 0 }, tendered{ 0 };
printf("Enter the price of the fuel per liter: ");
if (scanf("%f", &liter) != 1) {
return error_handler(/*error params*/);
}
printf("Enter the number of liters the customer wants refueled: ");
if (scanf("%f", &refueled) != 1) {
return error_handler(/*error params*/);
}
printf("Enter the amount tendered: ");
if (scanf("%f", &tendered) != 1) {
return error_handler(/*error params*/);
}
printf("your change is %.2f pesos. Thank you and come again!\n", get_change(liter, refueled, tendered));
return 0;
}
Update:
Following the comments below I updated my solution with:
Skeleton for error handling for scanf.
A separate function for the change calculation. In this case it seems a bit contrived, but it's correct from a methodical software engineering point of view (imagine this calculation getting a lot more complex in some real life scenario). Note: you can further apply this principle and extract for example the code for getting input from the user to a separate function. In my code above I decided it is enough to demonstrate it with get_change and error_handler.
Your scanning attempts, e.g. scanf("%f",&liter); uses the format specifier for float, but gives the address of an integer.
That causes undefined behaviour, which means "do not do this" for practicals (otherwise look up the term, or for fun "nasal demons").
The simplest fix (assuming you input integer values) is to switch to "%d".
If you instead switch to using float for the variable (probably necessary), you should know, for the cases of currency (e.g. tendered), that a very recommended best practice is to then convert to an integer variable which counts the smallest denomination, e.g. cents.
I took the answer of wohlstad, which was nearly perfect and added a function for your calculation...
#include <stdio.h>
fload calculation(fload tendered, fload liter, fload refueled);
int main()
{
float liter, refueled, tendered, changed;
printf("Enter the price of the fuel per liter: ");
scanf("%f", &liter);
printf("Enter the number of liters the customer wants refueled: ");
scanf("%f", &refueled);
printf("Enter the amount tendered: ");
scanf("%f", &tendered);
changed = calculation(tendered, liter, refueled);
printf("your change is %.2f pesos. Thank you and come again!", changed);
return 0;
}
fload calculation(fload tendered, fload liter, fload refueled){
fload calcVal = tendered - liter * refueled;
return calcVal;
}
Now you can edit your calculation like you need it, adding more or less things etc...

How to prevent the wrong value entered by the user from getting stored in the variable?

I'm trying to prevent the user from entering a wrong value in this simple C program by using an if statement within while loop. But the problem is that whenever the user enters a wrong value, it gets stored in the variable and the same value is then use for further calculations.
Here's the actual program:
#include <stdio.h>
#include <stdlib.h>
/*Program to calculate the marks obtained scored by the class in a quiz*/
int main()
{
float marks, average, total = 0.0;
int noStudents;
printf("Enter the total number of students: ");
scanf("%d", &noStudents);
int a=1;
while(a<=noStudents)
{
printf("Enter marks obtained out of 20: ");
scanf("%f", &marks);
if(marks<0 || marks >20)
{
printf("You have entered wrong marks\nEnter again: ");
scanf("%d", &marks);
}
total = total+marks;
a++;
}
average = total/(float)noStudents;
printf("Average marks obtained by the class are: %f", average);
return 0;
}
The first problem is the inconsistency in your code. Inside the condition statement body, you wrote
scanf("%d", &marks);
which uses mismatched argument type for %d. This invokes undefined behavior. You should be using %f, as before.
That said,
you're relying on user to correct themselves in the second attempt, don't do that. Use a loop and only after you get a valid value, break out of that.
In the statement average = total/(float)noStudents;, you don't need the cast. One of the operand, total is already of float type, so the other operand will be automatically promoted and floating point division will take place, even in absence of the explicit cast.
Have slightly tweaked your code. Hope it helps. As already mentioned in one of the comment, don't expect user to give the correct value in out of range scenario. You should keep on asking the user to enter within the range unless he feeds in the correct value.
#include<stdio.h>
#include<stdlib.h>
int main()
{
float marks, average, total = 0.0;
int noStudents;
printf("Enter the total number of students: ");
scanf("%d", &noStudents);
int a=1;
while(a<=noStudents)
{
printf("Enter marks obtained out of 20: ");
scanf("%f", &marks);
if(marks<0 || marks >20)
{
printf("You have entered wrong marks.Enter again:\n ");
continue;
}
total = total+marks;
a++;
}
average = total/noStudents;
printf("Average marks obtained by the class are: %f", average);
return 0;
}

averaging while looping, the sum won't clear and thus keeps adding numbers from previous loop entry

#include <stdio.h>
int main () {
int days, flights, t, b;
float length, mean, sum;
printf("How many days has your dragon been practicing?\n");
scanf("%d", &days);
for(t=1; t<=days; t++) {
printf("How many flights were completed in day #%d?\n", t);
scanf("%d", &flights);
for(b=1; b<=flights; b++) {
printf("How long was flight #%d?\n", b);
scanf("%f", &length);
sum+=length;
}
mean = sum/flights;
printf("Day #%d: The average distance is %.3f.\n", t, mean);
}
}
the sum used to calculate the mean is supposed to be only the number from one iteration of the loop added together. instead the sum used numbers from the new iteration and old iteration added together.
If I understood your problem correctly, after the last printf() statement, you should reset sum to 0, like sum = 0;.
That said, the major issue in your code is that, you're using sum (an automatic storage local variable) while uninitialized. You should be initializing sum to some value (0, maybe) before making use (sum+=) of it. Otherwise, it it invokes undefined behavior.
To quote C11 standard, chapter ยง6.7.9
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. [...]
sum won't clear because you don't clear it ! The point of writing code is to make your dumb machine(yeah dumb!) know when it's got to do what!
So immediately after
for(t=1;t<=days;t++)
{
Add this:
sum=0;
This will ensure that your sum value is reset every day your dragon takes a flight! Otherwise C will use some random garbage value as your sum and you would receive weird answers!
Some suggestions:
1) If you call scanf() just after you call printf(), there is no reason to use '\n' inside that printf at the end.
2) Always check scanf() for errors or your code is useless if errors occurs.
Now about your code:
When you use something like x+=y this means x = x + y.
So, in your case sum+=length means sum=sum+length. Do you know the value of sum? Yes is a garbage value.
About this line mean = sum/flights;, what is mean, sum and what is flights? Yes, first are float but second is int.
Now putting all together:
#include <stdio.h>
int main (void){
int days, flights, t, b;
float length, mean, sum=0;
printf("How many days has your dragon been practicing?: ");
if((scanf("%d", &days)) != 1){
printf("Error\n");
}
for(t=1; t<=days; t++) {
printf("How many flights were completed in day #%d?: ", t);
if((scanf("%d", &flights)) != 1){
printf("Error\n");
}
for(b=1; b<=flights; b++) {
printf("How long was flight #%d?\n", b);
if((scanf("%f", &length)) != 1){
printf("Error\n");
}
sum+=length;
}
mean = sum/(float)flights;
printf("Day #%d: The average distance is %.3f.\n", t, mean);
}
return 0;
}

Smallest number of bills program in C function-pointer issue

so C-programming noob here. I'm working on some practice questions, and I can't seem to figure out where I'm making a mistake on this one.
I'm pretty sure there is an error in how the pointers are being grabbed by the main function, but I've tried everything I could think of/read up on and have no idea how to resolve my problem.
Some more information about the question - the change calculation has to be a function, and I made up a program to get input from the user to then go through the function and spit out the smallest number of bills/coins used. No small change (quarters,dimes,nickels, pennies), so only int number are required.
#include <stdio.h>
#include <math.h>
int main(void)
{
/* local variable definition of enter amount*/
int dollars, *twenties, *tens, *fives, *toonies, *loonies;
printf("enter amount: ");
scanf("%d", &dollars);
printf("\nChange for $%d is:\n", dollars);
/* Calling pay_amount function to get smallest bills*/
printf("$20s: %d\n", &twenties);
printf("$10s: %d\n", &tens);
printf("$5s: %d\n", &fives);
printf("$2s: %d\n", &toonies);
printf("$1s: %d\n", &loonies);
return;
}
/*Function pay_amount declaration */
void pay_amount(int dollars, int *twenties, int *tens, int *fives, int *toonies, int *loonies)
{
while (dollars>=0);
*twenties = (dollars/20);
*tens = ((dollars%20)/10);
*fives = (((dollars%20)%10)/5);
*toonies = ((((dollars%20)%10)%5)/2);
*loonies = (((((dollars%20)%10)%5)%2));
}
unwanted result example:
enter amount: 120
Change for $120 is:
$20s: -4196336
$10s: -4196340
$5s: -4196344
$2s: -4196348
$1s: -4196352
There are several issues with your program. Here are a few of them.
First, you don't want your actual variables to be pointers, but simple ints for you to point to:
int dollars, twenties, tens, fives, toonies, loonies;
Second, you need to pass the actual variable values to printf, not their addresses:
printf("$20s: %d\n", twenties);
printf("$10s: %d\n", tens);
printf("$5s: %d\n", fives);
printf("$2s: %d\n", toonies);
printf("$1s: %d\n", loonies);
Third, you don't actually call your pay_amount function.
Fourth, if you were to call it, it would loop indefinitely due to this completely extraneous loop that you should just remove:
while (dollars>=0);
Fifth; while this isn't actually a bug (it won't stop your program from working in any way), the additional reminder operations in pay_amount are redundant:
*twenties = (dollars/20);
*tens = ((dollars%20)/10);
*fives = ((dollars%10)/5);
*toonies = ((dollars%5)/2);
*loonies = ((dollars%2));
Sixth, as a note on terminology, this has nothing to do with "function pointers", which signify pointers that point to functions, rather than pointers that are passed to functions.
you need change:
/* local variable definition of enter amount*/
int dollars, *twenties, *tens, *fives, *toonies, *loonies;
to
/* local variable definition of enter amount*/
int dollars, twenties, tens, fives, toonies, loonies;
function pay_amount() like this:
pay_amount(int *dollars,int *twenties,int *tens,int *fives,int *toonies,int *loonies)
call function like this: pay_amount(&dollars, &twenties, etc);
and inside the pay_amount() like this:
while (*dollars>=0);
*dollars/20;
*tens = ((*dollars%20)/10);

I can't get this (simple) loop to work properly

I'm in a programming class right now, and was asked to create a program that calculated the sum of a user's input for multiple numbers--then calculate the nth root of the sum. If the number they input was less than 0, the loop is supposed to discard the less than 0 number, then ask again.
Unfortunately, no matter what number I input--it displays "Value needs to be greater than zero!" I tried putting a fflush(stdin); statement in the loop, but that didn't seem to do anything.
Here is my code. I really appreciate any and all help.
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
int main() {
int mTotalNums, mNth; //amount of numbers in set
float mProd = 1, x, mNroot;
printf("How many numbers are in the set?\n");
scanf("%i", &mTotalNums);
mNth = mTotalNums; //set the value of mTotalNums equal to mNth becuase we'll lose the original value of mTotalNums after the loop
while (mTotalNums > 0) {
printf("Input number: ");
scanf("%lf", &x);
if (x > 0) {
mProd *= x;
} else
printf("\nValue needs to be greater than zero!\n");
}
mNroot = pow(mProd, (1 / mNth));
printf("\nThe nth root of the product of %i terms is: %.2f\n", mNth, mNroot);
return 0;
}
"%lf" is the scanf format for a double, but x is declared as float.
To scan a float, you have to use the %f format.
Note also that mTotalNums is not decremented in the loop, so that it will never
terminate.
Read the documentation of scanf(3). Since x is declared as a float, use %f as the scanf format control string. Also, take into account the result of scanf (it would be 1 if successfully read one item).
You should enable all warnings and debug info in your compiler, then learn how to use the debugger (notably to run your program step by step, display local variables, etc....).
(On Linux, if compiling with gcc -Wall -g you would get a useful warning, and the gdb debugger would be helpful...)
Try these modifications to your program (added comments with changes made)
#include "stdafx.h"
#include <stdio.h>
#include <math.h>
int main() {
//amount of numbers in set
int mTotalNums, mNth;
// Change to double for added precision
double mProd = 1.0, x, mNroot;
printf("How many numbers are in the set?\n");
scanf("%i", &mTotalNums);
// Set the value of mTotalNums equal to mNth becuase
// we'll lose the original value of mTotalNums after the loop
mNth = mTotalNums;
// Don't forget to decrement the loop counter
while (mTotalNums-- > 0) {
printf("Input number: ");
scanf("%lf", &x);
if (x > 0) {
mProd *= x;
} else {
printf("\nValue needs to be greater than zero!\n");
}
}
// Change to 1.0 to force compiler to treat as a double
mNroot = pow(mProd, (1.0 / mNth));
printf("\nThe nth root of the product of %i terms is: %.2f\n", mNth, mNroot);
return 0;
}
You mention "calculate the nth root of the sum", but your loop is clearly tallying the cumulative product. To change it to calculate the sum, try the following additions:
// Declare a sum variable
double sum = 0;
// Sum inside your while loop
sum += x;
// Calculate the nth root of the sum instead
mNroot = pow(sum, (1.0 / mNth));
Add printf commands to see what your variables contain before you check them in your logic statements.
You also need to do something to increment/decrement your variable for your while loop... currently nothing is changing mTotalNums, so it will be an infinite loop.
while (mTotalNums > 0) {
printf("Input number: ");
scanf("%lf", &x);
printf("x=%d", x);
if (x > 0) {
mProd *= x;
} else
printf("\nValue needs to be greater than zero!\n");
mTotalNums--;
}

Resources