Если вы не собираетесь использовать 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);
}
Их бесконечно много.второстепенные варианты, такие как отбрасывание лишних символов, если строка должна быть обрезана.Если вы хотите обработать DOS, (старые) окончания строк Mac или Unix, позаимствуйте лист из кода CSV из "Практика программирования" Kernighan & Pike (отличная книга) и используйте:
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);
}
Затем вы можете использовать это вместо теста 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);