승1's B(log n)

[자료구조 - C++] Assignment 2 Doubly Linked List를 응용한 간단한 문서편집기 만들기 본문

Data Structures & Algorithms

[자료구조 - C++] Assignment 2 Doubly Linked List를 응용한 간단한 문서편집기 만들기

승1이 2022. 6. 24. 15:49

두번째 과제는 Doubly Linked List를 응용하여 간단한 문서편집기를 만드는 것이었다. 주어진 파일은 총 다섯개로, doublylinkedlist.h, doublylinkedlist.txx, main.cpp, texteditor.cpp, texteditor.h가 주어졌고 이중에서 doublylinkedlist.txx 파일과 texteditor.cpp 파일을 수정하여 제출해야 했다.

1-1) 구현해야 하는 함수들 - doublylinkedklist.txx

class Iterator : public Iterator_Base {
	public:
		Iterator(NodeType * startNode = 0) : Iterator_Base(startNode) {}
		Iterator& operator++();    // ToDo
		Iterator  operator++(int); // ToDo
		Iterator& operator--();    // ToDo
		Iterator  operator--(int); // ToDo
	};
		
	class Reverse_Iterator : public Iterator_Base {
	public:
		Reverse_Iterator(NodeType * startNode = 0) : Iterator_Base(startNode) {}
		Reverse_Iterator& operator++();    // ToDo
		Reverse_Iterator  operator++(int); // ToDo
		Reverse_Iterator& operator--();    // ToDo
		Reverse_Iterator  operator--(int); // ToDo

	};
    
    
    // Default constructor - ToDo
	DoublyLinkedList();
	
	// Copy constructor - ToDo
	DoublyLinkedList(const DoublyLinkedList& source);

	// Destructor - ToDo
	~DoublyLinkedList();

	// Assignment operator - ToDo
	DoublyLinkedList& operator = (const DoublyLinkedList& source);
    
    
    // Insert a new node to the list as the first node
	// Return the pointer of new node - ToDo
	Iterator InsertFirst(const T & data);

	// Insert a new node to the list as the last node
	// Return the pointer of new node - ToDo
	Iterator InsertLast(const T & data);

	// Insert a new node to the list after pos
	// Return the pointer of new node - ToDo
	Iterator InsertNext(Iterator pos, const T & data);
	
	// Insert a new node to the list before pos
	// Return the pointer of new node - ToDo
	Iterator InsertPrev(Iterator pos, const T & data);
	
	// Total number of nodes in the list - ToDo
	int Size() const;				
		
	// Delete node at pos in the list - ToDo
	bool DeleteNode(Iterator pos);
	
	// Delete first node - ToDo
	bool DeleteFirst();
	
	// Delete last node - ToDo
	bool DeleteLast();

참고사항 :

  • Node data type is defined by the template parameter. : 노드의 데이터 타입은 템플릿 매개변수로 정의되어 있음.
  • Copy constructor and assignment operator are implemented so that a new linked list can be created by an existing list. : 복사생성자와 대입연산자는 이미 구현이 되어있어서 존재하는 리스트로 새로운 linked list를 생성할 수 있음.
  • An empty list must contain a header node, and first pointer points to it. : 빈 리스트는 반드시 헤더 노드를 가지고 있어야 하며, first 포인터가 그것을 지목하고 있어야 함.
  • Assume that the traverse order is from left to right. Reverse traversal order is from right to left. : 순회하는 방향은 왼쪽에서 오른쪽으로 가정한다. 역순환의 방향은 오른쪽에서 왼쪽이다.
  • The class should provide iterators for forward-order and reverse-order traversal of the list. You must provide start/end location of forward iterator using Begin()/End(), and those of reverse iterator using rBegin()/rEnd(). : 해당 클래스는 반복자의 정방향과, 역방향의 순회를 지원해야 한다. 반복자의 시작과 끝을 정방향 순회의 경우 Begin()/End()를 이용해 제공하고, 역방향 순회의 경우 rBegin()/rEnd()를 통해 제공해야 한다.
  • ++ or –- operator is used to increase / decrease the location of the iterator based on the traversal direction. For example, ++ for Iterator moves the iterator from left to right. However, ++ for Reverse_Iterator moves the iterator from right to left (++ operator is defined in both classes differently). : ++와 -- 연산자는 반복자의 순회방향에 따라서 증가/감소 시키는 역할을 갖고 있다. 예컨대, 정방향에서의 ++연산자는 왼쪽에서 오른쪽으로 이동시키는 역할을 수행하지만, 역방향에서의 ++연산자는 오른쪽에서 왼쪽으로 이동시키는 역할을 수행한다.
  • New node can be inserted to / deleted from either end (left or right) and in the middle where the location is given by the iterator. : 노드는 왼쪽, 오른쪽 끝에서든 반복자가 가리키고 있는 중간에서든 삽입 또는 제거될 수 있다.

