|
|
[10장 연습문제]
// 1
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
template < class T >
T biggest(T* arr, int len);
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
int x[] = {1, 10, 100, 5, 4};
cout << biggest<int>(x, 5) << endl;
}
// 9_func.cpp
// X
// 2
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
template <class T> T* concat(T* arr1, int len1, T* arr2, int len2) {
T* p = new T[len1 + len2]; for (int i = 0; i < len1; i++) p[i] = arr1[i];
for (int i = 0; i < len2; i++) p[len1 + i] = arr2[i]; return p; }
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
int x[] = {1, 2, 3, 4, 5};
int y[] = {6, 7, 8, 9, 10};
int* arr = concat<int>(x, 5, y, 5);
for(int i = 0; i < 10; i++)
cout << arr << ' '
;
delete[] arr;
}
// 9_func.cpp
// X
// 3
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Circle {
int r;
public:
Circle(int r = 1);
int getr();
};
bool operator>(Circle a, Circle b);
template <class T> T bigger(T a, T b) {
if (a > b) return a; else return b; }
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
int a = 20, b = 50, c;
c = bigger(a, b);
cout << "20과 50중 큰 값은 " << c << endl;
Circle waffle(10), pizza(20), y;
y = bigger(waffle, pizza);
cout << "큰 것의 반지름은 " << y.getr() << endl;
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
Circle::Circle(int r) { this->r = r; }
int Circle::getr() { return r; }
bool operator>(Circle a, Circle b) { return a.getr() > b.getr(); }
}
// 4
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Comparable {
public:
virtual bool operator > (Comparable& op2)=0;
virtual bool operator < (Comparable& op2)=0;
virtual bool operator == (Comparable& op2)=0;
};
class Circle2 : public Comparable {
int r;
public:
Circle2(int r = 1);
int getr();
bool operator > (Comparable& op2) override;
bool operator < (Comparable& op2) override;
bool operator == (Comparable& op2) override;
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
int a = 20, b = 50, c;
c = bigger(a, b);
cout << "20과 50중 큰 값은 " << c << endl;
Circle2 waffle(10), pizza(20), y;
y = bigger(waffle, pizza);
cout << "큰 것의 반지름은 " << y.getr() << endl;
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
Circle2::Circle2(int r) { this->r = r; }
int Circle2::getr() { return r; }
bool Circle2::operator > (Comparable& op2) {
Circle2* p = (Circle2*)&op2; return this->r > p->r; }
bool Circle2::operator < (Comparable& op2) {
Circle2* p = (Circle2*)&op2; return this->r < p->r; }
bool Circle2::operator == (Comparable& op2) {
Circle2* p = (Circle2*)&op2; return this->r == p->r; }
}
// 5
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
// 5
// X
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
vector<int> v;
int n;
while (true) {
cout << "정수를 입력하세요(0을 입력하면 종료)>>";
cin >> n;
if (n == 0) break;
v.push_back(n);
int sum = 0;
for (int x : v) sum += x;
cout << "평균 = " << (double)sum / v.size() << endl;
}
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
// 5
// X
}
// 6
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class countrycity {
std::vector<std::string> country;
std::vector<std::string> city;
public:
void (countrycity::*action)();
enum{ MENU, PUSH, POP, EXIT };
void run(); // 수도 맞추기 게임 시작
void menu(); // 메뉴 (정보입력: 1, 퀴즈 출제: 2, 종료: 3);
void real_push(std::string country, std::string city); // 현재 저장된 나라의 개수 출력, 입력 받는 포멧: "(현재 정보 개수)>>" 나라와 수도 정보 입력, no no가 입력될 때까지 반복 호출
void push(); // 함수 포인터 호출용 함수
void pop(); // **의 수도는? 후 정답체크, 답이 exit 가 입력될 때까지 반복 호출, 탈출 후 메뉴 호출
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
countrycity game;
game.run();
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
void countrycity::run() {
std::srand(static_cast<unsigned int>(std::time(NULL)));
int choice;
while (true) {
menu();
if (!(std::cin >> choice)) break;
if (choice == PUSH) {
action = &countrycity::push;
} else if (choice == POP) {
action = &countrycity::pop;
} else if (choice == EXIT) {
std::cout << "게임을 종료합니다." << std::endl;
break;
} else {
std::cout << "잘못된 입력입니다." << std::endl;
continue;
}
(this->*action)();
}
}
void countrycity::menu() {
std::cout << "\n(정보입력: 1, 퀴즈 출제: 2, 종료: 3) >> ";}
void countrycity::real_push(std::string country_in, std::string city_in) {
this->country.push_back(country_in);
city.push_back(city_in);}
void countrycity::push() {
std::string c, s;
std::cout << "현재 " << country.size() << "개의 나라가 입력되어 있습니다." << std::endl;
std::cout << "나라와 수도를 입력하세요 (종료: no no)" << std::endl;
while (true) {
std::cout << country.size() << ">>";
std::cin >> c >> s;
if (c == "no" && s == "no") break;
bool already_exists = false;
for (int i = 0; i < country.size(); i++) {
if (country[i] == c) {
std::cout << c << "는 이미 있는 나라입니다. 중복되는 내용입니다." << std::endl;
already_exists = true; break;
}
}
if (already_exists) continue;
real_push(c, s);
}
}
void countrycity::pop() {
if (country.empty()) {
std::cout << "입력된 정보가 없습니다. 먼저 정보를 입력하세요." << std::endl;
return;}
std::string user_ans;
while (true) {
int r = std::rand() % country.size();
std::cout << country[r] << "의 수도는? ";
std::cin >> user_ans;
if (user_ans == "exit") {
std::cout << "퀴즈를 종료하고 메뉴로 돌아갑니다." << std::endl;
break; }
if (user_ans == city[r])
std::cout << "정답입니다!" << std::endl;
else
std::cout << "아닙니다! 정답은 " << city[r] << "입니다." << std::endl;
}
}
}
// 7
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Book {
int year;
std::string name;
std::string autor;
public:
Book(int y, std::string n, std::string a) : year(y), name(n), autor(a) {}
int getYear() const { return year; }
std::string getName() const { return name; }
std::string getAutor() const { return autor; }
};
class Managebook {
std::vector<Book> v;
public:
void input();
void searchautor();
void searchyear();
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
Managebook lib;
cout << "입고할 책을 입력하세요. 년도에 -1을 입력하면 종료합니다." << endl;
lib.input();
lib.searchautor();
lib.searchyear();
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
void Managebook::input() {
int y;
string n, a;
while (true) {
cout << "년도>> ";
cin >> y;
if (y == -1) break;
cin.ignore();
cout << "책이름>> ";
getline(cin, n);
cout << "저자>> ";
getline(cin, a);
v.push_back(Book(y, n, a));
}
cout << "입고 종료. 현재 " << v.size() << "권이 입고되었습니다." << endl;
}
void Managebook::searchautor() {
string target;
cout << "\n저자검색: 이름을 입력하세요 >> ";
cin.ignore();
getline(cin, target);
for (int i = 0; i < v.size(); i++) {
if (v[i].getAutor() == target) {
cout << v[i].getYear() << " " << v[i].getName() << " " << v[i].getAutor() << endl;
}
}
}
void Managebook::searchyear() {
int target_year;
cout << "\n년도검색: 년도를 입력하세요 >> ";
cin >> target_year;
for (int i = 0; i < v.size(); i++) {
if (v[i].getYear() == target_year) {
cout << v[i].getYear() << " " << v[i].getName() << " " << v[i].getAutor() << endl;
}
}
}
}
// 8
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Engtest {
std::vector<std::string> eng;
std::vector<std::string> kor;
public:
void run(); // ******* 영어 어휘 테스트를 시작합니다. ******* 출력 후 manu 호출
// 어휘 삽입 포멧: 영어 단어에 exit 를 입력하면 입력 끝
// 영어 >> (입력)
// 한글 >> (입력)
void push(); // 어휘 삽입
// 테스트 포멧: 영어 어휘 테스트를 시작합니다. 1~4 외 다른 입력시 종료.
// (영단어)?
// 1~4번까지 무작위의 단어 3 개와 정답 1개 무작위 번호로 출력(알고리즘 최적화 필요)
void test(); // 어휘 테스트
void menu(); // 0은 메뉴, 1은 push, 2는 test 그 외 입력 시 종료(exit)
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
Engtest test;
test.run();
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
void Engtest::run() {
cout << "******* 영어 어휘 테스트를 시작합니다. *******" << endl;
menu();
}
void Engtest::menu() {
int sel;
while (true) {
cout << "어휘 삽입: 1, 어휘 테스트: 2, 종료: 그외키 >> ";
if (!(cin >> sel)) break;
if (sel == 1) push();
else if (sel == 2) test();
else break;
}
}
void Engtest::push() {
string e, k;
while (true) {
cout << "영어 >> "; cin >> e;
if (e == "exit") break;
cout << "한글 >> "; cin >> k;
eng.push_back(e); kor.push_back(k);
}
}
void Engtest::test() {
if (eng.size() < 4) { cout << "단어가 부족합니다." << endl; return; }
srand((unsigned int)time(0));
cout << "영어 어휘 테스트를 시작합니다. 1~4 외 다른 입력시 종료." << endl;
while (true) {
int answerIdx = rand() % eng.size(), bogi[4], correctPos = rand() % 4;
bogi[correctPos] = answerIdx;
for (int i = 0; i < 4; i++) {
if (i == correctPos) continue;
int r;
while (true) {
r = rand() % eng.size();
bool dup = (r == answerIdx);
for (int j = 0; j < i; j++) if (bogi[j] == r) dup = true;
if (!dup) break;
}
bogi[i] = r;
}
cout << eng[answerIdx] << "?" << endl;
for (int i = 0; i < 4; i++) cout << "(" << i + 1 << ") " << kor[bogi[i]] << " ";
int choice; cout << ":> "; cin >> choice;
if (choice < 1 || choice > 4) break;
cout << (bogi[choice - 1] == answerIdx ? "Excellent !!" : "No. !!") << endl;
}
}
}
// 9
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Managescore {
std::map<std::string, int> stus;
public:
void run(); // ***** 점수관리 프로그램을 시작합니다. ***** 출력 후 menu 호출
void menu(); // 입력:1, 조회:2, 종료3 >> 출력 후 입력에 맞게 함수 호출
void push(); // 이름과 점수>> 출력 후 입력 받아 저장 후 메뉴로
void searchname(); // 이름>> 출력 후 이름 입력받아 **의 점수는 ** 출력후 메뉴로
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
Managescore stus;
stus.run();
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
void Managescore::run() {
cout << "***** 점수관리 프로그램을 시작합니다. *****" << endl;
menu();
}
void Managescore::menu() {
int sel;
while (true) {
cout << "입력:1, 조회:2, 종료3 >> ";
if (!(cin >> sel) || sel == 3) break;
if (sel == 1) push();
else if (sel == 2) searchname();
}
}
void Managescore::push() {
string name;
int score;
cout << "이름과 점수>> ";
cin >> name >> score;
stus[name] = score;
}
void Managescore::searchname() {
string name;
cout << "이름>> "; cin >> name;
if (stus.find(name) != stus.end())
cout << name << "의 점수는 " << stus[name] << endl;
else
cout << name << "은(는) 존재하지 않는 이름입니다." << endl;
}
}
// 10
// 10.h
#ifndef HEADER_10_HPP
#define HEADER_10_HPP
#include <string>
#include <vector>
#include <map>
namespace header_10 {
class Shape {
protected:
virtual void draw()=0;
public:
void paint();
virtual ~Shape() {}
};
class Circle3 : public Shape {
protected:
void draw() override;
};
class Ract : public Shape {
protected:
void draw() override;
};
class Line : public Shape {
protected:
void draw() override;
};
class Graphic_editor {
std::vector<Shape*> board; // shape타입 포인터 벡터, 파생 클래스 조작
void (Graphic_editor::*action)(); // 함수 포인터. 메뉴에서 이 포인터로만 함수 호출
public:
~Graphic_editor();
enum {MENU, INSERT, DEL, PRINTALL, EXIT};
void run(); // 그래픽 에디터입니다. 출력 후 manu 호출
void manu(); // 삽입:1, 삭제:2, 모두보기:3, 종료:4 >> 출력 후 입력에 따라 맞는 함수 함수 포인터로 호출
void insert(); // 선:1, 원:2, 사각형:3 >> 출력 후 입력에 따라 벡터에 해당 객체 생성 후 저장 enum {NONE, LINE, CIRCLE, RACT}; 사용해서 구현
void del(); // 삭제하고자 하는 도형의 인덱스 >> 출력 후 입력 값에 따라 해당 객체 제거 후 배열 정리
void printall(); // 벡터 배열의 0번째 인덱스부터 순차적으로 모두 출력. 포멧: (인덱스번호): (객체클래스 이름)
};
}
// 10_main.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;
using namespace header_10;
int main() {
Graphic_editor board;
board.run();
}
// 9_func.cpp
#include "10.hpp"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <vector>
using namespace std;
namespace header_10 {
void Shape::paint() { draw(); }
void Circle3::draw() { cout << "Circle" << endl; }
void Ract::draw() { cout << "Ract" << endl; }
void Line::draw() { cout << "Line" << endl; }
Graphic_editor::~Graphic_editor() {
for (int i = 0; i < board.size(); i++) delete board[i];
}
void Graphic_editor::run() {
cout << "그래픽 에디터입니다." << endl;
manu();
}
void Graphic_editor::manu() {
int sel;
void (Graphic_editor::*funcs[])() = { nullptr, &Graphic_editor::insert, &Graphic_editor::del, &Graphic_editor::printall };
while (true) {
cout << "삽입:1, 삭제:2, 모두보기:3, 종료:4 >> ";
if (!(cin >> sel) || sel == EXIT) break;
if (sel >= INSERT && sel <= PRINTALL) {
action = funcs[sel];
(this->*action)();
}
}
}
void Graphic_editor::insert() {
int type;
enum {NONE, LINE, CIRCLE, RACT};
cout << "선:1, 원:2, 사각형:3 >> ";
cin >> type;
if (type == LINE) board.push_back(new Line());
else if (type == CIRCLE) board.push_back(new Circle3());
else if (type == RACT) board.push_back(new Ract());
}
void Graphic_editor::del() {
int idx;
cout << "삭제하고자 하는 도형의 인덱스 >> ";
cin >> idx;
if (idx >= 0 && idx < board.size()) {
delete board[idx];
board.erase(board.begin() + idx);
}
}
void Graphic_editor::printall() {
for (int i = 0; i < board.size(); i++) {
cout << i << ": ";
board[i]->paint();
}
}
}
// [10장 정리문제]
// 1) 템플릿이 왜 필요한가
// 템플릿은 함수나 클래스에서 코드는 동일하지만 처리하는 데이터 타입만 다를 때, 이를 일반화하기 위해 사용한다.
// 템플릿이 없을 경우 모든 자료형마다 동일한 로직을 가진 함수를 중복해서 정의해야 해 코드가 중복되고 유지보수가
어려워진다.
// 템플릿을 사용하면 데이터 타입을 매개변수화하여 하나의 코드로 다양한 자료형을 모두 수용할 수 있다.
// 이를 통해 코드의 중복을 획기적으로 줄이고 재사용성을 높이는 제네릭 프로그래밍이 가능해지고 컴파일 시간에 타입
검사가 이루어져 실행 시의 오류를 방지하는 타입 안전성까지 확보할 수 있어 안정적인 프로그램 작성이 가능해진다.
// 2) 배열대신에 vector 클래스를 사용하면 얻을 수 있는 장점이 무엇인지 설명하라
// 가장 큰 장점은 가변 크기 배열을 구현할 수 있다는 점이다. 일반 배열은 선언 시 크기를 고정해야 하지만, vector는 동적
할당을 사용하여 원소의 개수에 따라 스스로 저장 공간을 늘리거나 줄이는 기능을 갖추고 있어 메모리를 효율적으로 관리할
수 있고, push_back(), size(), empty()와 같은 다양한 멤버 함수를 제공하여 데이터를 삽입하거나 상태를 확인하는 작업을
매우 편리하게 만들어 준다.
이를 통해 코딩 과정에서 복잡한 메모리 할당과 해제 과정에 신경 쓰지 않고도 객체 지향적인 방식으로 컨테이너를 다룰 수
있게 되고, at() 멤버 함수를 활용해 인덱스 범위를 점검함으로써, 잘못된 메모리 접근으로 인한 인덱스 오류를 방지하고
프로그램의 안정성을 높일 수 있다.
// 3) STL 이란 무엇인가
// STL은 C++ 표준 템플릿 라이브러리를 의미하며, 프로그램 개발에 자주 사용되는 다양한 템플릿 클래스와 함수를 모아놓은 집합체이다. STL은 개발자가 복잡한 알고리즘이나 자료 구조를 직접 구현하지 않고도 이미 검증된 코드를 활용하여
프로그램을 쉽고 빠르게 작성할 수 있도록 돕는다. 즉, C++ 언어 차원에서 제공하는 강력한 표준 도구 상자와 같다.
// 4) STL 의 컨테이너 클래스에 대하여 설명하라
// 컨테이너는 데이터를 저장하는 자료 구조를 구현한 템플릿 클래스를 말한다. 컨테이너에는 가변 배열인 vector,
연결 리스트인 list, 선입선출 구조의 queue, 후입선출 구조의 stack, 키와 값의 쌍으로 이루어진 map 등이 존재한다.
// 또한 단순히 데이터를 담는 변수의 역할을 넘어, 각 자료 구조의 특성에 맞춰 데이터를 효율적으로 보관하고 관리할 수
있는 환경 또한 제공한다.
// 5) STL 의 3 가지 요소 컨테이너 , 이터레이터 , 알고리즘의 기능을 각각 설명하라
// STL은 데이터를 관리하고 조작하기 위해 상호작용하는 세 가지 핵심 요소로 구성되는데, 먼저 컨테이너는 데이터를
저장하는 변수 역할을 한다. 그리고 이터레이터는 컨테이너의 원소에 접근하기 위한 클래스로, 원소에 대한 포인터를
객체화하여 컨테이너 사이를 이동하며 데이터를 가리키는 역할을 수행한다.
마지막으로 알고리즘은 컨테이너의 멤버 함수가 아닌 전역 함수 형태로 구현되며, 이터레이터를 통해 컨테이너의 원소들을
복사, 검색, 삭제, 정렬하는 구체적인 처리 기능을 담당한다.
|
|
