C++/기초를 탄탄히 세워주는 C++ 프로그래밍 입문(황준하 저)

기초를 탄탄히 세워주는 C++ 프로그래밍 입문 13장 연습문제

꾸준함. 2017. 7. 14. 13:09

[13.1]

/*

CPoint 객체를 원소로 갖는 vector 객체를 만들려고 한다.

사용자는 CPoint 객체의 (x, y) 값을 계속해서 입력할 것이다.

만약 (0, 0)이 입력된다면 입력이 종료됨을 의미한다.

사용자가 입력한 CPoint 객체를 vector 객체의 원소로 추가하도록 한다.

*/

#include <iostream>

#include <vector>

using namespace std;

 

class CPoint

{

private:

        int x;

        int y;

public:

        CPoint(int a = 0, int b = 0) :x(a), y(b)

        {

        }

        void Print()

        {

               cout << "(" << x << ", " << y << ")" << endl;

        }

};

 

int main(void)

{

        int x, y;

        vector<CPoint> cAry;

        int idx = 0;

        while (1)

        {

               cout << "x y 값 입력:(0, 0 입력시 종료) ";

               cin >> x >> y;

               if (x == 0 && y == 0)

                       break;

               cAry.push_back(CPoint(x, y));

               idx++;

        }

        for (int i = 0; i < idx; i++)

               cAry[i].Print();

        return 0;

}

[13.2]

/*

list는 마지막 원소 다음에 새로운 원소를 추가하는 것도 가능하며, 첫 번째 원소의 앞에 새로운 원소를 추가하는 것도 가능하다.

int list를 만들어 본다. 그리고 사용자로부터 양의 정수값과 앞 또는 뒤에 추가할 것인지를 입력받아 해당 원소를 추가하도록 한다.

추가할 값으로 0을 입력하면 프로그램이 종료된다. 그리고 첫 번째 원소의 값과 마지막 원소의 값을 출력한다.

참고로 첫 번째 원소 앞에 원소를 추가하려면 push_front 함수를 사용하면 된다

*/

#include <iostream>

#include <list>

using namespace std;

 

int main(void)

{

        list<int> MyList;

        int num, place, idx = 0;

 

        while (1)

        {

               cout << ", 위치(0:, 1:) 입력:(0 입력시 종료): ";

               cin >> num >> place;

               if (num == 0)

                       break;

               if (place == 0)

                       MyList.push_front(num);

               else if (place == 1)

                       MyList.push_back(num);

               else

               {

                       cout << "다시 입력하세요" << endl;

                       continue;

               }

               idx++;

        }

        cout << "첫 번째 원소의 값: ";

        cout << MyList.front() << endl;

        cout << "마지막 원소의 값: ";

        cout << MyList.back() << endl;

        return 0;

}

 

[13.3]

/*

예제 13.7에서 작성한 Node, ListIterator, MyList를 그대로 사용하는 경우 다음과 같은 CPoint

클래스 객체를 원소로 사용하더라도 문제없이 수행될 수 있을까?

CPoint 클래스를 추가하고 main 함수에서 CPoint 원소를 수용할 수 있도록 MyList<CPoint>로 변경한 후 수행해본다.

*/

#include <iostream>

#include <list>

using namespace std;

 

template <typename T>

struct Node

{

        T data;

        Node<T> *next;

        Node(T d, Node<T> *n = NULL) :data(d), next(n)

        {

        }

};

 

template <typename T>

class ListIterator

{

private:

        Node<T> *ptr; //특정 노드에 대한 포인터

public:

        ListIterator(Node<T> *p = 0) :ptr(p)

        {

        }

        void operator++(int)

        {

               ptr = ptr->next;

        }

        T &operator*()

        {

               return ptr->data;

        }

        void operator=(Node<T> *p)

        {

               ptr = p;

        }

};

 

template <typename T>

class MyList

{

private:

        Node<T> *start;

        Node<T> *last;

 

public:

        MyList() :start(NULL), last(NULL)

        {

        }

        typedef ListIterator<T> iterator;

