#c #templates #iterator
#c #шаблоны #итератор
Вопрос:
Как мне объявить и написать ostream_iterator для использования с моей программой
Моя цель — вызвать следующие функции с моим контейнером и типом данных:
transform(myList.begin(), myList.end(), ostream_iterator<string> (cout), appendSpace);
copy(myList.begin(), myList.end(), ostream_iterator<string> (cout, ' '));
У меня есть пользовательский класс string с именем BLString, который действует как обычный класс string .
У меня есть пользовательский класс списка с именем DblLinkedList, который представляет собой двусвязный список, такой же, как список STL.
Я превратил DblLinkedList в форму шаблона и добавил пользовательский встроенный класс итератора.
Я опустил некоторые файлы из соображений простоты, могу включить при необходимости.
Код приведен ниже:
////
/// DblLinkedList.h
////
#ifndef DblLinkedList_h
#define DblLinkedList_h
#include "BLString.h"
#include <iterator>
using namespace std;
// Node class creates containers for linked list
template<typename type>
class Node { // fully defined here due to its simplicity
public:
Node() {
next = prev = nullptr;
}
Node(type str) {
data = str;
next = prev = nullptr;
}
type data;
Node *next;
Node *prev;
};
//DblLinkedList class links together Node class objects
template<typename type>
class DblLinkedList {
public:
class Iterator{
Node<type>* it;
public:
Iterator(Node<type> *itArg){it = itArg;}
void operator (){it = it->next;}
void operator (int){it = it->next;}
void operator --(){it = it->prev;}
type operator *(){return it->data;}
bool operator == (Iterator itArg){return (it == itArg);}
bool operator != (Iterator itArg){return (it != itArg);}
//FIXME: write this instead of overloading ostream_iterator class?
//Iterator(ostreamamp; ostr){ostr << it->data;}
};
//FIXME: possible to overload class to make usable with copy() and transform() ?
/*
template<typename Type>
class ostream_iterator{
public:
ostream_iterator<Type> (ostreamamp; ostrm){
ostrm << *(Iterator::it->data);
}
};
*/
Iterator begin(){return Iterator(head);}
Iterator end(){return Iterator(tail);}
//default constructor
DblLinkedList();
//copy constructor
DblLinkedList(const DblLinkedList amp;dll);
//assingment operator
DblLinkedList operator=(const DblLinkedList amp;dll);
//destructor
~DblLinkedList();
//insertion operator
//friend ostreamamp; operator<<(ostreamamp; ostrm, const DblLinkedList amp;dll);
friend ostreamamp; operator<<(ostreamamp; ostrm, const DblLinkedList amp;dll){
dll.resetIterator();
while(dll.it){
ostrm << dll.next() << " ";
}
return ostrm;
}
//insert
bool insert(const type amp;str);
//remove
bool remove(const type amp;str);
//remove last
bool pop_back();
// resets iterator
void resetIterator() const;
// has more
bool hasMore() const;
// next string
type next() const;
// test connections
void testConnections();
// list size
int getCount() const;
// for testing
static int getCreatedNodes();
// for testing
static int getCurrentNodes();
private:
Node<type> *head, *tail;
// mutable says that it can change in a const member function
mutable Node<type> *it;
int count;
static int currentNodes, createdNodes;
};
// for testing
template<typename type>
int DblLinkedList<type>::createdNodes = 0;
// for testing
template<typename type>
int DblLinkedList<type>::currentNodes = 0;
// for testing
template<typename type>
int DblLinkedList<type>::getCreatedNodes(){return createdNodes;}
// for testing
template<typename type>
int DblLinkedList<type>::getCurrentNodes(){return currentNodes;}
// Default constructor
template<typename type>
DblLinkedList<type>::DblLinkedList() {
head = nullptr;
tail = nullptr;
it = nullptr;
count = 0;
}
// copy constructor
template<typename type>
DblLinkedList<type>::DblLinkedList(const DblLinkedList amp;dll){
head = nullptr;
tail = nullptr;
it = nullptr;
count = 0;
// if copying empty list
if(!dll.head)
head = tail = nullptr;
// if copying list with 1 or more items
else{
dll.resetIterator();
while(dll.hasMore()){
Node<type>* temp = new Node<type>(dll.it->data);
createdNodes ;// for testing
currentNodes ;// for testing
//if copying list with 1 item or 1st item
if(!head){
head = tail = temp;
count ;
//if copying list with more than 1 item
}else{//adding to back of list
temp->prev = tail;
tail->next = temp;
tail = temp;
count ;
}
dll.it = dll.it->next;
}
}
}
// Assingment operator
template<typename type>
DblLinkedList<type> DblLinkedList<type>::operator=(const DblLinkedList amp;dll){
if(this != amp;dll){// self assignment check
resetIterator();
while(hasMore()){
head = it->next;
currentNodes--;// for testing
delete it;
it = head;
}
head = nullptr;
tail = nullptr;
it = nullptr;
count = 0;
dll.resetIterator();
// if copying empty list
if(!dll.head)
head = tail = nullptr;
//if copying list with 1 or more items
while(dll.hasMore()){
Node<type>* temp = new Node<type>(dll.it->data);
createdNodes ;// for testing
currentNodes ;// for testing
// if copying list with 1 item
if(!head){
head = tail = temp;
count ;
//if copying list with more than 1 item
}else{
temp->prev = tail;
tail->next = temp;
tail = temp;
count ;
}
dll.it = dll.it->next;
}
}
return *this;
}
//destructor
template<typename type>
DblLinkedList<type>::~DblLinkedList(){
resetIterator();
while(hasMore()){
head = it->next;
delete it;
currentNodes--;// for testing
it = head;
}
}
// instertion operator
//template<typename type> // move inside
//insert
template<typename type>
bool DblLinkedList<type>::insert(const type amp;str){
bool inserted = false;
//if instering in blank list
if(!head){
Node<type> *temp = new Node<type>(str);
createdNodes ;// for testing
currentNodes ;// for testing
head = tail = temp;
inserted = true;
count ;
}
// if inserting to front
else if((str < head->data)){
Node<type> *temp = new Node<type>(str);
createdNodes ;// for testing
currentNodes ;// for testing
head->prev = temp;
temp->next = head;
head = temp;
inserted = true;
count ;
}
// if inserting at end
else if(str > tail->data){
Node<type> *temp = new Node<type>(str);
createdNodes ;// for testing
currentNodes ;// for testing
tail->next = temp;
temp->prev = tail;
tail = temp;
inserted = true;
count ;
}
// if inserting inside
else{
resetIterator();
while(it){
//alphebetical placement qualifier
//does not enter statment if word already exists in list
if ((str < it->data) amp;amp; (str > it->prev->data)){
Node<type> *temp = new Node<type>(str);
createdNodes ;// for testing
currentNodes ;// for testing
it->prev->next = temp;
temp->prev = it->prev;
temp->next = it;
it->prev = temp;
inserted = true;
count ;
break;
}
it = it->next;
}
}
return inserted;
}
//remove
template<typename type>
bool DblLinkedList<type>::remove(const type amp;str){
bool removed = false;
//if list is not empty
if(head){
// if removing head
if(str == head->data){
head->next->prev = nullptr;
it = head;
head = head->next;
currentNodes--;// for testing
delete it;
removed = true;
count--;
}
//if removing tail
else if(str == tail->data){
tail->prev->next = nullptr;
it = tail;
tail = tail->prev;
currentNodes--;// for testing
delete it;
removed = true;
count--;
//if removing inside
}else{
resetIterator();
while(it){
if(str == it->data){
it->prev->next = it->next;
it->next->prev = it->prev;
currentNodes--;// for testing
delete it;
removed = true;
count--;
break;
}
it = it->next;
}
}
}
return removed;
}
template<typename type>
bool DblLinkedList<type>::pop_back(){
it = tail;
tail->prev->next = nullptr;
tail = tail->prev;
delete it;
currentNodes--;
count--;
return true;
}
// reset iterator
template<typename type>
void DblLinkedList<type>::resetIterator() const{
if(head)
it = head;
else
it = nullptr;
}
// has more
template<typename type>
bool DblLinkedList<type>::hasMore() const{
bool tempBool = false;
if(it)
return true;
return tempBool;
}
// next
template<typename type>
type DblLinkedList<type>::next() const{
type tempData;//possible ineficiency source
tempData = it->data;
it = it->next;
return tempData;
}
// for testing
template<typename type>
void DblLinkedList<type>::testConnections(){
if(head->prev == nullptr){
cout << "head->data --- " << head->data << endl;
cout << "head->prev == nullptr ----- PASSED" << endl;
}
if(tail->next == nullptr){
cout << "tail->data --- " << tail->data << endl;
cout << "tail->next == nullptr ----- PASSED" << endl;
}
resetIterator();
while(hasMore()){
if(it != tail){
if(it == it -> next -> prev)
cout << "(it != it -> next -> prev) ---- PASSED" << endl;
}
it = it->next;
}
}
// getCount
template<typename type>
int DblLinkedList<type>::getCount() const {return count;}
#endif /* DblLinkedList_h */
////
/// main.cpp
////
// #include "pch.h" // didn't need this
#include <iostream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <string>//need because fin doesn't accept BLString
#include "BLString.h"
#include "DblLinkedList.h"
using namespace std;
template<typename type>
void advanceIterator(typename DblLinkedList<type>::Iterator amp;it_Name, unsigned int n){
for(int i = 0; i < n; i)
it_Name ;
}
template<typename type>
type addSpace(type data);
//changer function per specs
template<typename type>
void changer(DblLinkedList<type> dll);
//print lists
template<typename type>
void printListSizes(const DblLinkedList<type> amp;list1, const DblLinkedList<type> amp;list2, const DblLinkedList<type> amp;modList1, const DblLinkedList<type> amp;modList2);
//read from file to list
template<typename type>
void fileToList(DblLinkedList<type> amp;dll, string fileName);
//print from list to file
template<typename type>
void listToFile(DblLinkedList<type> amp;dll, string fileName);
//remove from modList all of the strings stored in list
template<typename type>
void removeFrom(DblLinkedList<type> amp;modList, DblLinkedList<type> amp;list);
int main() {
DblLinkedList<BLString> list1;
string fileName;
//reading from infile1.txt into list 1
fileName = "infile1.txt";
fileToList(list1, fileName);
cout << endl;
cout << "list1: ";
auto it = list1.begin(); //DblLinkedList<BLString>::Iterator it = list1.begin();
for(int i = 0; i < 5; i){
cout << * it << " ";
it;
}
/* FIXME: not working; need to write overloaded class in DblLinkedList.h */
//copy(it, it_3, ostream_iterator<BLString>(cout));
cout << endl;
}
template<typename type>
void changer(DblLinkedList<type> dll){
dll.insert("ZIP");
dll.insert("ZAP");
cout << "Inside changer. Size of list: "<< dll.getCount() << endl;
}
template<typename type>
void printListSizes(const DblLinkedList<type> amp;list1, const DblLinkedList<type> amp;list2, const DblLinkedList<type> amp;modList1, const DblLinkedList<type> amp;modList2) {
cout << endl;
cout << "List sizes" << endl;
cout << "--------------" << endl;
cout << left << setw(10) <<"list1 " << right << list1.getCount() << endl;
cout << left << setw(10) <<"list2 " << right << list2.getCount() << endl;
cout << left << setw(10) <<"modList1 " << right << modList1.getCount() << endl;
cout << left << setw(10) << "modList2 " << right << modList2.getCount() << endl;
}
template<typename type>
void fileToList(DblLinkedList<type> amp;dll, string fileName){
ifstream fin(fileName);
type word;
while(!fin.eof()){
fin >> word;
dll.insert(word);
}
fin.close();
}
template<typename type>
void listToFile(DblLinkedList<type> amp;dll, string fileName){
ofstream fout(fileName);
fout << dll;
fout.close();
}
template<typename type>
void removeFrom(DblLinkedList<type> amp;modList, DblLinkedList<type> amp;list){
list.resetIterator();
while(list.hasMore())
modList.remove(list.next());
}
//FIXME: not completed
template<typename type>
type addSpace(type data){
return data " ";
}
infile1.txt содержит главу из книги; просто набор слов для тестирования программы.
Пример:
Эти беспорядочные, возбужденные группы состояли в основном из мужчин с зелеными ветками на шляпах и самым нелепым оружием в руках. Некоторые, правда, держали на плечах охотничьи ружья, а кое-где размахивали мечами; но большинство из них были вооружены дубинками, и большинство из них тащили за собой гигантские пики, сделанные из кос, столь же грозные на вид, сколь и неуклюжие в руке. Среди этих импровизированных военных были ткачи, пивовары, плотники, кузнецы, каменщики, сапожники и представители всех других мирных профессий. Бриджуотер, как и Тонтон, так щедро пожертвовал своей мужественностью на службу герцогу-бастарду, что для любого, кто воздержался, чей возраст и сила допускали его ношение оружия, означало заклеймить себя трусом или папистом.