1-2) 구현해야 하는 함수들 - texteditor.cpp

class TextEditor
{
public:
	// Default constructor
	TextEditor();

	// Destructor
	~TextEditor();

	// Insert a new line after the current position
	void Insert(const char* s);
	
	// Delete the current line
	void Delete();
	
	// Move one line up
	void MoveUp();
	
	// Move one line down
	void MoveDown();
	
	// Print the current line with the line number
	void Print();

	// Print all with the line number
	void PrintAll();
	
	// Run interactive mode
	void Run();

참고사항 :

  • TextEditor() : constructor : 생성자
  • ~TextEditor() : destructor : 소멸자
  • Insert(char*) : Insert a new line after the current position, and change the current position to the newly inserted line. : 현재 위치에 새로운 문장을 추가하고, 새로운 문장을 current position으로 지정한다.
  • Delete() : If the buffer is empty, print out the message “Buffer is empty”. If not, you delete the current line and set the new current line as next line (if exists). If not, set the new current line as previous line. : 만약 버퍼가 비었다면 "버퍼가 비어있습니다"라는 메세지를 출력하고, 만약 그렇지 않다면 현재 라인을 지우고 현재 라인의 다음 라인을 current position으로 지정한다. 만약 다음 라인이 존재하지 않는다면 현재 라인의 이전 라인을 current position으로 지정한다.
  • MoveUp() : Move current line up by one. If the current line is the first line, do not move and print out the message “Beginning of the buffer”. : current position을 하나 위로 이동시킨다. 만약 현재 위치가 맨 위라면, 이동시키지 말고 "버퍼의 시작입니다"라는 문구를 출력한다. 
  • MoveDown() : Move current line down by one. If the current line is the last line, do not move and print out the message “End of the buffer”. : current position을 하나 아래로 이동시킨다. 만약 현재 위치가 맨 아래라면, 이동시키지 말고 "버퍼의 끝입니다"라는 문구를 출력한다. 
  • Run() : Run the text editor in interactive mode. : 문서 편집기의 상호작용 모드를 활성화 시킨다.
  •  Available commands are u(up), d(down), p(print), pa(print all), r (delete), i(insert), and x(exit) : 상호작용 모드에서는 u(위로), d(아래로), p(현재 라인 출력), pa(모든 라인 출력), r(현재 라인 삭제), i(삽입), x(종료)의 커맨드만이 인식된다.
 

2) doublylinkedlist.h

#ifndef DoublyLinkedList_H
#define DoublyLinkedList_H

#include <iostream>

template<class T>
class DoublyLinkedList;


// List Node class
template<class T>
class DoublyLinkedListNode{
	friend class DoublyLinkedList<T>;
	friend class DoublyLinkedList<T>::Iterator_Base;
	friend class DoublyLinkedList<T>::Iterator;
	friend class DoublyLinkedList<T>::Reverse_Iterator;
private:
	T data;         // data
	DoublyLinkedListNode<T> * llink;    // left link
	DoublyLinkedListNode<T> * rlink;    // right link
};


// List class
template<class T>
class DoublyLinkedList
{
public:
	typedef DoublyLinkedListNode<T> NodeType;
		
	// iterator
	class Iterator_Base {
	public:
		Iterator_Base(NodeType * startNode = 0) { current = startNode; }
		~Iterator_Base() {}
		
