我正在尝试使用以下代码从文件中读取特定行。
char *getlinenum(char *filename, int lnum)
{
FILE *f;
int i;
char *linebuf = NULL, *tmp = NULL;
if ((f = fopen(filename, "r")) != NULL)
{
linebuf = (char *)malloc(2048);
memset(linebuf, 0, 2048);
for (i = 0; i < lnum; i++)
{
if (fscanf(f, "%[^\n]\n", linebuf) == EOF)
{
free(linebuf);
fclose(f);
printf("Returning NULL\n");
return NULL;
}
}
//tmp = strdup(linebuf);
//free(linebuf);
fclose(f);
return linebuf;
}
return NULL;
}
无论如何,这总是只返回一个空(零)字符串。您看到的任何问题?这是测试文件:
/home/mainframe/b
/home/mainframe/dead.letter
/home/mainframe/.bash_history
/home/mainframe/a
/home/mainframe/f
/home/mainframe/e
/home/mainframe/c
/home/mainframe/g
/home/mainframe/.ssh/authorized_keys
/home/mainframe/.ssh
/home/mainframe/d
我真的不明白最终会出现零字符串(不是空指针)。
答案 0 :(得分:1)
这段代码对我有用(除了删除uncesessary tmp
变量之外没有任何变化)
一个问题是如果传递0,则for循环永远不会进入。只需将其更改为&lt; =和/或在开头添加另一个if语句:
if( lnum <= 0 )
return NULL;
抓住这个问题。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *getlinenum(char *filename, int lnum)
{
FILE *f;
int i;
char *linebuf = NULL;
if( lnum <= 0 )
return NULL;
if ((f = fopen(filename, "r")) != NULL)
{
linebuf = (char *)malloc(2048);
memset(linebuf, 0, 2048);
for (i = 0; i <= lnum; i++)
{
if (fscanf(f, "%[^\n]\n", linebuf) == EOF)
{
free(linebuf);
fclose(f);
printf("Returning NULL\n");
return NULL;
}
}
free(linebuf);
fclose(f);
return linebuf;
}
return NULL;
}
int main()
{
printf("%s\n", getlinenum("input.txt", 2));
return 0;
}
输出:
/home/mainframe/dead.letter
答案 1 :(得分:1)
一个相当明显的问题是,如果有一条长于2048的行,这段代码会溢出缓冲区。
另一个问题是你的fscanf
字符串会跳过空行(文件的第一行除外)。我不确定这是否是故意的。你在字符串末尾的\n
匹配器意味着匹配所有空格,直到下一个非空格,即使该空格包含多个换行符。
要解决该问题,您可以删除该\n
,并在每个fgetc()
后执行fscanf
以使用一个换行符。
要修复缓冲区溢出,我建议跳过你想要的行而不存储任何内容,然后使用fgets
来获取你感兴趣的行。例如(这里我也考虑了清理代码):
if (lnum < 1 || (f = fopen(filename, "r")) == NULL)
return NULL;
char *buffer = NULL;
for ( ; lnum > 1; --lnum )
{
if ( fscanf(f, "%*[^\n]") == EOF || fgetc(f) == EOF )
break;
}
if ( lnum == 1 )
{
// or use the POSIX getline() function or similar, to avoid any size limitation and
// avoid the mucking around with fgets and \n
buffer = calloc(1, 2048);
if ( ! fgets(buffer, 2048, f) )
{
free(buffer);
buffer = NULL;
}
else if ( buffer[0] && buffer[strlen(buffer)-1] == '\n' )
buffer[strlen(buffer)-1] = 0;
}
fclose(f);
return buffer;
此外,使用unsigned long long
line_num
可以让您阅读更多内容!