Accepting larger numbers with decimal values in C - c

I'm writing a code that allows the user to add employees by ID, age and salary however, for salary I'm not sure what value to use in order to scanf and printf a number such as 78950.86. I used double for SALARY because there are more values to hold and I've tried playing around with the printf and scanf for this variable, but it I either get segmentation faults or random numbers. Here's my code:
#include <stdio.h>
#define SIZE 2
// Define Number of Employees "SIZE" to be 2
struct Employee{
int ID;
int AGE;
double SALARY;
};
//Declare Struct Employee
/* main program */
int main(void) {
int option = 0;
int i;
struct Employee emp[SIZE];
printf("---=== EMPLOYEE DATA ===---\n\n");
// Declare a struct Employee array "emp" with SIZE elements
// and initialize all elements to zero
do {
// Print the option list
printf("1. Display Employee Information\n");
printf("2. Add Employee\n");
printf("0. Exit\n\n");
printf("Please select from the above options: ");
// Capture input to option variable
scanf("%d",&option);
printf("\n");
switch (option) {
case 0: // Exit the program
break;
case 1: // Display Employee Data
// #IN-LAB
printf("EMP ID EMP AGE EMP SALARY\n");
printf("====== ======= ==========\n");
//Use "%6d%9d%11.21f" formatting in a
//printf statement to display
//employee id, age and salary of
//all employees using a loop construct
for(i=0; i<SIZE; i++) {
printf("%d %d %11.2lf", emp[i].ID, emp[i].AGE, emp[i].SALARY);
}
//The loop construct will be run for SIZE times
//and will only display Employee data
//where the EmployeeID is > 0
break;
case 2: //Adding Employee
// #IN-LAB
printf("Adding Employee\n");
printf("===============\n");
for(i=0;i<SIZE;i++) {
printf("\nEnter employee ID: ");
scanf ("%d", &emp[i].ID);
printf("\nEnter employee Age: ");
scanf ("%d", &emp[i].AGE);
printf("\nEnter employee Salary: ");
scanf ("%11lf", &emp[i].SALARY);
}
//Check for limits on the array and add employee
//data accordingly
break;
default:
printf("ERROR: Incorrect Option: Try Again\n\n");
}
} while (option!= 0);
return 0;
}