		Iterator_Base(const Iterator_Base& source) { current = source.current; }
		
		// dereferencing operators
		T& operator*() const { return current->data; }
		T* operator->() const { return &current->data;}
		
		// get the node pointer directly
		NodeType* GetNodePointer() { return current; }
		
		// equality testing
		bool operator!=(const Iterator_Base it) const
			{ return current != it.current; }
		bool operator==(const Iterator_Base it) const
			{ return current == it.current; }
		
	protected:
		NodeType* current;
	};
		
	class Iterator : public Iterator_Base {
	public:
		Iterator(NodeType * startNode = 0) : Iterator_Base(startNode) {}
		Iterator& operator++();    // ToDo
		Iterator  operator++(int); // ToDo
		Iterator& operator--();    // ToDo
		Iterator  operator--(int); // ToDo
	};
		
	class Reverse_Iterator : public Iterator_Base {
	public:
		Reverse_Iterator(NodeType * startNode = 0) : Iterator_Base(startNode) {}
		Reverse_Iterator& operator++();    // ToDo
		Reverse_Iterator  operator++(int); // ToDo
		Reverse_Iterator& operator--();    // ToDo
		Reverse_Iterator  operator--(int); // ToDo

	};
	
	// Default constructor - ToDo
	DoublyLinkedList();
	
	// Copy constructor - ToDo
	DoublyLinkedList(const DoublyLinkedList& source);

	// Destructor - ToDo
	~DoublyLinkedList();

	// Assignment operator - ToDo
	DoublyLinkedList& operator = (const DoublyLinkedList& source);

	// Get leftmost node iterator
	Iterator Begin() const { Iterator it(first); return ++it; };
		
	// Get end iterator
	Iterator End() const {  Iterator it(first); return it; }
	
	// Get rightmost iterator
	Reverse_Iterator rBegin() const { Reverse_Iterator it(first); return ++it; };
	
	// Get end iterator
	Reverse_Iterator rEnd() const {  Reverse_Iterator it(first); return it; }
	
	// Insert a new node to the list as the first node
	// Return the pointer of new node - ToDo
	Iterator InsertFirst(const T & data);

	// Insert a new node to the list as the last node
	// Return the pointer of new node - ToDo
	Iterator InsertLast(const T & data);

	// Insert a new node to the list after pos
	// Return the pointer of new node - ToDo
	Iterator InsertNext(Iterator pos, const T & data);
	
	// Insert a new node to the list before pos
	// Return the pointer of new node - ToDo
	Iterator InsertPrev(Iterator pos, const T & data);
	
	// Total number of nodes in the list - ToDo
	int Size() const;				
		
	// Delete node at pos in the list - ToDo
	bool DeleteNode(Iterator pos);
	
	// Delete first node - ToDo
	bool DeleteFirst();
	
	// Delete last node - ToDo
	bool DeleteLast();

	// Print list
	void Print(bool reverse=false);
		
private:
	// first pointer of the list
	NodeType * first;
};

#ifndef DoublyLinkedList_TXX
#define DoublyLinkedList_TXX
#include "doublylinkedlist.txx"
#endif

#endif

3) doublylinkedlist.txx - 구현 파일

#include "doublylinkedlist.h"
#include <iostream>
#include <math.h>

/*
 * Iterator
 */
template<class T>
typename DoublyLinkedList<T>::Iterator& 
DoublyLinkedList<T>::Iterator::operator++() //pre increment
{
Iterator_Base::current = Iterator_Base::current->rlink; //for the precise position of current, declare Iterator_Base:: or use this-> pointer
return *this;
}

template<class T>
typename DoublyLinkedList<T>::Iterator  
DoublyLinkedList<T>::Iterator::operator++(int) 
{
Iterator pos = *this;   //post increment
Iterator_Base::current = Iterator_Base::current->rlink;
return pos;
}

template<class T>
typename DoublyLinkedList<T>::Iterator& 
DoublyLinkedList<T>::Iterator::operator--() //pre decrement
{
Iterator_Base::current = Iterator_Base::current->llink; 
return *this;
}

