Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
file3.cpp
#include <file1.hpp>
#include <file2.hpp>
// What the compiler should call here?
int i=value();
namespace
file1.hpp
namespace space1
{
int value(){ return 5;}
}
file2.hpp
namespace space2
{
const double pi=3.1416
int value(){ return 2*pi;}
}
namespace
file3.cpp
#include <file1.hpp>
#include <file2.hpp>
int i=space1::value(); // file1.hpp
int j=space2::value(); // file2.hpp
namespace
file3.cpp
#include <file1.hpp>
#include <file2.hpp>
using namespace space1;
int i=value(); // file1.hpp
using namespace space2;
int j=space2::value(); // file2.hpp
// Compiler generates an error without
space2:: , for it don’t understans what
to call.
Наконец,
namespace std
{
Библиотека ввода/вывода
Консольный ввод/вывод
Следующие классы работают с консолью, то есть
клавиатурой и текстовым выводом на экран.
class istream
Форматированный ввод
istream& operator>> (bool& val);
istream& operator>> (short& val);
istream& operator>> (unsigned short& val);
istream& operator>> (int& val);
istream& operator>> (unsigned int& val);
istream& operator>> (long& val);
istream& operator>> (unsigned long& val);
istream& operator>> (long long& val);
istream& operator>> (unsigned long long& val);
istream& operator>> (float& val);
istream& operator>> (double& val);
istream& operator>> (long double& val);
istream& operator>> (void*& val);
class istream
Неформатированный ввод
single character
int get();
istream& get (char& c);
c-string
istream& get (char* s, streamsize n);
istream& get (char* s, streamsize n,
char delim);
istream& put (char& c);
c-string
<< only!
Потоки
Для консольных программ определено несколько
переменных для ввода и вывода
cin – консольный ввод (клавиатура)
cout – консольный вывод (черное окошко)
cerr – поток ошибок (окно компилятора с
ошибками)
clog – поток журнала (там, где у компилятора
пишется запуск/остановка приложения, загрузка
библиотек, …)
Консольный ввод/вывод
// istream::getline example
#include <iostream> // std::cin, std::cout
int main () {
char name[256], title[256];
std::cout << "Please, enter your name:";
std::cin.getline (name,256);
std::cout << «Enter your favorite movie:";
std::cin.getline (title,256);
std::cout << name << "'s favorite movie is " <<
title;
return 0;
}
Консольный ввод/вывод
Конструкторы
ifstream();
explicit ifstream (const char* filename,
ios_base::openmode mode = ios_base::in);
explicit ifstream (const string&
filename, ios_base::openmode mode =
ios_base::in);
ifstream (const ifstream&) = delete;
ifstream (ifstream&& x);
class ifstream
Режимы открытия файлов.
File open for reading: the internal stream buffer
in input
supports input operations.
File open for writing: the internal stream buffer
out output
supports output operations.
Operations are performed in binary mode
binary binary
rather than text.
ate at end The output position starts at the end of the file.
All output operations happen at the end of the
app append
file, appending to its existing contents.
Any contents that existed in the file before it is
trunc truncate
open are discarded.
class ifstream
Открытие и закрытие файлов
void open (const char* filename,
ios_base::openmode mode = ios_base::in);
void open (const string& filename,
ios_base::openmode mode = ios_base::in);
void close();
bool good() const;
bool eof() const;
ifstream/ofstream classes
Чтение двоичных данных
istream& read (char* s, streamsize n);
Запись двоичных данных
ostream& write (const char* s,
streamsize n);
class ifstream
Позиционирование в открытом классе
istream& seekg (streampos pos);
istream& seekg (streamoff off,
ios_base::seekdir way);
ios_base::beg beginning of the stream
ios_base::cur current position in the stream
ios_base::end end of the stream
// Returns the current position.
streampos tellg();
ifstream (Пример)
// reads a file into memory
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is ("test.txt",
std::ifstream::binary);
if (is) {
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
ifstream (Пример)
char * buffer = new char [length];
is.read (buffer,length);
is.close();
std::cout.write (buffer,length);
delete[] buffer;
}
return 0;
}
ifstream (Пример)
int *buffer=
new int [length/sizeof(int)];
is.read ((char*)buffer,length);
is.close();
…
delete [] buffer;
}
return 0;
}
Сериализация объектов
class Unit
{
UnitKind getKind() { return kind; };
virtual void write(ofstream &file)=0;
virtual void read(ifstream &file)=0;
virtual void move()=0;
private:
UnitKind kind;
};
Сериализация объектов
class Infantry: Unit
{
virtual void write(ofstream &file);
virtual void read(ifstream &file);
virtual void move();
private:
float shield, force, health;
};
Сериализация объектов
void Infantry::write(ofstream &file)
{
file << shield << ”, ” << force
<< ”, ” << health << ”\n”;
};
// Case of text file.
void Infantry::read(ifstream &file)
{char c;
file >> shield >> c >> force >> c
>> health >> c;
};
Сериализация объектов
void Infantry::write(ofstream &file)
{
file.write((char*)&shield,sizeof(float))
;
file.write((char*)&force,sizeof(float));
file.write((char*)&health,sizeof(float))
;
};
// Case of binary file (the same name).
void Infantry::read(ifstream &file)
{file.read((char*)&shield,sizeof(float))
;
Сериализация объектов
class UnitCollection
{
…
void write(std::string filename);
void read (std::string filename);
…
};
Сериализация объектов
… ::write(std::string filename)
{std::ofstream ofile(filename);
int tmp;
ofile.write((char*)&ucnt, sizeof(int));
for( int i=0; i<ucnt; i++ )
{tmp=units[i]>getKind()
ofile.write((char*)&tmp, sizeof(int));
units[i]>write(ofile);
}
}
Сериализация объектов
… ::write(std::string filename)
{std::ofstream ofile(filename);
int tmp;
ofile.write((char*)&ucnt, sizeof(int));
for( int i=0; i<ucnt; i++ )
{tmp=units[i]>getKind()
ofile.write((char*)&tmp, sizeof(int));
units[i]>write(ofile);
}
} // Why don’t I close the file?
Сериализация объектов
… ::read(std::string filename)
{std::ifstream ifile(filename);
int tmp;
ifile.read((char*)&ucnt, sizeof(int));
units=new Unit*[ucnt];
for( int i=0; i<ucnt; i++ )
{ifile.read((char*)&tmp, sizeof(int));
if(tmp==utInf) units[i]=new Infantry;
else if(tmp==utChiv)units[i]=new Chival;
…
units[i]>read(ifile);
} }
Однако…
Приведенный код нехорош.
На свете существуют виртуальные функции, но при
этом вызываем их явно.
И что делать?
Надо создать виртуальные функции чтения и
записи у Unit и переопределить их у дочерних
классов. Но как понять кого читать?
Можно создать функцию фабрики классов, которая
будет возвращать Unit* на объект правильного
типа, принимая при этом параметр, указывающий
на тип объекта. А тип объекта можно читать из
файла.
Сериализация объектов
class Unit
{// A Unit can read and write its type.
UnitKind getKind() { return kind; };
void writeKind(ofstream &file);
UnitKind readKind(ifstream &file);
virtual void write(ofstream &file)=0;
virtual void read(ifstream &file)=0;
virtual void move()=0;
private:
UnitKind kind;
};
Сериализация объектов
class Infantry: public Unit
{
virtual void write(ofstream &file);
virtual void read(ifstream &file);
virtual void move();
private:
float shield, force, health;
};
Сериализация объектов
// Writing and reading a binary file.
void Infantry::write(ofstream &file)
{
file.write((char*)&shield,sizeof(float))
;
file.write((char*)&force,sizeof(float));
file.write((char*)&health,sizeof(float))
;
};
void Infantry::read(ifstream &file)
{file.read((char*)&shield,sizeof(float))
;
Функция фабрики классов
Unit *unitFactory(UnitKind kind)
{
if(kind==utInf) return new Infantry;
if(kind==utChiv) return new Chival;
...
//Hope there will be an error somewhere.
return NULL;
}
Функция фабрики классов
Должна существовать только одна такая функция
для группы классов. Ее не надо копировать.
При появлении нового производного класса
достаточно внести изменения лишь в одно место.
Функция фабрики классов
ofstream &operator << (ofstream &file,
Unit *data)
{
data>writeKind(file);
data>write(file);
return file;
}
Функция фабрики классов
ifstream &operator >> (ifstream &file,
Unit *&data)
{UnitKind tmpKind;
file.read((char*)&tmpKind,
sizeof(UnitKind));
data=unitFactory(tmpKind);
data>read(file);
return file;
}
Функция фабрики классов
class UnitCollection
{
…
void write(std::string filename);
void read (std::string filename);
…
};
Функция фабрики классов
… ::write(std::string filename)
{std::ofstream ofile(filename);
ofile.write((char*)&ucnt, sizeof(int));
for( int i=0; i<ucnt; i++ )
ofile<<units[i];
}
Функция фабрики классов
… ::read(std::string filename)
{std::ifstream ifile(filename);
ifile.read((char*)&ucnt, sizeof(int));
units=new Unit*[ucnt];
for( int i=0; i<ucnt; i++ )
ifile>>units[i];
}
ifstream class
} // namespace std, part 1.
Quote of the Day