如果你不打算使用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);
这是`CH =龟etc(FP)`;而不是`ch = fgetc()`。除此之外......你为什么不能使用`fgets()`的原因? – ThiefMaster 2010-11-27 19:32:01
也会出现分段错误:buffer [num_chars ++] = ch; 如果文件中的一行超过80个字符。 – 2010-11-27 20:52:16
while(!feof(fp)){,不是必须的吗? – Nyan 2010-11-28 02:27:51