Как посчитать количество строк в файле c

Обновлено: 16.07.2024

Строки файла строк в языке С разделяются символом \n , поэтому программа ввода строк с клавиатуры и подсчета их количества будет выглядеть так, как показано в листинге 2.5.

using namespace System;

//признак конца файла

printf("Enter your string and press <Enter> and <Ctrl + z> >\n"); while((c=getchar()) !=eof)

printf("String's number is: %d\n",nl); _getch();

Здесь новое по сравнению с предыдущими подобными программами только то, что появилась операция == (равно) и новый оператор if — это оператор условного перехода, изменяющий последовательное (сверху вниз) выполнение операторов программы в зависимости от истинности/ложности условия (оно записывается в круглых скобках в заголовочной части оператора и может представлять собой выражение). Если условие истинно, то выполняется тело оператора, которое обладает точно такими же свойствами, что и тела операторов while и for : если в теле всего один оператор, то этот оператор может не заключаться в фигурные скобки, в противном случае фигурные скобки обязательны. В нашем случае тело состоит из од-

Часть I. Изучение языка С/С++

ного оператора nl++ , который выполняется всякий раз, когда введен не символ конца строки. В противном случае тело if не выполняется. Для простоты понимания мы ввели фигурные скобки там, где их можно опустить, выделяя тем самым тело оператора. Тело оператора while тоже состоит из одного оператора if (неважно, сколько операторов включает тело if ), поэтому оператор while записан без фигурных скобок.

Программа работает так: обнуляется счетчик количества вводимых строк ( nl ), начинает выполняться оператор цикла while , обеспечивающий ввод с клавиатуры потока символов (вычисляется, как обычно, выражение в заголовочной части while , чтобы проверить условие на истинность/ложность, что требует нового ввода символа). Среди потока символов встречаются символы \n , сигнализирующие об окончании строки: когда мы набираем строки в консольном окне, мы заканчиваем их ввод символом <Enter>. Как только такой символ обнаруживается с помощью оператора if , в счетчик nl , расположенный в теле if , добавляется единица. Когда после последней строки, завершающейся символом \n , мы нажмем комбинацию клавиш <Ctrl>+<z> (символ конца ввода), ввод строк завершится. Условие выполнения оператора while нарушится, и управление будет передано на оператор, следующий за его телом. Это будет оператор вывода printf() . Результат работы программы представлен на рис. 2.4.

Рис. 2.4. Результат работы программы листинга 2.5

Подсчет количества слов в файле

Договоримся, что слово — это любая последовательность символов, не содержащая пробелов, символов табуляции ( \t ) и новой строки ( \n ). Наряду с количеством слов программа будет подсчитывать количество символов и строк.

В текстовом файле посчитать количество строк, а также для каждой отдельной строки определить количество в ней символов и слов.

Подсчет строк:
Ввести счетчик, присвоить ему 0.
Пока не будет достигнут конец файла, считывать очередную строку файла и увеличивать счетчик на 1.

Подсчет символов в строке:
Измерять длину очередной строки с помощью встроенный в язык программирования функции.

