How can I avoid prompting the user multiple times for input? - c

I am creating a simple program which asks for user input in one function mark and then passes the input values to a second function characters for validation.
#include <stdio.h>
void marks(float *mark1, float *mark2, float *mark3);
void characters(float mark1, mark2, float mark3);
void marks(float *mark1, float *mark2, float *mark3) {
float firstMark, secMark, thirdMark;
printf("Enter mark1, mark2, and mark3: ");
scanf("%f,%f,%f", mark1, mark2, mark3);
while (mark1 < 0 || mark2 < 0 || mark3 < 0) {
printf("Error, marks can't be less than zero \n");
printf("Enter mark1, mark2, and mark3: ");
scanf("%f,%f,%f", mark1, mark2, mark3);
firstMark = *mark1;
secMark = *mark2;
thirdMark = *mark3;
}
}
void characters(float mark1, float mark2, float mark3) {
marks(&mark1, &mark2, &mark3);
if (mark1 < 50 || mark2 < 50 || mark3 < 50) {
printf("Really Bad! You have failed. \n");
}
else if (mark1 > 50 && mark2 > 50 && mark3 > 50) {
printf("You have passed. \n");
}
else {
printf("ERROR! \n");
}
}
int main(void) {
int i;
float mark1, mark2, mark3;
printf("Grade list \n");
marks(&mark1, &mark2, &mark3);
characters(mark1, mark2, mark3);
}
The problem is in characters when I call the mark it asks for user input, but I only want the program to ask user to enter marks in main.
How can I call marks in characters without the program asking for data input, so that I can use it's parameters to calculate values?

If you do not want to ask the user for the input twice, remove the second call to marks. The input has been collected for characters by main through calling marks, and passed through the three parameters; there is no need to call it the second time.
This will fix your problem:
void characters(float mark1, float mark2, float mark3) {
// No second call to marks
if (mark1 < 50 || mark2 < 50 || mark3 < 50) {
...
}
...
}

Related

Beginner in C: Can't properly printf first and last element in double array?

