Шаг 70.
Решение задач с использованием функций высокоуровневого ввода/вывода

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


    Пример 1. Напишите программу очистки содержимого данного файла (имя файла задается в командной строке).
#include <iostream.h>
#include <stdio.h>
void main (int argc,char *argv[])
{
      FILE *in;
      /* ------ */
      if  (argc < 2)
         cout << "Отсутствует имя файла в командной строке.";
      else
      {
         in = fopen (argv[1],"w"); fclose (in);
      }
   }
Текст этой программы можно взять здесь.


    Пример 2. Заданный файл копировать в новый файл, который имеет расширение red и содержит только те символы исходного файла, номера позиций которых в исходном файле кратны трем (0,3,6,9,...).
#include <iostream.h>
#include <stdio.h>
#include <string.h>
void main (int argc,char *argv[])
{
      FILE *in,*out;
      char ch;
      static char name[20];
      int count=0;
      /* -------------------- */
      if  (argc < 2)
         /* Проверяем, введено ли имя входного файла. */
         cout << "Отсутствует имя файла \n";
      else
      {
         if  ((in=fopen(argv[1],"r")) != NULL)
         {
            /* Копируем имя файла в строку. */
            strcpy (name,argv[1]);
            /* Проверяем, есть ли расширение. */
            char *p = strchr (name,'.');
            if (p) 
               *p=NULL; //Удалить расширение.
            /* Добавляем .red к имени файла. */
            out = fopen (strcat (name,".red"),"w");
            while  ( (ch=getc (in)) != EOF)
               /* Печатаем каждый третий символ файла. */
               if  (count++%3==0)
                  putc (ch,out);
            fclose (in); fclose (out);
         }
         else  cout << "Файл не существует!";
      }
}
Текст этой программы можно взять здесь.

    Теперь если мы поместим эту программу в файл c70_2.cpp и откомпилируем ее, а в файл edd.txt поместим Даже Эдди нас опередил с детским хором, то после выполнения командной строки:

   C:\>c70_2.exe edd.txt
получим в файле edd.red: Дед спел тихо.


    Пример 3. Вывод на экран дисплея содержимого нескольких текстовых файлов последовательно один за другим.
#include <iostream.h>
#include <stdio.h>
void main (int argc,char *argv[])
{
      FILE *in;
      char   t;
      /* ------ */
      if  (argc < 2)
         cout << "Не заданы параметры в командной строке \n";
      else
         for  (int i=1; i < argc; i++)
            if  ((in=fopen(argv[i],"r")) != NULL)
            {
               cout << "Содержимое файла \"" << argv[i] << "\":" << endl;
               while  ((t=getc(in)) != EOF)
                   cout << t;
               fclose (in);
               cout << endl;
            }
            else cout << "Файла с именем \"" << argv[i] << "\" нет";
}
Текст этой программы можно взять здесь.


    Пример 4. Дан символьный файл. Записать компоненты файла в обратном порядке (в командной строке сначала указывается имя файла-источника, а затем имя файла- приемника).
#include <iostream.h>
#include <stdio.h>
void main (int argc,char *argv[])
{
    FILE *in,*out;
    char a;
    /* -------- */
    if  (argc < 3)
      cout << "Не заданы параметры в командной строке \n";
    else
    {
      in = fopen (argv[1],"r"); out = fopen (argv[2],"w");
      int i = -1;
      while  (!fseek(in,i,SEEK_END))
      {
       a=getc(in);
       if ((int)a==0x0a) {putc('\n',out); i--; }
       else
         putc (a,out);
       i--;
      }
      fclose (in); fclose (out);
    }
}
Текст этой программы можно взять здесь.

    Прокомментируем текст приведенной программы. Сначала немного поясним общий ход решения задачи. Будем читать посимвольно содержимое первого файла (с конца файла!) и записывать в начало второго файла. Для того, чтобы осуществить чтение с конца файла, нужно разместить там файловый указатель. Это осуществляется функцией

     fseek(in,i,SEEK_END) 

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

    Поясним условие

     if ((int)a==0x0a) {putc('\n',out); i--; }

Переход на следующую строку в файле кодируется двумя байтами: 0D 0A. Так как мы читаем содержимое первого файла с конца, то первый прочитанный байт будет 0A. Если мы его встретили, то во второй файл помещаем символ перехода на новую строку ('\n') и пропускаем следующий байт (0D) командой i--, переходя к очередному байту.

    На следующем шаге мы поговорим о форматном вводе/выводе.


Предыдущий шаг Содержание Следующий шаг