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);
Related
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!
Obviously I'm not going to post my whole code here as it IS very long, it is a tax calculator after all. This problem applies to all my scanfs that need double values as input from the user. Basically as the title says, my program doesn't ask the user to input another value even if it's a character, which obviously isn't a double value so some help will be very appreciated. Forgive me as I'm still in the first year of my course and don't know everything about programming.
double salary;
printf("This program will compute your yearly and monthly witholding tax for you \n");
printf("How much is your total monthly salary? ");
fflush(stdin);
scanf("%lf", &salary);
while (salary < 0)
{
printf("\n");
printf("Invalid Input\n");
printf("How much is your total monthly salary? ");
fflush(stdin);
scanf("%lf", &salary);
}
You correctly diagnosed the problem: invalid input stays in the input buffer, causing every subsequent scanf to fail. You cannot correct this with fflush, because it is not defined for input streams. Note that you also misuse scanf as you do not test the return value.
The simple and generic solution to your problem is this: replace calls to scanf with calls to a function that reads a line from the user and parses it as a string repeatedly until either EOF or correct input is entered.
This function takes a range for validity checking. You can pass infinities if you dont want to accept all input.
int getvalue(const char *prompt, double *vp, double low, double high) {
char buffer[128];
for (;;) {
printf("%s ", prompt);
if (!fgets(buffer, sizeof buffer, stdin)) {
printf("EOF reached, aborting\n");
// you can also return -1 and have the caller take appropriate action
exit(1);
}
if (sscanf(buffer, "%lf", vp) == 1 && *vp >= low && *vp <= high)
return 0;
printf("invalid input\n");
}
}
In your code fragment, you would replace everything with this:
double salary;
printf("This program will compute your yearly and monthly withholding tax for you\n");
getvalue("How much is your total monthly salary?", &salary, 0.0, HUGE_VAL);
HUGE_VAL is defined in <math.h>, but its value seem a bit high for a salary anyway, you can just write a decent maximum such as 1E9.
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;
}
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));
}
I learnt (self-learning) the basics of structure in C today and wrote this simple code. it is compiling without any error. I know that successful compilation is no guarantee for a bug-free software. While execution, it scans the inputs for two structure variables only and gives erroneous display. for the sake of simplicity I chose a char to store the book name. I am not able to figure out the bug here. could you find one?
#include<stdio.h>
int main(void)
{
struct book
{ char name;
float price;
int pages;
};
struct book b[3];
int i;
for (i = 0; i <= 2; i++){
printf("\nEnter name, price and pages ");
scanf("%c %f %i", &b[i].name, &b[i].price, &b[i].pages);
}
for (i = 0; i <= 2; i++)
printf("\n%c %f %i",b[i].name, b[i].price, b[i].pages);
return 0;
}
You need to remove "extra" input by adding while((ch=getchar())!='\n'); ( to flush the input buffer) (Please declare the char ch;):
for (i = 0; i <= 2; i++){
printf("\nEnter name, price and pages ");
scanf("%c %f %i",&b[i].name,&b[i].price, &b[i].pages);
while((ch=getchar())!='\n'); //eat the chars
}
Tutorial/posts:
"Flushing" the input stream
How to Get User Input from console -- safely.