template<class T>
typename DoublyLinkedList<T>::Iterator  
DoublyLinkedList<T>::Iterator::operator--(int) 
{
Iterator pos = *this; //post decrement
Iterator_Base::current = Iterator_Base::current->llink;
return pos;
}


/*
 * Reverse Iterator
 */
template<class T>
typename DoublyLinkedList<T>::Reverse_Iterator&
DoublyLinkedList<T>::Reverse_Iterator::operator++() //reverse normal iterator. pre increment
{
Iterator_Base::current = Iterator_Base::current->llink;
return *this;
}

template<class T>
typename DoublyLinkedList<T>::Reverse_Iterator
DoublyLinkedList<T>::Reverse_Iterator::operator++(int)  //post increment
{
Reverse_Iterator pos = *this;
Iterator_Base::current = Iterator_Base::current->llink;
return pos;
}

template<class T>
typename DoublyLinkedList<T>::Reverse_Iterator&
DoublyLinkedList<T>::Reverse_Iterator::operator--() // pre decrement
{
Iterator_Base::current = Iterator_Base::current->rlink;
return *this;
}

template<class T>
typename DoublyLinkedList<T>::Reverse_Iterator
DoublyLinkedList<T>::Reverse_Iterator::operator--(int)  //post decrement
{
Reverse_Iterator pos = *this;
Iterator_Base::current = Iterator_Base::current->rlink;
return pos;
}

/*
 * Doubly linked list
 */
// Default constructor
template<class T>
DoublyLinkedList<T>::DoublyLinkedList()
{
first = new NodeType;   //memory allocation
first->rlink = first->llink = first;    //when it's empty node, point each other.
}

// Copy constructor
template<class T>
DoublyLinkedList<T>::DoublyLinkedList(const DoublyLinkedList& source)
{
if(this != &source) //when it's not same with itself.
{
 first = new NodeType; //do it like default constructor
 first->rlink = first->llink = first;

 for(Iterator iter = source.Begin(); iter != source.End(); iter++)  //traverse the iterator of source.
 {
  NodeType* temp = iter.GetNodePointer(); //As the current is under protected, use the Getter function(GetNodePointer()).
  InsertLast(temp->data); //put it next to the last one.
 }

}
}


// Destructor
template<class T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
for(Iterator iter = Begin(); iter != End(); iter++) //traversing the iterator
    DeleteFirst();  //delete from the first one.
}


// Assignment operator
template<class T>
DoublyLinkedList<T>& 
DoublyLinkedList<T>::operator = (const DoublyLinkedList<T>& source)
{
if(this != &source) //when it's not same with the source.
{
 first = new NodeType; //do it like default constructor
 first->rlink = first->llink = first;

 for(Iterator iter = source.Begin(); iter != source.End(); iter++)  //traversing the source's iterator.
 {
  NodeType* temp = iter.GetNodePointer();   //access to current by using GetNodePointer
  InsertLast(temp->data);   //put it next to the last one.
 }
}
return *this;   //As it's non void function, we shoud return something. Like *this.
}



// Total number of nodes in the list
template<class T>
int 
DoublyLinkedList<T>::Size() const
{
int count = 0;  //stores the size.

for(Iterator iter = Begin(); iter != End(); ++iter) //traverse the iterator.
count++;    //As it traverses, add one at count variable.

return count;
}


// Insert a new node to the list as the first node
// Return the pointer of new node
template<class T>
typename DoublyLinkedList<T>::Iterator 
//typename Iterator
DoublyLinkedList<T>::InsertFirst(const T& data)
{
NodeType* newNode = new NodeType;   //stores data value at newNode, memory allocation.
newNode->data = data;   //data storage

if(first->rlink == nullptr)//when it's empty list
{
 first->llink = first->rlink = newNode;
 newNode->rlink = nullptr;
 newNode->llink = nullptr;
}

else
{
 newNode->llink = first->rlink->llink;
 newNode->rlink = first->rlink;
 first->rlink->llink = newNode;
 first->rlink = newNode;
}

return newNode;
}


