C goto loop does not work - c

I am trying to learn C, and I copied a code which calculates VAT> I modified it to recalculate if the user answers yes and exit if the answer in no. To my surprise it behaves in a strange way in that if the answer is yes, it is supposed to go to the beginning as ask the user to enter the item cost. Instead it expects the cost to entered immediately after y is pressed.
The code below;
/* VAT Calculation*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
float price_with_vat(float cost, float vat, int quant);
main()
{
float cost, vat, full_price;
int quant,count=0;
char answer[2];
char reply[2]={"y"};
x:
count=count+1;
printf("count= %d\n",count);
printf("Please enter the item cost:\n\n");
scanf("%f", &cost);
printf("\nPlease enter the quantity of product:\n");
scanf("%d", &quant);
printf("\nquantity=%d\n",quant);
/* exit(0); */
printf("\nPlease enter the VAT percentage:\n");
scanf("%f", &vat);
printf("\ncost=%6.2f quant=%d vat=%6.2f\n",cost, quant, vat);
/* exit(0); */
full_price = price_with_vat(cost, vat, quant);
printf("The total price is %6.2f\n\n",full_price);
printf("\nDo you want to perform another transaction? (y/n)\n");
scanf("%c\n", &answer);
if(answer==reply)
{
system("cls");
main();
}
else
return 0;
}
float price_with_vat(float cost, float vat, int quant)
i replace the part
if(answer==reply)
{
system("cls");
main();
}
else
with
if(answer==reply)
goto x
I know the goto construct is discouraged in C (and also in Fortran). I have a variant which uses a do-while loop. It behaves the same.
Any ideas why this behaviour?
Zilore Mumba

You can't compare strings with == in C, so this is wrong:
if(answer==reply)
You need to use strcmp():
if (strcmp(answer, reply) == 0)
strcmp() requires both arguments to be null-terminated strings. You're never adding a null terminator to answer; you should initialize it as:
char answer[] = { '\0', '\0' };
Or, instead of using strings for reply and answer, you could declare them as single characters:
char reply = 'y';
char answer;
Then you can use == to compare them.

Too many mistakes in your program.
You have used goto.
In the statement scanf("%c\n", &answer);, %c expects a char but you are passing it a char (*)[2].
You declared char reply[2]={"y"};, which is not a valid C syntax.
However if reply is declared char array then if(answer==reply) is completely wrong.
Conclusion:
Go through a good tutorial on C or read a good book to know about basic syntax of C.

