6. Потоци
Четене и запис в текстови файлове
* Пренасочване на входа и изхода

* Четене от файл:
А) файл за четене:
- дефиниране на файлове променлива за четене
ifstream inp_data;
- отваряне на файл
inp_data.open("input.dat");
- четене от файл
--- цели числа и числа с плаваща точка:
   int n;
   double x;
   inp_data >> n >> x;
--- низове:
   string s;
   inp_data >> s;
   getline(inp_data, s);
--- символи:
   char ch;
   inp_data.get(ch);
   input_stream.unget();
   input_stream.put_back(ch);
- затваряне на файл
   inp_data.close();

Пример:
#include <fstream>                /* включване на заглавен файл */
int main()
{  ifstream in_data; /* дефиниране на файлова променлива за четене */
   in_data.open("input.txt");            /* отваряне на файла */

   string s;
   in_data >> s;                            /* четене на дума */
   getline(in_data, s);                      /* четене на ред */
   int n;
   double x;
   in_data >> n >> x;                /* четене на числови данни */
   char ch;
   in_data.get(ch);                       /* четене на символ */

   in_data.close();                      /* затваряне на файла */
   return 0;
}

* Записване на файл:
- дефиниране на файлове променлива за писане
   ofstream out_data;
- отваряне на файл
   out_data.open("output.dat");
- писане във  файл
--- с изходен поток:
   int n = 2;
   double x = 1.5;
   string s = " Hello";
   out_data << n << "  " << x << s;
--- с член-функции
   char ch = 'A';
   out_data.put(ch);
- затваряне на файл
   out_data.close();

Пример:
#include <fstream>                 /* включване на заглавен файл */
int main()
{  ofstream out_data; /* дефиниране на файлова променлива за четене */
   out_data.open("output.txt");           /* отваряне на файла */

   string s = "Hello";
   out_data << s;                             /* писане на низ */
   int n = 5;
   double x = 5.5;
   out_data << n << x;               /* писане на числови данни */
   char ch = 'T';
   out_data.put(ch);                      /* писане на символ */

   out_data.close();                     /* затваряне на файла */
   return 0;
}

* Програма за четене на заплати и чертаене на диаграма
// readdata.cpp
#include "ccc_win.cpp"

void read_data(vector<double>& v, ifstream& in)
{
   double s;
   while (in >> s) v.push_back(s);
}

double maximum(vector<double> v)
{
   if (v.size() == 0) return 0;
   double highest = v[0];
   int i;
   for (i = 1; i < v.size(); i++)
      if (v[i] > highest) highest = v[i];
   return highest;
}

void plot_data(vector<double> v)
{
   double highest = maximum(v);
   cwin.coord(0, 0, highest, v.size());
   int i;
   for (i = 0; i < v.size(); i++)
   {  Point left(0, i);
      Point right(v[i], i);
      Line bar(left, right);
      Message label(left, v[i]);
      cwin << bar << label;
   }
}

int main()
{  string filename
      = cwin.get_string("Please enter the data file name: ");
   ifstream infile;
   infile.open(filename.c_str());
   vector<double> data;
   read_data(data, infile);
   infile.close();
   plot_data(data);
   return 0;
}
 
* Четене и писане в един файл:
- дефиниране на файлове променлива за писане и четене
   fstream io_data;
- отваряне на файл
   io_data.open("io.dat");

Текстови потоци

Аргументи от командния ред
* Стартиране на програмата prog:

C:\mydir\>prog -v input.dat

 * Текста на програмата:
int main(int argc, char * argv[])
{
 cout << argc;               /* брой на аргументите - 3 */
 cout << string(argv[0]);    /* prog */
 cout << string(argv[1]);    /* -v */
 cout << string(argv[2]);    /* input.dat */
 return 0;
}

Произволен достъп
-- файлове с променлива или фиксирана дължина на записа

-- включване на заглавен файл:
#include <fstream>

-- файлова променлива за четене и писане:
fstream fs;

-- преместване на позициите за четене и писане:
long n = 10;
fs.seekg(n, ios::beg);
fs.seekp(n, ios::beg);

-- намиране на текущите позициите за четене и писане:
long n;
n = fs.tellg();
n = fs.tellp();

* Пример с база-данни за повишаване на заплати
// database.cpp
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
using namespace std;

#include "ccc_empl.cpp"

const int NEWLINE_LENGTH = 2; /* or 1 on Unix */
const int RECORD_SIZE = 30 + 10 + NEWLINE_LENGTH;

double string_to_double(string s)
{
   istringstream instr(s);
   double x;
   instr >> x;
   return x;
}

void raise_salary(Employee& e, double percent)
{
   double new_salary = e.get_salary() * (1 + percent / 100);
   e.set_salary(new_salary);
}

void read_employee(Employee& e, fstream& fs)
{
   string line;
   getline(fs, line);
   if (fs.fail()) return;
   string name = line.substr(0, 30);
   double salary = string_to_double(line.substr(30, 10));
   e = Employee(name, salary);
}

void write_employee(Employee e, fstream& fs)
{
   fs << e.get_name()
      << setw(10 + (30 - e.get_name().length()))
      << fixed << setprecision(2)
      << e.get_salary()
      << "\n";
}

int main()
{  cout << "Please enter the data file name: ";
   string filename;
   cin >> filename;
   fstream fs;
   fs.open(filename.c_str());
   fs.seekg(0, ios::end); /* go to end of file */
   int nrecord = fs.tellg() / RECORD_SIZE;

   cout << "Please enter the record to update: (0 - "
      << nrecord - 1 << ") ";
   int pos;
   cin >> pos;

   const double SALARY_CHANGE = 5.0;

   Employee e;
   fs.seekg(pos * RECORD_SIZE, ios::beg);
   read_employee(e, fs);
   raise_salary(e, SALARY_CHANGE);
   fs.seekp(pos * RECORD_SIZE, ios::beg);
   write_employee(e, fs);

   fs.close();
   return 0;
}