2010-11-27 61 views
5

这就是我已经做到了,但我不知道这是首选的成语:阅读C文件行()

FILE *fp = fopen(argv[0], "r"); 
// handle fopen() returning NULL 

while (!feof(fp)) { 
    char buffer[80]; // statically allocated, may replace this later with some more sophisticated approach 
    int num_chars = 0; 

    for (int ch = fgetc(fp); ch != EOF && ch != '\n'; ch = fgetc()) { 
     buffer[num_chars++] = ch; 
    } 

    // null-terminate the string 
    buffer[num_chars] = '\0'; 

    printf("%s\n", buffer); 
} 

这样行,任何改善这个建议吗?

+1

这是`CH =龟etc(FP)`;而不是`ch = fgetc()`。除此之外......你为什么不能使用`fgets()`的原因? – ThiefMaster 2010-11-27 19:32:01

+1

也会出现分段错误:buffer [num_chars ++] = ch; 如果文件中的一行超过80个字符。 – 2010-11-27 20:52:16

+2

while(!feof(fp)){,不是必须的吗? – Nyan 2010-11-28 02:27:51

回答

12

如果你不打算使用fgets()(也许是因为你要删除的换行符,或者你要处理与"\r""\n""\r\n"行尾,或者你想知道有多少个字符中读取),你可以使用这个作为骨架功能:

int get_line(FILE *fp, char *buffer, size_t buflen) 
{ 
    char *end = buffer + buflen - 1; /* Allow space for null terminator */ 
    char *dst = buffer; 
    int c; 
    while ((c = getc(fp)) != EOF && c != '\n' && dst < end) 
     *dst++ = c; 
    *dst = '\0'; 
    return((c == EOF && dst == buffer) ? EOF : dst - buffer); 
} 

它只能识别换行符作为行结束;它会删除换行符。它不会溢出缓冲区;它不会丢弃多余的字符,所以如果被调用来读取一个很长的行,它会以块读取该行;它返回读取的字符数。如果你需要溢出,出现这种情况是缓冲区长度的线来区分 - 1,那么你可能需要保留换行符 - 与代码中的相应修改:

int get_line(FILE *fp, char *buffer, size_t buflen) 
{ 
    char *end = buffer + buflen - 1; /* Allow space for null terminator */ 
    char *dst = buffer; 
    int c; 
    while ((c = getc(fp)) != EOF && dst < end) 
    { 
     if ((*dst++ = c) == '\n') 
      break; 
    } 
    *dst = '\0'; 
    return((c == EOF && dst == buffer) ? EOF : dst - buffer); 
} 

有无尽的轻微变种就此而言,如果该行必须被截断,则丢弃任何多余的字符。

static int endofline(FILE *ifp, int c) 
{ 
    int eol = (c == '\r' || c == '\n'); 
    if (c == '\r') 
    { 
     c = getc(ifp); 
     if (c != '\n' && c != EOF) 
      ungetc(c, ifp); 
    } 
    return(eol); 
} 

然后你可以使用:如果你想处理DOS,(旧)的Mac或Unix行结尾,然后由Kernighan的&派克(一个很好的书),并利用借叶出CSV代码从"The Practice of Programming"到位的c != '\n'测试:

int get_line(FILE *fp, char *buffer, size_t buflen) 
{ 
    char *end = buffer + buflen - 1; /* Allow space for null terminator */ 
    char *dst = buffer; 
    int c; 
    while ((c = getc(fp)) != EOF && !endofline(fp, c) && dst < end) 
     *dst++ = c; 
    *dst = '\0'; 
    return((c == EOF && dst == buffer) ? EOF : dst - buffer); 
} 

处理全过程的其他替代方法是使用fread()fwrite()

void copy_file(FILE *in, FILE *out) 
{ 
    char buffer[4096]; 
    size_t nbytes; 
    while ((nbytes = fread(buffer, sizeof(char), sizeof(buffer), in)) != 0) 
    { 
     if (fwrite(buffer, sizeof(char), nbytes, out) != nbytes) 
      err_error("Failed to write %zu bytes\n", nbytes); 
    } 
} 

在上下文中,你会打开该文件,并检查其有效性,然后调用:

copy_file(fp, stdout); 
1

如果您需要每个字符为了检查它或修改或其他任何字符然后使用fgets。 对于其他一切,请使用fgets。

fgets (buffer, BUFFER_SIZE, fp); 

请注意,fgets将读取,直到到达新的行或EOF(或缓冲区充满当然)。如果从文件读取,则新字符串“\ n”也附加到字符串。空字符也被追加。

fgets returns :

成功时,该函数返回相同的海峡参数。
如果遇到文件结束并且没有读取任何字符,则str的内容保持不变,并返回空指针。
如果发生错误,则返回空指针。
使用ferror或feof来检查是否发生错误或已达到文件结束。

1

如果用户输入80个或更多字符,则可能导致缓冲区溢出。

我与ThiefMaster:你应该使用fgets(),而不是。将输入读入大于任何合法输入的缓冲区,然后检查最后一个字符是换行符。

1

除非您希望以超高效的方式设置读取的字符数,否则请使用fgets()

用类似但不同的简单fgets()替换您的示例,您将“丢失”num_chars变量。

fgets(buffer, sizeof buffer, stdin); 
fputs(buffer, stdout); /* buffer contains a '\n' */ 

如果需要删除最后一个“\ n”

buffer[0] = 0; 
if (!fgets(buffer, sizeof buffer, stdin)) /* error or eof */; 
num_chars = strlen(buffer); 
if (num_chars && (buffer[num_chars - 1] == '\n')) buffer[--num_chars] = 0; 
puts(buffer); /* add a '\n' to output */ 

如果字符串真的是堆积如山的(如42兆个字节价值),你可能会更好的性格和保存读取字符计数为num_chars,比先使用fgets后再使用strlen

-1

没有LINESIZE限制UND严格C89(你的代码是唯一的C99),如:

FILE *fp = fopen(argv[0], "r"); 
size_t len=1; 
char c, *buffer=calloc(1,1); 
/* handle fopen() returning NULL*/ 
while(c=fgetc(fp),!feof(fp)) 
    if(c=='\n') 
    { 
    puts(buffer); 
    len=1; 
    *buffer=0; 
    } 
    else 
    strncat(buffer=realloc(buffer,++len),&c,1); /* check for NULL needed */ 

puts(buffer); 
free(buffer); 
fclose(fp); 
-2
#include<stdio.h> 
void main() 
{ 
    FILE *fp; 
    char c; 
    int ch=0,w=0,l=0; 
    fp=fopen("c:\read.txt","w"); 
    clrscr(); 
    if(fp==NULL) 
    { 
     printf("\n\n\tDOES NOT EXIXST"); 
     getch(); 
     exit(0); 
    } 
    while(!feof(fp)) 
    { 
     c=fgetc(fp); 

     ch++; 
     if(c==' ') 
     { 
      w++; 
     } 
     if(c=='\n') 
     { 
      l++; 
      w++; 
     } 
    } 

    printf("\n\n\tTOTAL CHAR = %d\n\n\tTOTAL WORDS = %d\n\n\tTOTAL LINES = %d",ch,w,l); 

}