tmp += cur;

  last = cur;

 }

}

int main(int argc, char** argv) {

 if (argc < 3)

  return(EXIT_FAILURE);

 int w = 72;

 ifstream in(argv[1]);

 ofstream out(argv[2]);

 if (!in || !out)

  return(EXIT_FAILURE);

 if (argc == 4) w = atoi(argv[3]);

 textWrap(in, out, w);

 out.close();

 if (out)

  return(EXIT_SUCCESS);

 else

  return(EXIT_FAILURE);

}

Обсуждение

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

Пример 4.25 использует потоки почти так же, как и рецепт 4.15. За дополнительной информацией о потоках и их использовании обратитесь к этому рецепту.

Смотри также

Рецепт 4.15.

4.17. Подсчет числа символов, слов и строк в текстовом файле

Проблема

Требуется подсчитать число символов, слов и строк — или каких-либо других элементов текста — в текстовом файле.

Решение

Для чтения символов по одному используйте входной поток и по мере чтения символов, слов и строк увеличивайте счетчики. Пример 4.26 содержит функцию countStuff, которая именно это и делает.

Пример 4.26. Подсчет статистики по текстовому файлу

#include <iostream>

#include <fstream>

#include <cstdlib>

#include <cctype>

using namespace std;

void countStuff(istream& in,

 int& chars, int& words, int& lines) {

 char cur = '';

 char last = '';

 chars = words = lines = 0;

 while (in.get(cur)) {

  if (cur == ' ' ||

   (cur == 'f' && last == ' '))

   lines++;

  else chars++;

  if (!std::isalnum(cur) && // Это конец

   std::isalnum(last))      // слова

   words++;

  last = cur;

 }

 if (chars > 0) {         // Изменить значения слов

  if (std::isalnum(last)) // и строк для специального

   words++;               // случая

  lines++;

 }

}

int main(int argc, char** argv) {

 if (argc < 2)

  return(EXIT _FAILURE);

 ifstream in(argv[1]);

 if (!in)

  exit(EXIT_FAILURE);

 int c, w, l;

 countStuff(in, c, w, l);

 cout << 'символов: ' << c << ' ';

 cout << 'слов: ' << w << ' ';

 cout << 'строк: ' << l << ' ';

}

Обсуждение

Этот алгоритм очень прост. С символами все просто: увеличивайте счетчик символов при каждом вызове get для входного потока. Со строками все не намного сложнее, так как способ представления концов строк зависит от операционной системы. К счастью, обычно это либо символ новой строки ( ), либо последовательность из символов возврата каретки и перевода строки ( ). Отслеживая текущий и предыдущий символы, можно легко обнаружить вхождения этой последовательности. Со словами все проще или сложнее, в зависимости от определения того, что такое «слово».

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

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату