2014-05-11 126 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