Программирование. Принципы и практика использования C++ Исправленное издание, стр. 278
2. Каким-то образом разделить документ и использовать обычную пунктуацию (например,
.3. Разделить строку, длина которой превышает некий порог (например, 50 символов), на две.
Кроме этого, несомненно, существуют менее очевидные варианты. Для простоты выберем первую альтернативу.
Представим документ в нашем редакторе в виде объекта класса
Documenttypedef vector<char> Line; // строка — это вектор символовstruct Document { list<Line> line; // документ — список строк Document() { line.push_back(Line()); }};Каждый объект класса
DocumentDocumentЧтение и разделение на строки можно выполнить следующим образом:
istream& operator>>(istream& is, Document& d){ char ch; while (is.get(ch)) { d.line.back().push_back(ch); // добавляем символ if (ch=='\n') d.line.push_back(Line()); // добавляем новую строку } if (d.line.back().size()) d.line.push_back(Line()); // добавляем пустую строку return is;}Классы
vectorlistback()back()DocumentLine'\n'20.6.2. Итерация
Если бы документ хранился как объект класса
vector<char>list<Line>::iteratorDocumentclass Text_iterator { // отслеживает позицию символа в строке list<Line>::iterator ln; Line::iterator pos;public: // устанавливает итератор на позицию pp в ll-й строке Text_iterator(list<Line>::iterator ll, Line::iterator pp) :ln(ll), pos(pp) { } char& operator*() { return *pos; } Text_iterator& operator++(); bool operator==(const Text_iterator& other) const { return ln==other.ln && pos==other.pos; } bool operator!=(const Text_iterator& other) const { return !(*this==other); }};Text_iterator& Text_iterator::operator++(){ if (pos==(*ln).end()) { ++ln; // переход на новую строку pos = (*ln).begin(); } ++pos; // переход на новый символ return *this;}Для того чтобы класс
Text_iteratorDocumentbegin()end()struct Document { list<Line> line; Text_iterator begin() // первый символ первой строки { return Text_iterator(line.begin(), (*line.begin()).begin()); } Text_iterator end() // за последним символом последней строки { return(line.end(), (*line.end()).end));}};Мы использовали любопытную конструкцию
(*line.begin()).begin()line.begin()line.begin()–>begin()–>Теперь можем перемещаться по символам документа.
void print(Document& d){ for (Text_iterator p = d.begin(); p!=d.end(); ++p) cout << *p;}