Search code examples
cgccmakefilestructure

I am trying to split this code into two .c and one .h file, but the structure is not getting accesssed by the other .c file


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:

OUTPUT SCREENSHOT

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");
}

Solution

  • 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() { ...