Потоковый ввод-вывод в файлы

Потоковый ввод-вывод в файлы

Работа с файлами с использованием конструкций языка Си была рассмотрена здесь.

Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода. Выводимая информация записывается в поток, вводимая информация считывается из потока.

Для работы с файлами необходимо подключить заголовочный файл <fstream>. В нем определены несколько классов и подключены заголовочные файлы

  • <ifstream> — файловый ввод ;
  • <ofstream> — файловый вывод.

Файловый ввод-вывод аналогичен стандартному вводу-выводу, единственное отличие – это то, что ввод-вывод выполнятся не на экран, а в файл.

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

При работе с файлом можно выделить следующие этапы:

  • создать объект класса fstream (возможно, ofstream или ifstream);
  • связать объект класса fstream с файлом, который будет использоваться для операций ввода-вывода;
  • осуществить операции ввода-вывода в файл;
  • закрыть файл.
1
2
3
4
5
6
7
8
9
10
#include <fstream>
using namespace std;
int main() 
{
  ofstream fout;
  fout.open("file.txt");
  fout << "Привет, мир!";
  fout.close();
  return 0;
}

В результате будет создан файл

Режимы открытия файлов устанавливают характер использования файлов. Для установки режима в классе ios предусмотрены константы, которые определяют режим открытия файлов.

Константа Описание
ios::in открыть файл для чтения
ios::out открыть файл для записи
ios::ate при открытии переместить указатель в конец файла
ios::app открыть файл для записи в конец файла
ios::trunc удалить содержимое файла, если он существует
ios::binary открытие файла в двоичном режиме

Режимы открытия файлов можно устанавливать непосредственно при создании объекта или при вызове метода open().
ofstream fout(«file.txt», ios::app); fout.open(«file.txt», ios::app);

Режимы открытия файлов можно комбинировать с помощью поразрядной логической операции ИЛИ |, например:

ios::out | ios::in — открытие файла для записи и чтения.

Произвольный доступ к файлу

Система ввода-вывода С++ позволяет осуществлять произвольный доступ с использованием методов seekg() и seekp().

  • ifstream &seekg(Смещение, Позиция);
  • ofstream &seekp(Смещение, Позиция);

Смещение определяет область значений в пределах файла (long int).

Система ввода-вывода С++ обрабатывает два указателя, ассоциированные с каждым файлом:

  • get pointer g — определяет, где именно в файле будет производиться следующая операция ввода;
  • put pointer p — определяет, где именно в файле будет производиться следующая операция вывода.

Позиция смещения определяется как

Значение
Позиция
ios::beg Начало файла
ios::cur Текущее положение
ios::end Конец файла

Всякий раз, когда осуществляются операции ввода или вывода, соответствующий указатель автоматически перемещается.

С помощью методов seekg() и seekp() можно получить доступ к файлу в произвольном месте.

Можно определить текущую позицию файлового указателя, используя следующие функции:

  • streampos tellg() — позиция для ввода
  • streampos tellp() — позиция для вывода

Пример на С++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <fstream>
using namespace std;
int main() 
{
  system("chcp 1251");
  system("cls");
  char s[80];
  fstream inOut;
 
 inOut.open("file.txt", ios::out);
  inOut << "строчка текста" << endl;
  inOut.seekp(8, ios::beg);
  inOut << "еще строчка текста";
  inOut.close();
  inOut.open("file.txt", ios::in);
  inOut.seekg(-6, ios::end);
  inOut >> s;
  inOut.close();
  cout << s;
  cin.get();
  return 0;
}

В результате выполнения первой части программы будет создан файл

Вторая часть программы выведет в консоль

Считывание данных из файла

Ещё один пример. Допустим, нам нужно заполнять таблицу

ФИОДата рожденияХобби
   

Причем каждая вновь введенная строка должна размещаться в таблице непосредственно под «шапкой».

