Код просто не будет читать предоставленный мною текстовый файл
Ваша проблема, вероятно, исходит от:
char line[4096];
while (fgets(line, sizeof line,fp))
{
size_t len = strlen(line);
if (len && (line[len - 1] != '\n'))
из-за (line[len - 1] != '\n')
, что, вероятно, никогда не соответствует действительности, поскольку fgets может прочитать большую строку и учитывая fscanf после того, как строки содержат только несколько данных.
Почему вы хотите работать с / * неполной строкой * / ?
Работа на полных линиях с тестом
if (len && (line[len - 1] == '\n'))
У вас также есть неожиданное возвращение в
if (!hashTable[hashIndex].head)
{
hashTable[hashIndex].head = newNode;
hashTable[hashIndex].count = 1;
return;
}
из-за этого вы не можете прочитать более одного ответа, поместите строки после в else { ... }
Обратите внимание, что ваш код предполагает, что пользователь попросит только один раз вставить, если он сделает это несколько раз, вы добавите несколько раз одни и те же элементы.
После прочтения строки вы снова читаете файл, выполняя
fscanf(fp,"%s %s %s %d",node.AM, node.first_name, node.last_name, &node.grade);
так что вы сохраняете данные только с половины строк, которые вы хотели сделать
sscanf(line,"%s %s %s %d",node.AM, node.first_name, node.last_name, &node.grade);
У вас есть дополнительные проблемы
В Хэш вы предполагаете, что идентификатор имеет как минимум 7 символов, если это не тот случай, когда вы читаете из имени (после нулевого символа) с неопределенным поведением
Сделайте что-то вроде:
int Hash(char *AM, int n)
{
int i;
int hashIndex = 0;
for (i=0; (i< 8) && (AM[i] != 0); i++)
{
hashIndex += AM[i];
}
return hashIndex % n;
}
Несмотря на то, что ваш хэш очень плох, есть намного лучшие способы хешировать строку
В
fscanf(fp,"%s %s %s %d",node.AM, node.first_name, node.last_name, &node.grade);
Вы используете формат % d для int , но node.grade
является float , замените % d на % f , а также проверьте fscanf , возвращает 4
Я также призываю вас ограничить размер строки чтения, чтобы не рисковать выписыванием из полей, поэтому (на самом деле fscanf должен быть заменен sscanf )
fscanf(fp,"%99s %99s %99s %f", ...)
В
printf("Student ID : %d\n", myNode->AM);
и
printf("%-12d", myNode->AM);
вы используете формат % d для int , но вы даете char*
Заменить d на s или изменить тип AM (и как читать и использовать его в другом месте, конечно)
Возвращение в конце insertToHash бесполезно, есть и другие бесполезные return , где
В
printf("grade : %d\n", myNode->grade);
и
printf("%d\n", myNode->grade);
вы используете формат % d для int , но вы даете двойной
Заменить % d на % lf или % lg etc
В
int hashIndex = Hash(AM, 19);
AM не инициализируется, поведение не определено
Вы хотели
int hashIndex = Hash(node.AM, 19);
В
struct node *newnode = createNode(AM, first_name, last_name, grade);
AM
и first_name
и last_name
и grade
не инициализированы, поведение не определено
Вы хотели
struct node *newnode = createNode(node.AM, node.first_name, node.last_name, node.grade);
и удалите бесполезные переменные hashIndex, grade, last_name, first_name, AM
В deleteFromHash и searchInHash тест
if (myNode->AM == AM)
неправильно, потому что вы сравнили указатели, вы хотели
if (!strcmp(myNode->AM, AM))
В
struct node
{
float grade;
char AM[100];
char first_name[100];
char last_name[100];
struct node *next;
}node;
одно и то же имя используется для структуры и глобальной переменной, это не очень хорошая идея.
Также глобальная переменная узел используется только в insertToHash , поэтому вам она не нужна, удалите глобальную переменную и добавьте локальную переменную в insertToHash .
После редактирования добавляем main
scanf("%d", &AM);
должно быть (2 раза)
scanf("%99s", AM);
Ваши переменные first_name, last_name
и grade
не используются
Код, учитывающий все мои замечания:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
struct hash *hashTable = NULL;
int eleCount = 0;
struct Node
{
float grade;
char AM[100];
char first_name[100];
char last_name[100];
struct Node *next;
};
struct hash
{
struct Node *head;
int count;
};
struct Node * createNode(char *AM, char *first_name, char *last_name, float grade)
{
struct Node *newNode;
newNode = (struct Node *) malloc(sizeof(struct Node));
strcpy(newNode->AM, AM);
strcpy(newNode->last_name, last_name);
strcpy(newNode->first_name, first_name);
newNode->grade = grade;
newNode->next = NULL;
return newNode;
}
int Hash(char *AM, int n)
{
int i;
int hashIndex = 0;
for (i=0; (i< 8) && (AM[i] != 0); i++)
{
hashIndex += AM[i];
}
return hashIndex % n;
}
void insertToHash()
{
struct Node node;
FILE *fp;
fp = fopen ("Foitites-Vathmologio-DS.txt","rb");
if (fp == NULL)
{
fprintf(stderr,"Could not open file");
return;
}
char line[4096];
while (fgets(line, sizeof line,fp)) {
size_t len = strlen(line);
if (len && (line[len - 1] == '\n')) {
/* complete line */
if (sscanf(line,"%99s %99s %99s %f",node.AM, node.first_name, node.last_name, &node.grade) != 4) {
puts("invalid file");
return;
}
int hashIndex = Hash(node.AM, 19);
struct Node *newNode = createNode(node.AM, node.first_name, node.last_name, node.grade);
/* head of list for the bucket with index "hashIndex" */
if (!hashTable[hashIndex].head)
{
hashTable[hashIndex].head = newNode;
hashTable[hashIndex].count = 1;
}
else {
/* adding new Node to the list */
newNode->next = (hashTable[hashIndex].head);
/*
* update the head of the list and no of
* Nodes in the current bucket
*/
hashTable[hashIndex].head = newNode;
hashTable[hashIndex].count++;
}
}
}
fclose(fp);
printf("Done! \n");
}
void deleteFromHash(char *AM)
{
/* find the bucket using hash index */
int hashIndex = Hash(AM, 19);
int flag = 0;
struct Node *temp, *myNode;
/* get the list head from current bucket */
myNode = hashTable[hashIndex].head;
if (!myNode) {
printf("Given data is not present in hash Table!!\n");
return;
}
temp = myNode;
while (myNode != NULL) {
/* delete the Node with given AM */
if (!strcmp(myNode->AM, AM)) {
flag = 1;
if (myNode == hashTable[hashIndex].head)
hashTable[hashIndex].head = myNode->next;
else
temp->next = myNode->next;
hashTable[hashIndex].count--;
free(myNode);
break;
}
temp = myNode;
myNode = myNode->next;
}
if (flag)
printf("Data deleted successfully from Hash Table\n");
else
printf("Given data is not present in hash Table!!!!\n");
}
void searchInHash(char *AM) {
int hashIndex = Hash(AM, 19);
int flag = 0;
struct Node *myNode; myNode = hashTable[hashIndex].head;
if (!myNode) {
printf("Search element unavailable in hash table\n");
return;
}
while (myNode != NULL) {
if (!strcmp(myNode->AM, AM)) {
printf("Student ID : %s\n", myNode->AM);
printf("First Name : %s\n", myNode->first_name);
printf("Last Name : %s\n", myNode->last_name);
printf("grade : %lg\n", myNode->grade);
flag = 1;
break;
}
myNode = myNode->next;
}
if (!flag)
printf("Search element unavailable in hash table\n");
}
void display() {
struct Node *myNode;
int i;
for (i = 0; i < eleCount; i++) {
if (hashTable[i].count == 0)
continue;
myNode = hashTable[i].head;
if (!myNode)
continue;
printf("\nData at index %d in Hash Table:\n", i);
printf("Student ID First Name Last Name Grade \n");
printf("--------------------------------\n");
while (myNode != NULL) {
printf("%-12s", myNode->AM);
printf("%-15s", myNode->first_name);
printf("%-15s", myNode->last_name);
printf("%lg\n", myNode->grade);
myNode = myNode->next;
}
}
}
int main()
{
int n=19, ch;
char AM[100];
int insertDone = 0;
eleCount = n;
/* create hash table with "n" no of buckets */
hashTable = (struct hash *) calloc(n, sizeof(struct hash));
while (1) {
printf("\n1. Insertion\t2. Deletion\n");
printf("3. Searching\t4. Display\n5. Exit\n");
printf("Enter your choice:");
scanf("%d", &ch);
switch (ch) {
case 1:
if (insertDone)
puts("Inserton was already done");
else {
/*inserting new Node to hash table */
insertToHash();
insertDone = 1;
}
break;
case 2:
printf("Enter the AM to perform deletion:");
scanf("%99s", AM);
/* delete Node with "AM" from hash table */
deleteFromHash(AM);
break;
case 3:
printf("Enter the AM to search:");
scanf("%99s", AM);
searchInHash(AM);
break;
case 4:
display();
break;
case 5:
exit(0);
default:
printf("U have entered wrong option!!\n");
break;
}
}
return 0;
}
Компиляция и исполнение:
pi@raspberrypi:/tmp $ gcc -g -pedantic -Wextra -Wall c.c
pi@raspberrypi:/tmp $ cat Foitites-Vathmologio-DS.txt
123 aze qsd 1.23
456 iop jkl 4.56
pi@raspberrypi:/tmp $ ./a.out
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:4
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:1
Done!
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:4
Data at index 7 in Hash Table:
Student ID First Name Last Name Grade
--------------------------------
456 iop jkl 4.56
Data at index 17 in Hash Table:
Student ID First Name Last Name Grade
--------------------------------
123 aze qsd 1.23
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:1
Inserton was already done
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:3
Enter the AM to search:123
Student ID : 123
First Name : aze
Last Name : qsd
grade : 1.23
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:3
Enter the AM to search:1234
Search element unavailable in hash table
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:2
Enter the AM to perform deletion:1
Given data is not present in hash Table!!
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:2
Enter the AM to perform deletion:123
Data deleted successfully from Hash Table
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:4
Data at index 7 in Hash Table:
Student ID First Name Last Name Grade
--------------------------------
456 iop jkl 4.56
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:2
Enter the AM to perform deletion:456
Data deleted successfully from Hash Table
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:4
1. Insertion 2. Deletion
3. Searching 4. Display
5. Exit
Enter your choice:5
pi@raspberrypi:/tmp $