我正在将文件加载到内存中,我正在使用以下语句:
if ((ch = fread(&temp[i],1,1,loadDict)) == EOF)
break;
但我收到了分段错误。在使用gdb检查后,我验证了该行发生了故障(if语句,在中断之前)。为什么它没有看到它会出错(使用EOF的全部意义)?
我认为可能是我在if语句中使用EOF而不是在while()语句中。是否可以在if语句中使用EOF?
更新:更多代码
bool load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char* new = malloc(sizeof(char)); // for storing the "new-line" character
*new = 0x0A;
// defines a node, which containes one word and points to the next word
typedef struct node
{
char* word;
struct node* next;
}
node;
node* head = malloc(sizeof(node));
node* temp = malloc(sizeof(node));
head->next=temp;
// copies a word from the dictionary file into a node
int* numStore = malloc(sizeof(int)); //count for number of words in dictionary
int num = 0;
int ch = 0; // to hold for EOF
int flag = 0; // for breaking out of while loop
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
int i = -1;
do
{
i++;
if (!feof(loadDict) || !ferror(loadDict))
{
flag = 1;
break;
}
fread(&temp[i],1,1,loadDict);
if (memcmp (new, &temp[i], 1) == 0)
num += 1;
}
while(memcmp (new, &temp[i], 1) != 0);
temp=newNode;
if (flag == 1)
break;
}
numStore = #
return true;
}
答案 0 :(得分:4)
typedef struct node
{
char* word;
struct node* next;
}
您定义的结构可能会崩溃,至少我见过的实现有。节点内的char *没有固定值。所以当你这样做时:
node* head = malloc(sizeof(node));
malloc()将分配一个内存(对于char指针使用1个字节,对于节点使用int size指针,在32位计算机上默认为4个字节)5个字节。当你读取超过5个字节时会发生什么?
此外,你不必要地使这一点复杂化:
int* numStore = malloc(sizeof(int));
如果你想在dictonary中存储单词的数量,请立即使用int numstore
,减少头痛:)
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
...
}
现在,这是一个有趣的概念。如果要读到文件末尾,您有两个选择:
1)使用feof()
2)在循环结束时,试试这个:
while(true)
{
....
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
此外,这一行:temp->word=malloc(46);
为什么要手动分配46个字节?
Armin是正确的,& temp [i],而我确实被分配到0,do {...} while();完全没必要。
同样来自男人的恐惧:http://www.manpagez.com/man/3/fread/ 你正在读我看起来像1个角色的东西。
在我看来,尝试这样的事情:
设置字长的最大值(如50,实际用途更多) 用fscanf读入它 用fscanf获取它的长度 分配内存
此外,您不需要为* head分配内存;它可以保存为迭代器符号 我差点忘了,如果你要返回bool,你将如何使用返回的列表,* head丢失,从而造成内存泄漏,因为你无法解除其余的?除非你使用c99,否则c不支持bool
/*Global declaration*/
typedef struct node
{
char* word;
struct node* next;
}node;
node *head, *tmp;
/* for the bool if you really want it*/
typedef enum { false, true } bool;
node* load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char word[50];
int num = 0;
int len;
node *old;
while(true)
{
/*node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);*/
fscanf(loadDict,"%s ",word);
len = strlen(word);
tmp = malloc(len + sizeof(node));
strcpy(tmp->word,word);
tmp->next = NULL;
if(head==NULL)
{
head = tmp;
old = head;
}
else
old->next = tmp;
old = tmp;
num++;
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
printf("number of counted words::\t%d\n",num);
fclose(loadDict);
return head;
}
此外,请记住,我只考虑了单词每个空格分隔的行为,所以请加载文件t =这样,或更改算法:)此外,请务必在使用后释放内存该计划!
void freeDict()
{
node *i;
while(head!=NULL)
{
i = head;
head = head->next;
free(i);
}
}
希望这会有所帮助:)
答案 1 :(得分:2)
这编译......我现在也运行它。分配失败时的错误处理是应该受到谴责的;它应该至少给出一个错误消息,并且应该释放所有已分配的节点并从函数返回0(NULL)(并关闭文件)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
char *word;
struct Node *next;
} Node;
Node *dict_load(const char *dictionary)
{
FILE *loadDict = fopen(dictionary, "r");
if (loadDict == 0)
return 0;
Node *head = 0;
char line[4096];
while (fgets(line, sizeof(line), loadDict) != 0)
{
size_t len = strlen(line); // Includes the newline
Node *node = malloc(sizeof(*node));
if (node == 0)
exit(1); // Reprehensible
node->word = malloc(len);
if (node->word == 0)
exit(1); // Reprehensible
memmove(node->word, line, len - 1); // Don't copy the newline
node->word[len-1] = '\0'; // Null terminate the string - tweaked!
node->next = head;
head = node;
}
fclose(loadDict);
return head;
}
如果您必须从函数返回bool
,那么您可能需要:
static bool dict_load(const char *dictionary, Node **head)
如果参数列表只是固定在文件名中,那么你就不得不使用一个全局变量,这对于设置练习的人来说是很讨厌的。它是“可行的”,但“像罪一样丑陋”。
上面的代码确实有用(注意调整后的行);添加函数dict_free()
和dict_print()
以释放字典并打印字典以及dict_load()
中的正确错误处理,并且简单main()
允许我在其自己的源代码上测试它,它的工作原理(向后打印源)。它也从valgrind
获得了健康的健康状况。
答案 2 :(得分:0)
你使用temp [i]引起怀疑,你可能正在访问外部记忆 引用K&amp; R:
If pa points to a particular element of an array, then by definition pa+1 points
to the next element, pa+i points i elements after pa, and pa-i points i elements
before.
These remarks are true regardless of the type or size of the variables in
the array a. The meaning of ``adding 1 to a pointer,'' and by extension,
all pointer arithmetic, is that pa+1 points to the next object, and pa+i
points to the i-th object beyond pa.