为什么从文件功能读取会崩溃? [英] Why is reading from file function crashing?
问题描述
试图从文件中读取多行以将它们存储在由字符串元素组成的结构中,但是,当我运行该程序时,它只是崩溃了,我不知道为什么.
Trying to read multiple line from file to store them in a structure made up of the string elements, however when I run the program it simply crashes and I haven't the faintest idea why.
有问题的功能
Hashtbl* loadfromfile(Hashtbl* hashtbl, char *path){
int i = 0;
char line[100];
char* string[40];
FILE *f = fopen(path, "r");
if(f == NULL){
printf("FILE NO FOUND!");
}else{
while(fgets(line, sizeof(line), f)!=NULL){
strcpy(string[i],line);
i++;
}
fclose(f);
for(i = 0; i<(SIZE*2); i++){
strcpy(hashtbl[i].subscript, string[i]);
i++;
}
for(i = 1; i<(SIZE*2); i++){
strcpy(hashtbl[i].value, string[i]);
i++;
}
return hashtbl;
}
}
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "hashtable.h"
int main() {
Hashtbl* numbers;
numbers = init_hashtbl(); //init_hashtable initialises numbers
loadfromfile(numbers, "test.txt");
for(int i = 0; i<SIZE; i++) {
printf("%s1", numbers[i].subscript);
printf("%s2\n", numbers[i].value);
}
}
哈希表结构:
typedef struct Hashtbls{
char *subscript;
char *value;
} Hashtbl;
init_hasthable函数:
init_hasthable function:
Hashtbl* init_hashtbl(){
Hashtbl* hashtbl;
hashtbl = calloc(SIZE, sizeof(Hashtbl));
for(int i = 0; i<SIZE; i++){
hashtbl[i].subscript = "ZERO";
hashtbl[i].value = "ZERO";
}
return hashtbl;
}
推荐答案
您在这里有很多问题:
if(f == NULL){
printf("FILE NO FOUND!");
}
如果无法打开文件,则无法继续.另外消息可能
稍后再打印,请使用printf("FILE NOT FOUND!\n");
.
If the file cannot be opened, then you cannot continue. Also the message might
be printed way later, use printf("FILE NOT FOUND!\n");
instead.
char* string[40];
...
while(fgets(line, sizeof(line), f)!=NULL){
strcpy(string[i],line);
i++;
}
string
是未初始化指针的数组,您无法编写任何内容
那里.你应该做
string
is an array of uninitialized pointers, you cannot write anything
there. You should do
while(fgets(line, sizeof line, f))
{
string[i] = malloc(strlen(line) + 1);
if(string[i] == NULL)
{
// error handling is needed
}
strcpy(string[i], line);
i++;
if(i == sizeof string / sizeof *string)
break;
}
// or if your system has strdup
while(fgets(line, sizeof line, f))
{
string[i] = strdup(line);
if(string[i] == NULL)
{
// error handling is needed
}
i++;
if(i == sizeof string / sizeof *string)
break;
}
您也不会检查您是否阅读了40多行.我做到了
最后一个if
. sizeof array / sizeof *array
返回
数组可以容纳的元素.请注意,这仅适用于数组,不适用于数组
指针,通常是sizeof array != sizeof pointer
.也不要忘记
释放之后分配的内存.
Also you are not checking whether you read more than 40 lines. I did that with
the the last if
. sizeof array / sizeof *array
returns the number of
elements that an array can hold. Note that this only works for arrays, not
pointers, since in general sizeof array != sizeof pointer
. Also don't forget
to free the allocated memory afterwards.
strcpy(hashtbl[i].subscript, string[i]);
...
strcpy(hashtbl[i].value, string[i]);
这里的subscript
和value
参数是否以某种方式初始化?查看
您的init_hashtbl()
.
Are the subscript
and value
parameters here initialized in some way? Check
your init_hashtbl()
.
编辑
现在您发布了init_hashtbl
:
for(i = 0; i<(SIZE*2); i++){
strcpy(hashtbl[i].subscript, string[i]);
i++;
}
您正在使用字符串文字初始化subscript
和value
,它们
指向只读内存位置,strcpy
将失败.你有
使用malloc
分配内存或使用数组更改结构.
You are initializing subscript
and value
with string literals, they
are pointing to read-only memory location, strcpy
is going to fail. You have
to either allocate memory with malloc
or change your structure with arrays.
选项1
保留结构,更改init_hashtbl
Hashtbl* init_hashtbl(){
Hashtbl* hashtbl;
hashtbl = calloc(SIZE, sizeof(Hashtbl));
for(int i = 0; i<SIZE; i++){
hashtbl[i].subscript = malloc(SOME_MAXIMAL_LENGTH + 1);
strcpy(hashtbl[i].subscript, "ZERO");
hashtbl[i].value = malloc(SOME_MAXIMAL_LENGTH + 1);
strcpy(hashtbl[i].value, "ZERO");
}
return hashtbl;
}
您应始终检查malloc
/calloc
的返回值.还有
这里的问题是,如果您要复制一个长度比
SOME_MAXIMAL_LENGTH
,您将有一个缓冲区溢出.所以你应该
在阅读例程中使用realloc:
You should always check the return value of malloc
/calloc
. Also the
problem here is that if you want to copy a string that is longer than
SOME_MAXIMAL_LENGTH
, you are going to have a buffer overflow. So you should
use realloc in the reading routine:
for(i = 0; i<(SIZE*2); i++){
char *tmp = realloc(hashtbl[i].subscript, strlen(string[i]) + 1);
if(tmp == NULL)
{
// error handling
}
hashtbl[i].subscript = tmp;
strcpy(hashtbl[i].subscript, string[i]);
i++;
}
如果您不想在这里处理realloc
,则必须确保
string[i]
长于SOME_MAXIMAL_LENGTH
.
If you don't want to deal with realloc
here, you have to make sure, that no
string[i]
is longer than SOME_MAXIMAL_LENGTH
.
选项2
更改您的结构和初始化:
Change you structure and init:
typedef struct Hashtbls{
char subscript[SOME_MAXIMAL_LENGTH];
char value[SOME_MAXIMAL_LENGTH];
} Hashtbl;
Hashtbl* init_hashtbl(){
Hashtbl* hashtbl;
hashtbl = calloc(SIZE, sizeof(Hashtbl));
for(int i = 0; i<SIZE; i++){
strcpy(hashtbl[i].subscript, "ZERO");
strcpy(hashtbl[i].value, "ZERO");
}
return hashtbl;
}
然后在loadfromfile
中您不必处理realloc
,如图所示
上面,您可以保留您的代码.但是,您必须检查是否没有string[i]
长于SOME_MAXIMAL_LENGTH - 1
,否则缓冲区溢出.
Then in loadfromfile
you don't have to deal with the realloc
as shown
above, you can keep your code. However, you have to check that no string[i]
is longer than SOME_MAXIMAL_LENGTH - 1
, otherwise buffer overflow.
最后一件事,fgets
读取整行,假设
行小于sizeof line
,则将换行符添加到
线.您很可能不想拥有它.摆脱的一种方法
换行符是:
One last thing, fgets
reads a whole line, assuming that the length of the
line is lesser than sizeof line
, the newline character will be added to the
line. You most likely don't want to have that. One way of getting rid of the
newline is:
fgets(line, sizeof line, f);
int len = strlen(line);
if(line[len - 1] == '\n')
line[len - 1] = 0;
这篇关于为什么从文件功能读取会崩溃?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!