我就是这样做的,但我不确定这是首选的习语:
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);
}
Run Code Online (Sandbox Code Playgroud)
这没关系,有什么建议可以改善吗?
Jon*_*ler 13
如果你不打算使用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);
}
Run Code Online (Sandbox Code Playgroud)
它只识别换行符作为行尾; 它放弃了换行符.它不会溢出缓冲区; 它不会丢弃多余的字符,所以如果要求读取一个很长的行,它将以块的形式读取该行; 它返回读取的字符数.如果你需要区分溢出和恰好是缓冲区长度的行 - 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);
}
Run Code Online (Sandbox Code Playgroud)
这有无穷无尽的小变种,例如,如果必须截断该行,则丢弃任何多余的字符.如果你想处理DOS,(旧)Mac或Unix行结尾,那么从Kernighan&Pike的"编程实践"中借用CSV代码(一本优秀的书)并使用:
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);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以用它代替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);
}
Run Code Online (Sandbox Code Playgroud)
处理整个过程的另一种方法是使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
在上下文中,您打开文件并检查其有效性,然后调用:
copy_file(fp, stdout);
Run Code Online (Sandbox Code Playgroud)