我编写了这个简单的readline
函数,它可以返回每个行长度,但它不会返回指向已分配缓冲区的指针。另一个问题是忽略了最后一行(它没有返回它):
FILE *passFile = NULL;
char *current = NULL;
size_t len = 0;
passFile = fopen("pass.txt", "r");
while(readline(passFile, ¤t, &len) != -1) {
printf("%s\n", current); // SEGMENTAION FAULT
printf("%d\n", len);
free(current);
current = NULL;
}
ssize_t
readline(FILE *file, char **bufPtr, size_t *len)
{
char c, *buf = NULL;
size_t n = 0;
buf = (char*)malloc(sizeof(char));
while((c = fgetc(file)) != '\n' && (c != EOF)) {
buf[n] = c;
++n;
buf = realloc(buf, n + 1);
}
buf[n] = '\0';
*bufPtr = buf;
*len = n;
if(c == EOF) // reach end of file
return -1;
return 0;
}
答案 0 :(得分:2)
您的readline()
函数未返回指向已分配内存的指针。在您的通话中,current
永远不会被设置,因此指针无效并且您收到错误。
在C中,函数是“按值调用”。在readline()
内,bufPtr
是传递给readline()
的内容的副本。分配给bufPtr
只会覆盖本地副本,并且不会返回调用代码可以看到的值。
在伪代码中:
TYPE a;
define function foo(TYPE x)
{
x = new_value;
}
foo(a); // does not change a
这仅更改x
的本地副本,并且不返回值。你改变它使用指针...函数仍然得到一个副本,但现在它是一个指针的副本,它可以使用该指针值来找到原始变量。在伪代码中:
TYPE a;
define function foo(TYPE *px)
{
*px = new_value;
}
foo(&a); // does change a
现在,要改变你的功能:
ssize_t
readline(FILE *file, char **pbufPtr, size_t *len)
{
// ...deleted...
buf[n] = '\0';
*pbufPtr = buf;
// ...deleted...
}
你这样称呼它:
while(readline(passFile, ¤t, &len) != -1)
P.S。以你在这里的方式致电realloc()
并不是一个好主意。这可能是一个非常慢的功能,对于65个字符的输入字符串,你会称之为65次。最好使用内部缓冲区进行初始文件输入,然后使用malloc()
分配一个大小合适的字符串并将字符串复制到缓冲区中。如果字符串太长而无法一次放入内部缓冲区,请使用malloc()
获取足够大的位置来复制内部缓冲区中的字符串部分,然后继续使用内部缓冲区复制更多字符串,然后根据需要调用realloc()
。基本上我建议您有一个大小为N的内部缓冲区,并一次将字符串复制为N个字符的块,从而最小化调用realloc()
的次数,同时仍然允许任意长度的输入字符串。
编辑:您的最后一行问题是,当您点击文件末尾时返回-1,即使有一行要返回。
更改您的代码,以便仅在c == EOF
和 n == 0
时返回-1,因此将正确返回以EOF结尾的最后一行。
您还应该readline()
使用feof()
函数来检查file
是否位于文件末尾,如果是,则返回-1而不调用malloc()
基本上,当你返回-1时,你不想调用malloc()
,当你调用malloc()
并将数据复制到其中时,你不想返回-1! -1应该表示“你没有得到任何东西,因为我们命中了文件结尾”。如果你在我们点击文件末尾之前得到了一些东西,那就不是-1,那就是0.然后 next 调用readline()
之后会返回-1。
答案 1 :(得分:1)
在readline
功能中,您按值current
传递。因此,如果您在函数内更改bufPtr
,则不会更改current
之外的值。如果您想更改current
的值,请参考:¤t
并将readline()
参数更改为char **bufPTR
。
如果你想改变它所指向的东西,你可以按照你所做的方式通过current
,但你想在第一时间改变它指向的地方。
< / p>
答案 2 :(得分:0)
用此
替换您的readline
功能
char* readline(FILE *file, size_t *len)
{
char c, *buf = NULL;
size_t n = 0;
buf = (char*)malloc(sizeof(char));
while((c = fgetc(file)) != '\n' && (c != EOF)) {
buf[n] = c;
++n;
buf = realloc(buf, n + 1);
}
buf[n] = '\0';
bufPtr = buf;
*len = n;
if(c == EOF) // reach end of file
return NULL;
return buf;
}
然后在main
中用此while(readline(passFile, current, &len) != -1)
替换此行while((current = readline(passFile, &len) != NULL)
答案 3 :(得分:0)
现在可行:
ssize_t
readline(FILE *file, char **bufPtr, size_t *len)
{
if(feof(file)) // reach end of file
return -1;
char c, *buf = NULL;
size_t n = 0, portion = CHUNK;
buf = (char*)malloc(sizeof(char) * CHUNK);
while((c = fgetc(file)) != '\n' && (c != EOF)) {
buf[n] = c;
++n;
if(n == portion) {
buf = realloc(buf, CHUNK + n);
portion += n;
}
}
buf[n] = '\0';
*bufPtr = buf;
*len = n;
return 0;
}