// Insert a new node to the list as the last node
// Return the pointer of new node
template<class T>
typename DoublyLinkedList<T>::Iterator
DoublyLinkedList<T>::InsertLast(const T & data)
{
NodeType* newNode = new NodeType;
newNode->data = data;

if(first->rlink == nullptr)//when it's empty list
{
 first->llink = first->rlink = newNode;
 newNode->rlink = nullptr;
 newNode->llink = nullptr;
}

else
{
 newNode->llink = first->llink;
 newNode->rlink = first->llink->rlink;
 first->llink->rlink = newNode;
 first->llink = newNode;
}

return newNode;
}

// Insert a new node to the list after pos
// Return the pointer of new node
template<class T>
typename DoublyLinkedList<T>::Iterator 
DoublyLinkedList<T>::InsertNext(DoublyLinkedList<T>::Iterator pos, const T & data)
{
NodeType* newNode = new NodeType;   //make newNode and memory allocation
newNode->data = data;   //data storage in newNode

if(first->rlink == nullptr)// when it's empty list
{
 first->llink = first->rlink = newNode;
 newNode->rlink = nullptr;
 newNode->llink = nullptr;
}

else
{
 NodeType* posNode = pos.GetNodePointer();  //as current Node is under protected class, use GetNodePointer function
 NodeType* posNext = posNode->rlink;    //set posNext as the next node of the current node
 newNode->rlink = posNext;
 newNode->llink = posNode;
 posNext->llink = newNode;
 posNode->rlink = newNode;
}

return newNode;
}


// Insert a new node to the list before pos
// Return the pointer of new node
template<class T>
typename DoublyLinkedList<T>::Iterator 
DoublyLinkedList<T>::InsertPrev(DoublyLinkedList<T>::Iterator pos, const T & data)
{
NodeType* newNode = new NodeType;   //make newNode and memory allocation
newNode->data = data;   //data storage in newNode

if(first->rlink == nullptr)//when it's empty list
{
 first->llink = first->rlink = newNode;
 newNode->rlink = nullptr;
 newNode->llink = nullptr;
}

else
{
 NodeType* posNode = pos.GetNodePointer();
 NodeType* posPrev = posNode->llink;
 newNode->llink = posPrev;
 newNode->rlink = posNode;
 posPrev->rlink = newNode;
 posNode->llink = newNode;
}

return newNode;
}


// Delete node at pos in the list
template<class T>
bool 
DoublyLinkedList<T>::DeleteNode(Iterator pos)
{
if(first->rlink == first && first->llink == first) //when it's empty list
 return false;

else
{
 NodeType* del_pos = pos.GetNodePointer();  //stores data of deleting node's current value.

 if(del_pos->llink == nullptr)//when it's first element
  DeleteFirst();

 else if(del_pos->rlink == nullptr)//when it's last element
  DeleteLast();

 else//그 외
 {
  del_pos->llink->rlink = del_pos->rlink;
  del_pos->rlink->llink = del_pos->llink;
 }
}

return true;
}

// Delete first node
template<class T>
bool 
DoublyLinkedList<T>::DeleteFirst()
{
if(first->rlink == first && first->llink == first)  //when it's empty list
 return false;

else
{

 if(first->rlink->rlink != nullptr) //when the nodes are more than one.
 {
  first->rlink = first->rlink->rlink;
  first->rlink->llink = nullptr;
 }

 else//when the node is just one.
  first->rlink = first->llink = first;

}

 return true;
}


// Delete last node
template<class T>
bool 
DoublyLinkedList<T>::DeleteLast()
{
if(first->rlink == first && first->llink == first)//when it's empty list
 return false;

else
{
 if(first->rlink == first->llink)//when the node is just one.
 {
  first->rlink = first->llink = first;
 }

 else   //when the nodes are more than one.
 {
  first->llink->llink->rlink = first->llink->rlink;
  first->llink = first->llink->llink;
 }
 
}
 return true;
}


template<class T>
void 
DoublyLinkedList<T>::Print(bool reverse)
{
if(reverse)
{
		for(Reverse_Iterator rit = rBegin(); rit!=rEnd(); rit++)
		{	
			std::cout << *rit << ", ";
		}
	}
	else 
	{		
		for(Iterator it = Begin(); it!=End(); it++)
		{	
			std::cout << *it << ", ";
		}		
	}
	
	std::cout << std::endl;
}

