In my problem, I need to read lines from a txt file.
Each line contains student_id, name, birthdate, gender, department, and grade(class).
e.g ( 155898933;Nuh Kaplan;26/01/1998;M;ME;2 )
Then I need to store them in a Linked List.
I declared my structure as follows:
struct Node{
int id;
char name[100];
int date; //YYYYMMDD (String date will be converted to integer. I created dateStrInt function for this conversion.)
char gender[2];
char departmentCode[6];
int classGrade;
struct Node *next;
};
Then I read lines and store in an character array with this part of code:
if (fptr != NULL) {
while (fgets (buff, 100, fptr)) {
char* split = strtok(buff, ";");
while( split != NULL ) {
strcpy(arr[i][j], split);
j++;
split = strtok(NULL, ";");
}
i++;
j = 0;
}
}
After I stored lines into character array, I need to store them in a linked list. I tried to do it as follows:
for(int i = 0; i < len; i++) {
p = (struct Node*) malloc(sizeof(struct Node));
j = 0;
p->id = (int)arr[i][j];
strcpy(p->name, arr[i][j+1]);
p->date = dateStrInt(arr[i][j+2]);
strcpy(p->gender,arr[i][j+3]);
strcpy(p->departmentCode, arr[i][j+4]);
p->classGrade = (int)arr[i][j+5];
j = 0;
if(list == NULL){
list = p;
p -> next = NULL;
last = p;
}
else {
last -> next = p;
p -> next = NULL;
last = p;
}
}
However when I run my code, I get garbage values for student id and classGrade.
Can you help me to solve this problem?
My hole code:
#include <stdio.h>
#include<string.h>
#include <stdlib.h>
#include <ctype.h>
struct Node {
int id;
char name[100];
int date; //YYYYMMDD
char gender[2];
char departmentCode[6];
int classGrade;
struct Node *next;
};
int dateStrInt(char str[]) {
int d, m, y;
sscanf(str, "%d/%d/%d", &d, &m, &y);
return (y * 10000 + m * 100 + d);
}
int countLines(char* filename) {
int count = 0;
FILE *fptr;
fptr = fopen(filename, "r");
if(fptr == NULL){
printf("File does not exist.");
exit(1);
}
else {
for(char ch = getc(fptr); ch != EOF; ch = getc(fptr)) {
if(ch == '\n'){
count++;
}
}
}
return count + 1;
}
struct Node* createList(struct Node* list, int len, char filename[]){
struct Node* last;
struct Node* p;
char buff[100];
char arr[len][6][100];
int i = 0, j = 0;
FILE* fptr = fopen(filename,"r");
if (fptr != NULL) {
while (fgets (buff, 100, fptr)) {
char* split = strtok(buff, ";");
while( split != NULL ) {
strcpy(arr[i][j], split);
j++;
split = strtok(NULL, ";");
}
i++;
j = 0;
}
}
int o = 0;
for(int k = 0; k < len; k++){
printf("\nID = %s", arr[k][o]);
printf("\nName = %s", arr[k][o+1]);
printf("\nBirth Date = %s", arr[k][o+2]);
printf("\nGender = %s", arr[k][o+3]);
printf("\nDepartment = %s", arr[k][o+4]);
printf("\nGrade = %s", arr[k][o+5]);
o = 0;
}
for(int i = 0; i < len; i++){
p = (struct Node*) malloc(sizeof(struct Node));
j = 0;
p->id = (int)arr[i][j];
strcpy(p->name, arr[i][j+1]);
p->date = dateStrInt(arr[i][j+2]);
strcpy(p->gender,arr[i][j+3]);
strcpy(p->departmentCode, arr[i][j+4]);
p->classGrade = (int)arr[i][j+5];
j = 0;
if(list == NULL){
list = p;
p -> next = NULL;
last = p;
}
else {
last -> next = p;
p -> next = NULL;
last = p;
}
}
return list;
}
void printList(struct Node *list, int len){
struct Node *p;
p = list;
int cnt = 0;
printf("\nThe list = ");
while(p != NULL) {
if(cnt != len - 1) {
printf("\n{%d, %s, %d, %s, %s, %d} ---->",p->id, p->name, p->date,
p->gender, p->departmentCode, p->classGrade);
cnt++;
}
else
printf("\n{%d, %s, %d, %s, %s, %d} ",p->id, p->name, p->date,
p->gender, p->departmentCode, p->classGrade);
p = p->next;
}
}
int main(void) {
struct Node *head = NULL;
char filename[10];
printf("Enter file name: ");
scanf("%s", filename);
int len = countLines(filename);
struct Node* list = createList(head, len, filename);
printList(list, len);
}
test.txt file :
149875280;Burcu Aksu;04/04/1994;F;CS;3
180201201;Mustafa Kursat Yavuz Tur;12/06/1996;M;CS;3
Output:
Enter file name: test.txt
ID = 149875280
Name = Burcu Aksu
Birth Date = 04/04/1994
Gender = F
Department = CS
Grade = 3
ID = 180201201
Name = Mustafa Kursat Yavuz Tur
Birth Date = 12/06/1996
Gender = M
Department = CS
Grade = 3
The list =
{-1883589280, Burcu Aksu, 19940404, F, CS, -1883588780} ---->
{-1883588680, Mustafa Kursat Yavuz Tur, 19960612, M, CS, -1883588180}
Why are you declaring char array, instead you should be creating array of Node type. Just typecasting the string value to int will not convert the 2 integer fields correctly. Use the conversion function like atoi().
Change this line,
p->id = (int)arr[i][j];
to
p->id = atoi(arr[i][j]);
Related
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>
#define SIZE 1024
typedef struct rational
{
int numerator;
int denominator;
struct rational *next;
}rational;
double add_rationals(rational*);
void multiply_rationals();
void subtract_rationals();
void divide_rationals();
void read_data(FILE*, int[], int*);
void display_values(rational*);
rational * createList(int []);
int main()
{
system("cls");
FILE* ifp;
ifp = fopen("file.txt", "r");
int data[SIZE] ={0};
int sz = SIZE;
read_data(ifp, data, &sz);
printf("\nRead Integer Count:%d\n", sz);
rational* HEAD = createList(data);
display_values(HEAD);
/*
want to start after the 1st number because 1st number is size of arr
data[0] is the 1st number we just read from the text
*/
//display_values(HEAD, data[0]); // passing data[0] as size cuz the 1st number is size
}
// double add_rationals(rational* r)
// {
// rational* c;
// c = r;
// static double x = 0 , y = 0, sum;
// x = r->numerator;
// y = r->denominator;
// while(c->next != NULL)
// {
// sum = x/y + add_rationals(r->next);
// }
// return sum;
// }
rational * createList(int data[])
{
rational *head = NULL;
rational *temp = NULL;
rational *p = NULL;
rational *r = NULL;
int count = 0;
for (int i = 1; i < 5; i++)
{
temp = (rational*)malloc(sizeof(double));
temp->numerator = data[i];
temp->denominator = data[++i];
temp->next = NULL;
if(head == NULL) // Checking if the List has started yet
{
count++;
head = temp;
printf("\nHEAD NUMERATOR: %d, HEAD DENOMINATOR: %d\n\n", head->numerator, head->denominator);
}
else
{
p = head;
while (p->next != NULL)
{
count++;
p = p->next;
}
p->next = temp;
}
}
}
void display_values(rational* HEAD)
{
rational* o = NULL;
o = HEAD;
while(o->next != NULL)
{
printf("\n\nNUM: %d, DEN: %d", o->numerator, o->denominator);
o = o->next;
}
}
void read_data(FILE* fptr, int d[], int*size)
{
*size = 0;
while ((fscanf(fptr, "%d", &d[*size])) == 1)
(*size)++;
}
PROBLEMS>>>
I am unable to display all the elements from the linked list in the function void display_values() function
The pre-requisites are like this .. take the 1st number from a text file and create an array of that size...
Let me show you with example:
2 5 2 6 7 being the integers in the text file
I want to read the 2nd and 4th items to a struct as numerators and the 3rd and 5th as denominators
I want 5/2 and 6/7 as rationals and do all these operations with them
Like Add, Sub, Mul , Div...etc
You are making it much too complex.
You should:
read a single integer from the input file
allocate an array of that number of rational struct
loop that number of times reading one struct and making it point to the next in the array
make next=NULL for the last element of the array
That way, you use one single malloc, and avoid the data integer array.
Possible code:
...
rational* read_data(FILE*, int*);
...
rational* HEAD = read_data(ifp, &sz);
printf("\nRead Integer Count:%d\n", sz);
display_values(HEAD);
...
rational* read_data(FILE* fptr, int* size)
{
*size = 0;
if (1 != fscanf(fptr, "%d", size)) return NULL;
rational* ls = malloc(*size * sizeof(rational)); // never cast return value of malloc!
for (int i = 0; i < *size; i++) {
if (2 != fscanf(fptr, "%d%d", &ls[i].numerator, &ls[i].denominator)) {
free(ls);
return NULL;
}
ls[i].next = ls + i + 1; // by definition same as &(ls[i+1])
}
ls[*size - 1].next = NULL;
return ls;
}
But you should add some error processing for fopen returning NULL or read_data returning NULL (file read error)...
there are multiple problems in your code, I corrected them below in comments:
rational* createList(int data[])
{
rational *head = NULL;
rational *temp = NULL;
rational *p = NULL;
rational *r = NULL; // this variable is not used
int count = 0; // I didn't see the purpose of this variable
for (int i = 1; i < 5; i++) // the 5 is a magic number,
{ //if the input file changes, the code will not run as intended
temp = (rational*)malloc(sizeof(double)); // space should be allocated for rational type not double type
temp->numerator = data[i];
temp->denominator = data[++i];
temp->next = NULL;
if(head == NULL)
{
count++;
head = temp;
printf("\nHEAD NUMERATOR: %d, HEAD DENOMINATOR: %d\n\n", head->numerator, head->denominator);
}
else
{
p = head;
while (p->next != NULL)
{
count++;
p = p->next;
}
p->next = temp;
}
}
// the return value for this function is missing.
}
void display_values(rational* HEAD)
{
rational* o = NULL;
o = HEAD;
while(o->next != NULL) // this condition will miss the last node of the linked list
{
printf("\n\nNUM: %d, DEN: %d", o->numerator, o->denominator);
o = o->next;
}
}
I'm new to the C language, and I'm trying to make a calendar using SDL2, but for some reason my code just skips storing the first data. When I try to return with the "head" of my linked list (which stores structures), some of the data is saved, but some is not. I have a function called linecutter. It should work fine according to my tests. The structure of the file is something like
for some reason the comment part returns correctly. If I printf the location data, it returns correctly, but otherwise it doesn't work as intended.
An examle of a file used:
Prog spec;2020/10/05;2020/11/01;00/00;23/59;Infoc;shouldnt forget it and leave to the last min
something;2020/10/05;2020/11/01;00/00;23/59;location;just a comment
asd asd;2020/2/02;2020/9/01;00/00;23/59;Infoc;lkasjd laksdj
This code should print the event names twice. Once when reading the file, once when checking in the main. But it only prints when reading.
#include <stdio.h>
#include <stdlib.h>
typedef struct Date{
int y;
int m;
int d;
} Date;
typedef struct Time{
int h;
int m;
} Time;
typedef struct Event{
char* name;
Date startdate;
Date enddate;
Time starttime;
Time endtime;
char* location;
char* comment;
} Event;
typedef struct Lista{
Event event;
struct Lista * next;
} Lista;
Date datecreate(char*todate)
{
Date *tmp = (Date *)malloc(sizeof(Date)*1);
int len = strlen(todate);
char date[len];
strcpy(date,todate);
char y[5];
char m[5];
char d[4];
int i =0;
for(; i<4; i++)
y[i] = date[i];
i++;
for(int var = 0; i<7; var++, i++)
{
m[var] = date[i];
}
i++;
for(int var = 0; i<10; var++, i++)
{
d[var] = date[i];
}
tmp->d = atoi(d);
tmp->m = atoi(m);
tmp->y = atoi(y);
return *tmp;
}
Time timecreator(char*totime)
{
Time tmp;
char h[3];
char m[3];
for(int i = 0; i<2; i++)
h[i] = totime[i];
for(int i = 4; i<6; i++)
m[i-4] = totime[i];
h[3] = '\0';
m[3] = '\0';
tmp.h = atoi(h);
tmp.m = atoi(m);
return tmp;
}
Event linecutter(char* line)
{
int i = -1;
int loc = 0;
char name[256], startdate[12],enddate[12],starttime[7],endtime[7],location[256],comment[512];
do{
i++;
name[i] = line[loc];
loc++;
}
while(name[i] !=';');
name[i] = '\0';
i=-1;
do{
i++;
startdate[i] = line[loc];
loc++;
}
while(startdate[i] !=';');
startdate[i] = '\0';
i=-1;
do{
i++;
enddate[i] = line[loc];
loc++;
}
while(enddate[i] !=';');
enddate[i] = '\0';
i=-1;
do{
i++;
starttime[i] = line[loc];
loc++;
}
while(starttime[i] !=';');
starttime[i] = '\0';
i=-1;
do{
i++;
endtime[i] = line[loc];
loc++;
}
while(endtime[i] !=';');
endtime[i] = '\0';
i=-1;
do{
i++;
location[i] = line[loc];
loc++;
}
while(location[i] !=';');
location[i] = '\0';
i=-1;
do{
i++;
comment[i] = line[loc];
loc++;
}
while(comment[i] !='\0');
comment[i] = '\0';
Event tmp;
tmp.name = name;
tmp.location = location;
tmp.comment = comment;
tmp.starttime = timecreator(starttime);
tmp.startdate = datecreate(startdate);
tmp.enddate = datecreate(enddate);
tmp.endtime = timecreator(endtime);
return tmp;
}
Lista * read(void)
{
FILE *fp;
char line[5000];
fp = fopen("esemenyek.txt" , "rw+");
if(fp == NULL) {
perror("error opening");
return NULL;
}
char buf[3];
fscanf(fp, "%3c", buf);
if (memcmp(buf, "\xEF\xBB\xBF", 3) != 0) //this is just for the encoding stuff
fseek(fp, 0, SEEK_SET);
/* ... handling the file ... */
Lista * head= NULL;
Lista * current = NULL;
while(fgets(line, sizeof(line), fp)!=NULL){
Lista *node = (Lista*)malloc(sizeof(Lista));
if(node == NULL)
{
perror("error");
return NULL;
}
node->event = linecutter(line);
node->next =NULL;
if(head== NULL){
current = head = node;
} else {
current = current->next= node;
}
for(int i = 0; i<500; i++)
line[i] ='\0';
printf("%s\n", current->event.name);
}
fclose(fp);
return head;
}
int main(void){
Lista * lst = read();
Lista *move;
for (move= lst; move!= NULL; move= move->next)
printf("%s\n", move->event.name);
return 0;
}
What am I doing wrong, or why is this not working? If someone could help me, I'd really appreciate it. I found another post here, it helped me to get here, but I don't know how to proceed from here.
I have made a queue of nodes to store the data.
And the data should be implemented through file I/O.
In .txt file:
"Name1"
"Birthday1 (month date)"
"Genre1"
"Name2"
"Birthday2 (month date)"
"Genre2"
(above form is repeated)
Whenever I try to run through the code, it shows some strange characters for Name, Genre, and Birthday.
Also, same lines are repeated for 14 times.
I guess the problem has to do with data_in function.
What is the problem, and how can I fix it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable:4996)
typedef struct node {
char *name, *genre;
int month, date;
struct Node *next;
}Node;
typedef struct Queue {
Node *front;
Node *rear;
int count;
}Queue;
void queue_init(Queue *queue) {
//Initializing needed in order to use the queue
queue->front = queue->rear = NULL;
queue->count = 0;
}
int isEmpty(Queue *queue) {
//Check whehter the queue is empty or not
return (queue->count == 0);
}
void display_node(Node *node) {
printf("\nName: %s", node->name);
printf("\nFavorite Genre: %s", node->genre);
printf("\nBirthday: %d / %d", node->month, node->date);
printf("\n");
}
void data_in(Queue *queue) {
Node *now = (Node *)malloc(sizeof(Node));
FILE *f;
f = fopen("C:\\Users\\brain\\Desktop\\School\\2-2 GWU\\Data Structures and Algorithm\\LAB\\Lab Assignment\\Lab Assignment 3.txt", "r");
for(int i = 0; i < 14; i++) {
char n[100], g[100];
fscanf(f, "%s", &n);
fscanf(f, "%d %d", &now->month, &now->date);
fscanf(f, "%s", &g);
fgets(f);
now->name = (char *)malloc(sizeof(char)*strlen(n));
now->genre = (char *)malloc(sizeof(char)*strlen(g));
now->name = n;
now->genre = g;
if (isEmpty(queue))
queue->front = now;
else
queue->rear->next = now;
queue->rear = now;
queue->count++;
}
fclose(f);
}
void search(Queue *queue) {
Node *now = queue->front;
char c[100], check[100];
int ch, cnt = 0;
printf("Which section do you want to search? (Genre or Month): ");
scanf("%s", &c);
if (strcmp(c, "Genre") == 0) {
printf("Type the genre: ");
scanf("%s", &check);
for (int i = 0; i < queue->count; i++) {
if (now != NULL) {
if (strcmp(now->genre, check)) {
display_node(now);
now = now->next;
cnt = 1;
}
}
}
if (cnt == 0) printf("\n.....No results found...");
}
else if (strcmp(c, "Month") == 0) {
printf("Type month as an integer: ");
scanf("%d", &ch);
for (int j = 0; j < queue->count; j++) {
if (now != NULL) {
if (now->month == ch) {
display_node(now);
now = now->next;
cnt = 1;
}
}
}
if (cnt == 0) printf("\n.....No results found...");
}
}
int main(void) {
int check = 1;
Queue DSA;
queue_init(&DSA);
data_in(&DSA);
while (check == 1) {
search(&DSA);
printf("\nDo you want to continue searching? (1 or 0): ");
scanf("%d", &check);
printf("\n============================================================\n");
}
system("pause");
return 0;
}```
These two lines are definitely NOT what you want:
fscanf(f, "%s", &n);
fscanf(f, "%s", &g);
they should read:
fscanf(f, "%s", n);
fscanf(f, "%s", g);
(notice the removed &).
Also, the next line:
fscanf(f, "%d %d", &now->month, &now->date);
should have a space as the first character of the format string:
fscanf(f, " %d %d", &now->month, &now->date);
I am trying to write a C program that provides autocomplete suggestions looking at the contents of a directory. I have most of it done, however I get errors where directory names contain symbols that are not alphabets (such as . , / _). I get errors whenever I try to change things, including array size and looping values. Could you please take a look at my code and suggest what changes I need to make to include symbols in autocomplete suggestions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#define MAX 1000
struct node {
int data;
struct node *array[26];
};
struct node* new_node(struct node *h)
{
int i;
h = malloc(sizeof (struct node));
for (i = 0; i < 24; ++i)
h->array[i] = 0;
return h;
}
struct node* insert(struct node *h, char *c, int value)
{
int i;
if (strlen(c) == 0)
return h;
if (h == NULL)
h = new_node(h);
struct node *p = h;
for (i = 0; i < strlen(c); ++i) {
if (p->array[c[i] - 'a'] == NULL)
p->array[c[i] - 'a'] = malloc(sizeof (struct node));
p = p->array[c[i] - 'a'];
}
p->data = value;
return h;
}
int dfs(struct node *h, char *dat)
{
int i;
char k[1000] = {0};
char a[2] = {0};
if (h == NULL)
return 0;
if (h->data > 0)
printf("Match: %s\n", dat);
for(i = 0; i < 26; ++i) {
strcpy(k, dat);
a[0] = i + 'a';
a[1] = '\0';
strcat(k, a);
dfs(h->array[i], k);
}
}
void search(struct node *h, char *s, char *dat)
{
int i;
char l[1000] = {0};
char a[2];
strcpy(l, dat);
if (strlen(s) > 0) {
a[0] = s[0];
a[1] = '\0';
if(h->array[a[0]-'a'] != NULL) {
strcat(dat, a);
search(h->array[a[0]-'a'], s+1, dat);
} else
printf("No Match \n");
} else {
if (h->data != 0)
printf("Match: ");
for (i = 0; i < 26; ++i) {
strcpy(l, dat);
a[0] = i + 'a';
a[1] = '\0';
strcat(l, a);
dfs(h->array[i], l);
}
}
}
struct node* read_keys(struct node *h, char *file)
{
char s[MAX];
FILE *a = fopen(file, "r");
if (a == NULL)
printf("Error while opening file");
else
while (feof(a) == 0) {
fscanf(a, "%s", s);
h = insert(h, s, 1);
}
return h;
}
int main()
{
DIR *d;
struct dirent *dir;
char direct[MAX];
printf("Enter a folder name: ");
scanf("%s",direct);
d = opendir(direct);
FILE *f = fopen("file.txt", "w");
if (f == NULL)
{
printf("Error opening file!\n");
exit(1);
}
if (d)
{
while ((dir = readdir(d)) != NULL)
{
fprintf(f,"%s\n", dir->d_name);
}
}
fclose(f);
char c[1000];
FILE *fptr;
if ((fptr = fopen("file.txt", "r")) == NULL)
{
printf("Error! opening file");
exit(1);
}
FILE* file = fopen("file.txt", "r");
char line[1000];
while (fgets(line, sizeof(line), file)) {
printf("%s", line);
}
fclose(fptr);
printf("Enter beginning of filename \n");
struct node *h = 0;
h = read_keys(h, "file.txt");
char s[MAX];
scanf("%s", s);
char dat[1000] = "";
search(h, s, dat);
return 0;
}
I have a problem and I really dont know what to do.
I'am trying to insert "new students" to an student-array. The array contains pointers to the created structs. Can somebody find the error? It adds the student-structs to the array but especially the printing doesnt work.
It would be really helpful, if somebody could help me. :) PS: You can just copy the code.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_HASH 10
typedef struct student
{
unsigned int matnr;
char *name;
struct student *next_student;
} Student;
Student **hash_tabelle[MAX_HASH];
void insert_student (unsigned int matnr, char *name)
{
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(sizeof(*name)+1);
neuer_student->matnr = matnr;
strcpy(neuer_student->name, name);
neuer_student->next_student = NULL;
// Index im Hash-Array ermitteln
int hash_index = matnr % 10;
if(hash_tabelle[hash_index] == NULL)
{
neuer_student->next_student = hash_tabelle[hash_index];
hash_tabelle[hash_index] = neuer_student;
}
else
{
while(*hash_tabelle[hash_index] != NULL && (((*hash_tabelle[hash_index])->matnr - neuer_student->matnr) <= 0))
hash_tabelle[hash_index] = &(*hash_tabelle[hash_index])->next_student;
neuer_student->next_student = *hash_tabelle[hash_index];
*hash_tabelle[hash_index] = neuer_student;
}
}
void print_hash_tabelle()
{
for(int i = 0; i != MAX_HASH - 1; i++){
printf("%d)\t", i);
hash_tabelle[i] = &(*hash_tabelle[i])->next_student;
for(; hash_tabelle[i] != NULL; hash_tabelle[i] = &(*hash_tabelle[i])->next_student){
printf("%s (%d)", (&(*hash_tabelle[i])->name), (&(*hash_tabelle[i])->matnr));
}
printf("\t");
}
}
int main()
{
unsigned int matnr;
char name[100];
do
{
printf("Matrikelnummer:\t");
scanf("%d", &matnr);
fflush(stdin);
getchar(); // um das \n aus dem Puffer zu kriegen und rauszuschmeiĆen
printf("Name:\t\t");
fgets(name, 30, stdin);
insert_student(matnr, name);
}
while (matnr != 0);
print_hash_tabelle();
return 0;
}
Using a hash table is so simple... No need to use dereferencing for a fixed-size array of linked-list pointers.
Step 1 - a hash table is a array of linked-list pointers.
As #BLUEPIXY suggests:
Student *hash_tabelle[MAX_HASH];
Step 2 - to allocate and free each linked-list, initialize each item to NULL.
Otherwise, if(hash_tabelle[hash_index] == NULL) is Undefined
behavior in the function insert_student().
void hash_init()
{
for(int i=0;i<MAX_HASH;i++) {
hash_tabelle[MAX_HASH]=NULL;
}
}
Step 3 - allocate enough char to store the char *name to insert_student().
As # WhozCraig suggests, use strlen().
void insert_student (unsigned int matnr, char *name)
{
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(strlen(name)+1);
neuer_student->matnr = matnr;
strcpy(neuer_student->name, name);
neuer_student->next_student = NULL;
Step 4 - add the neuer_student in the hash_tabelle[] (function insert_student())
Warning: the index shall be included in the size of the array
[0..MAX_HASH[. (using 10 instead of MAX_HASH could become a bug).
int hash_index = matnr % MAX_HASH;
When the hash_tabelle[hash_index] is NULL, simple store the
neuer_student. No need to modify neuer_student->next_student.
if(hash_tabelle[hash_index] == NULL)
{
hash_tabelle[hash_index] = neuer_student;
}
Else explore the linked-list of hash_tabelle[hash_index] to store
the neuer_student at the end.
else
{
Student *tmp;
tmp = hash_tabelle[hash_index];
while (tmp->next_student!=NULL) {
tmp = tmp->next_student;
}
tmp->next_student = neuer_student;
}
Step 5 - to print the all items of the hash table (function print_hash_tabelle())
Reuse the same method to explore each linked-list pointer.
Warning: explore all item from 0 to MAX_HASH-1
void print_hash_tabelle()
{
for(int i = 0; i < MAX_HASH; i++){ // ERR != MAX_HASH - 1; i++){
printf("%d)\t", i);
Student *tmp = hash_tabelle[i];
while (tmp!=NULL) {
printf("%s (%d)", tmp->name, tmp->matnr);
tmp = tmp->next_student;
}
printf("\n");
}
}
Step 6 - free the memory of each item of the hash_tabelle[].
Free the allocated string free(tmp->name);.
Remove the current student hash_tabelle[i] = tmp->next_student;
Free the allocated student free(tmp);
Repeat until the end of the linked-list
That's all (no change in the main() except adding a call to hash_free() at the end).
void hash_free()
{
for(int i=0;i<MAX_HASH;i++) {
Student *tmp = hash_tabelle[i];
while (tmp!=NULL) {
free(tmp->name);
hash_tabelle[i] = tmp->next_student;
free(tmp);
tmp = hash_tabelle[i];
}
}
}
like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_HASH 10
typedef struct student {
unsigned int matnr;
char *name;
struct student *next_student;
} Student;
Student *hash_tabelle[MAX_HASH];
void insert_student (unsigned int matnr, char *name){
Student *neuer_student = malloc(sizeof(Student));
neuer_student->name = malloc(strlen(name)+1);
strcpy(neuer_student->name, name);
neuer_student->matnr = matnr;
//neuer_student->next_student = NULL;
int hash_index = matnr % MAX_HASH;
Student head = { .next_student = hash_tabelle[hash_index] };
Student *prev = &head, *curr = head.next_student;
while(curr != NULL && curr->matnr <= neuer_student->matnr){
prev = curr;
curr = curr->next_student;
}
neuer_student->next_student = curr;
prev->next_student = neuer_student;
hash_tabelle[hash_index] = head.next_student;
}
void print_hash_tabelle(void){
for(int i = 0; i < MAX_HASH; i++){
printf("%d)\t", i);
for(Student *p = hash_tabelle[i]; p; p = p->next_student){
printf("%s (%d)\t", p->name, p->matnr);
}
printf("\n");
}
}
void free_hash_tabelle(void){
for(int i = 0; i < MAX_HASH; i++){
Student *p = hash_tabelle[i];
while(p){
Student *temp = p->next_student;
free(p->name);
free(p);
p = temp;
}
}
}
int main(void){
int matnr = -1;//for %d of scanf
char name[100];
while(1){
printf("Matrikelnummer(-1 for end input): ");fflush(stdout);
scanf("%d", &matnr);
if(matnr < 0)
break;
while(getchar() != '\n');
printf("Name: ");fflush(stdout);
fgets(name, sizeof name, stdin);
name[strcspn(name, "\n")] = 0;
insert_student(matnr, name);
}
print_hash_tabelle();
free_hash_tabelle();
return 0;
}