2017-04-04 1071 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]); 
} 

...