Четене и запис в текстови
файлове.
** Досега за четене от и запис във файлове (вж 9. Цикли) - чрез пренасочване
на стандартните вход и/или изход със средствата на операционната система
** В заглавния файл fstream
са дефинирани обекти, функции и операции за работа с файлове.
А) Четене от файл.
* дефиниране на файлова променлива за четене - обект от класа ifstream:
ifstream inp_data;
* отваряне на файл от текущата директория с име input.dat:
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);
// чете един символ
inp_data.unget();
// връща последния прочетен символ в буфера
* затваряне на файл
inp_data.close();
Пример на цяла програма.
// readf.cpp
#include <iostream>
#include <fstream>
/* включване на заглавен файл */
#include <string>
using namespace std;
int main()
{ ifstream in_data; /* дефиниране
на файлова променлива за четене */
in_data.open("readf.txt");
/* отваряне на файла readf.txt */
string s1, s2;
getline(in_data, s1);
/* четене на ред */
in_data >> s2;
/* четене на дума */
int n;
double x;
in_data >> n >> x;
/* четене на числови данни */
char ch;
while (!in_data.eof())
in_data.get(ch);
/* четене на символ */
in_data.close();
/* затваряне на файла */
cout << s1 <<
endl << s2 << " "
<< n << " " << x << " " << ch << endl;
return 0;
}
Файл readf.txt:
many happy words
one_word 123 9.98 N |
many happy words
one_word 123 9.98 N |
Б) Писане във файл.
* дефиниране на файлова променлива за писане - обект от класа ofstream:
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();
Пример на цяла програма.
// writef.cpp
#include <iostream>
#include <fstream>
/* включване на заглавен файл */
#include <string>
using namespace std;
int main()
{ ofstream out_data; /* дефиниране
на файлова променлива за писане */
out_data.open("writef.txt");
/* отваряне на файла writef.txt */
string s = "Hello";
out_data << s <<
endl; /* писане на низ */
int n = 5;
double x = 5.5;
out_data << n <<
" " << x << " "; /* писане на числови данни */
char ch = 'T';
out_data.put(ch); /* писане
на символ */
out_data.close();
/* затваряне на файла */
return 0;
}
Файл writef.txt:
Hello
5 5.5 T |
В) Четене и писане във файл.
* дефиниране на файлове променлива за четене и писане - обект от класа
fstream:
fstream io_data;
* отваряне на файл, четене и писане - както са описани по-горе.
* * Програма за четене на заплати и чертаене на диаграма.
// 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];
for (int 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());
for (int 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;
}
Файл readdata.txt:
|
Пример: Преобразуване на момент от време в низ.
// readtime.cpp
#include <iostream>
#include <sstream>
using namespace std;
string int_to_string(int n)
{ ostringstream outstr;
outstr << n;
return outstr.str();
}
void read_time(int &hours, int &minutes)
{ string line;
getline(cin, line);
istringstream instr(line);
instr >> hours;
minutes = 0;
char ch;
instr.get(ch);
if (ch == ':') instr >> minutes;
else
instr.unget();
string suffix;
instr >> suffix;
if (suffix == "pm") hours += 12;
}
string time_to_string(int hours, int minutes,
bool am_pm)
{ string suffix;
if (am_pm)
{ if (hours < 12) suffix = "am";
else { suffix = "pm";
hours -= 12; }
if (hours == 0) hours
= 12;
}
string result = int_to_string(hours)
+ ":";
if (minutes < 10) result = result
+ "0";
result = result + int_to_string(minutes);
if (am_pm) result = result + "
" + suffix;
return result;
}
int main()
{ cout << "Please enter the time:
";
int hours, minutes;
read_time(hours, minutes);
cout << "Using am/pm:
" << time_to_string(hours, minutes, true) << "\n";
cout << "Military time: "
<< time_to_string(hours, minutes, false) << "\n";
return 0;
}
Please enter the time: 10:20 pm
Using am/pm: 10:20 pm Military time: 22:20 |
Аргументи от командния ред.
* Определение и използване.
Операционните системи UNIX и DOS могат да предават
данни от командния ред за стартиране на програма на С и С++ на самата програма.
За тази цел главната функция main
може да има два формални параметри - int argc
и
char* argv[].
Следващият
пример илюстрира тази възможност.
// argum.cpp
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char * argv[])
{ cout << argc << endl;
/* брой на аргументите */
for (int i=0; i<argc; i++)
{ string s = static_cast<string>(argv[i]);
cout << s <<
" ";
/* пореден аргумент */
}
cout << endl;
return 0;
}
Изпълнение на програмата:
d:\pub\book2\cpp>argum
-a b cc d
5 D:\PUB\BOOK2\CPP\ARGUM.EXE -a b cc d |
* Шифър на Цезар.
Шифрирането се състои в замяна на буква от даден
(изходен) текст с друга буква, която се намира е след key
букви в азбуката. Дешифрирането на шифриран текст се състои във възстановяване
на изходното съобщение.
Програмта работи със следните аргументи от командния
ред:
- флаг -d (незадължителен) за работа на програмата
по дешифриране;
- флаг -k<число> (незадължителен) за задаване на
ключ (по подразбиране ключът е 3);
- име на входен файл;
- име на изходен файл.
// ceasar.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
void usage(string program_name)
{ cout << "Usage: " << program_name
<<
" [-d] [-kn] infile outfile\n";
exit(1);
}
void open_file_error(string filename)
{ cout << "Error opening file "
<< filename << "\n";
exit(1);
}
int remainder(int a, int n)
{ if (a >= 0) return a % n;
else
return n - 1 - (-a - 1) % n;
}
char encrypt(char ch, int k)
{ const int NLETTER = 26;
if ('A' <= ch && ch
<= 'Z')
return static_cast<char>('A'
+ remainder(ch-'A'+k, NLETTER));
if ('a' <= ch && ch
<= 'z')
return static_cast<char>('a'
+ remainder(ch-'a'+k, NLETTER));
return ch;
}
void encrypt_file(ifstream& in, ofstream&
out, int k)
{ char ch;
while (in.get(ch)) out.put(encrypt(ch,
k));
}
int string_to_int(string s)
{ istringstream instr(s);
int n;
instr >> n;
return n;
}
int main(int argc, char* argv[])
{ bool decrypt = false;
int key = 3;
int nfile = 0;
ifstream infile;
ofstream outfile;
if (argc<3 or argc>5) usage(string(argv[0]));
for (int i = 1; i < argc; i++)
{ string arg = string(argv[i]);
if (arg.length() >=
2 and arg[0] == '-')
{ char option = arg[1];
if (option
== 'd') decrypt = true;
else if
(option == 'k')
key = string_to_int(arg.substr(2, arg.length() - 2));
}
else
{ nfile++;
if (nfile
== 1)
{ infile.open(arg.c_str());
if (infile.fail()) open_file_error(arg);
}
else if
(nfile == 2)
{ outfile.open(arg.c_str());
if (outfile.fail()) open_file_error(arg);
}
}
}
if(nfile != 2) usage(string(argv[0]));
if (decrypt) key = -key;
encrypt_file(infile, outfile,
key);
infile.close();
outfile.close();
return 0;
}
Изпълнение на програмата:
>ceasar
>Usage: CEASAR.EXE [-d] [-kn] infile outfile |
Файл input.txt:
This is a text to encrypt (1-st) and decrypt
(2-nd).
One more line. End. |
Изпълнение на програмата:
>ceasar input.txt encrypt1.txt |
Wklv lv d whaw wr hqfubsw (1-vw) dqg ghfubsw
(2-qg).
Rqh pruh olqh. Hqg. |
Изпълнение на програмата:
>ceasar -k7 input.txt encrypt2.txt |
Aopz pz h alea av lujyfwa (1-za) huk kljyfwa
(2-uk).
Vul tvyl spul. Luk. |
Изпълнение на програмата:
>ceasar -d -k7 encrypt2.txt output.txt |
This is a text to encrypt (1-st) and decrypt
(2-nd).
One more line. End. |
Harry Hacker 500 | Johny Johnson 600 | Tedy Tompson 700.20 |
1234567890123456 | 12345678901234567 | 1234567890123456789 |
Harry Hacker 500 | Johny Johnson 600 | Tedy Tompson 700.20 |
1234567890123456789012 | 1234567890123456789012 | 1234567890123456789012 |
- включване на заглавен файл:
#include <fstream>
- дефиниране на файлова променлива за четене и писане:
fstream fs;
- преместване на позициите за четене и писане:
long n = 10;
/* преместване на позицията за четене
10 байта след началото на файла */
fs.seekg(n, ios::beg);
/* преместване на позицията за писане
10 байта след началото на файла */
fs.seekp(n, ios::beg);
/* преместване на позицията за писане
в края на файла */
fs.seekp(n, ios::end);
/* преместване на позицията за писане
10 байта напред относно текущата позиция */
fs.seekp(n, ios::cur);
- намиране на текущите позициите за четене и писане:
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; /* или 1
за 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);
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;
}
Файл data.txt преди изпълнение
на програмата:
Harry Hacker
500
Johny Johnson 600 Tedy Tompson 777 |
Please enter the data file name: data.txt
Please enter the record to update: (0 - 2) 1 |
Harry Hacker
500
Johny Johnson 630.00 Tedy Tompson 777 |