I have this simple project where I'm supposed to create 4 arrays and enter employee's data into, the arrays are: The employee's ID, their salary, the salary cuts, and the net salary. I am also supposed to print the average salary, the ID # of the employee with the highest salary, and the ID # of the employee with the lowest cut.
The code works fine, except if I enter a letter, then it just executes the whole program in a weird way (no formatting, random numbers).
Why is that? The letter gets converted to an integer, right? What causes it to stop working properly?
Also, would you mind looking at the coding style I used and telling me if there's a way I can improve it?
#include <stdio.h>
#define SIZE 100
int main(void){
int n; /*Number of employees*/
float average; /*Average of the employee's salary*/
int max; /*Highest salary*/
int min; /*Minimum cut*/
int i;
int employee_number = 1;; /*The number (index +1) of the employee*/
float sum = 0; /*The sum of the employee's salary*/
int num_highest; /*The number of the employee with the highest
salary*/
int num_lowest; /*The number of the employee with the lowest cut*/
int id_number[SIZE]; /*Array to hold employee's IDs in*/
float salary[SIZE]; /*Array for employee's salaries*/
float cuts[SIZE]; /*Array for salary cuts*/
float net_salary[SIZE]; /*Net salary after cuts*/
printf("Enter the number of employees\t");
scanf("%i", &n);
for(i = 0; i < n; i++){
printf("Enter the ID of employee #%i\t", employee_number);
scanf("%i", &id_number[i]);
printf("Enter the salary of employee #%i\t", employee_number);
scanf("%f", &salary[i]);
printf("Enter the salary cut of employee #%i\t", employee_number);
scanf("%f", &cuts[i]);
employee_number++;
}
for(i = 0; i < n; i++){
net_salary[i] = salary[i] - (salary[i] * cuts[i] * 1/100);
}
for(i = 0; i < n; i++){
sum += net_salary[i];
}
average = sum/(float)n;
printf("The average salary is %.2f\n", average);
max = net_salary[0];
min = cuts[0];
for(i = 0; i < n; i++){
if(net_salary[i] > max){
max = net_salary[i];
num_highest = i;
}
if(cuts[i] <= min){
min = cuts[i];
num_lowest = i;
}
}
printf("Employee with ID # %i has the highest salary which is %i\n", id_number[num_highest], max);
printf("Employee with ID # %i has the lowest cut of %i and a base salary of %.2f", id_number[num_lowest], min, salary[num_lowest]);
}
You should check the value returned by every call to function scanf.
If this value is smaller than the number of input arguments that the function is supposed to obtain from the user, then it has failed and you should call it again.
In terms of coding style, you can use a struct to store information about each employee, and create an employees[] array of structs that way. This helps in organizing your code better, and avoids having to use 4 separate arrays to store information about the employees.
The struct can look like this:
typedef struct {
int id_number;
float salary;
float cuts;
float net_salary;
} employee_t;
And then you can create an array of structs like this:
employee_t employees[n]; /* n is number of employees */
It is also good to check the return of scanf().
So instead of doing simply:
scanf("%i", &n);
Be extra careful and change this to:
if (scanf("%i", &n) != 1) {
/*exit program if true */
}
I wrote some code to demonstrate these points:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int id_number;
float salary;
float cuts;
float net_salary;
} employee_t;
void get_number_employees(int *n);
void get_user_input(employee_t employees[], int n, float *average);
void print_results(employee_t employees[], int n, float average);
int highest_salary(employee_t employees[], int n);
int lowest_cut(employee_t employees[], int n);
int
main(void) {
int n;
float average;
get_number_employees(&n);
employee_t employees[n];
get_user_input(employees, n, &average);
print_results(employees, n, average);;
return 0;
}
void
get_number_employees(int *n) {
printf("Enter number of employees: ");
if (scanf("%d", n) != 1) {
printf("Invalid number.\n");
exit(EXIT_FAILURE);
}
}
void
print_results(employee_t employees[], int n, float average) {
int high_sal, low_cut;
high_sal = highest_salary(employees, n);
low_cut = lowest_cut(employees, n);
printf("The average salary is %f\n", average);
printf("Employee with ID # %d has the highest salary which is %f\n",
employees[high_sal].id_number, employees[high_sal].net_salary);
printf("Employee with ID # %d has the lowest cut of %f and a base salary of %f\n",
employees[low_cut].id_number, employees[low_cut].cuts, employees[low_cut].salary);
}
void
get_user_input(employee_t employees[], int n, float *average) {
int i, employee_number = 1, sum = 0;
for (i = 0; i < n; i++) {
printf("Enter the ID of employee #%d: ", employee_number);
if (scanf("%d", &(employees[i].id_number)) != 1) {
printf("Invalid number.\n");
exit(EXIT_FAILURE);
}
printf("Enter the salary of employee #%d: ", employee_number);
if (scanf("%f", &(employees[i].salary)) != 1) {
printf("Invalid salary.\n");
exit(EXIT_FAILURE);
}
printf("Enter the salary cut of employee #%d: ", employee_number);
if (scanf("%f", &(employees[i].cuts)) != 1) {
printf("Invalid cuts.\n");
exit(EXIT_FAILURE);
}
employees[i].net_salary = employees[i].salary - (employees[i].salary * employees[i].cuts * 1/100);
sum += employees[i].net_salary;
employee_number++;
}
*average = (1.0f * sum)/n;
}
int
highest_salary(employee_t employees[], int n) {
float max;
int i, idx;
max = employees[0].net_salary;
for (i = 1; i < n; i++) {
if (employees[i].net_salary > max) {
max = employees[i].net_salary;
idx = i;
}
}
return idx;
}
int
lowest_cut(employee_t employees[], int n) {
float min;
int i, idx;
min = employees[0].cuts;
for (i = 1; i < n; i++) {
if (employees[i].cuts < min) {
min = employees[i].cuts;
idx = i;
}
}
return idx;
}
Letters are char or char* when taken as input for many C and C++ functions. char can generally be output to the console as an ASCII encoded digit or as an integer value.
char can be cast into int very easily in C because it's actually considered a numeric value. For example, A becomes 41, and B becomes 42.
Related
So I what I specifically want is to find which elements of an array are between two different values, not two different indexes. The code so far looks like this:
#include <stdio.h>
#define SIZE 5
int main(void){
float grades[SIZE];
float g;
int i;
for (i=0;i<SIZE;i++){
printf("Enter a grade: ");
scanf("%f", &g);
grades[i]= g;
}
float a,b;
printf("Enter a grade range: \n");
scanf("%f %f", &a,&b);
return 0;
}
What I want is to tell the program, after the last scanf, to search for the array's values that are between the numbers the user enters, and then print the number of said values.
First, you need to sort your array:
#include <stdio.h>
#define SIZE 5
//We need a utility function for our integrated qsort algorithm:
int cmpfunc (const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int main(void){
float grades[SIZE];
float g;
int i;
for (i=0;i<SIZE;i++){
printf("Enter a grade: ");
scanf("%f", &g);
grades[i]= g;
}
float a,b;
printf("Enter a grade range: \n");
scanf("%f %f", &a,&b);
//Call qsort() function
qsort(grades, SIZE, sizeof(float), cmpfunc);
//Now array grades[] is sorted
int j = 0;
for(j; grades[j] <= a && (j < SIZE); j++){
}
//grades[j] >= a
for(j;grades[j] <= b && (j < SIZE); j++){
printf("%f ", grades[j]);
}
printf("\n");
return 0;
}
By sorting your array, you create the opportunity to sequentially search for the first element, that is >= a, which means that your task will be done in O(n) complexity, worst case scenario.
For an even more optimal solution, you could also use a binary search.
After the first element that is needed to print is found, you can simply run through the rest of the elements, printing them if they are <= b, until you reach b or the end of the array (that is why those (j < SIZE) things are needed too.
can you try this one.
in this way it do not sort, but it will display values, that are between the numbers the user enters
#include <stdio.h>
#define SIZE 5
int main(void){
float grades[SIZE];
float g;
int i;
for (i=0;i<SIZE;i++){
printf("Enter a grade: ");
scanf("%f", &g);
grades[i]= g;
}
float a,b;
printf("Enter a grade range: \n");
scanf("%f %f", &a,&b);
for (i=0;i<SIZE;i++){
if(a>b){
if(grades[i]>=b && grades[i]<=a){
printf("%f ", grades[i]);
}
}else{
if(grades[i]>=a && grades[i]<=b){
printf("%f ", grades[i]);
}
}
}
return 0;
}
This should work:
#include <stdio.h>
#define ARRAY_LEN(x) (sizeof(x) / sizeof(*(x)))
size_t count_elems(const float * const arr, size_t arr_size, float min, float max)
{
size_t count = 0;
for (size_t i = 0; i < arr_size; i += 1)
{
if ((arr[i] >= min) && (arr[i] <= max))
{
count += 1;
}
}
return count;
}
int main()
{
float a[5] = {1.0, 0.5, 2, 3, 4};
printf("%lu\n", count_elems(a, ARRAY_LEN(a), 0.5, 3));
return 0;
}
The way the function works is by receiving a pointer to the float array, and iterating element by element to see if it falls within the correct range. The reason it needs the arr_size is because it can't tell the array length by itself.
It's worth noting that ARRAY_LEN() should only be used on statically allocated arrays.
Write a program that asks the user to enter daily rainfall amounts. Your program will need to accept 5 daily rainfall inputs. Only allow non-negative rainfall amounts. When the user enters a negative number, tell them that the number is invalid, and that they should enter another, valid value.
Calculate the total rainfall and the average rainfall. Determine the largest daily rainfall and the smallest daily rainfall.
Output the total, average, largest, and smallest values using informative messages.
The following things cannot happen in main:
Accepting user input
Calculation of total or average
Determination of largest or smallest
Outputting results
=============================================
Right now i'm just trying to figure out how to enter the 5 numbers, I have this code so far but it's having me put it in an infinite amount of times. I've been working on this project for hours, so any advice would be amazing.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
double CollectRainfall() {
double amount;
double rainfall[SIZE];
int i;
printf("Enter a rainfall amount: \n"); // enter amount
scanf_s("%lf", &amount);
for (i = 0; i < SIZE; i++) {
rainfall[i] = CollectRainfall();
while (amount < 0.0) { // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter another rainfall amount: \n");
}
}
}
int main() {
CollectRainfall();
return 0;
}
As said the recursion as you have it will essentially create an infinite loop, and really, for this you dont need it either, you can do something like:
Running sample (commented changes)
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
void CollectRainfall() { //no return needed
double rainfall[SIZE], sum = 0, max = 0, min = 0;
int i;
for (i = 0; i < SIZE; i++)
{
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &rainfall[i]); //save values into the array
while (rainfall[i] < 0.0)
{ // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter another rainfall amount: \n");
i--; // iterate back to replace negative number
}
}
printf("Values:");
for (i = 0, min = rainfall[i]; i < SIZE; i++)
{
printf(" %.2lf", rainfall[i]); // print all values
sum += rainfall[i]; // sum values
if(rainfall[i] > max){ //max value
max = rainfall[i];
}
if(min > rainfall[i]){ //min value
min = rainfall[i];
}
}
printf("\nSum: %.2lf", sum); // print sum
printf("\nMax: %.2lf", max); // print max
printf("\nMin: %.2lf", min); // print min
printf("\nAverage: %.2lf", sum / SIZE); //print average
}
int main() {
CollectRainfall();
return 0;
}
You can create a struct to store you data and do the operation.
Something like:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5 // have the user enter it 5 times
typedef struct data {
double rainfall[SIZE];
double average;
double min;
double max;
} data_t;
static void collectRainfall(double rainfall[SIZE]) {
for (int i = 0; i < SIZE; i++) {
double amount;
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &amount);
while (amount < 0.0) { // if it's a negative number
printf("The number is invalid.\n"); // display error message if a negative # was entered
printf("Enter a rainfall amount: \n"); // enter amount
scanf("%lf", &amount);
}
rainfall[i] = amount;
}
}
static void compute(data_t *data) {
data->min = data->rainfall[0];
data->max = data->rainfall[0];
data->average = data->rainfall[0];
for (int i = 1; i < SIZE; i++) {
double rainfall = data->rainfall[i];
if (rainfall > data->max) {
data->max = rainfall;
}
if (rainfall < data->min) {
data->min = rainfall;
}
data->average += rainfall;
}
data->average /= SIZE;
}
static void display(data_t *data) {
printf("min %f, max %f, average %f\n",
data->min, data->max, data->average);
}
int main() {
data_t data;
collectRainfall(data.rainfall);
compute(&data);
display(&data);
return 0;
}
scanf is a pain in case of bad input best is to read a line then parse it, check if strtod is ok
static void collectRainfall(double rainfall[SIZE]) {
for (int i = 0; i < SIZE; i++) {
char str[32];
double amount = -1;
printf("Enter a rainfall amount [%d/%d]: \n", i , SIZE);
while (42) {
char *res = fgets(str, sizeof(str), stdin);
if (res && (amount = strtod(str, &res)) >= 0 && res != str)
break;
printf("The number is invalid.\n");
printf("Enter a rainfall amount [%d/%d]: \n", i , SIZE);
}
rainfall[i] = amount;
}
}
So here's my code:
#include <stdio.h>
double CalculateFinalScore(int assignment[], int midterm[], int finalExam[], double *scoreSum[]) {
int i = 0;
for (i = 0; i < 4; ++i) {
*scoreSum[i] = (assignment[i] * 0.2) + (midterm[i] * 0.3) + (finalExam[i] * 0.5);
}
}
int main(void) {
const int NUM_SCORES = 4; // Array size
double testScores[NUM_SCORES]; // User test scores
int i = 0;
double finalScore = 0.0;
int x[100];
int y[100];
int z[100];
double q;
// Prompt user to enter test scores
printf("Enter %d students test scores:\n", NUM_SCORES);
for (i = 0; i < NUM_SCORES; ++i) {
printf("Input student %d assignment score: ", (i+1));
scanf("%d", &(x[i]));
printf("Input student %d midterm score: ", (i+1));
scanf("%d", &(y[i]));
printf("Input student %d final exam score: ", (i+1));
scanf("%d", &(z[i]));
printf("\n");
}
printf("\n");
// Call function to calculate final score
CalculateFinalScore(x, y, z, &q);
for (i = 0; i < NUM_SCORES; ++i) {
printf("Final student test score: ");
printf("%lf\n", q);
}
return 0;
}
Basically, I want to have an output that display the final score for each student that I have inputed before. But the when my code tries to display the output its always segmentation fault. I tried to return the array before but it seems that it doesn't fix it. Can somebody help me?
Using your code (not tested)
#include <stdio.h>
#include <stdint.h>
#define NUM_SCORES 4
double CalculateFinalScore(int assignment[], int midterm[], int finalExam[], double scoreSum[], uint8_t num_scores)
{
int i = 0;
for (i = 0; i < num_scores; ++i)
{
scoreSum[i] = (assignment[i] * 0.2) + (midterm[i] * 0.3) + (finalExam[i] * 0.5);
}
}
int main(void)
{
double testScores[NUM_SCORES]; // User test scores
int i = 0;
int x[NUM_SCORES];
int y[NUM_SCORES];
int z[NUM_SCORES];
// Prompt user to enter test scores
printf("Enter %d students test scores:\n", NUM_SCORES);
for (i = 0; i < NUM_SCORES; ++i)
{
printf("Input student %d assignment score: ", (i+1));
scanf("%d", &(x[i]));
printf("Input student %d midterm score: ", (i+1));
scanf("%d", &(y[i]));
printf("Input student %d final exam score: ", (i+1));
scanf("%d", &(z[i]));
printf("\n");
}
printf("\n");
// Call function to calculate final score
CalculateFinalScore(x, y, z, testScores, NUM_SCORES);
for (i = 0; i < NUM_SCORES; ++i)
{
printf("Final student %d test score: ", )i+1));
printf("%lf\n", testScores[i]);
}
return 0;
}
You are passing a single double while your function need an array
Your function needs an array of double, not a pointer to an array of double
This question may be annoying, but I am trying to write code the way that I can most easily mentally process it and at this point it is without calling functions. I am rewriting my professors example code into my own, but am having a problem with what to store it into? He uses a pointer, but I just don't know how/where to declare it.
My apologies if this question is incorrectly worded. I am one of those people who just doesn't 'get it' when it comes to programming unfortunately.
My Professors:
#include <stdio.h>
#include <stdlib.h>
/* Program that computes the average salary of the employees with an age equal or greater
than x, x is passed as a parameter to the main function. Employee is a structure with two
fields: age and salary. */
struct employee {
int age;
float salary;
};
void readValues(struct employee *EMP, int n ) {
int i;
for(i=0; i<n; i++) {
printf("Employee %i\n", i+1);
printf("\tAge: ");
scanf("%i", &EMP[i].age);
printf("\tSalary: ");
scanf("%f", &EMP[i].salary);
}
}
float getAvg(struct employee *EMP, int minAge, int n ) {
int i, nE = 0;
float sum=0;
for(i=0; i<n; i++) {
if(EMP[i].age >= minAge) {
sum = sum + EMP[i].salary;
nE = nE + 1;
}
}
return sum/nE;
}
int main(int argc, char *argv[]) {
int x, n;
struct employee E[100];
if (argc<3) {
printf("Error: Some parameters missing.\n");
return -1;
}
x = atoi(argv[1]);
n = atoi(argv[2]);
readValues(E, n);
float avg = getAvg(E, x, n);
printf("Avg. Salary = %.2f\n", avg);
return 0;
}
My attempt:
#include <stdio.h>
#include <stdlib.h>
#define minage 20
struct employee{
int age;
float salary;
};
int main()
{
struct employee emp = {0};
int i, n, numb=0, sum=0, avg;
printf("How many employees do you have today?\n");
scanf("%i", n);
for(i=0; i<n; i++)
{
printf("Employee %i", i+1);
printf("Age:\n");
scanf("%i", &emp[i].age);
printf("Salary:\n");
scanf("%f", &emp[i].salary);
}
if (emp[i].age >= minage)
{
for(i=0, i<n; i++){
sum = sum + emp[i].salary
numb = numb + 1
}
}
avg = sum / numb;
printf("The average salary is %i\n", avg);
}
Refer the below Code: Comments Inline
#include <stdio.h>
#include <stdlib.h>
#define minage 20
struct employee{
int age;
float salary;
};
int main()
{
/* Use array of struct to store the employee record. */
struct employee emp[100];
int i, n, numb=0, sum=0;
float avg = 0; /* If avg is of type int then you will loose the precision when finding the average */
printf("How many employees do you have today?\n");
scanf("%i",&n); /* Use `&` when using scanf to read value into integer*/
for (i = 0; i < n; i++) {
printf("Employee %i", i+1);
printf("Age:\n");
scanf("%i", &emp[i].age);
printf("Salary:\n");
scanf("%f", &emp[i].salary);
}
/* Your professor is calculating avg salary only if age >= minage.
* But in your code your are trying to check if the last employee age is
* >= minage only after which calculating the avg salary of all employee's*/
for (i = 0; i < n; i++) {
if (emp[i].age >= minage) {
sum = sum + emp[i].salary;
numb = numb + 1;
}
}
/* Make sure to check whether numb != 0, else divide by zero exception
* when there are no employee's with age greater than 20 (minage) */
if (numb)
avg = sum / numb;
printf("The average salary is %.2f\n", avg);
/* return 0; when return type of main() is int.
* If not required then change to void main()*/
return 0;
}
Also as your professor is initializing minage from user input. In your code it is hard coded to a fixed number 20.
Try to read the minage from user as you did to get the number of employee's.
Need to pass a struct array to 2 functions so that the user can input the values.
This is the structure needed:
struct Sale {
double quantity;
double unit_p;
char taxable;
};
Calling the function in the main functions as:
no_sales = enter(sales, MAX_SALES);
total(sales, no_sales);
and i am inputting values by:
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
printf("Unit Price : ");
scanf("%lf", &s[i].unit_p);
printf("Taxable(y/n) : ");
scanf("%*c%c%*c", &s[i].taxable);
It compiles fine in gcc compiler. When I ran the program I can enter the values but when I try to print the values it displays all values as 0. The values are not being stored in struct array
output I am getting:
Quantity : 2
Unit Price : 1.99
Taxable(y/n) : y
Quantity Unit Price
0.000000 0.000000
The whole code:
program accepts the values and calculates total price in 2 separate functions
#include <stdio.h>
const int MAX_SALES = 10;
struct Sale {
double quantity;
double unit_p;
char taxable;
};
void total(const struct Sale *s,int n);
int enter(struct Sale *s, int M);
int main()
{
int no_sales;
struct Sale sales[MAX_SALES];
printf("Sale Records \n");
printf("=============\n");
no_sales = enter(sales, MAX_SALES);
total(sales, no_sales);
}
int enter(struct Sale *s, int M)
{
int i = 0;
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
while(s[i].quantity != 0) {
printf("Unit Price : ");
scanf("%lf", &s[i].unit_p);
printf("Taxable(y/n) : ");
scanf("%*c%c%*c", &s[i].taxable);
i++;
if(i == M) {
printf("Maximum exceeded\n");
break;
}
printf("Quantity : ");
scanf("%lf", &s[i].quantity);
}
int j;
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[i].quantity, s[i].unit_p, s[i].taxable);
}
return i;
}
void total(const struct Sale *s,int n)
{
int i, subtot = 0, hst = 0, tot = 0;
for(i = 0; i < n; i++) {
subtot = subtot + (s[i].quantity * s[i].unit_p);
if(s[i].taxable == 'y' || s[i].taxable == 'Y') {
hst = hst + (0.13 * s[i].quantity * s[i].unit_p);
}
}
tot = subtot + hst;
printf("\n%-12s%.2lf", "Subtotal", subtot);
printf("\n%-12s%.2lf", "HST (13%)", hst);
printf("\n%-12s%.2lf\n", "Total", tot);
}
In function enter() you are using the wrong index variable i to access the struct:
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[i].quantity, s[i].unit_p, s[i].taxable);
}
which should be
for(j = 0; j < i; j++) {
printf("%lf %lf %c\n", s[j].quantity, s[j].unit_p, s[j].taxable);
}
Second, in function total(), your variables for calculating the totals, should be of type double
int i;
double subtot = 0, hst = 0, tot = 0;
...