2017-04-04 256 views
0
FILE *fp = fopen("story.txt", "r"); 
if(fp == NULL){ 
    printf("\nError opening file.\nExiting program.\n"); 
    exit(1); 
} 
char text[100]; 

while(fgets(text, 100, fp) != NULL){ 
    printf("%s", text); 
} 
printf("\n"); 
fclose(fp); 

我試圖打印文本文件的前100個字符,包括新行,但是當我使用上面的代碼時,它呈現出一些奇怪的行爲。首先,它只打印文本文件的最後一行,它本身不超過100個字符。另外,如果我包括在while循環即使用fgets從.txt文件讀取並打印多行

while(fgets(text, 100, fp) != NULL){ 
    printf("%s", text); 
    printf("%s", text); 

}兩個打印語句

它打印比文本文件(某處十萬,這是一個很大的文本文件)的125個字符多了不少,並且所述文本的內容是來自文件中的一串看似隨機的片斷,不會有新的行或任何東西。

所以我想我的問題是有沒有辦法使用fgets,以便從頂部開始打印文件中的文本,幷包含新行?我最終必須使用它來將文本文件轉換爲字符數組,以便可以基於該數組創建一個新的,修改過的字符數組,並將其打印到新的文本文件中。所以如果有更好的方法來實現這個最終目標,那將是值得讚賞的。

編輯:經過一些討論後,我意識到我正在使用的文本只是一個帶有回車符和沒有換行符的文本大塊。我猜在這一點上我的主要問題是如何將這個文本文件與回車轉換爲字符數組。

+0

文本文件中的行多長時間? –

+0

我懷疑你的線條比100個字符長得多,所以在大多數情況下'text'中沒有換行符。你可以在調用printf()後添加'fflush(stdout);'。 –

+0

似乎線條少於100個字符,並且正在打印的這些線段的長度小於100個字符。目前所有的輸出都有很多奇怪的行爲。例如,當我包含兩個prinf語句並將終端的大小調整爲似乎超過100個結果的範圍時,僅打印出文本文件的最後一行,還有一些額外的看似隨機的單詞,文本。但是,當終端調整到更小的尺寸時,它會打印出更多的文本。當只使用一個printf語句時會發生類似的情況 –

回答

0

如果目標是以100個字符的行讀取文本文件並取消回車,只要您還記得fgets()將帶有字符(包括下一個換行符),您仍然可以使用fgets() ,或者直到讀取了小於指定數量的字符。

下面的代碼讀取一行文字,最多可達BUFFER_SZ-1個字符,增加內存分配來保存新的文本行,並將行復制到分配的空間中,刪除回車符和任何後續換行符。請注意,重新分配空間的地址首先存儲在臨時指針中。 realloc()在發生分配錯誤時返回空指針,並且此步驟可避免潛在的內存泄漏。

由於行被打破在BUFFER_SZ-1字符,可能會跨行分割單詞,並且您可能需要開發其他邏輯來處理此問題。如同在這裏所做的那樣,以更大的塊重新分配並且不太頻繁,而不是每一行一次更有效。還要注意,以二進制模式打開文件以更加緊密地解析行結束可能很有用。

#include <stdio.h> 
#include <stdlib.h> 

#define BUFFER_SZ 100 

int main(void) 
{ 
    FILE *fp = fopen("story.txt", "r"); 
    if (fp == NULL) { 
     fprintf(stderr, "Unable to open file\n"); 
     exit(EXIT_FAILURE); 
    } 

    char buffer[BUFFER_SZ]; 
    char (*text)[sizeof buffer] = NULL; 
    char (*temp)[sizeof buffer] = NULL; 
    size_t numlines = 0; 

    while (fgets(buffer, sizeof buffer, fp) != NULL) { 
     ++numlines; 
     /* Allocate space for next line */ 
     temp = realloc(text, sizeof(*text) * numlines); 
     if (temp == NULL) { 
      fprintf(stderr, "Error in realloc()\n"); 
      exit(EXIT_FAILURE); 
     } 
     text = temp; 

     /* Copy buffer to text, removing carriage returns and newlines */ 
     char *c = buffer; 
     char *line = text[numlines-1]; 
     while (*c != '\n' && *c != '\0') { 
      if (*c != '\r') { 
       *line++ = *c; 
      } 
      ++c; 
     } 
     *c = '\0'; 
    } 

    if (fclose(fp) != 0) { 
     fprintf(stderr, "Unable to close file\n"); 
    } 

    for (size_t i = 0; i < numlines; i++) { 
     printf("%s\n", text[i]); 
    } 

    free(text); 

    return 0; 
} 

另一種選擇是用換行符替換回車符。這可能是OP想到的。上面的程序很容易修改來實現這一點。請注意,從顯示結果的printf()語句中刪除了\n,因爲換行符現在包含在字符串中。

... 

    /* Copy buffer to text, converting carriage returns to newlines */ 
    char *c = buffer; 
    char *line = text[numlines-1]; 
    while (*c != '\n' && *c != '\0') { 
     if (*c == '\r') { 
      *line++ = '\n'; 
     } else { 
      *line++ = *c; 
     } 
     ++c; 
    } 
    *c = '\0'; 
} 

if (fclose(fp) != 0) { 
    fprintf(stderr, "Unable to close file\n"); 
} 

for (size_t i = 0; i < numlines; i++) { 
    printf("%s", text[i]); 
} 

...