, : struct, : Top


14 Файлы

Данный листочек посвящен основам чтения данных из файлов и вывода данных в файл.

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

Для того, чтобы в C++ работать с файлами необходимо подключить заголовочный файл fstream:

     #include <fstream>

После этого можно объявлять объекты, привязанные к файлам: для чтения данных из файла используются объекты типа ifstream (аббревиатура от input file stream, для записи данных в файл используются объекты типа ofstream (output file stream). Например

     ifstream in;  // Поток in будем использовать для чтения
     ofstream out; // Поток out будем использовать для записи

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

     in.open("input.txt");
     out.open("output.txt");

После открытия файлов и привязки их к файловым потокам, работать с файлами можно так же, как со стандартными потоками ввода-вывода cin и cout. Например, чтобы вывести значение переменной x в поток out используются следующая операция

     out<<x;

А чтобы считать значение переменной из потока in

     in>>x;

Для закрытия ранее открытого файла используется метод close() без аргументов:

     in.close();
     out.close();

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

При считывании данных из файла может произойти ситуация достижения конца файла (end of file, сокращенно EOF). После достижения конца файла никакое чтение из файла невозможно. Для того, чтобы проверить состояние файла, необходимо вызвать метод eof(). Данный метод возвращает true, если достигнут конец файла или false, если не достигнут. Кроме того, состояние файлового потока можно проверить, если просто использовать идентификатор потока в качестве логического условия:

     if (in)
     {
     }

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

     int d;
     while(in>>d)
     {
     }

А организовать считывание файла построчно (считая, что строка заканчивается символом перехода на новую строку) так:

     string S;
     while ( getline(in,S))
     {
     }

А еще полезно повторить листок "Строки".

Упражнения

Во всех заданиях этого листка программа должна читать данные из файла input.txt и выводить результат в файл output.txt. Пробельными символами называются символы пробела, табуляции, перехода на новую строку. Непробельными символами называются все остальные символы, чьи ASCII-коды не меньше 20h. Словом называется последовательность непробельных символов, разделенных пробельными символами.

  1. (A) Сумма

    Входной файл содержит два целых числа. Запишите в выходной файл их сумму.

  2. (B) Удалить лишние пробелы

    В файле записан текст, состоящий из строк. Удалите из каждой строки все лишние пробелы: лидирующие пробелы в начале каждой строки, концевый пробелы в конце строки, замените все пробелы между словами на один. Результат выведите в файл.

    Пример:

    input.txt

              У        лукоморья
                 дуб     зеленый
    

    output.txt

              У лукоморья
              дуб зеленый
    
  3. (C) Выравнивание по левому краю

    Первая строка входного файла содержит целое число N. Далее (начиная со следующей строки) идет текст. Необходимо данный текст разбить на строки, длина которых не превосходит N и вывести его в файл. В каждой выведенной строке не должно быть пробелов в начале строки, пробелов в конце строки, слова в строке должны разделяться одним пробелом. При этом каждая строка должна быть максимально длинной, то есть строки формируются по "жадному" принципу: добавляем слова из входного файла до тех пор, пока длина полученной строки не превышает N, после этого ставим разрыв строки. Гарантируется, что во входном файле нет слов длиннее N символов.

    Пример:

    input.txt

              20
              Для того дорога и дана, чтоб души вниманье не дремало.
              Человеку важно знать немало, потому дорога и трудна.
    

    output.txt

              Для того дорога и
              дана, чтоб души
              вниманье не дремало.
              Человеку важно знать
              немало, потому
              дорога и трудна.
    
  4. (D) Выравнивание по правому краю

    Решите предыдущую задачу при условии, что текст должен быть выровнен по правому краю, то есть каждая строка в выводе должна иметь длину ровно N символов, в противном случае ее нужно дополнить в начале строки пробелами до длины N. Последний символ каждой строки должен быть непробельным.

    Пример:

    input.txt

              20
              Для того дорога и дана, чтоб души вниманье не дремало.
              Человеку важно знать немало, потому дорога и трудна.
    

    output.txt

                 Для того дорога и
                   дана, чтоб души
              вниманье не дремало.
              Человеку важно знать
                    немало, потому
                  дорога и трудна.
    
  5. (E) Выравнивание по ширине

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

    Последнюю строку в выводе должна быть выровнена по левому краю.

    Пример:

    input.txt

              20
              Для того дорога и дана, чтоб души вниманье не дремало.
              Человеку важно знать немало, потому дорога и трудна.
    

    output.txt

              Для  того  дорога  и
              дана,    чтоб   души
              вниманье не дремало.
              Человеку важно знать
              немало,       потому
              дорога и трудна.
    
  6. (F) Частотная таблица - 1

    Входной файл содержит некоторый текст. Для каждой буквы латинского алфавита посчитайте, сколько раз она встречается в тексте. Заглавные и строчные буквы считайте вместе, остальные символы игнорируйте. Программа должна вывести все буквы латинского алфавита (заглавные, от A до Z, по одной букве в строке), после этого на этой же строке количество появления этой буквы в исходном тексте.

    Пример:

    input.txt

              AaB
    

    output.txt

              A 2
              B 1
              C 0
              (и т.д.)
    
  7. (G) Частотная таблица - 2

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

    Пример:

    input.txt

              AaA Bb ZZZZZZZZZZZZZZZZ
    

    output.txt

              Z 16
              A 3
              B 2
    
  8. (H) Обращение длинной последовательности

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

    Пример:

    input.txt

              1 2 3 4 5 6 7
    

    output.txt

              7 6 5 4 3 2 1
    

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

    1. Использовать динамические массивы: указатели и перераспределяемую память.

    2. Программа должна создать массив некоторого размера.

    3. Данные читаются в виде while (in>>d), то есть до окончания входного потока.

    4. После считывания число записывается в массив.

    5. Если при этом не хватает размера динамического массива, необходимо перераспределить память: создать новый массив большего размера при помощи оператора new, скопировать в него все ранее считанные данных, освободить память, занимаемую старым массивом при помощи оператора delete.