I'm trying to display a Wish List on the command line. The user enters the cost of the item, the level of priority (1-3), and whether or not it has financing options (y/n). The inputted values are put in multiple arrays. After the user enters all their values, they're displayed in a table at the end.
Everything in my code works fine except when I try to printf the user inputed cost values (double itemCosts[numOfItems];) in the table. The first and last element don't print properly, even when I input the same price (6225.88) for all of them. The last element is just 0.000000. See included pic of table output.
I tried debugging the issue by separating the cost-related loops and compiling/running them as another file and the costs display correctly...so I'm thinking the bug is somewhere else, but I can't find it.
#define MAX_ITEMS 10
#include <stdio.h>
int main()
{
const double MIN_INCOME = 500, MAX_INCOME = 400000;
int numOfItems;
double netIncome, itemTotal;
double itemCosts[numOfItems];
int itemPriors[numOfItems];
char itemFinOps[numOfItems];
printf("+--------------------------+\n");
printf("+ Wish List Forecaster |\n");
printf("+--------------------------+\n\n");
// Prompt for net monthly income
do
{
printf("Enter your monthly NET income: $");
scanf("%lf", &netIncome);
if (netIncome < MIN_INCOME)
{
printf("ERROR: You must have a consistent monthly income of at least $500.00\n\n");
}
else if (netIncome > MAX_INCOME)
{
printf("ERROR: Liar! I'll believe you if you enter a value no more than $400000.00\n\n");
}
} while (!(netIncome >= MIN_INCOME && netIncome <= MAX_INCOME));
printf("\n");
// Prompt for # of wish list items
do
{
printf("How many wish list items do you want to forecast?: ");
scanf("%d", &numOfItems);
if (!(numOfItems > 0 && numOfItems <= MAX_ITEMS))
{
printf("ERROR: List is restricted to between 1 and 10 items.\n\n");
}
printf("\n");
} while (!(numOfItems > 0 && numOfItems <= MAX_ITEMS));
// Store wish list item details
for (int i = 0; i < numOfItems; i++)
{
printf("Item-%d Details:\n", i + 1);
do //////////////// ******** PROMPT COST ********** //////////
{
printf("Item cost: $");
scanf("%lf", &itemCosts[i]);
if (!(itemCosts[i] >= (double)100))
{
printf(" ERROR: Cost must be at least $100.00\n");
}
} while (!(itemCosts[i] >= (double)100));
do // prompt priority
{
printf("How important is it to you? [1=must have, 2=important, 3=want]: ");
scanf("%d", &itemPriors[i]);
if (!(itemPriors[i] >= 1 && itemPriors[i] <= 3))
{
printf(" ERROR: Value must be between 1 and 3\n");
}
} while (!(itemPriors[i] >= 1 && itemPriors[i] <= 3));
do // prompt finance options
{
printf("Does this item have financing options? [y/n]: ");
scanf(" %c", &itemFinOps[i]);
if (!(itemFinOps[i] == 'y' || itemFinOps[i] == 'n'))
{
printf(" ERROR: Must be a lowercase 'y' or 'n'\n");
}
} while (!(itemFinOps[i] == 'y' || itemFinOps[i] == 'n'));
printf("\n");
}
///////// display summary of item details in TABLE //////////
printf("Item Priority Financed Cost\n");
printf("---- -------- -------- -----------\n");
for (int j = 0; j < numOfItems; j++)
{
printf(" %d %d %c %lf\n", j + 1, itemPriors[j], itemFinOps[j], itemCosts[j]);
itemTotal += itemCosts[j];
}
return 0;
}
int numOfItems;
double netIncome, itemTotal;
double itemCosts[numOfItems];
int itemPriors[numOfItems];
char itemFinOps[numOfItems];
It is undefined behaviour as your numOfItems is not inilized. In C table will not grow or shrink to the size when you change this variable
Change to:
double itemCosts[MAX_ITEMS];
int itemPriors[MAX_ITEM];
char itemFinOps[MAX_ITEM];
Always check the result of scanf. Exmaple:
if(scanf("%lf", &netIncome) != 1){ /* handle error*/}
As Vlad from Moscow and 0___________ said, you cannot define an array using a not initialised variable for the number of its elements. You can define the variables as
double *itemCosts;
int *itemPriors;
char *itemFinOps;
and after the variable numOfItems is given a value, you dynamically allocate memory as follows:
itemCosts = (double*) malloc(numOfItems * sizeof(double));
itemPriors = (int*) malloc(numOfItems * sizeof(int));
itemFinOps = (char*) malloc(numOfItems * sizeof(char));
or
itemCosts = (double*) calloc(numOfItems, sizeof(double));
itemPriors = (int*) calloc(numOfItems, sizeof(int));
itemFinOps = (char*) calloc(numOfItems, sizeof(char));
calloc initialises all elements of array to 0
At the end you must free the allocated memory:
free(itemCosts);
free(itemPriors);
free(itemFinOps);

Finding Mean in C program