4) texteditor.h

#ifndef TEXTEDITOR_H
#define TEXTEDITOR_H

#include "doublylinkedlist.h"
#include <string>

typedef DoublyLinkedList<std::string> BufferType;


/* Very simple line text editor */
class TextEditor
{
public:
	// Default constructor
	TextEditor();

	// Destructor
	~TextEditor();

	// Insert a new line after the current position
	void Insert(const char* s);
	
	// Delete the current line
	void Delete();
	
	// Move one line up
	void MoveUp();
	
	// Move one line down
	void MoveDown();
	
	// Print the current line with the line number
	void Print();

	// Print all with the line number
	void PrintAll();
	
	// Run interactive mode
	void Run();
		
private:
	// Data
	BufferType buffer;
	
	BufferType::Iterator pos;
	
	int currLine;
};

#endif

5) texteditor.cpp - 구현 파일

#include "texteditor.h"
#include <iostream>
using namespace std;

// Default constructor 
TextEditor::TextEditor()
{
    BufferType(); //By calling BufferType, call default constructor of doublylinked list
    pos = buffer.Begin();   //Set BufferType::Iterator pos as buffer.Begin()
    currLine = 0;   //initialize int currLine as 0
}

TextEditor::~TextEditor()
{
    
    for(BufferType::Iterator it = buffer.Begin(); it!= buffer.End(); it++)  //traverse from begin to end of the buffer.pos and simultaneously delete.
    {
        Delete();
    }
    currLine = 0;   //initialize currLine as 0
}

// Insert a new line after the current position
void TextEditor::Insert(const char* s)
{
    buffer.InsertNext(pos, s); //By using DL's InsertNext function, insert s next to the position.
    pos++;  //After storage, increase iterator by 1. So that newly inserted line becomes currLine.
    currLine += 1;  //Same as the currLine.
}

// Delete the current line
void TextEditor::Delete()
{
    if(buffer.Size() < 1) { //if the buffer's node is under 1, it should warn that buffer is empty.
        std::cout << "Buffer is empty" << std::endl;
    }
    else
    {
        buffer.DeleteNode(pos); //delete current node.
        if(++pos == buffer.End())   //if next to current is end then it should decrease iterator's position and also currLine too.
        {
            --pos;
            currLine -= 1;
        }
    }
}

// Move one line up
void TextEditor::MoveUp()
{
    // ToDo
    if(pos-- == buffer.Begin()) // if pos-- is begin then it should warn that it is the beginning of the buffer.
    {
        cout << "Beginning of the buffer" << endl;
        ++pos;  //as the iterator's before value doesn't exist, it should increase the pos of iterator by 1.
    }
    else
        currLine -= 1;  //as it moved up, currLine should be decreased by 1.
}

// Move one line down
void TextEditor::MoveDown()
{
    // ToDo
    if(++pos == buffer.End())   //if ++pos is the end then it should warn it is the end of the buffer.
    {
        cout << "End of the buffer" << endl;
        --pos;  //as the iterator's next value doesn't exist, it should decrease the pos of iterator by 1.
    }
    else
        currLine += 1;  //as it moved down, currLine should be increased by 1.
}

//
// Interactive mode
//
void TextEditor::Run()
{
    string inp;
    
    while(1)
    {
        cout << "> ";
        getline(cin, inp);
        
        // ToDo	- implement other functions
        
        if(inp == "u") MoveUp();
        else if(inp == "x") exit(0);
        else if(inp == "d") MoveDown();
        else if(inp == "p") Print();
        else if(inp == "pa") PrintAll();
        else if(inp == "r") Delete();
        else if(inp == "i")
        {
            char input[100];    //declare the insertion values' array's largest size.
            cout << "(Insert) > ";
            cin.getline(input, 100);    //size becomes same with input's size.
            char* j = input;    //In cin.getline, input should be pointer of char.
            Insert(j);  //insert next to the current position.
        }
        else
        {
            cout << "No such command. Available commands are u(up), d(down), p(print), pa(print all), r (delete), i(insert), and x(exit)" << endl;
        }
    }
}