        Node<T> *begin()

        {

               return start;

        }

        void push(T d)//새로운 노드 추가

        {

               Node<T> *temp = new Node<T>(d, NULL);

               if (start == NULL)

               {

                       start = temp;

                       last = temp;

               }

               else

               {

                       last->next = temp;

                       last = temp;

               }

        }

};

 

class CPoint

{

private:

        int x, y;

public:

        CPoint(int a = 0, int b = 0) :x(a), y(b)

        {

        }

        friend ostream &operator<<(ostream &os, CPoint &Po);

};

 

ostream &operator<<(ostream &os, CPoint &Po)

{

        cout << "(" << Po.x << ", " << Po.y << ")" << endl;

        return os;

}

 

int main(void)

{

        MyList<CPoint> CPointL;

        MyList<CPoint>::iterator llter; //원소 중 하나를 가리킬 이터레이터 생성

 

        for (int i = 0; i < 5; i++)

               CPointL.push(CPoint(i, i));

 

        llter = CPointL.begin(); //첫 번째 원소를 가리킴

        for (int i = 0; i < 5; i++)

        {

               cout << *llter << endl;

               llter++;

        }

        return 0;

}

 

[13.4]

/*

vector를 사용하여 실행결과와 같이 int형 데이터를 추가, 삭제, 출력할 수 잇는 프로그램을 작성해 본다

*/

#include <iostream>

#include <vector>

using namespace std;

 

void PrintVector(vector<int> intV)

{

        vector<int>::iterator iter;

        for (iter = intV.begin(); iter != intV.end(); iter++)

               if(*iter!=0)

                       cout << *iter << " ";

        cout << endl;

}

 

void AddVector(vector<int> &intV, int place, int num)

{

        intV.insert(intV.begin() + place, num);

}

 

void erase(vector<int> &intV, int place)

{

        cout << "삭제" << endl;

        intV.erase(intV.begin() + place);

}

 

int main(void)

{

        vector<int> intV(10);

        int sel, place, num;

 

        while (1)

        {

               cout << ">> 메뉴- 추가(1), 삭제(2), 출력(3), 종료(0): ";

               cin >> sel;

               if (sel == 0)

               {

                       break;

               }

               else if (sel == 1)

               {

                       cout << ", 위치(?번째 앞): ";

                       cin >> num >> place;

                       AddVector(intV, place, num);

                       //intV.insert(intV.begin() + place, num);

               }

               else if (sel == 2)

               {

                       cout << "위치: ";

                       cin >> place;

                       erase(intV, place);

                       //intV.erase(intV.begin() + place);

               }

               else if (sel == 3)

               {

                       PrintVector(intV);

               }

               else

               {

                       cout << "번호를 다시 입력해주세요" << endl;

                       continue;

               }

        }

        return 0;

}

[13.5]

/*

다음 main 함수와 같이 string 객체를 원소로 갖는 vector 객체를 만들었다.

vector 객체의 원소를 오름차순으로 정렬하여 출력할 수 있도록 main 함수에 필요한 코드를 추가해 본다.

또한번은 내림차순으로 정렬해보도록 한다

*/

#include <iostream>

#include <vector>

#include <algorithm>

#include <string>

using namespace std;

 

bool Compare2(string s1, string s2)

{

        if (s1.compare(s2) < 0)

               return true;

        else

               return false;

}

 

bool Compare(string s1, string s2) //내림차순

{

        if (s1.compare(s2) > 0)

               return true;

        else

               return false;

}

 

int main(void)

{

        vector<string> strV;

        vector<string>::iterator iter;

 

        strV.push_back("c++");

        strV.push_back("programming");

        strV.push_back("apple");

        strV.push_back("banana");

 

        cout << "<< 정렬 전 >>" << endl;

        for (iter = strV.begin();iter != strV.end(); iter++)

               cout << *iter << endl;

 

        cout << "<< 오름차순 정렬 후 >>" << endl;

        sort(strV.begin(), strV.end(), Compare2); //Compare 기준 모든 원소 정렬

        for (iter = strV.begin();iter != strV.end(); iter++)

               cout << *iter << endl;

 

        cout << "<< 내림차순 정렬 후 >>" << endl;

        sort(strV.begin(), strV.end(), Compare); //Compare 기준 모든 원소 정렬

        for (iter = strV.begin();iter != strV.end(); iter++)

               cout << *iter << endl;

        return 0;

}

