How to match a varible in a struct array, then the position - c

first post here. Somewhat new to coding aswell.
Right now I'm at halt. What I need to do is get input from the user of an employee id then find it in a struct array variable, and keep asking until a correct one is entered.. all in a do-while loop. Then I need to print the salary of that employee and update it to something new.
I'm having a hard time trying to figure out how to search the struct array for that employee ID, then when that's done, saving what position the struct array in is so I can print THAT employees salary, then update it to something else.
Heres some code to show the struct array
#define SIZE 4
struct employee{
int id[SIZE] ;
int age[SIZE];
double salary[SIZE];
};
/* main program */
int main(void) {
struct employee emp[SIZE] = { 0 };
Here is some to show the code to what I've done
case 3: //Update Employee
printf("Update Employee Salary\n");
printf("======================\n");
int employid;
do{
printf("Enter Employee ID: ");
scanf("%d", &employid);
}while(employid != emp->id[SIZE]);
printf("The current salary is %lf", emp->salary[SIZE]);
break;
I know this is wrong. The While just looks at the current position, and the printf only prints the salary of the current arrays employee aswell.
Any help would be appreciated.
Bonus:
Notice when I'm assigning/working with my struct, I have to put "->" to actually tell my compiler that I'm pointing to that specific variable in the struct. Usually I put "." and have no idea why I need to put ->.. I just found the fix online.
Usually it would be "emp.id[SIZE];"
NOT "emp->id[SIZE];"
Anyone have any ideas?
Thanks all

Considering that your input to the structure is right, there are few things you can do.
The thing is you need to realize that you need a while/for loop to iterate over the employee array.
Second thing is, here you are not comparing it correctly. You are just comparing with the first element.
Now what you can do is
bool found = false;
int foundEmpId = -1;
do{
printf("Enter Employee ID: ");
scanf("%d", &employid);
for(size_t i = 0; i< SIZE; i++)
if( emp[i].id == employid ){
foundEmpId = employid;
found = true;
break;
}
}while(!found);
// do your work.
Now this is simply the O(n) searching.
Apart from that there is one thing you can see in my code. I am using emp[i].id. Here the structure I considered is
struct employee{
int id ;
int age;
double salary;
};
If you think of an employee these are the attributes you need to add over here. What you did was working with different groups of employees.
Here you will work like this
struct employee emps[SIZE];
...
...
// the attributes of employee will be inputted like this
// if( scanf("%d",&emps[i].id) == 1 ) { /* */ }
...
Why did you need emp->id[SIZE] here?
Dissecting the emp->id[SIZE] is equivalent to (*emp).id[SIZE] or more precisly emp[0].id[SIZE].
To summarize the problems/suggestion:-
P The portion of the code that you have shown it shows that you are not comparing with all the employees.
P You have created groups of employees. But you are not iterating or using all the groups. You just worked on first employee group.
S Instead of using the array of employee groups you should simply use array of employees. Or Even if you do use groups of enployess then just one group will suffice.

Related

Sort a list of members in ascending and descending order

I'm creating a simple database containing students with the following information: first name, last name, personalnumber, study type (permanent or part time student).
If user hits "showasc" the program asks whether to show students in ascending order by their first name or last name.
Managed to sort the members by name, but the problem is that only the names gets sorted while the rest of the information about the student doesn't, it stays in the order it was created. Bare in mind that I'm still very new to programming.
This is the part of the code that sorts the names:
else if(strcmp(command, "showasc") == 0)
{
char input[15];
printf("Show in ascendant order by first name or last name?\n ");
scanf("%s", input);
struct Student copyOfListOfStudents[20];
memcpy(&copyOfListOfStudents, &listOfStudents, sizeof(listOfStudents));
int i, j;
char s[100];
for(i=0;i<20;i++)
{
for(j=i+1;j<20;j++)
{
if(copyOfListOfStudents[i].valid && copyOfListOfStudents[j].valid)
{
if(strcmp(copyOfListOfStudents[i].firstName,copyOfListOfStudents[j].firstName) > 0)
{
strcpy(s,copyOfListOfStudents[i].firstName);
strcpy(copyOfListOfStudents[i].firstName,copyOfListOfStudents[j].firstName);
strcpy(copyOfListOfStudents[j].firstName,s);
}
}
else
break;
}
}
printStudents(copyOfListOfStudents);
So for example, if user adds the the following students:
Lol Ipop, 7802034567, Full time
Anna Banana, 9901024356, Part time
And then wants to show students sorted by first name, this is what happens:
Anna Ipop, 7802034567, Full time
Lol Banana, 9901024356, Part time
How do I fix this problem?
(I hope that the code I'm showing is sufficient!)
You have already identified the problem. In your sorting algorithm, the names get sorted, but the other values are not.
To fix the issue, you need to change this part to swap the whole student struct:
if(strcmp(copyOfListOfStudents[i].firstName,copyOfListOfStudents[j].firstName) > 0)
{
Student tmp;
memcpy(tmp, copyOfListOfStudents[i], sizeof(Student));
memcpy(copyOfListOfStudents[i], copyOfListOfStudents[j], sizeof(Student));
memcpy(copyOfListOfStudents[j], tmp, sizeof(Student));
}
Code is untested...

How to store the salaries & IDs of employees in multi-dimensional arrays using for loop and updating them through another function ( C )

So the question should be rather simple (not to me tho for some reason).
i need to give some employees some IDs and give those IDs their own salary.and allow said employee to be stored IF their salary is above a set point. so far I've been able to (brokenly) implement this (i apologize if it seems like i'm talking a lot it's just that i can't seem to explain my problem that easily)
OLD code
#include <stdio.h>
void Employee_Data(int number_of_employees,
float Data[3][number_of_employees],float salary){
int i ;
for(i = 0 ;i < number_of_employees;i++){
printf("Employee %d\n\n",i+1);
printf("enter the salary of employee %d:",i+1);
scanf("%f",&salary);
printf("\n");
}
}
int main() {
printf("Enter the number of employees: ");
int number_of_employees = 0;
scanf("%d",&number_of_employees);
float Data[3][number_of_employees];
float salary;
Employee_Data(number_of_employees,Data,salary);
return 0;
}
what i need is a way to set an ID that the user inputs in the above function
and another function to print out the employees and their IDs if they have a salary over a number that the user also inputs and lastly (most likely the hardest) a function to give a raise to employees which are picked by their IDs and said raise is to be percentage wise of their current salary
Once again i apologize if it's too long and too confusing i have a bit of problems trying to get my point to be understood hopefully it is though.
NEW CODE
#include <stdio.h>
float employee_ID(int number_of_employees,int ID[number_of_employees]){
for (int i = 0; i<1;i++){
scanf("%d",&ID[i]);
}
return *ID;}
float Salary_of_employees(int number_of_employees,int salary[number_of_employees]){
for(int i = 0; i<1;i++){
scanf("%d",&salary[i]);
}
return *salary;}
void printing(int number_of_employees,int *salary[number_of_employees], int *ID[number_of_employees]){
for(int k = 0; k<number_of_employees;k++){
printf("Employee %d 's ID is %d and their salary is %d\n",k+1,*ID[number_of_employees],*salary[number_of_employees]);
}
}
int main() {
int number_of_employees;
int ID[number_of_employees];
int salary[number_of_employees];
printf("Please input the number of employees you need : ");
number_of_employees = 0;
scanf("%d",&number_of_employees);
int i;
for (int i = 0; i<number_of_employees;i++){
printf("please input the ID for employee %d\n",i+1);
employee_ID(number_of_employees,&ID[number_of_employees]);
printf("please input the salary of employee %d\n",i+1);
Salary_of_employees(number_of_employees,&salary[number_of_employees]);
}
printf("if you want to see the IDs and the salaries of the employees please write 1\n if you want to ");
int choice;
scanf("%d",&choice);
if (choice == 1){
printing(number_of_employees,salary,ID);
}
return 0;
}
Currently my problem with this is that i've got 2 warnings at the calling of the printing function (salary and ID are the warnings for some reason can't get them to be fixed)
And my other problem is that the storing only takes the last inputted number given by the user. for example if i give an ID of 321 and a salary of 543 the output of the printing function would be employee number(thank god the counter works)'s ID is 543 and the salary is 543 (TO EACH EMPLOYEE)
Edit1: So basically when i run the code it asks me to input the number of employees. (so far so good) when i insert the number it starts with employee number 1 and asks me to input the salary. upon inputting the salary it just gives me 2 new lines and stops basically what i need is that each time it'd -instead of saying employee 1- it'd first ask me to set the employee ID first and then say "Employee -insert ID-'s salary: "and then asks me to insert the salary of said employee. and then the same for each employee that i set . + the other functions
Edit2: Updated the code by removing the for loop that seemingly crashed the program and updated the title + (i think) explained the stuff that i need better
Edit 3: after messing around and legit deciding to restart the code i began experiencing some uhhh trouble with the storing for some reason. and decided to add the new code and keep the old one as well
You have an inner and outer loop over the number of employees. Not only will this behave strangely, but Its likely that if you enter more than 3 employees the code will crash. The J loop doesn't look right.

How to fix 'structuredfunctions not calling'

So I wrote this code as a part of my assignment like so, we are still learning C language and I am just unable to correct this one. We have to make a code on writing a function to print the names of all the students that joined in a particular year.
It runs the code till switch case, but doesn't work further.
#include<stdio.h>
struct stdnt
{
char stName[100];
char stRNo[100];
char Dept[50];
char crse[50];
int YoJ[4];
}s[2];
void stYr(p)
{
printf("Student Name = %s\t",s[p].stName);
}
void stRNm(q)// q RNm
{
int i;
for(i=0;i<=1;i++)
{if(q == s[i].stRNo)
{
printf("Student Name = %s\t",s[i].stName);
printf("Student Year of Joining = %d\t",s[i].YoJ);
printf("Student Department = %s\t",s[i].Dept);
printf("Student Course = %s\n",s[i].crse);
}
}
}
int main()
{
int i;
int year;
int RNm;
int ch;
printf("Please Enter the details of 2 Students.\n");
for(i=0;i<=1;i++)
{
printf("Enter Name of Student %d:\n",i+1);
scanf("%s",s[i].stName);
printf("Enter Department of Student %d:\n",i+1);
scanf("%s",s[i].Dept);
printf("Enter Year of Joining of Student %d:\n",i+1);
scanf("%d",s[i].YoJ);
printf("Enter Roll Number of Student %d:\n",i+1);
scanf("%s",s[i].stRNo);
printf("Enter Course of Student %d:\n",i+1);
scanf("%s",s[i].crse);
}
printf("Enter 1 to Print the List of Student using Year.\nEnter 2 to Search the details of student using Roll no.\n");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter the Year:\n");
scanf("%d",&year);
for(i=0;i<=1;i++)
{
if(year == s[i].YoJ)
{
stYr(i);
}
}
break;
case 2:
printf("Enter the roll number you want to search:\n");
scanf("%d",&RNm);
stRNm(RNm);
break;
}
return 0;
}
the question is
Create a structure to specify data on student given below : Roll number, Name, Department, Course, Year of Joining.
Assume that there are not more than 450 students (i am trying to code for 2 firstly will make it for 450 once it works)
also `
write a function to print name of all the students who joined in a particular year.
write another function to print the data of a student whose roll number is entered
make switch cases .
OUTPUT i am getting :
Please enter the details of 2 students .
Enter Name of Student 1:
katyal
Enter department :
Mech
Enter Year of joining:
2019
Enter roll number:
1
Enter Course :
C
Enter Name of Student 2:
Pranay
Enter department :
Mech
Enter Year of joining:
2019
Enter roll number:
2
Enter Course :
C
Enter 1 to Print the List of student using year
Enter 2 to print details of student using roll number
1
Enter the year:
2019
Process returned 0<0x0> execution time 30.600s
Press any key to continue.
Expected Output :
after the Year is entered after switch case, i expect the Function `stYr to get called and print the list of student with that Year as their Year of Joining
similarly if roll number is entered i want the details of that student printed.
As you're learning C code I think that you should start off by taking on board a few standard working practices.
It's very evident that either your teacher hasn't really coded in a working environment or they are expecting you to spot the mistakes.
I realise that there may be issues or restrictions due to your compiler, but here are some pointers that will help in future.
Here are some pointers based on your code.
Always initialise variables before use. If a variable can be null and that is not a valid value, check for null before use e.g. `char[] or pointer types.
Use typedef for structure declarations, this will allow the compiler to determine incorrect use through type checking during compilation.
Use long, meaningful variable and function names as an aid to understand the code.
Indentation with brackets e.g. { }, to make code easy to understand.
Refrain from using literal values in code as this can lead to introduction of bugs at a later stage if a value is not changed in all cases through the code.
Function parameters should be definitive in type - this makes code portable between compilers, environments and easier to understand.
In for loops try to only use less than < and greater than > comparisons.
In 'if' statements try to place non-assignable values on the left side as this will raise a compiler warning if you type = instead of ==.
Try and make functions re-entrant i.e. not reliant on global variables to determine their behaviour if possible, void func(void) should ring alarm bells.
Be careful when using signed values such as int use unsigned int in preference UNLESS you know that a variable will be assigned values of less than 0.
Declaring function parameters as const and then using local function variables as copies (if you wish to change their value) will make code easier to debug.
Switch statements should always include a default: to handle undetermined values.
struct stdnt /* REVIEW COMMENT: use typedef */
{
char stName[100]; /* REVIEW COMMENT: non-literal value for 100 */
char stRNo[100]; /* REVIEW COMMENT: Based upon later usage should this be unsigned int rather than char[] type */
char Dept[50];
char crse[50];
int YoJ[4]; /* REVIEW COMMENT: this is an array of int. Either use int or char[4] */
}s[2]; /* REVIEW COMMENT: separate out declaration for clarity and use a meaningful name */
I'd suggest that you change it to this
#define TEXT_LENGTH_LONG 100
#define TEXT_LENGTH_SHORT 50
#define NUMBER_OF_STUDENTS 2
typedef struct
{
char Name[NAME_LENGTH];
unsigned int RollNumber;
char Department[TEXT_LENGTH_SHORT];
char Course[TEXT_LENGTH_SHORT];
unsigned int YearOfJoining;
}student_t;
student_t students[NUMBER_OF_STUDENTS];
This function code has some issues.
void stRNm(q)/* REVIEW COMMENT: non-definitive declaration can cause confusion. Unclear function name and parameter */
{
int i;
for(i=0;i<=1;i++) /* REVIEW COMMENT: use of literal value makes maintenance more difficult and can introduce bugs if the array size is changed but this is missed */
{if(q == s[i].stRNo) /* REVIEW COMMENT: possible type mismatch in comparison - comparing int or char[] ?*/
{
printf("Student Name = %s\t",s[i].stName);
printf("Student Year of Joining = %d\t",s[i].YoJ);
printf("Student Department = %s\t",s[i].Dept);
printf("Student Course = %s\n",s[i].crse);
}
}
}
becomes
void PrintStudentInfo(const unsigned int rollNumOfStudent)/* Declaring rollNumOfStudent as const will give it compiler protection against being assigned to */
{
int i;
for(i=0;i<NUMBER_OF_STUDENTS;i++)
{
if(rollNumOfStudent == students[i].RollNumber)
{
printf("Student Name = %s\t",students[i].Name);
printf("Student Year of Joining = %d\t",students[i].YearOfJoining);
printf("Student Department = %s\t",students[i].Department);
printf("Student Course = %s\n",students[i].Course);
}
}
}
Okay this is just a start.
There are issues in your main function relating to what I've mentioned already that are causing the odd behaviour.
C is a language that is so loosely defined that it is very easy to introduce bugs due to shortcuts taken in coding.
Be pedantic.
Don't let the compiler make the decisions.
Be sure that the data types of variables are what you want rather than what the compiler determines.
Edit
Taking into account my comments about data types.
This line if(year == s[i].YoJ) is performing the following if(int == int[4])

( C ) Cannot find reason for Core Dump Error with Dynamic Allocating Structs

Disclaimer: This is my first question on StackOverflow and I'm a novice programmer, so my apologies ahead of time if you are appalled by my code or if I don't post my question appropriately.
Anyways, I'm working on a gradebook with dynamically allocated structures. I've divided the gradebook into three structues, a student structure (student name, student id), a course structure (course name, course id), and an enroll structure(student id, course id, grade).
Problem: I'm able to input as many grade as I need without errors for the first student. When I try to input a grade for the second student my program core dumps. I've checked all the variables involved to see if they are passed to my function appropriately and they are. The following is my Enroll structure and my add grade function.
typedef struct {
int Student_ID;
int Course_ID;
int *Grade;
int GradeCount;
} Enroll_Database;
Function...
void addGrade(Enroll_Database *Enroll)
{
int i = 0, j = 0, b, Course_Num, Student_Num, Grade;
printf("Enter Course Number: ");
scanf("%d", &Course_Num);
printf("Enter Student ID: ");
scanf("%d", &Student_Num);
/* For loop that traverses through the Enroll array until until it encounters
nothing in the Course ID */
for(i = 0; Enroll[i].Course_ID != 0; i++)
{
/* if the Student Number and the Course Number are equal to their
appropriate Enroll element, then ask user to input Grade */
if(Enroll[i].Student_ID == Student_Num && Enroll[i].Course_ID == Course_Num)
{
printf("Enter Grade: ");
scanf("%d", &Grade);
if(Enroll[i].GradeCount == 0)
{
Enroll->Grade = (int *) malloc(sizeof(int));
Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps
Enroll[i].GradeCount++;
}
else
{
Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int));
Enroll[i].Grade[Enroll[i].GradeCount] = Grade; //core dumps
Enroll[i].GradeCount++;
}
}
}
}
I've ran multiple checks and the core dump occurs after I malloc/realloc and assign user input to the grade value in the enroll structure.
I'd greatly appreciate any help, and I'm sorry again if my code is unreadable or I formatted wrong.
Thanks!
This only allocates space for one element,. and also it reallocates the wrong pointer:
Enroll->Grade = (int *) realloc(Enroll->Grade, sizeof(int));
It could be fixed like this:
Enroll[i].Grade = realloc(Enroll[i].Grade, sizeof(int) * (Enroll[i].GradeCount + 1));
Remembering that X->Y, (*X).Y, and X[0].Y all mean the same thing: your original version actually reallocated Enroll[0].Grade, instead of Enroll[i].Grade.
(The rest of this answer is some possible style improvement suggestions:)
To avoid this sort of error, I'd personally write just after the scanf:
Enroll_Database *found = &Enroll[i];
and then use found-> everywhere instead of Enroll[i]. Alternatively I'd consider having a separate function to actually add the grade (which is called once the database entry has been found).
Now, if you initialize Enroll[i].Grade to NULL when setting up the database, you actually wouldn't need this if...else statement. Since the behaviour of realloc(NULL, X) is the same as malloc(X), the same code would handle both situations.
Note that in C you should not cast the value returned by malloc and friends.
Another thing to bear in mind is that the style X = realloc(X, ... does not allow you to recover from allocation failure. To write robust code you need to take some sensible action when a malloc-family function returns NULL; this could be as simple as printing a message and calling exit.

input number in structs - check it already exists in file

I'm trying to write a data validation function, where the ID number has to be a unique number in an array of structs. Every time I try to save a valid ID number, the program is crashing - why is this happening?
this is the struct, and the declaration of an array of structs:
struct customer { // set up customer template //
char name [MAXNAM];
char surname [MAXNAM];
int idnum [MAX_ID];
};
struct customer data_cus[MAXCUS];
this is within the main program:
printf ("Please Enter ID Card, [NOTE! Only numbers are allowed!]\n");
int checkID;
while ((scanf ("%d",&checkID) == 0 || customerID(checkID, count)==1))
{
printf ("This ID is already taken! Please enter unique ID!\n");
while (getchar()!='\n')
{
continue;
}
*data_cus[count].idnum = checkID;
}
Here is the function used to check id the ID already exists in file:
int customerID (int cCheck, int count)
{
FILE * pcustomer;
int size = sizeof (struct customer);
struct customer temp;
rewind (pcustomer);
while (fread (&temp,size,count,pcustomer)==1)
{
if (*temp.idnum == cCheck)
{
return 1;
}
}
return 0;
}
Thank you for your help!
idnum is an array of integers. Is that really what you want, not just a simple integer?
I'm pretty sure that if you remove [MAX_ID] from your struct, things will work much better.
However, I reserve the right to alter the motivation as to why it's crashing once we see the code that is after the ID check code.
scanf returns the number of successfully matched items, I think you mean:
while (scanf ("%d",&checkID) == 1 && customerID(checkID, count)==1).
You should make sure count doesn't exceed MAXCUS only increment when you successfully read a unique ID, and you don't need an array of integer for idnum since each record has only one.
Also the function customerID is obviously wrong, here you read more than one customer structure and write to temp which is a single customer structure, this is most likely why it crashes:
while (fread (&temp,size,count,pcustomer)==1)
It's much easier if you keep track of IDs in an array instead of reading from file every time you want to check if a new ID is unique.

Resources