As explained in other comments and answers, there are several issues with the code presented, such as:
1) Use of goto is generally unnecessary, rarely used.
2) Calling main() from within main(). Mistake.
3) Execution flow is not well controlled within main body of program,
resulting in the unexpected behavior you described.
4) Comparison techniques are all wrong. Read up on ==, strcmp(), != etc.
Following is an example of similar code that should perform more predictably, illustrating how to execute a simple dialog with a user, and displaying results. I hope this will help you :)
Note: my environment did not require me to #include <conio.h>, so I removed it. You may have to add it back in for your environment.
/* VAT Calculation*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
float price_with_vat(float cost, float vat, int quant);
int main(void)
{
float cost, vat, full_price;
int quant,count=0;
char answer[2]={""};
float running_total=0.0;
count = 0;
//dialog section of code
while(answer[0] != 'n')
{
//get price, quantity and VAT
printf("Please enter the item cost:");
scanf("%f", &cost);
printf("\nPlease enter the quantity:");
scanf("%d", &quant);
printf("\nPlease enter VAT percentage:");
scanf("%f", &vat);
count++;
//results section
printf("\n\nCost: %6.2f\nQuantity: %d\nVAT percent: %6.2f", cost, quant, vat);
full_price = price_with_vat(cost, vat, quant);
running_total += full_price;
printf("The total price is %6.2f\n\n",full_price);
printf("\nRunning total is currently: %6.2f for %d items.\n",running_total, count);
//request if continue
printf("\nDo you want to perform another transaction? (enter \"y\" or \"n\")\n");
scanf("%s", answer);
}
return 0;
}
float price_with_vat(float cost, float vat, int quant)
{
return cost*((1.0)+vat)*((float)(quant));
}

Related

Scanning Values Until Getting a Significant Character in C

For my homework, I am trying to code a calculator which can also calculate average of taken numbers. I don't want to ask for number of numbers because our teacher don't want it in that way. So I thought of scanning values until the user presses "p". But as you would guess, the numbers are float and "p" is a character. What I want to do is assigning the value scanned to both of them if it is possible. I tried different ways, played with the codes but it isn't working properly. So I am seeking your advice.
It prints a value when p is inputted as like 3rd, 5th, 7th (oddth) number (sometimes right, sometimes wrong but I can fix it if I figure this out). But it doesn't print a value in other occasions and expects infinite inputs from the user.
This is the code I have written for this. scanf("%f %c", &number1, &pause); command is where I want to know about, actually.
#include<stdio.h>
float number1, number2, i, result;
char pause;
int main() {
scanf("%f", &number1);
i = 0;
while (pause != 'p') {
number2 = number1 + number2;
scanf("%f %c", &number1, &pause);
i++;
}
result = number2 / (i - 1);
printf("%f", result);
}
Use double not floats if there is no specific reason to do so (like using uC without double FPU).
You do not initialize the variables
Always check the result of the I/O operation.
#include <stdio.h>
int main ()
{
double number1= 0, number2 = 0, i = 0, result = 0;
char pause = 0;
char line[128];
while (pause != 'p')
{
if(fgets(line, sizeof(line), stdin))
{
if(sscanf(line, "%lf %c",&number1, &pause) != 2)
{
printf("Wrong input - try again\n");
pause = 0;
continue;
}
number2 = number1 + number2;
i++;
}
else
{
// do something with I/O error
}
}
result = number2 / (i-1);
printf("%lf",result);
}
You can play with it yourself : https://onlinegdb.com/Hy3y94-3r
I noticed 3 problems with your code.
First I would advise you to use meaningful variables names. number1, number2, etc. and the i which represents the number of inputs given can be an int instead of a float.
Secondly, you lack of printing to the user what's going on in your program; it's better to have messages like "enter your number, do you wanna stop? the result is...etc".
Lastly, having two inputs in one line of code can make it hard to debug, knowing that reading strings and characters in C is already hard for beginners. For example, %c does not skip whitespace before converting a character and can get newline character from the previous data entry.
Here is my fix: I changed some variables' names, printed some messages and read the two inputs in two different lines with adding scanf(" %c") with the space to avoid that problem.
#include<stdio.h>
float sum, temp, result;
int nb;
char pause;
int main () {
pause='a';
while (pause != 'p'){
printf("Enter your number: ");
scanf("%f",&temp);
sum+=temp;
nb++;
printf("type 'p' if you want to stop: ");
scanf(" %c",&pause);
}
result = sum / nb;
printf("the average is : %f",result);
}
I tested it, should work fine
Edit: after explaining that you don't want to ask the user each time, here is how the code should work (the case that the user don't input a float is not treated, and just take it as zero
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
float sum, temp, result;
int nb;
char input[50];
int main () {
sum=0;
nb=0;
printf("Enter your numbers, then type 'p' to stop\n");
do{
printf("Enter your next number: ");
scanf("%s", input);
if(strcmp(input,"p")!=0)
{
float temp= atof(input);
sum+=temp;
nb++;
}
}while(strcmp(input,"p")!=0);
if(nb!=0)
result = sum / nb;
printf("\nThe average is : %f",result);
}

how can i impliment a #define statement into my code?

First off, how can I implement a #define in this code? I'm fairly lost when it comes to defining and calling of that #define. Also, if there are any ways to make this code look better it would be greatly appreciated! I'm new to coding so any help would be awsome. This is technically homework but I met all the requirements for the assignment so now this is simply exploratory.
#include <stdio.h>
#include <math.h>
int main() {
int studentID;
int count= 0;
char course1[10]={};//issue with storing user input, used an array
char course2[10]={};
float coursecost1;
float coursecost2;
float credithour = 120.25;
float healthID=35.00;
float totalcost;
// Asks for student ID
printf("Enter the Students Id: \n");
scanf("%d",&studentID);
// Enter CRN/Credit hrs for first course
printf("Enter crn/credit hours for the first course: \n");
scanf("%s", &course1);
// Enter CRN/Credit hrs for Second Course
printf("Enter crn/credit hours for the second course: \n");
scanf("%s", &course2);
// Closing statement
printf("\nThank you!\nPRESS ANY KEY TO CONTINUE...\n\n");
// Calculates Cost of Class
int i = course1[5]-'0'; // Bad version of type casting from char to int.
int k = course2[5]-'0'; // Bad version of type casting from char to int.
coursecost1 = i*credithour;
coursecost2 = k*credithour;
totalcost= healthID+coursecost1+coursecost2;
// Printout
printf("\t\tVALENCE COMMUNITY COLLEGE\n\t\tORLANDO FL 10101\n\t\t");
do{
count++;
printf("*");
}while(count<26);
printf("\n\t\tFee Invoice Prepared for Student V%d\n",studentID);
printf("\t\t1 Credit Hour = %.2f\n",credithour);
printf("\t\tCRN\t CREDIT HOURS\n");
printf("\t\t%c%c%c%c\t %c\t\t $
%.2f\n",course1[0],course1[1],course1[2],course1[3],course1[5],coursecost1);
printf("\t\t%c%c%c%c\t %c\t\t $
%.2f\n",course2[0],course2[1],course2[2],course2[3],course2[5],coursecost2);
printf("\t\t\t Health & id fees $ %.2f\n",healthID);
printf("\t\t");
count=0;
do{ //could define a function to clean up code
count++;
printf("-");
}while (count < 39);
printf("\n\t\t\t Total Payments $ %.2f",totalcost);
return 0;
"define" is basically creating a shortcut for stuff you write often in your code, or stuff you want to change often in order to test your code.
An example:
#define fail printf("You did something wrong")
int main (void)
{
int number;
printf("Insert a number between 1 and 3");
scanf("%d", &number);
if (number>3||number<1)
{
fail;
return -1
}
else
{
printf("Insert a number between 4 and 6");
scanf("%d", &number);
if (number<4||number>6)
{
fail;
return -1;
}
else return 0;
}
}
When this program is read by the compiler, every "fail" gets substituted by "printf("you did something wrong").
This is the main use of define, and if you are beginning now, that's what I'd consider important.
About your code, when you do scanf for strings, don't use "&", or use the "gets" function. I could try to explain why to you, but I'm not the best person for this job. My tip is, keep studying and when you start seeing pointers, you'll understand better why this happens.
Also, when you use arrays without a starting value, you don't need to do the "={ }" thing, just call them without "=".
Now, as you asked, this is how I'd write your code, with the corrections done:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int studentID, intcount = 0; // Count is a function, better not mix things up, that's why I called it "intcount"
char course1[10], course2[10];
float coursecost1, coursecost2, totalcost;
float credithour = 120.25;
float healthID=35.00;
// Asks for student ID
printf("Enter the Students Id: \n");
scanf("%d",&studentID);
// Enter CRN/Credit hrs for first course
printf("Enter crn/credit hours for the first course: \n");
scanf("%s", course1);
// Enter CRN/Credit hrs for Second Course
printf("Enter crn/credit hours for the second course: \n");
scanf("%s", course2);
// Closing statement
// printf("\nThank you!\nPRESS ANY KEY TO CONTINUE...\n\n");
/* Decided not to delete this one, so you can
compare this printf with the new one and the system pause */
printf("\nThank you!\n");
system("pause");
// Calculates Cost of Class
// I'm not sure what you were trying to do in these lines, so I won't touch them
int i = course1[5]-'0';
int k = course2[5]-'0';
coursecost1 = i*credithour;
coursecost2 = k*credithour;
totalcost= healthID+coursecost1+coursecost2;
// Printout
printf("\t\tVALENCE COMMUNITY COLLEGE\n\t\tORLANDO FL 10101\n\t\t");
do
{
intcount++;
printf("*");
}
while(intcount<26);
printf("\n\t\tFee Invoice Prepared for Student V%d\n",studentID);
printf("\t\t1 Credit Hour = %.2f\n",credithour);
printf("\t\tCRN\t CREDIT HOURS\n");
printf("\t\t%c%c%c%c\t %c\t\t $%.2f\n",course1[0],course1[1],course1[2],course1[3],course1[5],coursecost1);
printf("\t\t%c%c%c%c\t %c\t\t $%.2f\n",course2[0],course2[1],course2[2],course2[3],course2[5],coursecost2);
printf("\t\t\t Health & id fees $ %.2f\n",healthID);
printf("\t\t");
intcount=0;
do
{ //could define a function to clean up code
intcount++;
printf("-");
}
while (intcount < 39);
printf("\n\t\t\t Total Payments $ %.2f",totalcost);
}
Basically just try to avoid placing too much information on the same line, even split single printfs into multiple ones if neccessary.
Hope I could be of some use!

