2014-05-11 125 views
0

特定行我试图读取使用下面的代码文件中的特定行。阅读从文件

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 

我真的不明白它可能以零字符串(而不是空指针)结束。

回答

1

此代码为我工作(除了做去除uncesessary tmp变量没有变化)

的一个问题是,如果传递0,for循环永远不会进入。只需将其更改为< =和/或在开始添加其他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 
+0

的作品对我来说太。如果你传递一个消极的行号可能以零字符串结束(或0) – kaman

+0

是啊,这个问题最终是一个简单的将其更改为<=,而不是仅仅<......想通了这一点只是一秒钟前。将提出一个编辑。 – phyrrus9

1

一个很明显的问题是,这种代码溢出缓冲区,如果有超过2048

另一个问题线较长的是,你的fscanf字符串将跳过空白行(文件的第一行除外)。我不确定这是否是故意的。该\n匹配,你对字符串的结束意味着匹配所有空格起来,直到下一个非空白即使空白包括多个换行。

要解决这个问题,你可以删除那个\n,然后在每个fscanf之后去掉一个fgetc()消耗一个换行符。

要修复缓冲区溢出问题,我会建议直接跳到你想要的行而不用存储任何东西,然后使用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 longline_num将让您了解更多!

+0

使用较大的整型是那种一个坏主意,因为只能有这么多的程序在做,但感谢你的龟etc – phyrrus9