Your format strings are using %ld.%02d when dealing with a double, which says to treat it as 2 integers separated by a period (which should have generated warnings). Fix the string to properly indicate one double, or if (as #MalcomMcLean suggests) you want to keep dollars and cents separately, use a different field/variable for each.

"I'm not sure what value to use in order to scanf and printf a number such as 78950.86."
Generally speaking, Salaries are not really "Large Numbers", in the world of Coding(or C data types, to be precise). For the example you have quoted even a single precision float data type will be sufficient. (Search for "max finite positive value in single precision" in the pagehttps://en.m.wikipedia.org/wiki/Single-precision_floating-point_format)
So the double data type you used is more than sufficient for the said purpose. As rightly pointed out by Scott, the segmentation faults are being caused because your format string suggests 2 data parameters, when there is only 1 double data type variable.
My opinion would be not to store salary data as separate dollars and cents. From the employer's perspective these cents are going to add up to dollars and they will eventually be merged with the dollar data, making your summation algorithm complicated.
In conclusion, you can use a double data type for salary variable. When printing salary, you can use "%.2f" in the format string. When using scanf to get salary in normal fixed point notation, you can use "%lf" in the format string.

Related

Getting incorrect output for a basic multiplication in my C programme

I'm new to learning C, and practicing some basic code.
I keep getting either a 0 or a very large random number for the bill multiplication at the end. I think I've narrowed it down to an issue with my "quant" value but I can't figure it out. Here's the first part of the programme (that only calculates for the pizza options so far):
#include <stdio.h>
int main()
{
int num, cho, quant, bill;
printf("Select a number from the menu:\n1. Pizza\n2. Burger\n3. Sandwiches\n4.
Beverages \n");
scanf("%d",&num);
if(num==1)
{
printf("Select a number for the food you want to order, and the quantity. \n");
printf("1. Pepperoni\t\tRs 1000 \n2. Fajita\t\tRs 1000\n3. Hot n spicy\t\tRs 1100\n4.
Chicken Tikka\tRs 1200\n");
scanf("%d,%d",&cho,&quant);
{
if(cho==1)
cho=1000;
else if(cho==2)
cho=1000;
else if(cho==3)
cho=1100;
else if(cho==4)
cho=1200;
}
bill=cho*quant;
printf("Please take your food item(s). Total bill = Rs %d \nThank you.",bill);
}
getchar();
getchar();
getchar(); getchar(); getchar();
return 0;
}
The way you have your scanf for cho and quant right now expects the user to enter two numbers separated by nothing but a comma, i.e. 2,10. If you do that format of input, your code works fine. However, if this format is broken the scanf does not properly read in a number to one or both of your variables, and they are left unitialized with potentially garbage information in them (hence the really large random numbers you're seeing).
You should probably change that line to
scanf("%d%d",&cho,&quant)

Accepting Multiple Strings in 2 dimensional array?

While executing this, loop is directly jumping to the end and giving me below output.
1.Generate Bill
2.Generate Bills of last 10 Purchase
Select Option:1
Enter Number of Groceries:3
Enter GroceryName:XYZ <Hit Enter>
Enter GroceryName:
Enter GroceryName:
Could you please suggest me better way of doing it in c ?
I have already tried certain links on stack overflow on this, however it doesn't seem to be working for me.
void main()
{
int iPrice[1000];
char cGroceName[100][100];
int iOption;
int iGrocNum;
printf("\n1.Generate Bill");
printf("\n2.Generate Bills of last 10 Purchase");
printf("\nSelect Option:");
scanf_s("%d", &iOption);
switch (iOption)
{
case 1:
printf("\nEnter Number of Groceries:");
scanf_s("%d",&iGrocNum);
for (int i = 0; i <iGrocNum; i++)
{
printf("\nEnter GroceryName:");
scanf_s(" %s",cGroceName[i]);
}
scanf_s(" %s",cGroceName[i]);
should be
scanf_s("%99s", cGroceName[i], sizeof cGroceName[i]);
as scanf_s requires a third argument for certain format specifiers such as %s denoting the maximum size of its corresponding argument.
See scanf_s documentation.

Reading in a list

I've to code a program that reads in a list of student's names and ids and sort them based on first name, last name, and id. But there are currently two problem with my code.
#include <stdio.h>
int main() {
char firstName[200][21], lastName[200][51];
unsigned short id[200]; // used short to decrease memory usage
int i;
for (i=0; i<200; ++i) {
printf("Enter first name of student %d: ",i+1);
getchar(); // FIX to consume enter
fgets(firstName[i],21,stdin);
printf("Enter last name of student %d: ",i+1);
fgets(firstName[i],21,stdin);
printf("Enter student number of student %d: ",i+1);
scanf("%hu",&id[i]);
printf("You've entered %s %s with ID %hu",firstName[i],lastName[i],id[i]);
}
// other functions to do after reading in the data is successfully done
}
Reading in the values must be stopped if students reach 200 or if the user enters EOF.
Student's First Name or Last Name might consist of multiple parts (something like "john john" so I used fgets instead of scanf and %s to read in the word which comes after space as well but it fails and only last name is stored.
Could you tell me how to stop the loop with EOF and read in the first and last name correctly? Thanks.
for checking the EOF , you can use function:
feof(FILE*) // if it returns 1 then it is EOF reached.
you can use it like the below snippet :
if (feof(fp) == 1)
break;
and the 2nd problem :
printf("Enter last name of student %d: ",i+1);
fgets(firstName[i],21,stdin); // this is incorrect.
use 'lastname' instead of 'firstname'. It should be like this :
fgets(lastName[i],21,stdin);
in this way you are overwriting the value of firstname

Can not output salary and mobile number. It's always produced an unexpected result in C

In my C program, I expected the result of salary and mobile number that I entered But it's produced some unexpected result. Why it's happened? Please help me any one to solve my problem.
Thanks in advance.
#include<stdio.h>
struct employee
{
int emp_id;
char name[20];
char address[50];
int salary[11];
int mobile[11];
};
void main()
{
struct employee e1, e2;
//Get value for employee 1
printf("Enter the id of employee 1: \n");
scanf("%d", &e1.emp_id);
printf("Enter the name of employee 1: \n");
fflush(stdin);
gets(e1.name);
printf("Enter the address of employee 1: \n");
gets(e1.address);
printf("Enter the salary of employee 1: \n");
scanf("%d", &e1.salary);
printf("Enter the mobile number of employee 1: \n");
scanf("%d", &e1.mobile);
//Output the value
printf("Value of employee 1\n\n");
printf("Id: %d\n", e1.emp_id); //Output right
printf("Name: %s\n", e1.name); //Output right
printf("Address: %s\n", e1.address); //Output right
printf("Salary: %d\n", e1.salary); // Unexpected result
printf("Mobile: %d\n", e1.mobile); // Unexpected result
}
salary and mobile members of the struct are arrays, not just one int. So, you can't scanf() it or printf() it using %d.
You just need to change your struct to:
struct employee
{
int emp_id;
char name[20];
char address[50];
int salary;
int mobile;
};
Also,
void main() is not a standard complaint signature for main(). Use int main(void) or int main(int argc, char**argv) or equivalent.
gets() should never be used in C (which has been removed from C11 anyway). Use fgets() instead.
In general, pay attention to your compiler warnings as you should be getting quite a few for your code (If not, increase the warning level on your compiler toolchain).
The first answer is correct, but you may for reasons we don't know you may want to retain all 11 elements of the salary and mobile arrays.
To do so, change your code like this:
#include<stdio.h>
struct employee
{
int emp_id;
char name[20];
char address[50];
int salary[11];
int mobile[11];
};
void main()
{
struct employee e1, e2;
//Get value for employee 1
printf("Enter the id of employee 1: \n");
scanf("%d\n", &e1.emp_id);
printf("Enter the name of employee 1: \n");
fflush(stdin);
gets(e1.name);
printf("Enter the address of employee 1: \n");
gets(e1.address);
printf("Enter the salary of employee 1: \n");
scanf("%d\n", &e1.salary[0]);
printf("Enter the mobile number of employee 1: \n");
scanf("%d\n", &e1.mobile[0]);
//Output the value
printf("Value of employee 1\n\n");
printf("Id: %d\n", e1.emp_id); //Output right
printf("Name: %s\n", e1.name); //Output right
printf("Address: %s\n", e1.address); //Output right
printf("Salary: %d\n", e1.salary); // Unexpected result
printf("Mobile: %d\n", e1.mobile); // Unexpected result
}
Also note that for your scanf calls you should include the newline as I've done in the above code. This tells scanf to end its job when it encounters the newline. Maybe not necessary, but good practice.
In addition I will disagree with the other answer about your "main signature", if you aren't inputting any command line parameters nor returning anything from main back to the system then the way you've done it is perfectly acceptable. Actually, the way you've wrote this code would be correct practice for embedded systems code, or code running without an OS (yes, alot of code runs on it's own without an OS - but unless you do that kind of work you wouldn't know that. And to those who say that something should "never" be done in C I say that's the programmer's prerogative. C programming is all about the programmer knowing what they are doing and why much better than any "conventional advice" which doesn't take your specific situation into account. I use gets all the time, done it for over a third of a century - not a single issue has occurred in my code because of it. C is not a language for academics, it's a language for hard core programmers who know what they are doing better than anyone else. C code is inherently dangerous all by itself, at least as dangerous as using gets. Putting training wheels on a 1000cc motorcycle doesn't do very much to make it less dangerous - the danger is in riding the motorcycle in the first place. See what I mean?

Issues with program validation. Please help!

//Guys I have issues with my code and have been tearing my hair apart trying to resolve this. THe issue is that I am trying to validate my code so it doesn't calculate for negative numbers. If any one can help smooth up this program I would really appreciate it. Please.
//The objective of the tax calculator program will be to use C programming to calcualte sales tax for each of the Kudler Fine Food stores (DelMar, Encinitas and La Jolla)
//Standard input/output processing
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
//Starting point
int main ()
{
//Variables defined
//st = sales tax, tax rated = tr, pa = total purchase amount, sa = purchase amoount
float fstDelmar;
float ftrDelmar;
float fpaDelmar;
float fstEncinitas;
float ftrEncinitas;
float fpaEncinitas;
float fstLajolla;
float ftrLajolla;
float fpaLajolla;
float fsaPurchaseAmount;
int fStoreselect;
//Variable initializations for tax rates and purchase amount
ftrDelmar = .0725;
ftrEncinitas = .075;
ftrLajolla = .0775;
fsaPurchaseAmount = 0;
//Header & Introduction
printf("\n***********************************************************************");
printf("\n* Kudler Fine Foods *");
printf("\n* Sales Tax Calculator *");
printf("\n* Version 3.0 *");
printf("\n***********************************************************************\n");
//Ask user to select store.
printf ("\n STORE LOCATION \n");
printf ("\n 1) Del Mar \n");
printf ("\n 2) Encinitas \n");
printf ("\n 3) La Jolla \n");
printf ("\n Please select the store location (1-3): \n");
scanf ("%d", &fStoreselect);
//Validate store selection.
while (fStoreselect < 1 || fStoreselect > 3) {
fflush (fStoreselect);
printf ("INVALID SELECTION! Please select a valid location (1-3): \n");
scanf ("%d", &fStoreselect);
}
//Ask user to enter in total purchase amount.
printf ("\n What was your purchase amount? ");
scanf("$%f", &fsaPurchaseAmount); //user enters variable amount
//Validation to ensure that user's enter in purchase amounts using correct format.
while (fsaPurchaseAmount <= 0.0)
{
fflush(fsaPurchaseAmount);
printf("\n INVALID SELECTION! Please enter a valid purchase amount greater than zero.\n");
printf("\n The purchase amount is: $ ");
scanf("%f", &fsaPurchaseAmount);
}
//Calculation of sales tax in dollars for each of the store locations
fstDelmar = fsaPurchaseAmount * ftrDelmar;
fstEncinitas = fsaPurchaseAmount * ftrEncinitas;
fstLajolla = fsaPurchaseAmount * ftrLajolla;
//Calculation of total sales amount for each of the locations
fpaDelmar = fsaPurchaseAmount + fstDelmar;
fpaEncinitas = fsaPurchaseAmount + fstEncinitas;
fpaLajolla = fsaPurchaseAmount + fstLajolla;
//Displaying sales amount for purchase for each of the different locations
switch (fStoreselect) {
case 1:
//for Delmar location
printf("\n Purchase Amount Sales Tax Total Sales Amount ");
printf("\n _______________ _________ _________________ ");
printf("\n $%.2f $%.2f $%.2f",fsaPurchaseAmount, fstDelmar, fpaDelmar);
break;
case 2:
//for Encinitas location
printf("\n Purchase Amount Sales Tax Total Sales Amount ");
printf("\n _______________ _________ _________________ ");
printf("\n $%.2f $%.2f $%.2f",fsaPurchaseAmount, fstEncinitas, fpaEncinitas);
break;
case 3:
//for La Jolla location
printf("\n Purchase Amount Sales Tax Total Sales Amount ");
printf("\n _______________ _________ _________________ ");
printf("\n $%.2f $%.2f $%.2f",fsaPurchaseAmount, fstLajolla, fpaLajolla);
break;
}
printf("\n Hit the ENTER key to exit program\n");
//Pause the screen and wait for user to hit the ENTER key
getchar();
//EOF
}
This line has bug:
scanf("$%f", &fsaPurchaseAmount); //user enters variable amount
it supposed to be:
scanf("%f", &fsaPurchaseAmount); //user enters variable amount
Here are some observation about the code as presented:
Don't use floating point for money. It will only cause grief later. Ideally, take advice from an accounting professional. In the mean time, do arithmetic in cents, and scale to and from dollars for display.
Calculations like sales tax might be correctly done with a floating point multiply, but make sure you comply with the accepted practices for rounding back to whole cents. Again, seek advice from an accounting professional.
fflush() doesn't do what you think it does. For a file descriptor opened for writing (such as stdout) it guarantees that all output on that descriptor has been completed. It is used after printing a prompt and before calling something like scanf() to read the input. An example is: printf("What is your favorite color? "); fflush(stdout); fgets(color, sizeof(color), stdin);
Always check the return value of scanf(). It returns the number of conversions that succeeded. If it doesn't match the number of format specifiers, then only those that succeeded had values written to the named variables.
Be wary of literal characters other than whitespace appearing in a scanf() format string. These must be matched exactly by the input text, or the conversion fails. So a format like "$%f" is only matched by input that includes a literal dollar sign. This is probably not what your user expects. The format "%f" is easier on the user. If you want to allow an optional dollar sign, then scanf() may not be the best choice.

Resources