Подсчет слов в строке:

  1. Ввести счетчик слов и присвоить ему 0.
  2. Ввести флаговую переменную и присвоить ей 0 (сигнал нахождения вне слова).
  3. Пока не будет достигнут конец строки:
    1. Если очередной символ не пробел и флаг указывает на нахождение вне слова, то увеличить счетчик слов и присвоить флаговой переменной 1 (сигнал нахождения внутри слова).
    2. Если же очередной символ пробел, то присвоить флагу 0.

    Pascal


    Файл выполнен в среде GNU/Linux, компилятор FreePascal. Русские символы считаются за 2 символа. Например, в данном примере во второй строке 9 кириллических символа, пробел и восклицательный знак: 18 + 2 = 20 символов.

    Язык Си

    посчитать количество строк в файле си


    Тот же "эффект", что и в Паскале: кириллический символ считается за 2.

    Функция fgets() считывает строку вместе с символом перехода на новую строку. Аргумент N не позволяет считать больше указанного количества символов, но длина строки определяется по количеству считанных (т.е. фактической длиной строки).

    Python

    python количество строк в файле


    Символ перехода на новую строку учитывается.

    КуМир

    Здесь считается общее количество слов и символов.

    Basic-256


    Переход на новую строку учитывается как символ.


    var
    f: text;
    s: string;
    line, chr, wrd: word;
    i: byte;
    flag: boolean;
    begin
    assign(f,'text.txt');
    reset(f);
    line := 0;
    while not EOF(f) do begin
    readln(f,s);
    write(s, ' - ');

    chr := length(s);
    write(chr, ' симв., ');

    wrd := 0;
    flag := false;
    for i:=1 to chr do
    if (s[i] ' ') and (flag = false) then begin
    wrd := wrd + 1;
    flag := true;
    end
    else
    if s[i] = ' ' then flag := false;
    writeln(wrd, ' сл.');
    end;
    close(f);
    writeln(line,' стр.');
    end.

    Hello world! - 12 симв., 2 сл.
    Привет мир! - 20 симв., 2 сл.
    One, two, three - 15 симв., 3 сл.
    Один, два, три - 24 симв., 3 сл.
    4 стр.


    Файл выполнен в среде GNU/Linux, компилятор FreePascal. Русские символы считаются за 2 символа. Например, в данном примере во второй строке 9 кириллических символа, пробел и восклицательный знак: 18 + 2 = 20 символов.

    посчитать количество строк в файле си

    word = 0;
    flag = 0;
    for (i=0; i

    python количество строк в файле

    f = open('text.txt')
    line = 0
    for i in f:
    line += 1

    flag = 0
    word = 0
    for j in i:
    if j != ' ' and flag == 0:
    word += 1
    flag = 1
    elif j == ' ':
    flag = 0

    Hello world!
    13 симв. 2 сл.
    Привет мир!
    12 симв. 2 сл.
    One, two, three
    16 симв. 3 сл.
    Один, два, три
    15 симв. 3 сл.
    4 стр.

    Символ перехода на новую строку учитывается.

    использовать Файлы П
    алг
    нач
    цел f, line, word, char, in, i
    лит s
    line := 0
    word := 0
    char := 0
    f := открыть на чтение ("текст.txt")
    нц пока не конец файла (f)
    Фввод f, s
    line := line + 1
    вывод s, нс
    char := char + длин(s)
    in := 0
    нц для i от 1 до длин(s)
    если s[i] " " и in = 0 то
    word := word + 1
    in := 1
    иначе
    если s[i] = " " то in := 0 все
    все
    кц
    кц
    закрыть(f)
    вывод нс, "строк - ", line, нс
    вывод "слов - ", word, нс
    вывод "символов - ", char
    кон

    Мне нужно прочитать количество строк в файле перед выполнением некоторых операций над этим файлом. Когда я пытаюсь прочитать файл и увеличить переменную line_count на каждой итерации, пока не достигну eof. В моем случае это было не так быстро. Я использовал ifstream и fgets . Они оба были медлительны . Есть ли хакерский способ сделать это, который также используется, например, BSD, Linux kernel или berkeley db.(может быть с помощью побитовых операций).

    Как я уже говорил, есть миллионы строк в этот файл и он продолжает увеличиваться, каждая строка имеет около 40 или 50 символов. Я использую Linux.

    Примечание.: Я уверен, что будут люди, которые могут сказать, что используют идиота DB. Но кратко в моем случае я не могу использовать db.

    единственный способ найти счетчик строк-прочитать весь файл и подсчитать количество символов конца строки. Самый быстрый способ сделать это, вероятно, прочитать весь файл в большой буфер с одной операцией чтения, а затем пройти через буфер, подсчитывая символы "\n".

    поскольку ваш текущий размер файла составляет около 60 мб, это не является привлекательным вариантом. Вы можете получить некоторую скорость, не читая весь файл, но читая его кусками., скажем, размер 1Mb. Вы также скажите, что о базе данных не может быть и речи, но она действительно выглядит лучшим долгосрочным решением.

    Edit: Я просто запустил небольшой тест на этом, и использование буферизованного подхода (размер буфера 1024K) кажется немного более чем в два раза быстрее, чем чтение строки за раз с getline (). Вот код - мои тесты были сделаны с g++, используя-O2 уровень оптимизации:

    Не используйте строки stl C++ и getline (или fgets C), просто необработанные указатели стиля C и либо блок чтения в кусках размера страницы, либо mmap файл.

    затем сканируйте блок в собственном размере слова вашей системы (т. е. либо uint32_t или uint64_t ), используя один из магические алгоритмы ' SIMD в рамках операций регистра (SWAR)' для тестирования байтов в word. Пример здесь; цикл с 0x0a0a0a0a0a0a0a0aLL в нем сканирует на разрывы строк. ( этот код получает около 5 циклов на входной байт, соответствующий регулярному выражению в каждой строке файла)

    если файл составляет всего несколько десятков или СТО или около того мегабайт, и он продолжает расти (т. е. что-то продолжает писать ему), то есть хорошая вероятность того, что linux кэширует его в памяти, поэтому он не будет ограничен дисковым вводом, но ограничена пропускная способность памяти.

    если файл только когда-либо добавляется, вы также можете запомнить количество строк и предыдущая длина, и начало от там.

    было указано, что вы можете использовать mmap с алгоритмами stl C++ и создать функтор для передачи в std::foreach. Я предложил вам не делать этого не потому, что вы не можете сделать это таким образом, но нет никакой выгоды в написании дополнительного кода для этого. Или вы можете использовать mmapped итератор boost, который обрабатывает все это для вас; но для проблемы код, с которым я связан, был написан для этого намного медленнее, и вопрос был о скорости, а не стиле.

    вы написали, что он продолжает расти. Это похоже на файл журнала или что-то подобное, где новые строки добавляются, но существующие строки не изменяются. Если это так, вы можете попробовать постепенный подход.

    разбор до конца файла. Запомните количество строк и смещение EOF. Когда файл растет fseek к смещению, проанализируйте EOF и обновите количество строк и смещение.

    существует разница между подсчетом строк и разделителями подсчета строк. Некоторые общие gotchas, чтобы следить за, если получение точного подсчета строк важно:

    какова кодировка файла? Байтовые решения будут работать для ASCII и UTF-8, но следите, если у вас есть UTF-16 или какая-то многобайтовая кодировка, которая не гарантирует, что байт со значением линейного канала обязательно кодирует линейный канал.

    много текста файлы не имеют разделителя строк в конце последней строки. Поэтому, если ваш файл говорит "Hello, World!" , вы можете получить счет 0 вместо 1. Вместо того, чтобы просто подсчитывать разделители линий, вам понадобится простая государственная машина для отслеживания.

    некоторые очень неясные файлы используют Unicode U+2028 LINE SEPARATOR (или даже U+2029 PARAGRAPH SEPARATOR ) как разделители линии вместо более общего возвращения экипажа и/или линии питания. Вы также можете следить за U+0085 NEXT LINE (NEL) .

    вам придется рассмотреть, хотите ли вы считать некоторые другие управляющие символы в качестве прерывателей строк. Например, если U+000C FORM FEED или U+000B LINE TABULATION (a.к. a. вертикальная вкладка) считается переходом на новую строку?

    текстовые файлы из более старых версий Mac OS (до OS X) используют возврат каретки ( U+000D ), а не перевода строки ( U+000A ) в отдельных строках. Если Вы читаете необработанные байты в буфер (например, с вашим потоком в двоичный режим) и сканирование их, вы придумаете количество 0 на этих файлах. Вы не можете подсчитать как возврат каретки, так и каналы строк, потому что файлы ПК обычно заканчивают строку с обоими. Опять же, вам понадобится простая государственная машина. (Кроме того, вы можете читать файл в текстовом режиме, а не в двоичном режиме. Текстовые интерфейсы нормализуют разделители строк до '\n' для файлов, которые соответствуют конвенции, используемой на вашей платформе. Если Вы читаете файлы с других платформ, вы вернетесь к двоичный режим с государственной машиной.)

    если у вас когда-либо была супер длинная строка в файле, getline() подход может вызвать исключение, вызывающее сбой простого счетчика строк на небольшом количестве файлов. (Это особенно верно, если Вы читаете старый файл Mac на платформе, отличной от Mac, вызывая getline() посмотреть весь файл как одну гигантскую строку.) Читая куски в буфер фиксированного размера и используя государственную машину, вы можете сделать его пулей доказательство.

    код в принятом ответе страдает от большинства из этих ловушек. Сделайте это прямо перед тем, как сделать это быстро.

    помните, что все fstreams буферизованы. Таким образом, они фактически читают кусками, поэтому вам не нужно воссоздавать эту функциональность. Все, что вам нужно сделать, это просканировать буфер. Не используйте getline (), хотя это заставит вас размер строки. Поэтому я бы просто использовал итераторы STL std::count и stream.

    Это не медленно из-за вашего алгоритма , это медленно, потому что операции ввода-вывода медленные. Я полагаю, вы используете простой алгоритм O(n), который просто последовательно просматривает файл. В таком случае, есть нет быстрый алгоритм, который может оптимизировать ваши программы.

    , Я сказал, что нет более быстрого алгоритма, но есть более быстрый механизм, который называется "сопоставленный файл памяти" , есть некоторый недостаток для сопоставленных файлов, и это может быть не подходит для вас случай, так что вам придется прочитать об этом и выяснить самостоятельно.

    сопоставленные с памятью файлы не позволят вам реализовать алгоритм лучше, чем O (n), но это мая уменьшит время доступа IO.

    вы можете получить окончательный ответ, только сканируя весь файл в поисках символов новой строки. Ничего не поделаешь.

    тем не менее, есть несколько возможностей, которые вы можете рассмотреть.

    1 / Если вы используете упрощенный цикл, читая по одному символу за раз, проверяя наличие новых строк, не делайте этого. Несмотря на то, что ввод-вывод может быть буферизован, сами вызовы функций являются дорогостоящими, с учетом времени.

    лучшим вариантом является чтение больших кусков файл (скажем, 5M) в память с одной операцией ввода-вывода, а затем обработать это. Вам, вероятно, не нужно слишком беспокоиться о специальной инструкции по сборке, так как библиотека времени выполнения C будет оптимизирована в любом случае - простой strchr() должны сделать это.

    2 / Если вы говорите, что общая длина строки составляет около 40-50 символов, и вам не нужно точно количество строк, просто возьмите размер файла и разделите на 45 (или любое среднее значение, которое вы считаете нужным использовать).

    3/ Если это что-то вроде файла журнала, и вы не есть чтобы сохранить его в одном файле (может потребоваться доработка на других частях системы), рассмотрите возможность периодического разделения файла.

    например, когда он достигает 5 м, переместите его (например, x.log ), чтобы от имени файла (например, x_20090101_1022.log ) и выяснить, сколько строк есть в этой точке (сохранение его в x_20090101_1022.count , затем начните новый x.log файл журнала. Характеристики файлов журнала означают, что этот созданный раздел dated будет никогда не изменяйте, поэтому вам никогда не придется пересчитывать количество строк.

    чтобы обработать журнал "файл", вы просто cat x_*.log через какую-то технологическую трубу, а не cat x.log . Чтобы получить количество строк "файла", сделайте wc -l на текущем x.войти (относительно быстро) и добавить его к сумме всех значений в x_*.count файлы.

    вещь, которая занимает время, загружает 40 + MB в память. Самый быстрый способ сделать это-либо запомнить его, либо загрузить его за один раз в большой буфер. Как только у вас есть это в памяти, так или иначе, цикл, пересекающий данные, ищущие \n символы практически мгновенно, независимо от того, как это реализовано.

    Итак, на самом деле, самый важный трюк-загрузить файл в память как можно быстрее. И самый быстрый способ сделать это-сделать это как один операция.

    в противном случае может существовать множество трюков для ускорения алгоритма. Если строки добавляются, Не изменены или удалены, и если Вы читаете неоднократно файла, можно кэш строки читал ранее, и в следующий раз вам придется прочитать файл, читали только вновь добавленных строк.

    или, возможно, вы можете поддерживать отдельный индексный файл, показывающий местоположение известных символов "\n", поэтому эти части файла можно пропустить.

    чтение большой объем данных с жесткого диска происходит медленно. Ничего не поделаешь.

    Мне нужно прочитать количество строк в файле, прежде чем делать какие-либо операции над этим файлом. Когда я пытаюсь прочитать файл и увеличивать переменную line_count на каждой итерации, пока не достигну eof. В моем случае это было не так быстро. Я использовал как ifstream, так и fgets. Они оба были медленными. Есть ли хакерский способ сделать это, который также используется, например, BSD, ядром Linux или Беркли БД (может быть с помощью побитовых операций).

    Как я уже говорил, в этом файле миллионы строк, и он продолжает увеличиваться, каждая строка содержит около 40 или 50 символов. Я использую Linux.

    Примечание: я уверен, что найдутся люди, которые скажут, что используют идиота БД. Но кратко в моем случае я не могу использовать БД.

    Единственный способ узнать количество строк - это прочитать весь файл и посчитать количество символов конца строки. Самый быстрый способ сделать это, вероятно, состоит в том, чтобы прочитать весь файл в большой буфер за одну операцию чтения, а затем пройти через буфер, считая символы '\n'.

    Поскольку текущий размер файла составляет около 60 МБ, это не очень привлекательный вариант. Вы можете получить некоторую скорость, не читая весь файл, а читая его кусками, скажем, размером 1Mb. Вы также говорите, что о базе данных не может быть и речи, но она действительно является лучшим долгосрочным решением.

    Изменить: я только что провел небольшой тест по этому вопросу, и использование буферизованного подхода (размер буфера 1024 КБ), кажется, более чем в два раза быстрее, чем чтение строки за раз с помощью getline(). Вот код - мои тесты были выполнены на g++ с использованием уровня оптимизации -O2:

    Не используйте строки C++ stl и getline (или fgets Си), просто необработанные указатели в стиле Си и либо блокирующие чтение в кусках размера страницы, либо mmap файл.

    Затем просканируйте блок по собственному размеру слова вашей системы (т.е. uint32_t или же uint64_t ) использование одного из магических алгоритмов "Операции SIMD в регистре (SWAR)" для проверки байтов в слове. Пример здесь; петля с 0x0a0a0a0a0a0a0a0aLL в нем сканирует разрывы строк. (этот код получает около 5 циклов на входной байт, соответствующий регулярному выражению в каждой строке файла)

    Если размер файла составляет всего несколько десятков или сотен или более мегабайт, и он продолжает расти (т.е. что-то продолжает записывать в него), то есть большая вероятность, что в linux он кэшируется в памяти, поэтому он не будет ограничен дисковым вводом-выводом., но пропускная способность памяти ограничена.

    Если файл только добавляется, вы также можете запомнить количество строк и предыдущую длину и начать с этого.

    Было отмечено, что вы можете использовать mmap с алгоритмами st ++ C++ и создать функтор для передачи в std::foreach. Я предложил вам не делать этого не потому, что вы не можете сделать это таким образом, но нет никакого смысла в написании дополнительного кода для этого. Или вы можете использовать итератор Mmapped, который обрабатывает все это за вас; но для проблемы код, на который я ссылался, был написан для этого намного медленнее, и вопрос был о скорости, а не о стиле.

    Вы написали, что он продолжает расти. Похоже, это файл журнала или что-то подобное, где новые строки добавляются, но существующие строки не изменяются. Если это так, вы можете попробовать поэтапный подход.

    Разбор до конца файла. Запомните количество строк и смещение EOF. Когда файл растет fseek до смещения, проанализируйте EOF и обновите счетчик строк и смещение.

    Существует разница между подсчетом строк и подсчетом разделителей строк. Некоторые распространенные ошибки, на которые стоит обратить внимание, если важно получить точное количество строк:

    Какая кодировка файла? Побайтовые решения будут работать для ASCII и UTF-8, но будьте внимательны, если у вас есть UTF-16 или какое-нибудь многобайтовое кодирование, которое не гарантирует, что байт со значением перевода строки обязательно кодирует перевод строки.

    Многие текстовые файлы не имеют разделителя строк в конце последней строки. Так что если ваш файл говорит "Hello, World!" , вы можете получить счетчик 0 вместо 1. Вместо того, чтобы просто считать разделители строк, вам понадобится простой конечный автомат для отслеживания.

    Некоторые очень непонятные файлы используют Unicode U+2028 LINE SEPARATOR (или даже U+2029 PARAGRAPH SEPARATOR ) в качестве разделителей строк вместо более распространенного возврата каретки и / или перевода строки. Вы также можете следить за U+0085 NEXT LINE (NEL) ,

    Вам нужно будет подумать, хотите ли вы считать некоторые другие управляющие символы в качестве переносчиков строк. Например, если U+000C FORM FEED или же U+000B LINE TABULATION (ака вертикальная вкладка) считается переход на новую строку?

    Текстовые файлы из более старых версий Mac OS (до OS X) используют возврат каретки ( U+000D ), а не переводы строки ( U+000A ) разделять строки. Если вы читаете необработанные байты в буфер (например, с вашим потоком в двоичном режиме) и сканируете их, вы получите счетчик 0 для этих файлов. Вы не можете сосчитать как возврат каретки, так и перевод строки, потому что файлы ПК обычно заканчивают строку обоими. Опять же, вам понадобится простой конечный автомат. (В качестве альтернативы вы можете прочитать файл в текстовом режиме, а не в двоичном режиме. Текстовые интерфейсы нормализуют разделители строк в '\n' для файлов, которые соответствуют соглашению, используемому на вашей платформе. Если вы читаете файлы с других платформ, вы вернетесь в двоичный режим с конечным автоматом.)

    Если у вас есть супер длинная строка в файле, getline() подход может выдать исключение, приводящее к сбою вашего простого счетчика строк на небольшом количестве файлов. (Это особенно верно, если вы читаете старый файл Mac на платформе не Mac, что приводит к getline() чтобы увидеть весь файл как одну гигантскую строку.) Считывая куски в буфер фиксированного размера и используя конечный автомат, вы можете сделать его пуленепробиваемым.

    Код в принятом ответе страдает от большинства этих ловушек. Сделайте это правильно, прежде чем сделать это быстро.

    Читайте также: