Click here to Skip to main content
15,891,033 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Write a complete C program that does the following:
1) Read the data stored in the file "rec.txt" into an array of records containing the student ids and the student names.
2) Sort the array of records following the students' names in alphabetical order and display the sorted names on the screen.
3) Prompt the user to search for the student id by the student's name.
4)You may use any sorting algorithm to sort the array of records, but you need to use hashing for searching.
Resolve any collision (if any).

The text file:
1171203258:HOSSAIN, MARUF
1181202660:KUHAN RAJ A/L TAMIL CHEL WAM
1181203465:PONG KAI SUN
1191102443:FAIZA OSAMA ABDALLA HASHIM
1201302289:LEE JIA WEI
1201302368:SHEIKH, AHNAF AZMAIN
1201100584:HI CHIA LING
1201101509:NG CHEA YEAT
1191103201:PHUAH CHEE HAOU
1201100879:MOSTAFA ARABY MADBOULY AHMED
1191103215:TONG JUN YANG
1191103119:ANG QIZHENG
1171302286:DARWIN KUMAR A/L MUNIAN
1181101192:HAIZUN NAJWA BINTI MOHD RIFIN
1201100926:NG XUE NIE
1191302417:ALMARHOON, ALI HUSSAIN A
1201100225:HEMAN RAO A/L SUBRAMANIAM
1181100823:LIM ZHEN BANG
1161202587:SOHEIL PRAKASAN SUPPAN
1201100603:AVINASH MURALI
1181101858:CHEAH KOK YEW
1191103071:GAN WEI TONG
1201100301:KEVIN THAM ZHENG YIT
1201100648:LIM CHER AIK
1201302222:SHIVAA RUTRAN A/L NAGATHEESAN
1201100779:TAN WEI XIANG
1191100919:WONG HONG WEI


What I have tried:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MDIR 27
#define MBUFF 2916
#define MHASH 521
#define MNAME 40



struct List{
    char name[40];
    int studID;
};

int readData(struct List dir[]);
int hashfunc(char *name);
void hash(struct List dir[], int ndir,
int hashtable[]);

int search(char *key,
struct List s[], int hashtable[]);

int main(){
	int ndir, result, hashtable[MHASH];
	int count;
	int i;
	int j;
    struct List s[27];
    char temp[27];
    char query[40];
    
	FILE *fptr;
	fptr = fopen("REC", "r+");
	if (fptr != NULL) {
    printf("File created successfully!\n");
  }
  else {
    printf("Failed to create the file.\n");
    // exit status for OS that an error occurred
    return -1;
  }
  
   for(count = 0; count < 27; count++){
       fscanf(fptr,"%d", &s[count].studID);
       fgets(s[count].name,40,fptr);
       
   }
        
        for(i=0;i<27;i++){
		for(j=i+1;j<27;j++){
			if(strcmp(s[i].name, s[j].name) > 0){
				strcpy(temp, s[i].name);
				strcpy(s[i].name, s[j].name);
				strcpy(s[j].name, temp);
		}
	}
}
	fclose(fptr);
	printf("Sorted Names\n");
	for(i=0;i<27;i++){
		printf("%s", s[i].name);
		}
		
		ndir=readData(s);
hash(s,ndir,hashtable);
puts("\nName to search>>");
fgets(query,MNAME-1,stdin);
query[strlen(query)-1]='\0';
result=search(query,s,hashtable);
if(result==-1)
printf("Not Found");
else
printf("%s's ID is %d\n",
s[result].name, s[result].studID);
	
		

		return 0;
}

//here is the problem I think
int readData(struct List dir[]){

FILE *fdir=fopen("REC","r");
char buff[MBUFF];
int i=0;
while(i<MDIR && fgets(buff,MBUFF-1,fdir)){
strcpy(dir[i].name,strtok(buff, ":"));
dir[i].studID=atol(strtok(buff,":"));    
i++;
}
return(i);
}

int hashfunc(char *name){
long sum=0;
int k=0;
while(name[k]){
sum+=name[k];
k++;
}
return( (int) (sum % MHASH) );
}

void hash(struct List dir[], int ndir,
int hashtable[]){
int k;
int index;
for(k=0;k<ndir;k++){
index = hashfunc(dir[k].name);
hashtable[index]=k;
}
}

int search(char *key, struct List dir[],
int hashtable[]){
int index=hashfunc(key);
int k=hashtable[index];
if(strcmp(key,dir[k].name)==0)
return(k);
else
return(-1);

}
Posted
Updated 12-Apr-22 10:16am
v2
Comments
jeron1 12-Apr-22 14:19pm    
Is there a specific question?
NG CHEA YEAT 12-Apr-22 14:21pm    
yes, how can I get the name from the file and strcpy it to dir[i].name
Rick York 12-Apr-22 21:00pm    
You have used the literal value 27 in many places. That is a very, very bad idea. You have made it a definition like the other constants and you should use it - MDIR.

1 solution

Start by indenting your code to make it readable - at the moment its not easy to see what is going on at all.
Then replace all the single character variables with descriptive names: s is meaningless as a variable name as it tells you nothing about what it might contain
if(strcmp(s[i].name, s[j].name) > 0){
Compared with
if(strcmp(students[i].name, students[j].name) > 0){

And calling your struct List is misleading as well - it isn't a list of anything, it's a Student's detail - so calling it a Student instead makes your code more self documenting.

Then think about what you are doing.
C
if(strcmp(s[i].name, s[j].name) > 0){
    strcpy(temp, s[i].name);
    strcpy(s[i].name, s[j].name);
    strcpy(s[j].name, temp);
What happens to the Id's when you swap the names over?
A better solution would be to make the Students collection an array of pointers to List objects, and swapping pointers instead of copying strings - it's a whole load more efficient, easier to read, and more obviously correct because you can't "separate" ID and names at any time (Hint: you will need malloc to allocate the space for each List object).

Quote:
But how can I only print the name on screen? If I not separate them?


If you have them in a struct then you have access to both of them via the struct members:
C
#include<stdio.h>

typedef struct 
    {
    int Count;
    float Price;
    } Item;
int main()
    {
    printf("Hello World");
    Item bike;
    bike.Count = 3;
    bike.Price = 123.45;
    Item car;
    car.Count = 1;
    car.Price = 43995.00;
    printf("We have %u bikes in stock, at £%0.2f\n", bike.Count, bike.Price);
    printf("We have %u cars in stock, at £%0.2f\n", car.Count, car.Price);
    
    return 0;
    }
 
Share this answer
 
v2
Comments
NG CHEA YEAT 12-Apr-22 23:12pm    
But how can I only print the name on screen? If I not separate them?
OriginalGriff 13-Apr-22 1:36am    
Answer updated

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900