[13.6]

/*

CPoint 클래스 객체를 원소로 포함하는 vector 객체에 대해 다음 main 함수와 같이 find 함수를 적용

할 수 있도록 CPoint 클래스를 작성해 본다

*/

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

 

class CPoint

{

private:

        int x;

        int y;

public:

        CPoint(int a = 0, int b = 0) :x(a), y(b)

        {

        }

        bool operator==(const CPoint &cpy) //find 함수를 위해

        {

               if (x == cpy.x&&y == cpy.y)

                       return true;

               else

                       return false;

        }

        friend ostream &operator<<(ostream &out, CPoint &Po);

};

 

ostream &operator<<(ostream &out, CPoint &Po)

{

        cout << "(" << Po.x << ", " << Po.y << ")" << endl;

        return out;

}

 

int main(void)

{

        vector<CPoint> poV(5);

        vector<CPoint>::iterator iter;

 

        poV[0] = CPoint(5, 3);

        poV[1] = CPoint(2, 9);

        poV[2] = CPoint(1, 1);

        poV[3] = CPoint(2, 5);

        poV[4] = CPoint(3, 7);

 

        iter = find(poV.begin(), poV.end(), CPoint(2, 5));

        if (iter != poV.end())

               cout << (*iter) << endl;

        else

               cout << "존재하지 않습니다" << endl;

 

        iter = find(poV.begin(), poV.end(), CPoint(100, 100));

        if (iter != poV.end())

               cout << (*iter) << endl;

        else

               cout << "존재하지 않습니다" << endl;

        return 0;

}

 

[13.7]

/*

알고리즘 중에는 merge라는 것이 있다.

단어에서 의미하듯이 2개의 범위를 병합하는 알고리즘이다.

도움말을 활용하여 이 알고리즘의 사용 방법을 확인하고 직접 사용 예를 만들어 테스트해본다.

*/

#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;

 

void PrintVector(vector<int> intV, char *name)

{

        vector<int>::iterator iter;

 

        cout << ">> " << name << ":";

        for (iter = intV.begin(); iter != intV.end(); iter++)

               if(*iter!=0)

                       cout << *iter << " ";

        cout << endl;

}

 

int main()

{

        vector <int> v1;

        v1.push_back(1);

        v1.push_back(3);

        v1.push_back(5);

        v1.push_back(6);

        v1.push_back(8);

 

        vector <int> v2;

        v2.push_back(2);

        v2.push_back(4);

        v2.push_back(7);

 

        vector<int> v3(10);//v3 공간을 확보

        vector<int>::iterator llter;

        llter = merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v3.begin()); //이티레이터에 합친다

        //v1 처음부터 끝까지, v2 처음부터 끝까지를 v3의 시작부터 넣는다

 

        PrintVector(v1, "v1 출력");

        cout << endl;

 

        PrintVector(v2, "v2 출력");

        cout << endl;

 

        PrintVector(v3, "v3 출력");

        cout << endl;

 

        return 0;

 

}

[13.8]

/*

13.4를 보면 vector의 기능이 후미에 신속하게 삽입하고 삭제할 수 있는데 반해 deque는 후미뿐만

아니라 선두에서도 신속 삽입, 삭제할 수 있도록 되어 있다.

마치 양쪽으로 늘어나는 배열과 같다. 이러한 기능을 수행하기 우해 deque가 제공하는 멤버 함수들에는

어떤 것들이 있는지 조사해 보고, deque의 기능을 보여줄 수 있는 간단한 프로그램을 작성해 본다

*/

#include <iostream>

#include <deque>

using namespace std;

 

int main(void)