I need some advice or hints about how to calculate the average of insurance, tax, gross and net salary. Just need some enlightment.
Tried to add average function before but it seems that its hard to get the value from other function.
Any ideas? This code is used to find the salary of employee and its average.
char EmpName[50];
int EmpID, EmpAge, EmpNum, i;
float gross_salary, net_salary;
float insurance, tax, total, total_insurance, total_tax;
int main()
{
int i;
FILE *file;
file = fopen("UserDetails.txt", "wt");
printf("Number of Employee to process: ");
scanf("%d", &EmpNum);
i = 1;
EmployeeName: while( i <= EmpNum)
{
printf("\nEmployee name: "); scanf("%s", &EmpName);
if (strlen(EmpName) <= 50){
EmployeeID: printf("Employee ID: "); scanf("%d", &EmpID);
if (EmpID >= 1000 && EmpID <= 9999){
EmployeeAge: printf("Employee Age: "); scanf("%d", &EmpAge);
if (EmpAge >= 18 && EmpAge <= 99){
printf("Employee Salary: "); scanf("%g", &gross_salary);
if (gross_salary >= 0.0 && gross_salary <= 9999.99){
goto Total;
}
}
else{
printf("\nInvalid Input!\nEmployee Age Is Between 18 To 99\n");
goto EmployeeAge;
}
}
else{
printf("\nInvalid Input!\nEmployee ID Number is Between 1000 To 9999\n");
goto EmployeeID;
}
}
else{
printf("\nInvalid Input!\nMax Character is 50\n");
goto EmployeeName;
}
Total: printf("\n");
SetInsurance(EmpAge);
IncomeTax(gross_salary);
TaxDeduction(tax);
InsuranceDeduction(insurance);
NetSalary();
Average(insurance,gross_salary,net_salary);
i++;
fprintf(file, "Employee name: %s\n", EmpName); //print data inside file
fprintf(file, "Employee ID: %d\n", EmpID);
fprintf(file, "Employee Age: %d\n", EmpAge);
fprintf(file, "Employee Salary: %g\n\n", gross_salary);
}
fclose(file);
}
float SetInsurance(int x){
while (i <= EmpNum){
if (x <= 35)
insurance = 110;
else if (x >=36 && x <= 65)
insurance = 160;
else if (x > 65)
insurance = 250;
else
printf("Under Age!");
total = insurance;
printf("\nInsurance: %.2f\n", total);
return total;i++;
};
}
float IncomeTax(float salary) {
int i = 0;
while(i < EmpNum){
if (salary <= 999.99)
tax = 0;
else if (salary >= 1000 && salary <= 2999.99)
tax = 2.5;
else if (salary >= 3000)
tax = 5;
else
printf("Invalid Input!\n");
printf("Income Tax Rate: %.2f%\n", tax);
return tax;
i++;
}
}
float InsuranceDeduction(float insurance){
if (insurance == 110){
total_insurance =+ 110;
}else if (insurance == 160){
total_insurance =+ 160;
}else if (insurance == 250){
total_insurance =+ 250;
}
return total_insurance;
}
float TaxDeduction(float tax){
if(tax == 2.5){
total_tax = gross_salary * 0.025;
}else if(tax == 5){
total_tax = gross_salary * 0.05;
}
return total_tax;
}
void NetSalary(){
total = TaxDeduction(tax) + InsuranceDeduction(insurance);
net_salary = gross_salary - total;
printf("Net Salary: RM%.2f\n", net_salary);
}
I order to solve the problem you face, I'd follow the recomendations you have received from other responses, and in addition:
If you fopen() a file, just check that the returned pointer is valid, as you can have several errors derived of:
Not having permissions to read the file.
file doesn't exist.
and these should be handled before you start processing the file.
Second, You don't need to store the data from the file, except for error purposes (it's preferable if you say that Martina Navratilova cannot be paying such ridiculous amount of taxes than saying that record 6437 in the file has a ridiculous amount of taxes to be payd -- you should search for it by counting, while your program has already done it)
If I would to decide how the input file is formatted, I should make a two line record, one line to specify the user name (which so, can have spaces embedded, as the new line marks the end of the name) so it can be read with fgets(), and a second line with all the numeric data you are going to fscanf(), after the sequence is done, you have all the data for a single user. Another possibility (to allow the name with spaces) is to put the name as the last field of the data file, so you can read all the last field characters upto the \n as the user name. This would allow to put each user in one single line
"I need some advice or hints., ...,any idea?"
First: Read and act on each of suggestions in first 3 comments under your post from #Chux.
Other suggestions:
Avoid using goto tag ... :tag statements to traverse code.
Create functions that can be called to do a simple task, then return.
Use a struct to contain related data when there can be more that one related data set.
Change
char EmpName[50];
int EmpID, EmpAge, EmpNum, i;
float gross_salary, net_salary;
float insurance, tax, total, total_insurance, total_tax;
To for example: (Note, not all these members may be necessary, depending on how you finally implement the records needed for each employee.)
typedef struct {
char EmpName[50];
int EmpID;
int EmpAge;
double gross_salary;
double net_salary;
double insurance;
double total_insurance; //may not be necessary in struct
double tax;
double total_tax; //may not be necessary in struct
}account_s;
Note, if "total" members are to be used as totals for all employees, then they should probably not be a members in the struct.
Create instance(s) of this struct in local space, Eg.
int main(void)
{
int EmpNum = 0;
...
printf("Enter number of Employees to process: ");
scanf("%d", &EmpNum);
account_s account[EmpNum];//creates an array of instances of account_s
memset(account, 0, sizeof account);//initializes array
Incorporate account_s into functions as return type, and/or function parameters. Eg.
The following is a very brief, but compilable and runable example to illustrate several things including how to pass a single function argument containing all the information needed to update and contain employee information (via struct).
//prototypes
void populateAccounts(int count, account_s record[count]);
void SetInsurance(account_s *record);
double Get_ave_salery(int c, account_s *account);
int main(void)
{
int EmpNum = 0;
printf("Number of Employee to process: ");
scanf("%d", &EmpNum);
account_s account[EmpNum];//creates an array of instances of account_s
memset(account, 0, sizeof account);//initializes array
populateAccounts(EmpNum, account);
double ave_salary = Get_ave_salery(EmpNum, account);
printf("Average Gross Salary: %lf\n", ave_salary);
return 0;
}
void populateAccounts(int count, account_s record[count])
{
//Read in information for each account
for(int i=0; i<count; i++)
{
printf("\nEnter employee name: ");
scanf("%s", record[i].EmpName);
printf("\nEnter employee ID: ");
scanf("%d", &record[i].EmpID);
printf("\nEnter employee Age: ");
scanf("%d", &record[i].EmpAge);
printf("\nEnter employee Salary: ");
scanf("%lf", &record[i].gross_salary);
SetInsurance(&record[i]);//function to set insurance via function argument
// etc.
}
}
void SetInsurance(account_s * record){
if (record->EmpAge <= 35)
record->insurance = 110;
else if (record->EmpAge >=36 && record->EmpAge <= 65)
record->insurance = 160;
else if (record->EmpAge > 65)
record->insurance = 250;
else
printf("Under Age!");
// total = record->insurance;
printf("\nInsurance: %.2f\n", record->insurance);
}
double Get_ave_salery(int c, account_s *account)
{
double ave = 0.0;
double sum = 0.0;
for(int i=0; i<c; i++)
{
sum += account[i].gross_salary;
}
return sum/c;
}
There is more for you to do here, but this should help you to get started.

Printing the average of combined student marks using C

I've made this program below to calculate the average mark of a student.
Everything works well until I use -1, it is supposed to stop the program as is display the average of all students that have been entered, say Goodbye! and then terminate.
I think my calculations might be wrong though because it is printing the wrong result for the average marks of the students.
Thanks in Advance.
#include <stdio.h>
int main(void)
{
float final_mark(int a_mark1, int a_mark2, int lab_mark, int quiz_mark, int exam_mark);
int i, a_mark1, a_mark2, lab_mark, quiz_mark, exam_mark;
float average_mark = 0.0;
do
{
for (i = 0; i < 2; i++)
{
printf("Enter assignment 1 mark (-1 to quit): ");
scanf("%d", &a_mark1);
if(a_mark1 == -1)
{
average_mark += final_mark(a_mark1, a_mark2, lab_mark, quiz_mark, exam_mark);
if ((average_mark > 1 ) && (average_mark < 100 ))
{
printf("The average student mark is %.2f%% \n", average_mark);
}
printf("Goodbye! \n");
return 0;
}
printf("Enter assignment 2 mark: ");
scanf("%d", &a_mark2);
printf("Enter laboratory mark: ");
scanf("%d", &lab_mark);
printf("Enter quiz mark: ");
scanf("%d", &quiz_mark);
printf("Enter exam mark: ");
scanf("%d", &exam_mark);
printf("Student %d final mark: %.2f \n", i + 1, final_mark(a_mark1, a_mark2, lab_mark, quiz_mark, exam_mark));
}
}
while(a_mark1 != -1);
return 0;
}
float final_mark(int a_mark1, int a_mark2, int lab_mark, int quiz_mark, int exam_mark)
{
float final_mark = a_mark1 * 0.1 + a_mark2 * 0.15 + lab_mark * 0.15 + quiz_mark * 0.1 + exam_mark * 0.5;
return final_mark;
}
I think you need to rethink your logic a little bit. Why not use a while loop to control the flow. Then you can bail out of the program immediately if user inputs -1 right away. You should use an array to store the averages for each student, then you can loop through and find the class average as well.
-Your float final_mark function seems a little sketchy without any parenthesis.
-You should put your function prototype outside of main as well. See below changes.
#include <stdio.h>
#define MAX_STUDENTS 10 //define what the max number of students is
float final_mark(int mark1, int mark2, int lab, int quiz, int exam);
int main()
{
int i = 0, mark1 = 0, mark2 = 0,
lab = 0, quiz = 0, exam = 0;
int num_students;
float students_avg[MAX_STUDENTS] = {0}; //array to hold averages for students
float average = 0;
while (i < MAX_STUDENTS) {
printf("Enter assignment 1 mark (enter -1 to quit):\n");
scanf("%d", &mark1);
if (mark1 == -1)
break; //no more students, break out of while loop
printf("Enter assignment 2 mark: ");
scanf("%d", &mark2);
printf("Enter laboratory mark: ");
scanf("%d", &lab);
printf("Enter quiz mark: ");
scanf("%d", &quiz);
printf("Enter exam mark: ");
scanf("%d", &exam);
average = final_mark(mark1, mark2, lab, quiz, exam);
students_avg[i] = average; //add this average to array
printf("Student # %d average was %.2f\n", i, students_avg[i]);//debug info
i++;
}
num_students = i; //how many students grades did we read?
average = 0; //reset to 0 so we can use below
for (i = 0; i < num_students; i++)
average += students_avg[i];
if (num_students > 0)
printf("Class average is %.2f\n", average/num_students);
else
printf("Goodbye!\n");
return 0;
}
float final_mark(int mark1, int mark2, int lab, int quiz, int exam)
{
//we can just return the calculation
return ((mark1 * 0.1) + (mark2 * 0.15) + (lab * 0.15) + (quiz * 0.1) + (exam * 0.5));
}
Just erase two lines above printf("GOODBYE! \n"); you will get what you want.
maybe you have to initialized mark s variables to 0. and a_mark1 to 0 too if the user enter -1

Why does my code jump to else immediately?

#include <stdio.h>
int printMenu(int);
int studentglobal;
float getCarryMark(float);
float cm1;
main()
{
printf("-----------------------------------------------------\n");
printf("\t\tTotal Score calculator\n");
printf("-----------------------------------------------------\n");
int counter, x, studentcount = 1,sum = 0 ;
x = printMenu(studentglobal);
for (counter = 0; counter < x; counter++)
{
studentcount = studentcount + counter;
printf("Student : %d \n", studentcount);
getCarryMark(cm1);
if (cm1 >= 0 && cm1 <= 50)
{
printf("right range!!\n");
}
else
{
printf("INVALID RANGE!!!\n");
}
printf("%.2f\n", cm1);
}
}
int printMenu(int nstudent)
{
printf("Enter no of student: ");
scanf("%d", &nstudent);
return(nstudent);
}
float getCarryMark(float carrymark)
{
printf("Enter your carrymarks: ");
scanf("%f", &carrymark);
return(carrymark);
}
So actually when I enter 200, it shows INVALID RANGE!!!, but when I enter 20 it still shows INVALID RANGE!!!. It somehow skipped the if statement. Please don't bother the other part, if I have any mistake tell me please. ert gf dfg dgd dg dfgd gd dg dg dgdfg
You need to return carrymark from getCarryMark:
float getCarryMark(float carrymark)
{
printf("Enter your carrymarks: ");
scanf("%f", &carrymark);
return(carrymark);
}
You are missing a return statement in getCarryMarks method !
You missed the return statement in getCarryMark
getCarryMark function takes a parameter by value, modifies the value and returns it back, however, the returned value is never used. Modifying the parameter's value does not reflect this change to the outside since it has been passed by value.
I have partially updated the code so that it could execute the if statement. Please try the following code.
#include <stdio.h>
int printMenu(int);
int studentglobal;
float getCarryMark(float);
float cm1;
main()
{
printf("-----------------------------------------------------\n");
printf("\t\tTotal Score calculator\n");
printf("-----------------------------------------------------\n");
int counter, x, studentcount = 1,sum = 0 ;
x = printMenu(studentglobal);
for (counter = 0; counter < x; counter++)
{
studentcount = studentcount + counter;
printf("Student : %d \n", studentcount);
cm1 = getCarryMark();
if (cm1 >= 0 && cm1 <= 50)
{
printf("right range!!\n");
}
else
{
printf("INVALID RANGE!!!\n");
}
printf("%.2f\n", cm1);
}
}
int printMenu(int nstudent)
{
printf("Enter no of student: ");
scanf("%d", &nstudent);
return(nstudent);
}
float getCarryMark()
{
float carrymark = 0.0;
printf("Enter your carrymarks: ");
scanf("%f", &carrymark);
return(carrymark);
}

my program fails when I build and succeeds when I rebuild?

Whenever I build my program using visual studio 2015, it says it fails, but when I rebuild immediately after, it says it succeeded. Another question is how do i store multiple inputs for SKU, price and price and then properly output it.
#include <stdio.h>
#define MAX_ITEMS 10
struct Item
{
int sku_[10];
int quantity_[10];
float price_[10];
};
int main(void)
{
int size = 0;
int input =1;
int i;
int j;
struct Item items[10];
printf("Welcome to the Shop\n");
printf("===================\n");
printf("Please select from the following options\n");
while (size <= MAX_ITEMS && input != 0)
{
printf("1) Display the inventory.\n2) Add to the inventory.\n0)Exit.\n);
printf("Select:");
scanf_s("%d", &input);
while (input < 0 || input >2 && input != 0)
{
printf("Invalid input, try again: Please select from the following);
printf("1)Display the inventory.\n2)Add to the inventory.\n0) Exit.\n");
printf("Select:");
scanf_s("%d", &input);
}
if (input == 1)
{
printf("Inventory\n");
printf("====================\n");
printf("Sku Price Quantity\n");
printf("%d", items[size].sku_);
}
else if (input == 2)
{
printf("Please input a SKU number:");
if (size >= MAX_ITEMS)
{
printf("The inventory is full");
}
else if (size < MAX_ITEMS)
{
scanf_s("%d", &items[size].sku_);
printf("Quantity:");
scanf("%d", &items[size].quantity_);
printf("Price:");
scanf("%f", &items[size].price_);
printf("The item is successfully added to the inventory.\n");
size += 1;
}
}
else if (input == 0)
{
printf("Good bye");
}
}
}
Here are errors detected in the source code:
1- As WhozCraig suggests, two printf() calls are bad terminated.
Instead of:
printf("1) Display the inventory.\n2) Add to the inventory.\n0)Exit.\n);
...
printf("Invalid input, try again: Please select from the following);
Add a text terminator:
printf("1) Display the inventory.\n2) Add to the inventory.\n0)Exit.\n");
...
printf("Invalid input, try again: Please select from the following");
2- When entering items[size].sku_, or .quantity_, or .price_, use a pointer to a value instead of a pointer to a array of value. The struct Item is malformed.
Just modify the struct Item:
struct Item
{
int sku_; // unexpected use [10];
int quantity_; // unexpected use [10];
float price_; // unexpected use [10];
};
3- When printing the inventory, use a loop and not the last index. And format all attributes of each items[i] to align with the header.
printf("Sku Price Quantity\n");
for(i=0;i<size;i++) {
printf("%6d %8d %6.2f\n", items[i].sku_,items[i].quantity_,items[i].price_);
}

Resources