2012-11-12 20 views
4

我想從文本文件中逐行讀取文本,並對這些行進行一些處理。我可以做所有的處理,但是我不能用malloc-realloc來增長內存。我首先給了有限的內存,如果我的文本文件的行字符在這個限制內,一切都可以。如果我使用每行10000字的大文件,它只會讀取我的限制。我不完全明白如何使用realloc()。我能做些什麼關於這個代碼?從文件中讀取文本並在需要時重新分配

void stat(char* fileptr) 
{ 

    FILE *fp; 
    char *linebuffer; 
    int line=0; 
    int sum=0; 
    int max=0; 
    int min=0; 
    int maxlinelen=512; 
    int i=0,j=0; 
    int maxlen=512; 
    int curlinelen[maxlen]; 

    linebuffer=(char*) malloc(maxlinelen * sizeof(char)); 
    if(linebuffer==NULL) 
    { 
     printf("Error occurred allocating memory for linebuffer"); 
     exit(1); 
    } 


    if((fp=fopen(fileptr,"r"))!=NULL) 
    { 
    while((fgets(linebuffer,maxlinelen,fp))!=NULL) 
     { 
    if(strlen(linebuffer)==maxlinelen) 
     { 
     maxlinelen*=2; 
     linebuffer=realloc(linebuffer,maxlinelen * sizeof(char)); 
     if(linebuffer==NULL) 
      { 
     printf("Error occurred reallocating space for linebuffer"); 
     exit(1); 
      } 
     } 
    line++; 

     sum=sum+strlen(linebuffer); 
    curlinelen[i]=strlen(linebuffer); 
    i++; 

     } 
    } 
    min=curlinelen[0]; 
    max=curlinelen[0]; 
    for(j=0;j<line;j++) 
    { 
     if(curlinelen[j]<min) 
    { 
     min=curlinelen[j]; 
    } 
     if(curlinelen[j]>max) 
    { 
     max=curlinelen[j]; 
    } 
    } 


printf("No. of lines  =%d\n",line); 
printf("Maximum line length =%d\n",max); 
printf("Minimum line length =%d\n",min);  
printf("Average line length =%8.2f\n",(float)sum/(float)line); 

fclose(fp); 
} 
+0

'* sizeof(char)'是不需要的,並且類型爲'malloc()'的返回是不明智的。 – Mike

+0

而不是'sizeof(char)'我會使用'sizeof(* linebuffer)',如果您決定將線緩衝區的類型更改爲寬字符串或其他類型,則會自動變大。 – Wug

回答

3
fgets(linebuffer,maxlinelen,fp) 

linebuffer至多maxlinelen - 1字符讀取並存儲和0-終止它。因此

if(strlen(linebuffer)==maxlinelen) 

是永不滿足,strlen(linebuffer)最多可以maxlinelen - 1。更改條件,如果文件包含長行(如果realloc失敗),則會看到maxlinelen增加。

然而,您當前的代碼會將讀取的部分行作爲整行進行計數,然後將該行的下一個塊作爲新行讀取。爲了增長緩衝區,直到整行適合,您必須在收集行長度並增加行數之前繼續從文件讀取數據。但是我們必須檢查是否讀取了全行(包括最後一個換行符),以防fgets在放大緩衝區之前讀取最大允許數量char s,或者我們將連接下一行並計數兩個(或者在畸形情況下甚至更多)線條爲一體。

while((fgets(linebuffer,maxlinelen,fp))!=NULL) 
    { 
    while((strlen(linebuffer) == maxlinelen-1) && (linebuffer[maxlinelen-2] != '\n')) 
    { 
    maxlinelen*=2; 
    linebuffer=realloc(linebuffer,maxlinelen * sizeof(char)); 
    if(linebuffer==NULL) 
    { 
     printf("Error occurred reallocating space for linebuffer"); 
     exit(1); 
    } 
    fgets(linebuffer + (maxlinelen/2 - 1), maxlinelen/2 + 1, fp); 
    } 

將是一個(效率相當低,由於strlen調用)的方式來做到這一點。

+0

您可能可以做更多的編碼工作,並避免通過使用'fgetc'來避免在可能的大字符串上重複使用strlen。雖然我不會去挑選它,但因爲那沒什麼好玩的。 – Wug

+0

謝謝丹尼爾!但我仍然有問題。我的示例文本文件(infile)就像那樣; 其正確輸出; 號線:2 最大線路長度:50001 最小線長度:10001 平均:30001.00 我的PROG輸出 無線:8 最大線路長度:25427 最小線長度:511 平均:7500 ,25 我不明白。它有什麼不對? – ccc

+0

@ccc這是因爲你增加行數'行++;'等,即使'fgets'沒有讀取整行。只要填滿即可打印出'curlinelen'數組。 –

-1

這是我的realloc()文件逐行讀取功能。

void ReadDataFile() 
{ 
    FILE *fi = NULL; 
    int i = 0; 
    char *szString = 0; 
    nLine = 0; 

    char **g_chArr; 
    char **strTmp; 
    char szTmp[200]; 
    char g_szDebug[1024]; 

    fi = fopen("test.txt", "r"); 

    if(!feof(fi)) 
    { 
     sprintf_s(g_szDebug, "%s\n", "Start Reading File..."); 
     OutputDebugString(g_szDebug); 
    } 

    g_chArr = (char **)calloc(1, sizeof(char *)); 

    while(!feof(fi)) 
    { 
     strTmp = (char **)realloc(g_chArr, sizeof(char *)*(nLine+1)); 
     if(strTmp != NULL) 
     { 
      g_chArr = strTmp; 
     } 
     g_chArr[nLine] = strdup(fgets(szTmp, sizeof(szTmp), fi)); 

     nLine++; 
    } 
    fclose(fi); 

    for(i=0; i<nLine; ++i) 
    { 
     free(g_chArr[i]); 
    } 
    free(g_chArr); 
} 
相關問題