I have made a code which runs perfectly fine in a single file but when I try to split the code into two .c and one .h file the makefile shows an error of UNDEFINED REFERENCE TO THE STRUCTURE which is global data.
How can I split this code into the .c and .h file such that the error of undefined reference does not pop and code runs smoothly?
I just need the split .c and .h files,I can make the .mk file, I am a beginner in makefile.
Here the command line argument is the name of the file from which the code reads information-emplyoyeeinfo.txt.
The error while running the makefile(4 .c and 1 .h files) is in the screenshot below:
employeeinfo.txt file has these contents (user name, ID, password, casualleave, medical leave, earned leave)
Ramesh,QW120345,PO56,10,15,7
Rajesh,QW120905,IO56,10,15,7
Kajal,JI456987,IWQ9,10,15,7
Harleen,HJ782013,ZM12,10,15,7
Jim,BN784569,KL45,10,15,7`
Code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
//this code works on ZERO INDEXING
int linematched;//global variable which stores the variable
void main2();//this containsthe main part of the code workings,its pupose is explained below just before the function
void final_print();//prints the details of the user on quitting the wizard
void quit();//this is one function which handles the termination of code prompting the user to take another trail
void again();//this function handles the login if user wishes to take another leave
void table(char file_n[]);//populating the structure from data elements from the file by using specific delimiter
int login();//this function verifies the password with the one present in the file database
int deduction(int linematched,int days,int type_of_leave);//this performs another validation and deducts the days user desires for taking the leave
struct Empdetials
{
char name[25];
char id[9];//onr extra character to store /n
char password[5];
int casual;//casual,medical,earned leave as per the question
int medical;
int earned;
}emp[5];//declaring array of structures which will later be populated using table() function
void main(int argc,char *argv[])//command line arguments takes the name of the file to be read
{
char file_name[30];
strcpy(file_name,argv[1]);
printf("%s\n\n",file_name);
table(file_name);//calling the function to initiate the process of filling a structure with all the data from the files
printf("--------------------------------HELLO-------------------------------\n");
printf("----------------------WELCOME TO LEAVE MANEGMENT SYSTEM--------------\n");
main2();//the use of this is explained below
}
/*main function has a call to table() and invoking main() for re-login used to reset the structure and the deductions were lost,so I copied
everything of the main function into another function called main2() which is basically the amin function without he table() invoking so the
structure is not resetted after every call from again() and quit() during Re-login and structure keeps a track of the deductions that happened and
in this way I also removed the Welcome sentence to the same user,but he main reason is to avoid rewriting of the structure on every call
and losing the deduction data*/
void main2()
{
int casualm=10;//defining the maximum possible leaves here
int medicalm=15;
int earnedm=7;
int leave_days=0;//handles the number of leaves that a user will enter
int choice=0;//type of leave is handled by this variable 1 is casual,2 is emergency,3 is earned
int log=0;//CHECKS IF LOGIN WAS SUCCESFULL OR NOT
int res=0;//CHECKS IF DEDUCTION WAS SUCCESFULL OR NOT
//-------------------------------------------------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------------------------------------------------
log=login();//login is invoked and log stores the value which determines wheter the ogin was succesful or not
if(log==1)//if log=1,implies that the login was succesful and the user was found
{
printf("PLEASE SELECT HE TYPE OF LEAVE YOU WANT TO TAKE\n");
printf("1.CASUAL LEAVE\n");
printf("2.MEDICAL LEAVE\n");
printf("3.EARNED LEAVE\n");
scanf("%d",&choice);
printf("PLEASE ENTER THE NUMBER OF LEAVES YOU WANT TO APPLY FOR\n");
scanf("%d",&leave_days);
}
else
{
printf("SORRY THE LOGIN CREDENTIALS DON'T MATCH WITH ANY USER\n\n\n");//when the login fails this message is displayed
again();//gives user another chance to take give the input
}
//first validation of the input values,this ompare the input with the largest value of holidays available
int flag=1;//this controls wheter the variable entetred is within the maximum limit and that decuction() function can be called
if(choice==1)
{
if(leave_days>casualm)
{
printf("THE ENTERED NUMBER OF DAYS CROSSES THE MAXIMUM LIMIT \n");
again();
flag=0;
}
}
else if(choice==2)
{
if(leave_days>medicalm)
{
printf("THE ENTERED NUMBER OF DAYS CROSSES THE MAXIMUM LIMIT \n");
again();
flag=0;
}
}
else if(choice==3)
{
if(leave_days>earnedm)
{
printf("THE ENTERED NUMBER OF DAYS CROSSES THE MAXIMUM LIMIT \n");
again();
flag=0;
}
}
else
{
printf("sorry!! wrong input\n");
again();
flag=0;
}
if(flag)//if the validation is succcesful the value of the variable remains 1 and this loop is entered
{
res=deduction(linematched,leave_days,choice);//if res==1 then thern the validation was succesful and then the deduction is called and parameter is passed
if(res==1)//if deduction was succesful then the
{
printf("DEDUCTION WAS SUCCESFUL\n\n");
again();
//final_print();
}
}
}
//I am trying to convert the file to a structure and then use the structure to access the data and I'm also using files to store the information
extern void table(char file_n[])//this function is responsible for populating the structure by reading the file
{
printf("%s\n\n",file_n);
FILE *fp;//definig a file pointer
char ch;
char line[256];//definig 256 here,any arbitary number can be used
char *token;//token pointer that points to the elements of a line
int tokenposition=0;//token here means the particular text separated by comma
int lineposition=0;//line here is the entire line which has entire details of the an emmployee
fp=fopen(file_n,"r");//opening the file in read mode as we are only accessing information and not rewrting it
//-------------------------------------------------------------------------------------------------------------------------------------------------
while(fgets(line,256,fp) !=NULL) //accessing the lines one by one and trying to recognize the end of a line
{
tokenposition=0;//when we tokenize the line we need the count to keep a track of where we are int he string
//printf("%s \n",line);//used to check which line is not being read by the compiler
token = strtok(line,",");
//this seperates a line into token(entity) based on a delimiter,here the delimiter is a comma
//strtok-tring tokenization method
while(token != NULL)
{
switch(tokenposition)//acessing the required element through the tokenposition counter
{
case 0://NAME
strcpy(emp[lineposition].name,token);
break;
case 1://ID
strcpy(emp[lineposition].id,token);
break;
case 2://PASSWORD
strcpy(emp[lineposition].password,token);
break;
case 3://CASUAL LEAVE
emp[lineposition].casual=atoi(token);
break;
case 4://MEDICAL LEAVE
emp[lineposition].medical=atoi(token);
break;
case 5://EARNED LEAVE
emp[lineposition].earned=atoi(token);
break;
}
token =strtok(NULL,",");
tokenposition++;//to access the next token in the same line
}
lineposition++;//after all the tokens are put in a structure,wwe move to the next line and redo the entire process of reading a line
}
}
int login()
{
int i;//for the loop
char userid[9];//user ID int he majn function,this will be passed to the the login function
char userpassword[5];//user password in the main function
printf("ENTER YOUR 8 CHARACTER USER ID\n");
scanf("%s",userid);
printf("ENTER THE 4 CHARACTER PASSWORD\n");
scanf("%s",userpassword);
linematched=0;
for(i=0;i<5;i++)
{
if((strcmp(emp[i].id,userid)==0)&&(strcmp(emp[i].password,userpassword)==0))//checking if login credentils are corre3ct or wrong
{
linematched=i;
printf("WELCOME %s TO THE LEAVE MANEGMENT SYSTEM\n",emp[linematched].name);
return 1;//TO INDICATE THAT USER WAS FOUND AND LOGIN WAS SUCCESFUL
break;
}
}
}
int deduction(int linematched,int days,int type_of_leave)//here all inputs are validated for the second time after the validation in main function
{
switch(type_of_leave)
{
case 1://casual leave
{
if(days>emp[linematched].casual)
{
printf("SORRY YOU HAVE EXHAUSTED YOUR LEAVE QUOTA\n\n");
again();
return 0;
break;
}
else
{
emp[linematched].casual=emp[linematched].casual-days;
return 1;
break;
}
break;
}
case 2://medical leave
{
if(days>emp[linematched].medical)
{
printf("SORRY YOU HAVE EXHAUSTED YOUR LEAVE QUOTA\n\n");
again();
return 0;
break;
}
else
{
emp[linematched].medical=emp[linematched].medical-days;
return 1;
break;
}
break;
}
case 3://earned leave
{
if(days>emp[linematched].earned)
{
printf("SORRY YOU HAVE EXHAUSTED YOUR LEAVE QUOTA\n\n");
again();
return 0;
break;
}
else
{
emp[linematched].earned=emp[linematched].earned-days;
return 1;
break;
}
break;
};
};
}
void quit()
{
char ans[5];
printf("ARE YOU SURE YOU WANT TO QUIT THE WIZARD? Y OR N\n");
scanf("%s", ans);
if (tolower(ans[0]) == 'y')
{
final_print();
printf("\n\n");
printf("---THANK YOU FOR USING OUR PORTAL--\n");
}
else
{
main2();
}
}
void again()
{
char ans1[5];
printf("SEARCH AGAIN USING ID AND PASSWORD? Y OR N\n");
scanf("%s", ans1);
if (tolower(ans1[0]) == 'y')
{
main2();//FOR RE-LOGIN PROCESS
}
else
{
quit();
}
printf("\n\n\n\n\n\n");
}
void final_print()
{
printf("----------------FINAL STATEMENT OF LEAVE OF EACH EMPLOYEE------------------------\n\n");
int i;
for (i = 0; i < 5; i++)
{
printf("NAME : %s\n",emp[i].name);
printf("USER ID : %s\n",emp[i].id);
printf("CASUAL LEAVE LEFT : %d\n",emp[i].casual);
printf("MEDICAL LEAVE LEFT : %d\n",emp[i].medical);
printf("EARNED LEAVE LEFT : %d\n\n",emp[i].earned);
}
printf("---------THANK YOU FOR USING LEAVE MANEGMENT PORTAL-----\n");
}
With
struct Empdetials
{
char name[25];
char id[9];//onr extra character to store /n
char password[5];
int casual;//casual,medical,earned leave as per the question
int medical;
int earned;
}emp[5];
you do basically two things in one step: (1) define struct Empdetials
and (2) define a variable emp
; Note that you cannot define a global variable in a headerfile, at least if you intend to include this header file in different .c-files.
You will need to separate the definition of struct Empdetials
, the declaration of a global variable emp
and the definition of this global variable in exactly one translation unit (i.e. exactly one .c
-file). Note the extern
-keyword in emp.h
, which declares that emp
will be defined once elsewhere (i.e. in emp.c later):
emp.h:
struct Empdetials
{
char name[25];
char id[9];//onr extra character to store /n
char password[5];
int casual;//casual,medical,earned leave as per the question
int medical;
int earned;
};
extern struct Empdetials emp[5]; // declaration of emp
emp.c:
#include "emp.h"
struct Empdetials emp[5]; // definition of emp
int main() { ...
again_final.c:
#include "emp.h"
// Note: no struct Empdetials emp[5]; any more...
again() { ...
login.c:
#include "emp.h"
// Note: no struct Empdetials emp[5]; any more...
login() { ...