// ----------------------

// Print the current line with the line number
void TextEditor::Print()
{
    if(buffer.Size() < 1) {
        std::cout << "Buffer is empty" << std::endl;
    }
    else {
        std::cout << "Current(L" << currLine << ") : " << *pos << std::endl;
    }
}

// Print all with the line number
void TextEditor::PrintAll()
{
    int i=1;
    for(BufferType::Iterator it=buffer.Begin(); it != buffer.End(); it++)
    {
        cout << "L" << i++ << " :";
        if(i == (currLine+1)) cout << "*";
        else cout << " ";
        cout << *it << endl;
    }
}

6) main.cpp

#include "doublylinkedlist.h"
#include "texteditor.h"
#include <iostream>

using namespace std;

int main()
{
	// 
	// 1. Test Doubly Linked List
	//
	DoublyLinkedList<int> list;
	
	list.InsertFirst( 10 );	
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;

	list.InsertFirst( 20 );
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;
	
	list.InsertFirst( 30 );
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;

	list.InsertFirst( 40 );
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;
	
	list.InsertLast( 50 );
    std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;

	list.InsertLast( 60 );
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;

	// assignment operator test
	DoublyLinkedList<int> list2;
	list2 = list;

	std::cout << "List 2 Size : " << list2.Size() << std::endl;
	list2.Print();
	std::cout << "--" << std::endl;

	// copy constructor test
	DoublyLinkedList<int> list3 = list;

	std::cout << "List 3 Size : " << list3.Size() << std::endl;
	list3.Print();
	std::cout << "--" << std::endl;
	
	list.DeleteFirst();
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;

	list.DeleteLast();
	std::cout << "List 1 Size : " << list.Size() << std::endl;
	list.Print();
	std::cout << "--" << std::endl;
	
	std::cout << "List 2 Size : " << list2.Size() << std::endl;
	list2.Print();
	std::cout << "--" << std::endl;
	
	std::cout << "List 3 Size : " << list3.Size() << std::endl;
	list3.Print();
	std::cout << "--" << std::endl;
	
	// insert middle test
	DoublyLinkedList<int>::Iterator it = list3.Begin();
	std::cout << "First element of list 3 : " << *it << std::endl;
	it++;
	std::cout << "Second element of list 3 : " << *it << std::endl;
	std::cout << "70 will be inserted after " << *it << std::endl;
	it = list3.InsertNext(it, 70);
	list3.Print();
	std::cout << "65 will be inserted before 70" << std::endl;
	it = list3.InsertPrev(it, 65);
	list3.Print();
	it++;it++;it++;
	std::cout << *it << " will be deleted" << std::endl;
	list3.DeleteNode(it);
	list3.Print();
	std::cout << "--" << std::endl;
	
	 //2. Test texteditor
	
	TextEditor vi;

	std::cout << "Print out the current buffer:" << std::endl;
	vi.PrintAll();

	vi.Insert("I am doing my assignment 2.");
	vi.Insert("This assignment is not so easy.");
	vi.Insert("But it is really fun.");
	vi.Insert("I hope I can make it.");
	vi.Insert("KU CSE rocks!");

	vi.PrintAll();
	vi.Print();

	std::cout << "Move up" << std::endl;
	vi.MoveUp();
	vi.Print();

	std::cout << "Move up" << std::endl;
	vi.MoveUp();
	vi.Print();

	std::cout << "Delete the current line" << std::endl;
	vi.Delete();
	vi.Print();

	std::cout << "Print out the current buffer:" << std::endl;
	vi.PrintAll();
    
	std::cout << "Move down" << std::endl;
	vi.MoveDown();
	vi.Print();

	std::cout << "Insert new line" << std::endl;
	vi.Insert("Finally I made it~");

	std::cout << "Print out the current buffer:" << std::endl;
	vi.PrintAll();


	// 3. Test interactive mode
	vi.Run();

	return 0;
}

도출해야 하는 결과 :

구현한 파일의 결과 :

점수 : 100/100

성취감 만땅!!!

Comments