undefined reference to `scanf_s'

I've got a piece of coursework to get done quickly which requires me to be able to debug the code in a certain way. In order to complete the assignment I have to be able to run the program I've been given and use breakpoints to guide the program step by step. The program we have been given is a basic view of an ATM and has a number of errors.
Please don't fix the errors in the code, but can someone please tell me what I can do about the errors I'm receiving in relation to the scanf_s lines as I keep getting the error 'undefined reference to scanf_s' The code is as follows:
/* This program has been altered purposefully
so that it contains problems.
Use the program to complete P2-Debugging a program
Remember to take screenshots of you do the following:
Adding a breakpoint at an appropriate point
Stepping into functions (F11) and over each line of code (F10)
Changing variables and altering other code, e.g. changing messages
Watching the values of variables.
Add comments to the code before taking screenshots.
Fix the problems if you can. Otherwise, just add comments to the code
indicating where you think the problems are and what the solution might be.
Place all evidence into one Word Document and submit it.
Can you add other improvements?
*/
#include <stdio.h>
int getOption()
{
int option = 0, nl;
printf("\nWelcome to the ATM\n");
printf("\nMenu\n");
printf("\n1. Withdraw Cash\n");
printf("\n2. Show Balance\n");
printf("\n3. Exit\n");
printf("\nEnter a number from 1 to 3:");
option = scanf_s("%d%c", &option, &nl);
return option;
}
//function to allow you to withdraw cash
int withdrawCash()
{
float amount;
int nl, option;
printf("\nHow much money do you want?");
amount = scanf_s("%d%c", &option, &nl);
return option;
}
//function to show you your balance
int getBalance()
{
float balance = 10000;
int nl, option;
printf("\nHow much money do you want?");
balance = scanf_s("%d%c", &option, &nl);
return balance;
}
//function to update your balance
int updateBalance(float balance, float amount)
{
int nl, option;
balance = balance - amount;
return balance;
}
// main function - start here
int main(void)
{
int ch;
int opt = 0;
int amount = 0;
int balance = 0;
float newbal = 0.0;
opt = getOption();
printf("\nYou chose option %d\n", opt);
if (opt == 1)
{
amount = withdrawCash();
newbal = updateBalance(10000, amount);
printf("\nHere is your %d, your balance is:\n", amount, newbal);
}
if (opt == 2)
{
balance = getBalance();
printf("\nHere is your balance: %d\n", balance);
}
printf("\nThank you. Please take your card.\n");
ch = getchar();
return 0;
}
One of either:
Use a Microsoft compiler for which scanf_s() is defined.
Use the ISO C90/C99 standard library function scanf() instead.
Use a compiler with the optional ISO C11 Annex K library support.
Add #define scanf_s scanf.
Note however that the arguments you are passing to scanf_s not correct given the format specifiers - they are correct for scanf - that may suggest a preferred solution (and it's not the last one ;-) ).
Code like has a linker problem and is using scanf_s() incorrectly.
scanf_s() expects 2 arguments with each "%s", "%[" and "%c": a char * address and rsize_t size.
// scanf_s("%d%c", &option, &nl);
scanf_s("%d%c", &option, &nl, (rsize_t) 1);

Working with scanf and loops in functions

I want to use a function to ask the user for a balance. If the balance is below 0 the user is prompted to enter a value above 0. Here is the code I have done so far:
#include <stdio.h>
#include <string.h>
float getPositiveValue();
int main()
{
float begbal;
begbal = getPositiveValue();
getPositiveValue();
printf("balance: %f\n", begbal);
return 0;
}
float getPositiveValue()
{
float money;
printf("Please enter the beginning balance: \n");
scanf("%f", &money);
if(money < 0)
{
printf("Enter a balance amount above 0:");
scanf("%f", &money);
}else{
}
}
I get the error "warning: control reaches end of non-void function". I know I need to end the else statement, but not sure what to put in there if they did enter a value above 0. Also, when the program is run it asks the user twice to enter the beginning balance for some reason. Seems like this should be a simple fix, for some reason I have trouble getting my head around functions heh.
Any help much appreciated.
revised working code(thanks):
#include <stdio.h>
#include <string.h>
float getPositiveValue();
int main()
{
float begbal;
begbal = getPositiveValue();
printf("balance: %f\n", begbal);
return 0;
}
float getPositiveValue()
{
float money;
printf("Please enter the beginning balance: \n");
scanf("%f", &money);
while(money < 0)
{
printf("Enter a balance amount above 0:");
scanf("%f", &money);
}
return money;
}
getPositiveValue() is supposed to return a value (float). You could add return money; before its closing }.
What if the user is particularly dense and doesn't enter a positive amount? Do you want to give them only one chance? If not, you probably want to use a while (money < 0.0) loop.
You need to return a float value, so in this case you can return money.
You are calling your function twice in the main function.
begbal = getPositiveValue();
getPositiveValue();
Just remove the last statement
"Also, when the program is run it asks the user twice to enter the
beginning balance for some reason."
because you have called function getPositiveValue() TWICE IN YOUR CODE
and your function needs to return the float value which is "money" in this case.
The user could persist in entering the wrong thing, so you need a loop to iterate till they get it right. Also, you need to return a value from this function.
float getPositiveValue()
{
float money;
fputs("Please enter the beginning balance: ", stdout);
for (;;) {
scanf("%f\n", &money);
if (money >= 0)
break;
fputs("Balance must be nonnegative.\n"
"Please enter the beginning balance: ", stdout);
}
return money;
}
But that's only the tip of the iceberg here. scanf should never be used, and floating-point numbers should not be used to keep track of money. What you should really be doing here is reading a line of text with getline (or fgets, if getline is unavailable), and parsing it with strtoul and custom logic, presumably as [$]dddd[.cc] (where square brackets indicate optional text), into a uint64_t value scaled to cents.
As the user may enter an invalid range (a negative number) or non-numeric text, need to consume offending input before next prompt.
float getPositiveValue() {
float money = 0.0;
printf("Enter a balance amount above 0:");
while ((scanf("%f", &money) != 1) || (money < 0)) {
int ch;
while (((ch = fgetc(stdin)) != '\n') && (c != EOF));
if (c == EOF) break;
printf("Enter a balance amount above 0:");
}
return money;
}

C programming return value odd

I tried to search this everywhere, but it's kind of difficult to word, it's most likely a simple fix. Basically when I go through my program that is supposed to compute the average rainfall for a year, it comes out with a very large number, however, I thought it may have been just that I was doing the arithmetic wrong or had a syntax error of some sort, but that was not the case, when I checked the value that the function returned it was the proper value.
#include <stdio.h>
#include <string.h>
void getData(float *, float *);
int main()
{
char state[2], city[81];
float rainFall[12], outputAverage, *pAverage;
printf("Name Here\n");
printf("Please enter the state using a two letter abreviation: ");
gets(state);
printf("Please enter the city : ");
gets(city);
pAverage = &outputAverage;
(getData(rainFall, pAverage));
printf("%.2f", outputAverage);
return (0);
}
void getData(float *rainFall, float *pAverage)
{
int i;
float total;
for (i=0; i<12; i++)
{
printf("Please enter the total rainfall in inches for month %d: ", i+1);
scanf("%f", &rainFall[i]);
total += rainFall[i];
}
*pAverage = total / 12;
}
you need to initialize total
float total = 0.0;
Initialize the total to 0
Why you make it complicated? Why not just
return total / 12 ?
and called it like
outputAverage = getData(rainfall)
This is a classic problem in C programming. You are mixing strings and numbers on the input. You are better off reading the input into a string and then, using sscanf to parse it properly.
You have uninitialized variable total which is taking garbage value, thus you see a very large answer.
changed your main.. have a look and let me know if you have understood what changes i have made?
#include <stdio.h>
#include <string.h>
void getData(float *);
int main(int argc, char*argv[])
{
char state[3]={0}, city[81]={0};
float outputAverage;
printf("Name Here\nPlease enter the state using a two letter abreviation: ");
scanf("%s",state);
printf("Please enter the city : ");
scanf("%s",city);
getData(&outputAverage);
printf("The Average Rainfall recorded for the year is %.2f\n", outputAverage);
return 0;
}
void getData(float *pAverage)
{
int i;
float rainFall[12]={0}, total=0;
for (i=0; i<12; i++)
{
printf("Please enter the total rainfall in inches for month %d: ", i+1);
scanf("%f", &rainFall[i]);
total += rainFall[i];
}
*pAverage = total / 12;
}
However instead of using gets you should use fgets but i forgot how to counter the issue of using simultaneous fgets to read input from the standard input stream.
Also initialize the total variable as you are adding in the loop new values to existing value in that variable which would not necessarily add to zero as the premier element. so it could be any garbage value + loop values.
I understand you are practicing pointer concept so you passed the address of the array of floats to your second function but if the rainfall function is not useful in main, Better to restrict the same where it would be useful

Resources