Какой самый простой способ подсчитать переводы строки в файле ASCII?
Какой самый быстрый способ получить строки файла ASCII?
5 ответов
Обычно вы читаете файлы в C, используя fgets
, Вы также можете использовать scanf("%[^\n]")
, но довольно много людей, читающих код, могут найти это запутанным и чуждым.
Изменить: с другой стороны, если вы действительно хотите просто посчитать строки, слегка измененную версию scanf
подход может работать довольно хорошо:
while (EOF != (scanf("%*[^\n]"), scanf("%*c")))
++lines;
Преимущество этого заключается в том, что с '*' в каждом преобразовании, scanf
читает и сопоставляет ввод, но ничего не делает с результатом. Это означает, что нам не нужно тратить память на большой буфер, чтобы хранить содержимое строки, которая нас не волнует (и все же есть шанс получить строку, которая даже больше этой, поэтому наш счетчик в итоге окажется неправильным если мы не проделали еще большую работу, чтобы выяснить, закончился ли ввод, который мы читали, новой строкой).
К сожалению, мы должны разбить scanf
на две части, как это. scanf
останавливает сканирование при сбое преобразования, и если вход содержит пустую строку (две последовательные строки), мы ожидаем, что первое преобразование завершится неудачно. Однако даже если это не удастся, мы хотим, чтобы произошло второе преобразование, чтобы прочитать следующую новую строку и перейти к следующей строке. Поэтому мы пытаемся сначала преобразовать, чтобы "съесть" содержимое строки, а затем выполнить %c
преобразование, чтобы прочитать новую строку (часть, которую мы действительно заботимся). Мы продолжаем делать оба до второго звонка scanf
возвращается EOF
(который обычно находится в конце файла, хотя это также может произойти в случае чего-то вроде ошибки чтения).
Edit2: Конечно, есть еще одна возможность, которая (по крайней мере, возможно) проще и проще для понимания:
int ch;
while (EOF != (ch=getchar()))
if (ch=='\n')
++lines;
Единственная часть этого, что некоторые люди находят нелогичным, состоит в том, что ch
должен быть определен как int
не char
чтобы код работал правильно.
Вот решение, основанное на fgetc(), которое будет работать для строк любой длины и не требует от вас выделения буфера.
#include <stdio.h>
int main()
{
FILE *fp = stdin; /* or use fopen to open a file */
int c; /* Nb. int (not char) for the EOF */
unsigned long newline_count = 0;
/* count the newline characters */
while ( (c=fgetc(fp)) != EOF ) {
if ( c == '\n' )
newline_count++;
}
printf("%lu newline characters\n", newline_count);
return 0;
}
Может быть, я что-то упускаю, но почему бы не просто
#include <stdio.h>
int main(void) {
int n = 0;
int c;
while ((c = getchar()) != EOF) {
if (c == '\n')
++n;
}
printf("%d\n", n);
}
если вы хотите посчитать частичные строки (т.е. [^\n]EOF):
#include <stdio.h>
int main(void) {
int n = 0;
int pc = EOF;
int c;
while ((c = getchar()) != EOF) {
if (c == '\n')
++n;
pc = c;
}
if (pc != EOF && pc != '\n')
++n;
printf("%d\n", n);
}
Общее, почему Вы сравниваете все символы? Это очень медленно. В 10 МБ файле это ~3 с.
По решению быстрее.
unsigned long count_lines_of_file(char *file_patch) {
FILE *fp = fopen(file_patch, "r");
unsigned long line_count = 0;
if(fp == NULL){
return 0;
}
while ( fgetline(fp) )
line_count++;
fclose(fp);
return line_count;
}
Как насчет этого?
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 4096
int main(int argc, char** argv)
{
int count;
int bytes;
FILE* f;
char buffer[BUFFER_SIZE + 1];
char* ptr;
if (argc != 2 || !(f = fopen(argv[1], "r")))
{
return -1;
}
count = 0;
while(!feof(f))
{
bytes = fread(buffer, sizeof(char), BUFFER_SIZE, f);
if (bytes <= 0)
{
return -1;
}
buffer[bytes] = '\0';
for (ptr = buffer; ptr; ptr = strchr(ptr, '\n'))
{
++count;
++ptr;
}
}
fclose(f);
printf("%d\n", count - 1);
return 0;
}