Показать полную графическую версию : STL
.::.DIMA.::.
22-04-2009, 16:43
Решено
.::.DIMA.::., дабы многократно не перечитывать файл, его содержимое можно загрузить в память и работать с ней.
В примере про функцию fread() по ссылке в теме Бинарные файлы (http://forum.oszone.net/thread-138194.html) как раз так и поступили.
В зависимости от идеи можно поступить по-разному.
Допустим матрица хранится в виде упорядоченного списка ненулевых элементов: {row, col, value}
тогда наша задача пробежать 2 файла и записать 3-й файл с ненулевым результатом в таком же упорядоченном виде. Используем алгоритм merge
struct cell_t
{
unsigned row;
unsigned col;
double value;
// для сортировки
friend bool operator<(const cell_t& a, const cell_t& b) {
return a.row<b.row || (a.row==b.row && a.col<b.col);
// для удобства потом
friend bool operator==(const cell_t& a, const cell_t& b) {
return a.row==b.row && a.col==b.col;
// ввод-вывод
friend ostream& operator<<(ostream& os, const cell_t& a)
{
return os << a.row << " " << a.col << " " << a.value;
}
friend istream& oeprator>>(istream& is, cell_t& a)
{
return is >> a.row >> a.col >> a.value;
}
};
struct mixer
{
cell_t prev;
ostream_iterator<cell_t,char> output_iter;
mixer() : prev(), output_iter(cout, "\n")
{
}
// строим хитрый итератор
mixer& operator*() {return *this;}
// так чтобы *iter=a давало нужный эфект
void operator=(const cell_t& a)
{
if (prev==a) prev.value += a.value;
else {
if (prev.value) *output_iter = prev;
prev = a;
}
}
void main()
{
ifstream matrix1("matrix1.txt");
ifstream matrix2("matrix2.txt");
mixer mixer1; // экономим копирования (передаём в шаблон ссылку, а не объект)
*merge(
istream_iterator<cell_t>(matrix1), istream_iterator<cell_t>(),
istream_iterator<cell_t>(matrix2), istream_iterator<cell_t>(),
static_cast<mixer&>(mixer1)) = cell_t(); // необходимо чтобы выгрузить последний накопленный результат
}
Итератор - это заменитель указателя в с++. Он даёт универсальное представление указателя на элемент контейнера для шаблонов перебора в с++. Пример шаблона копирования:
template<typename InputIterator, typename OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
for(; first!=last; ++first, ++result) *result = *first;
return result;
}
Есть соглашения по поводу назначения итераторов:
OutputIterator - предназначен для вывода в поток, во всех алгоритмах используются только конструции *iterator=..., и ++iterator или iterator++; (кстати, если компилятор будет ругаться при сборке на operator++() или operator++(int), надо его добавить, пустой)
InputIterator - для ввода с потока ...=*iterator и ++iterator или iterator++. При этом понимается, что значение надо брать и присваивать один раз.
для OutputIterator и InputIterator как правило явный конструктор без параметра строит итератор конца потока.
ForwardIterator - позволяет чтение, запись, оператор ++ (например для стека)
BidirectionalIterator - позволяет чтение, запись, операторы ++,-- (например для списка)
RandomAccessIterator - позволяет всё, что можно делать с указателем
Попробуем раскрыть шаблон copy с классом merge&:
// merge merge1
// copy(istream_iterator<cell_t>(cin), istream_iterator<cell_t>(), static_cast<merge&>(merge1))
merge& copy(istream_iterator<cell_t,char> first, istream_iterator<cell_t,char> last, merge& result)
{
// *first прочитает оператором >> и вернёт значение cell_t из потока
// *result вернёт result
// result =... вызовет merge::operator=(const cell_t&), который запишет в поток вывода результат
// merge::operator++() лучше оставить пустым {} тогда ++result просто пропустится
for(; first!=last; ++first, ++result) *result = *first;
// если идти дальше, у istream_iterator пустой operator++, а operator==(const istream_iterator& iter2)
// возвращает что-то вроде _stream.good()==iter2._stream.good();
// помним, что last._stream.good() даёт false
// получили примерно следующее: for(; first._stream.good()!=last._stream.good(); ) result.merge::operator=((first._stream>>first._value ? first._value : cell_t()));
return result;
}
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.