{

        deque<int> dq;

        deque<int>::iterator iter;

 

        //deque 뒤에 데이터 추가

        dq.push_back(10);

        dq.push_back(20);

        dq.push_back(30);

        //deque 앞에 데이터 추가

        dq.push_front(40);

        dq.push_front(50);

 

        for (iter = dq.begin(); iter != dq.end(); iter++)

               cout << (*iter)<< " ";

        cout << endl;

 

        cout << "앞에 데이터 삭제" << endl;

        dq.pop_front();

        for (iter = dq.begin(); iter != dq.end(); iter++)

               cout << (*iter)<<" ";

        cout << endl;

        cout << "맨 뒤 데이터 삭제" << endl;

        dq.pop_back();

        for (iter = dq.begin(); iter != dq.end(); iter++)

               cout << (*iter)<< " ";

        cout << endl;

        //이로써 deque vector와 다르게 양방향 연결리스트처럼 작동이 가능한 것을 알 수 있습니다

        return 0;

}

[13.9]

/*

스택 자료 구조(LIFO)에 해당하는 CStack 클래스를 직접 만들고 사용해 본다.

CStack 클래스는 타입에 관계없이 적용될 수 있도록 클래스 템플릿으로 작성하도록 하고,

테스트 시에는 int형 스택을 만들도록 한다.

CStack 클래스의 멤버 함수로는 값을 저장하는 push와 값을 가져오는 pop이 존재한다.

stack이 수용할 수 있는 원소의 개수는 10으로 가정한다

*/

#include <iostream>

using namespace std;

 

template <typename T>

class CStack

{

private:

        T stack[10];

        int top;

public:

        CStack()

        {

               top = 0;

        }

        void push(int b)

        {

               stack[top++] = b;

        }

        T pop()

        {

               return stack[top--];

        }

        void minusTop()

        {

               top--; //Pop의 정상작동을 위해

        }

};

 

int main(void)

{

        CStack<int> stack;

        int num;

        for (int i = 0; i < 10; i++)

        {

               cout << "스택에 넣을 숫자 입력하세요: ";

               cin >> num;

               stack.push(num);

        }

        stack.minusTop(); //마지막에 top ++ 했으므로 이를 다시 -- 하기 위해

        cout << "하나씩 꺼냅니다" << endl;

        for (int i = 0; i < 10; i++)

        {

               cout << 10 - i << "번 째로 넣은 숫자: ";

               cout << stack.pop() << endl;

        }

}

[13.10]

/*

이번에는 도움말을 참고하여 STL이 제공하고 있는 stack 클래스를 사용해 보고

연습문제 13.9와 차이점에 대해 생각해 본다. main 함수의 내용은 연습문제 13.9와 유사하게 작성하면 된다.

직접 만든 stack 클래스인 CStack 클래스와는 사용 방법에 있어서 다소 차이가 있을 수도 있다.

그러나 어떤 것이 옳고 그른지는 판단할 수 없다.

둘 다 stack 자료구조의 기본 개념에는 부합하고 있다. STL의 스택이 자신의 문제에 적합하다면 바로 적용

가능할 것이며, 만약 이와는 다른 스택을 원한다면 직접 만들어 사용할 수도 있을 것이다.

*/

#include <iostream>

#include <stack>

using namespace std;

 

int main(void)

{

        int i;

        stack<int> stk;

 

        cout << "스택에 대입 시작" << endl;

        for (int i = 0; i < 11; i++)

        {

               stk.push(i);

        }

 

        cout << "스택 크기: " << stk.size() << endl;

 

        cout << "삭제 시작" << endl;

        for (int i = 0; i < 11; i++)

        {

               cout << stk.top() << endl; //top에 있는 숫자를 반환

               stk.pop(); //top에 있던 숫자를 지워준다

        }

 

        if (stk.empty())

        {

               cout << "전부 삭제 완료" << endl;

        }

        return 0;

}

 


개발 환경:Visual Studio 2017


지적, 조언, 질문 환영입니다! 댓글 남겨주세요~


[참고] 기초를 탄탄히 세워주는 C++ 프로그래밍 입문 황준하 저

반응형