Алгоритм решения задачи следующий:

  • формируем очередную строку для вывода
  • открываем файл для чтения, считываем из него данные и сохраняем их в массив строк
  • закрываем файл
  • открываем файл для записи
  • выводим «шапку» таблицы
  • выводим новую строку
  • выводим все сохраненные строки обратно в файл, начиная со строки после шапки

Пример на C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <fstream>
using namespace std;
#define LINES 100 // максимальное количество строк в файле
int main() {
  system("chcp 1251");
  system("cls");
  char line[LINES][100];
  char str[30];
  char s[] = "|                              |                |                              |";
  // Ввод данных для размещаемой строки
  cout << "ФИО: ";
  cin.getline(str, 30); // вводим ФИО
  for (int i = 0; str != '\0'; i++) // копируем в строку без 0
    s[i + 2] = str[i];               // начиная с указанной позиции
  cout << "Дата: ";
  cin.getline(str,30);
  for (int i = 0; str != '\0'; i++)
    s[i + 33] = str[i];
  cout << "Хобби: ";
  cin.getline(str,30);
  for (int i = 0; str != '\0'; i++)
    s[i + 50] = str[i];
  fstream inOut;
 
 inOut.open("file.txt",  ios::in); // открываем файл для ввода
  // Считываем из файла имеющиеся данные
  int count = 0;
  while (inOut.getline(line[count], 100)) 
    count++;
  inOut.close(); // закрываем файл
 
 inOut.open("file.txt", ios::out); // открываем файл для вывода
  inOut << "--------------------------------------------------------------------------------" << endl;
  inOut << "|   ФИО                        |  Дата          | Хобби                        |" << endl;
  inOut << "--------------------------------------------------------------------------------" << endl;
  inOut << s << endl; // выводим сформированную строку
  inOut << "--------------------------------------------------------------------------------" << endl;
  // Выводим обратно в файл все строки кроме "шапки" (первые 3 строки)
  for (int j = 3; j < count; j++)
  {
    inOut << line[j] << endl;
  }
  inOut.close();
  cin.get();
  return 0;
}

Результат выполнения:

Полученный файл данных:

54 комментария к “Потоковый ввод-вывод в файлы”

  1. Евгений

    Здравствуйте Елена. Скажите, а можно ли как то узнать наступивший конец файла. Например, если количество строк в файле неизвестно, а нужно организовать цикл по их считыванию и прервать его по окончанию файла.

    1. Николай

      test.eof() — функция которая определяет конец файла елся файл закончился вернёт 1 иначе 0:

      1
      2
      3
      4
      5
      6
      ifstream test("U:\\prog struct17\\list.txt"); // полное имя файла
          if (!test) {
              cout << "not found test_file ";
              return 0;
      while(!test.eof()){ //пока не конец.
      ….}
    2. Метод eof().
      Например

      1
      2
      3
      4
      5
      6
      7
      8
      ifstream fsInp; 
      int nVar;
      fsInp.open("data.txt");
      while(!fsInp.eof())
           { fsInp >> nVar; // Считали
                            // Обработали
           }
      fsInp.close();
  2. Елена, здравствуйте! Помогите, пожалуйста. Есть код, работающий, но вывод делает в консоль, а так как вывод очень большой, то все результаты там не помещаются, только малая последняя часть. Подскажите, пожалуйста, где и что изменить, чтоб вывод записывало в файл. Если можно очень подробно или прям конкретным примером, я со всем этим только только столкнулась, поэтому пока не особо соображаю((
    Вот мой код

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import static java.lang.System.out;
    import java.util.Arrays;
    class Combinations
    {
        private static final int M = 12;
        private static final int N = 24;
        private static int[] generateCombinations(int[] arr)
        {
            if (arr == null)
            {
                arr = new int[M];
                for (int i = 0; i < M; i++)
                    arr[i] = i + 1;
                return arr;
            }
            for (int i = M — 1; i >= 0; i—)
                if (arr[i] < N — M + i + 1)
                {
                    arr[i]++;
                    for (int j = i; j < M — 1; j++)
                        arr[j + 1] = arr[j] + 1; 
                    return arr;
                }
            return null;
        }
        public static void main(String args[])
        {
            int[] arr = null;
            while ((arr = generateCombinations(arr)) != null)
                    out.println(Arrays.toString(arr));
        }
    }
    1. Елена Вставская

      В настройках консоли (меню в верхнем левом углу) изменить размер буфера

  3. Владимир

    Елена, не поможете? Я сделал сканер для 8-мм кинопленки, теперь хочу процесс усовершенствовать. Для лучшего сканирования нужно делать 2 BMP скана при разной экспозиции, затем слишком светлые пиксели (допустим сумма R, G и B выше 700 или где-то около этого, подберу при отладке), заменить аналогичными пикселями из второго файла, сделанного при меньшей экспозиции, затем сохранить изменения в первом файле, а второй удалить. Первый еще бы и в jpeg-e сохранить. В перспективе еще и 3-й скан должен появиться, в инфракрасном свете, но его пока нету, а если получится делать из 2-х, з-й не проблема. Размеры растра, тип файла известны и не могут измениться. Сжатия нет, 24-битный цвет. Думаю, что нужно без нестандартных библиотек открывать одним циклом (смещение 40) оба файла, затем вычислять сумму RGB, сравнивать с константой и при превышении заменять значениями их 2-го файла, затем удалить 2-й файл, сохранить 1-й ("шапку" просто скопировать, растр с изменениями) и еще бы его сразу jpeg -ом сделать. Просто скажите, я в правильную сторону копаю или нет? А если еще и какие-нибудь указания дадите, буду чрезвычайно признателен! Могу пленки отсканировать лучше "Мосфильма". Бесплатно, разумеется, я всем бесплатно это делаю. Это для души. Заранее благодарен

    1. Елена Вставская

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

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

    1. Елена Вставская

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

  5. Здравствуйте, попыталась сделать вывод данных в файл, но почему то только создался документ, а данных там нет. Что не так?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ofstream fout("file.txt", ios::out);
        fout.open("file.txt", ios::out);
        for (int i = 0; i < SIZE; i++)
        {
            for (int j = 0; j < SIZE; j++)
                printf("%5d ", a[i][j]); 
            printf("\n");
           
                fout << a[i] << endl;
            
        }
    fout.close();
    1. Елена Вставская

      Вы выводите в файл указатель на строку, а не элементы матрицы

    1. Елена Вставская

      Не совсем понимаю цель этого действия. Почему нельзя создать пустую строку?
      А вообще sr[0]=0;

  6. И ещё один вопрос. Можно ли ввести несколько слов с консоли в одно значение char?

  7. Можно ли как-то скопировать половину строки ?

    Выше вы копировали от середины и до конца, но мне нужно наоборот- от начала до середины ( или 10-го символа)

    1. Елена Вставская

      Вроде рассмотрены оба варианта: поиск позиции от начала строки и от конца

      1. Не совсем правильно сформулировала , от определённого индекса до определённого индекса. То есть, у нас есть строка(char sr[50]="blablablabla";)
        Я хочу скопировать с третього индекса по 10.

        1. Елена Вставская

          Мы с файлом работаем или со строкой?
          Если со строкой, то функция strncpy(&sr[3], 7, dst);

  8. Артём

    Здравствуйте, есть код:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #include <iostream>
    #include <cstdlib>
    #include <fstream>
    #include <iomanip>
    #include <cmath>
    #include <string>
    using namespace std;

    void FuncA()
    {
      cout << "Данные записаны" << endl << endl;
    }
    void FuncB()
    {
      cout << "Функция 2";
    }
    void FuncC()
    {
      cout << "Функция 3";
    }
    int main()
    {
      setlocale(0, "");
      cout << "Введите название файла" << endl;
      char filename[40];
      cin.getline(filename, 40);
      ofstream File (filename);
      File << ".";
      cout << "Файл создан!" << endl;
      File.close();
      ifstream fin (filename);
        if (!fin.is_open())
          {
          cout << "Файл не может быть открыт!" << endl;
          }
        else
        {
          cout << "Файл открыт" << endl;
        }
        cout << "Выберите операцию: " << endl;
        int cmd = -1;
        do
        {
          if (cmd == 1)
          FuncA();
          else if (cmd == 2)
          FuncB();
          else if (cmd == 3)
          FuncC();
          cout << "1-Вывод размера типов данных\n2-Рассчёт фрактала\n3-Рассчёт активности по цефепиму и L-аргинину\n0-Выход" << endl;
          cin >> cmd;
        }
      while (cmd);
      return 0;
    }

    Как в функции(например FuncA) начать работу с уже созданным файлом filename?

  9. Артур

    Здравствуйте, подскажите как считать данные из файла, сохранённых в следующем виде:
    Check Type | Check name | Cost check |
    12 |Full |50000 |
    38 |Half |25000 |
    156 |Special |79000 |
    и записать данные в структуру.
    Например:
    Поле "Struct->CheckType" имеет значение "12"
    Поле "Struct->CheckName" имеет значение "Full"
    Поле "Struct->CostCheck" имеет значение "50000"

    1. Елена Вставская

      Считывать по строкам, далее строку разделять по символу | и присваивать значения полям структуры. Если поля структуры целочисленные, то предусмотреть ещё перевод из строки в число.

  10. Михаил

    Здравствуйте. Возникла проблема, когда пытался переделать ваш код под себя. Выдается очень странный баг, хотя программа компилируется. Я добавил возможность использования программы повторно, без перезапуска консоли, через цикл while. И немного изменил шапку и ее ввод. В общем вот код. Если получится найти причину, буду очень благодарен.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #include <iostream>
    #include <fstream>
    using namespace std;
    #define LINES 100 
    int main() {
      system("chcp 1251");
      system("cls");
      int check = 1;
      char line[LINES][100];
      char str[41];
      char s[] = "|                    |                    |                                        |                    |                    |                    |                         |";
      while (check == 1) {
        cout << "Имя : ";
        cin.getline(str, 20);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 1] = str[i];
        cout << "Фамилия : ";
        cin.getline(str, 20);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 22] = str[i];
        cout << "Адрес проживания : ";
        cin.getline(str, 40);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 43] = str[i];
        cout << "Город : ";
        cin.getline(str, 20);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 84] = str[i];
        cout << "Почтовый индекс : ";
        cin.getline(str, 20);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 105] = str[i];
        cout << "Номер телефона : ";
        cin.getline(str, 20);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 126] = str[i];
        cout << "Адрес эл. почты : ";
        cin.getline(str, 25);
        for (int i = 0; str[i] != '\0'; i++)
          s[i + 147] = str[i];

        fstream abonent;
        abonent.open("file.txt", ios::in);

        int count = 0;
        while (abonent.getline(line[count], 100)) count++;
        abonent.close();

        abonent.open("file.txt", ios::app);
        abonent.seekg(0, ios::end);
        if (abonent.tellg() == 0) {
          abonent << "——————————————————————————————————————————————————————————" << endl;
          abonent << "|        Имя         |      Фамилия       |            Адрес проживания            |       Город        |  Почтовый индекс   |   Номер телефона   |     Адрес эл. почты     |" << endl;
          abonent << "——————————————————————————————————————————————————————————" << endl;
        }
        abonent << s << endl;
        abonent << "——————————————————————————————————————————————————————————" << endl;
        abonent.close();
        cout << "Продолжить? ";
        cin >> check;
      }
      cin.get();
      return 0;
    }

    1. Елена Вставская

      Пока вижу 2 бага, не знаю, какой Вы имеете в виду.
      1. Когда вводим данные второго и последующих лиц, программа "глотает" Имя.
      2. Если, допустим, фамилия второго человека окажется короче, чем у первого, то она будет дополнена "остатком" предыдущей фамилии.

  11. Николай

    Подскажите, а можно определить середину строки s, в файле при помощи tellg/tellp или seekg/seekp?

    1. Елена Вставская

      Считать всю строку. Найти ее длину с помощью strlen() и сместить курсор на «минус» половину этого значения от текущей позиции.

      1. Николай

        Наверно не то что Вы имели ввиду?

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        #include <iostream>
        using namespace std;
        int main()
        {
            string buf;
            ifstream infile;
            infile.open("text.txt", ios::in);
            if(infile.is_open()){
                infile >> buf;
                short n = strlen(buf);
                short k=0;
                if(n%2) {
                    k = n/2;
                    cout << buf[k];
                }
                else cout << buf[k] << " " << buf[k+1];
            }
            else{
                cout << "File error."<< endl;
                return 1;
            }
            infile.close();
        return 0;
        }
  12. Николай

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

    1
    2
    3
    4
    5
    6
    7
    std::string textoutbuf = "yjjfhjshdsjhf dkcfjdhj jfcjh 111111";
    textoutbuf.push_back('\n');
    //m_sock.fileLog << "yjjfhjshdsjhf dkcfjdhj jfcjh 111111";
    m_sock.fileLog << textoutbuf;
    INT qqq = GetLastError();
    m_sock.fileLog.flush();//очистить поток
    m_sock.fileLog.close();

    файл всегда нулевой длины. Что уже не пробовал, читал форумы но ответа пока не нашел. Может Вы подскажете в чем может быть проблема?
    Спасибо.

    1. Елена Вставская

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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      #include <fstream>
      using namespace std;
      int main()
      {
        ofstream m_sock;
        m_sock.open("C://1/file.txt");
        char textoutbuf[] = "yjjfhjshdsjhf dkcfjdhj jfcjh 111111\n";
        m_sock << textoutbuf;
        m_sock << "yjjfhjshdsjhf dkcfjdhj jfcjh 111111";
        m_sock.flush();
        m_sock.close();
        return 0;
      }
  13. А как записать данные в файл с названием, определяемым самим пользователем? Насколько я понял, в качестве названия файла можно использовать только константу (?)

    1. Елена Вставская

      Нет, Вы можете ввести имя файла в ходе выполнения программы.

      1
      2
      3
      4
      5
      char filename[40];
      cout >> "filename: ";
      cin << filename;
      inOut.open(filename,  ios::in);
  14. извините, я наверно вас уже заколебал, с этой 4 строчкой…
    Но мне надо прочитать строчку из файла и вывести ее в консоль.
    Т.е. В файле есть 4 строка мне ее надо прочитать и вывести на экран.
    inOut.open(«file.txt»,ios::out);
    for(int i=0; i<4; i++) cout<<line;

    выводит белиберду.
    То есть я хочу теперь эту табличку на экране увидеть, но не всю, а только ее часть, например строку 4.

    for(int i=0; i<100; i++)
    cout<<line[4][100];

    Тоже не  работает

  15. 1
    while ( inOut.getline (line[count], 100) ) count++;

    А как происходит перебор строк?
    Я как понимаю, мы читаем строку в массив line[1];
    Потом читаем еще раз строку, но в массив line[2]; и т.д. до line[100].

    А где мы говорим, что мы не читаем одну и туже строчку то?

    Как встать то на строчку 5? И прочитать что в строке 5 У нас Петров Петр.

    1. Почему если в файле «file.txt» есть информация, то данный код не просто читает он удаляет все из файла?

      1. Елена Вставская

        При считывании строки указатель позиции в файле автоматически смещается на её длину. Поэтому если мы считаем 4 строки, то окажемся на начале 5-ой. Считав её, мы получим нужную нам информацию.

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

        1. Спасибо большое за ответы. Но а как мне получить строку под номером 4? Допустим я не знаю что в файле, и я хочу прочитать только 4 строчку.
          line[4] выводит все четвертые буквы всех строк, но не всю строку целиком.
          Может как то можно получить массив строк и массив символов за раз? Например my_line_txt[4][5] — четвертая строка 5 символ.

          1. Елена Вставская

            line[4] — это и есть 4-ая строка. Первый индекс в массиве line[][] — это номер строки, второй — номер символа в строке.

            1
            2
            3
            int i;
            for(i=0; i<4; i++) inOut.getline(line[i], 100);
            inOut.getline(line[i], 100); // вот Ваша 4-ая строка
  16. Подскажите пожалуйста (нигде найти не могу)
    Как выводить в файл строки сверху.
    было
    То, как зверь, она завоет,
    То заплачет, как дитя,
    Надо вставить сверху строчки, что бы получилось так:
    Буря мглою небо кроет,
    Вихри снежные крутя;
    То, как зверь, она завоет,
    То заплачет, как дитя,
    Только не говорите что для этого отдельный файл создавать надо….:)

    1. Если использовать флаг ios::beg

      Да, он ставит курсор в начало файла. Но он удалит весь текст который там был. И вставить строчку не получиться.

      Вместо вставки происходит замена.

      1. Елена Вставская

        Я, конечно, не буду говорить, что нужно создавать отдельный файл 🙂
        Но придётся считать всю информацию из файла и где-то её сохранить. Потом открыть файл для записи. Записать недостающие строки сверху, а потом снова выгрузить сохраненное содержимое файла.

        1. А если надо  заполнить такую таблицу что бы последние введенные данные были наверху.
          То есть, есть шапка которую нельзя трогать.
          файл 1 «с шапкой»
          файл 2 «с новой строкой»
          файл 3 = файл 1+файл2; // итоговый наш файл
          файл 2 = получили новую строку
          файл 4 = скопировать все с 4 строчки и ниже из файла №3
          файл 3 = встаем на четвертую строчку и добавляем файл №2 с нашей строкой
          файл 3 = копируем все из файла 4.
          Только так можно это реализовать? Как можно установить курсор на 4 строчку?
          ————————————————————————————
          | Фамилия  | Имя  |  Отчество  |   дата рождения  |   хобби   |
          ————————————————————————————
          |_________|_____|__________|_______________|________|
          |_________|_____|__________|_______________|________|
          |_________|_____|__________|_______________|________|
          |_________|_____|__________|_______________|________|

          1. Как можно установить курсор на 4 строчку?

            И как можно скопировать все что ниже 4 строчки. Или удалить все что выше 4 строчки.

          2. Елена Вставская

            Ответила в тексте статьи

  17. Блог программиста

    Хорошая статья, но:

    1) в последнем листинге используются операторы >> и <<, в статье не объясняется как именно они работают;

    2) не упоминается функция getline — это единственный способ считать строку целиком;

    3) в начале упоминается про бинарные файлы, но не описано как с ними работать;

    4) если не всегда, то очень часто, входной файл обрабатывается до тех пор, пока не будут считаны все элементы. В статье нет слова про feof;

    5) что если файл не удалось открыть? — там целый комплекс флажков есть и еще можно объект сравнить с нулем (есть перегруженный оператор для этого, который проверяет набор каких-то флажков) — так очень часто делают;

    6) я не знаю что случится при попытке переместить каретку чтения в файле на недоступную позицию, но думаю, что вылетит исключение. Я могу посмотреть в документации, конечно, но мог бы и у вас прочитать (так-то в документации про seekp тоже написано);

    7) я думаю, стоит упомянуть, что если файл не закрывать — то он закроется сам когда объект будет разрушен. Ну потому, что так-то, мне кажется, файлы не часто закрывают — это нужно делать только если есть вероятность, что программа завершится настолько аварийно, что до деструктора файла дело не дойдет.

    ЗЫ:. вот этот system("cls") я бы лично не использовал (как и system вообще) — некроссплатформенно это… По крайней мере по возможности его стоит избегать, никакой острой необходимости вставлять его в такие учебные статьи я не вижу ((

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх