1. 문제

 

5. 디지털 회로에서 기본적인 게이트로 OR 게이트, AND 게이트, XOR 게이트 등이 있다. 이들은 각각 두 입력 신호를 받아 OR 연산, AND 연산, XOR 연산을 수행한 결과를 출력한다. 이 게이트들을 각각 ORGate, XORGate, ANDGate 클래스로 작성하고자 한다. ORGate, XORGate, ANDGate 클래가 AbstractGate를 상속받도록 작성하라.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
using namespace std;

class AbstractGate {
protected:
	bool x, y;
public:
	void set(bool x, bool y) { this->x = x; this->y = y; }
	virtual bool operation() = 0;
};
class ANDGate : public AbstractGate {
public:
	bool operation() {
		if (x == true && y == true) return true;
		else return false;
	}
};
class ORGate : public AbstractGate {
public:
	bool operation() {
		if (x == true || y == true) return true;
		else return false;
	}
};
class XORGate : public AbstractGate {
public:
	bool operation() {
		if (x != y) return true;
		else return false;
	}
};

int main() {
	ANDGate a;
	ORGate o;
	XORGate xo;

	a.set(true, false);
	o.set(true, false);
	xo.set(true, false);
	cout.setf(ios::boolalpha);
	cout << a.operation() << endl;
	cout << o.operation() << endl;
	cout << xo.operation() << endl;
}

 

4. 설명

 

and, or, xor 은 각각 &&, ||, != 로 표현 합니다.

 

 

visual studio 2017에서 and, or, xor 변수명이 오류가 발생하여서 임의로 바꾸어 실행 하였습니다.

 

 

아마 2017로 오면서 예약어로 바뀐 것 같습니다.

 

1. 문제

 

[3~4] 다음 추상 클래스 LoopAdder가 있다.

 

3. LoopAdder 클래스를 상속받아 다음 main() 함수와 실행 결과처럼 되도록 ForLoopAdder 클래스를 작성하라. ForLoopAdder 클래스의 calculate() 함수는 for 문을 이용하여 합을 구한다.

 

4. LoopAdder 클래스를 상속받아 다음 main() 함수와 실행 결과처럼 되도록 WhileLoopAdder, DoWhileLoopAdder 클래스를 작성하라. while 문, do-while 문을 이용하여 합을 구하도록 calculate() 함수를 작성하면 된다.

 

 

2. 결과

 

3.

 

4.

3. 코드

 

#include <iostream>
#include <string>
using namespace std;

class LoopAdder {
	string name;
	int x, y, sum;
	void read();
	void write();
protected : 
	LoopAdder( string name="") {
		this->name = name;
	}
	int getX() { return x; }
	int getY() { return y; }
	virtual int calculate() = 0;
public : 
	void run();
};

void LoopAdder::read() {
	cout << name << ":" << endl;
	cout << "처음 수에서 두번째 수까지 더합니다. 두 수를 입력하세요 >> ";
	cin >> x >> y;
}
void LoopAdder::write() {
	cout << x << "에서 " << y << "까지의 합 = " << sum << " 입니다" << endl;
}
void LoopAdder::run() {
	read();
	sum = calculate();
	write();
}

class ForLoopAdder : public LoopAdder {
public :
	ForLoopAdder(string name) : LoopAdder(name){;}
	int calculate() { 
		int sum=0;
		for(int i=getX(); i<=getY(); i++) 
			sum += i; 
		return sum;
	}
};

int main() {
	ForLoopAdder forLoop("For Loop");
	forLoop.run();
}
 

4.

#include <iostream>
#include <string>
using namespace std;

class LoopAdder {
	string name;
	int x, y, sum;
	void read();
	void write();
protected : 
	LoopAdder( string name="") {
		this->name = name;
	}
	int getX() { return x; }
	int getY() { return y; }
	virtual int calculate() = 0;
public : 
	void run();
};

void LoopAdder::read() {
	cout << name << ":" << endl;
	cout << "처음 수에서 두번째 수까지 더합니다. 두 수를 입력하세요 >> ";
	cin >> x >> y;
}
void LoopAdder::write() {
	cout << x << "에서 " << y << "까지의 합 = " << sum << " 입니다" << endl;
}
void LoopAdder::run() {
	read();
	sum = calculate();
	write();
}

class WhileLoopAdder : public LoopAdder {
public :
	WhileLoopAdder(string name) : LoopAdder(name){;}
	int calculate() { 
		int sum=0;
		int x = getX();
		while( x <= getY() ) {
			sum += x; 
			x++;
		}
		return sum;
	}
};
class DoWhileLoopAdder : public LoopAdder {
public :
	DoWhileLoopAdder(string name) : LoopAdder(name){;}
	int calculate() { 
		int sum=0;
		int x = getX();
		do {
			sum += x; 
			x++;
		} while( x <= getY() );
		return sum;
	}
};


int main() {
	WhileLoopAdder whileLoop("While Loop");
	DoWhileLoopAdder doWhileLoop("Do while Loop");
	
	whileLoop.run();
	doWhileLoop.run();
}

4. 설명

 

순수 가상 함수인 calculate를 각각 함수의 용도에 맞게 구현하는 문제 입니다.

 

for문과 while문으로 구현하는 방법은 거의 같다고 봐도 무방합니다.

 

※ 주의 하실 점은 do-while문은 우선 한번 실행한 후 조건문을 비교한다는 것입니다.

 

 

1. 문제

 

1. Converter 클래스를 상속받아 달러를 원화로 환산하는 WonToDollar 클래스를 작성하라. main() 함수와 실행 결과는 다음과 같다.

 

 

2. Converter 클래스를 상속받아 km를 mile(마일)로 변환하는 KmToMile 클래스를 작성하라. main() 함수와 실행 결과는 다음과 같다.

 

 

 

2. 결과

1.

 

2.

 

 

3. 코드

1.

#include <iostream>
#include <string>
using namespace std;

class Converter {
protected:
	double ratio;
	virtual double convert(double src)=0;
	virtual string getSourceString()=0;
	virtual string getDestString()=0;
public :
	Converter(double ratio) { this->ratio = ratio; }
	void run() {
		double src;
		cout << getSourceString() << "을 " << getDestString() << "로 바꿉니다. ";
		cout << getSourceString() << "을 입력하세요>> ";
		cin >> src;
		cout << "변환 결과 : " << convert(src) << getDestString() << endl;
	}
};

class WonToDollar : public Converter {
public :
	WonToDollar(int n) : Converter(n) { };
	double convert(double src) { 
		double re = src / 1010;
		return re;
	}
	string getSourceString() {
		return "원";
	}
	string getDestString() {
		return "달러";
	}
};

int main() {
	WonToDollar wd(1010);
	wd.run();
}

2.

#include <iostream>
#include <string>
using namespace std;

class Converter {
protected:
	double ratio;
	virtual double convert(double src)=0;
	virtual string getSourceString()=0;
	virtual string getDestString()=0;
public :
	Converter(double ratio) { this->ratio = ratio; }
	void run() {
		double src;
		cout << getSourceString() << "을 " << getDestString() << "로 바꿉니다. ";
		cout << getSourceString() << "을 입력하세요>> ";
		cin >> src;
		cout << "변환 결과 : " << convert(src) << getDestString() << endl;
	}
};

class KmToMile : public Converter {
public :
	KmToMile(int n) : Converter(n) { };
	double convert(double src) { 
		double re = src / 1.609344;
		return re;
	}
	string getSourceString() {
		return "Km";
	}
	string getDestString() {
		return "Mile";
	}
};

int main() {
	KmToMile toMile(1.609344);
	toMile.run();
}

 

4. 설명

 

 

Converter의 선언된 순수 가상함수인 convert, getSourceString, getDestString 함수를 자식 클래스에서 각각의 맞게 구현해 줍니다.

 

※ 주의하실 점은 자식 클래스에서 이들 중 구현을 하지 않은게 있다면 오류가 발생합니다.

 

이번 글에서는 이전 글 "안드로이드 DB(데이터베이스) 생성" 이후의 내용입니다.

 

2019/04/21 - [Android] - 안드로이드 DB(데이터베이스) 생성

 

이전 글에서 데이터베이스 파일을 생성하였다면 이제 그 데이터베이스 파일에 데이터를 추가하고 삭제하는 방법을 알아보겠습니다.

 

 

/* 실행 결과 */

 

 

 

이전 글에 이어서 작성하는 것으로, 메인 자바 외에 DBHelper나 레이아웃(. xml) 파일은 이전 글에서 확인해 주세요.

 

 

/* 메인 레이아웃(activity_main.xml) */

package com.tistory.godog.dbtest;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    EditText editText, editText2;
    ListView listView, listView2;

    DBHelper dbHelper;
    SQLiteDatabase db = null;
    Cursor cursor;
    ArrayAdapter adapter, adapter2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = findViewById(R.id.editText);
        editText2 = findViewById(R.id.editText2);
        listView = findViewById(R.id.listView);
        listView2 = findViewById(R.id.listView2);

        dbHelper = new DBHelper(this, 4);
        db = dbHelper.getWritableDatabase();    // 읽기/쓰기 모드로 데이터베이스를 오픈


    }


    public void listUpdate(View v) {
        cursor = db.rawQuery("SELECT * FROM tableName", null);
        startManagingCursor(cursor);    //엑티비티의 생명주기와 커서의 생명주기를 같게 한다.

        adapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1);
        adapter2 = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1);

        while (cursor.moveToNext()) {
            adapter.add(cursor.getString(0));
            adapter2.add(cursor.getString(1));
        }

        /*
        cursor.moveToFirst();
        cursor.moveToPrevious();
        cursor.moveToPosition(2);
        */

        listView.setAdapter(adapter);
        listView2.setAdapter(adapter2);
    }



    public void insert(View v) {
        String name = editText.getText().toString();
        String info = editText2.getText().toString();
        db.execSQL("INSERT INTO tableName VALUES ('" + name + "', '" + info + "');");

        Toast.makeText(getApplicationContext(), "추가 성공", Toast.LENGTH_SHORT).show();

        editText.setText("");
        editText2.setText("");
    }

    public void delete(View v) {
        String name = editText.getText().toString();
        db.execSQL("DELETE FROM tableName WHERE name = '" + name + "';");
    }

}

 

이전 과 달리 insert, delete, listUpdate 함수들이 추가되었다.

 

이들은 각각 버튼 '추가' '삭제' 'UPDATE'를 클릭하였을 때 실행된다.

 

 

insert 함수와 delete 함수를 보면 정작 데이터베이스의 데이터를 추가, 삭제하기 위해서 실행하는 문은 db.execSQL 한 줄이면 된다.

 

 

 

- insert 함수 

  db.execSQL("INSERT INTO tableName VALUES ('" + name + "', '" + info + "');");

execSQL은 SQL문을 실행시켜주는 기능을 한다.

 

위 문장은 tableName 테이블의 (name, info) Values를 insert(삽입) 한다는 의미이다.

 

 여기서 tableName 테이블의 이름으로 이는 저번 테이블을 CREATE(생성) 할 때 정한 테이블의 이름이다. 그러니 테이블을 생성할 때 의미의 맞게 테이블의 이름을 준 후 사용하면 된다.

 

 

※  ""(큰 따옴표), ''(작은 따옴표)을 어찌 사용해야 할지 혼란스러운 분들을 위해 간단한 팁을 드리자면 ""(큰 따옴표)는 안드로이드(자바)에서 사용되는 것이고, ''(작은따옴표)는 SQL문에서 사용되는 것이라 생각하면 편하다.

 

 위 문을 예로 들면 ""(큰 따옴표)만을 이어보면

"INSERT INTO tableName VALUES ('name', 'info');"   같은 문이 된다.

 

이 SQL문을 실행하는 것인데, 여기서 name과 info가 ''(작은따옴표)의 감싸 져 있는데 이들이 저장될 변수명 들이기 때문이다.

 

그러면 위 코드에서 ""(큰 따옴표)로 나눈 것도 name과 info가 변수명이기 때문이라는 것을 알 수 있다. 그러니 이는 평소 변수들을 문자열로 출력할 때처럼 +로 이어준 것뿐이라는 것이다.

 

 

정 어렵다면 우선 위 "INSERT INTO tableName VALUES ('name', 'info');"처럼 SQL문을 먼저 작성해본 후 여기서 변수만을 ""로 안 감싸도록 분리해서 한 문자열로 만들도록 하면 쉬울 것이다.

 

 

 

 

- delete 함수

db.execSQL("DELETE FROM tableName WHERE name = '" + name + "';");

delete 함수도 insert 함수랑 마찬가지이다.

 

단, SQL문에서 DELETE를 사용하여 삭제해준다. 그리고 WHERE은 if문 같은 것으로

 

조건은 name ='name'; 으로 editText1에서 name을 적은 후 삭제 버튼을 클릭하면 이미 기존 테이블에 저장되어 있는 name 데이터와 같은 것이 있으면 삭제되도록 한다.

 

 

 

 

 

- listUpdate 함수

여기서는 rawQuery 메서드를 사용하는데 SELECT 명령을 사용하기 위해서는 execSQL이 아닌 rawQuery를 사용해야만 한다.

 

 

rawQuery는 리턴 값으로는 Cursor 객체를 주며 이는 행을 가리키게 된다.

 

name info
aa 123
bb 234

             ↓ getString(0)            ↓getString(1)

cursor->

 

 

cursor는 행을 가리키므로 cursor를 아래로 이동[movoToNext()]을 while문으로 돌리고

 

cursor.getString(0) 는 cursor가 가리키는 행에서 첫 번째 열(name 열) 데이터를 가져오고

마찬가지로 cursor.getString(1) 는 cursor는 두 번째 열(info 열) 데이터를 가져온다.

 

 

그리고 이를 리스트 어뎁터의 추가하여 리스트 뷰로 출력하도록 만든 것이다.

 

 

여기서는 rawQuery와 Cursor 객체를 사용하여서 데이터베이스에서 데이터들을 가져오는 방법을 이해하였다면 된다.

 

 

 

1. 문제

 

다음과 같은 상속 관계를 가진 Product, Book, CompactDisk, ConversationBook 클래스를 작성하고 아래 실행 화면과 같이 상품을 관리하는 프로그램을 작성하라.

 

Product 클래스는 상품의 식별자(id), 상품 설명, 생산자, 가격을 나타내는 정보를 포함한다. Book 클래스는 ISBN 번호, 저자, 책 제목 정보를 포함한다. CompactDisc 클래스는 앨범 제목, 가수 이름 정보를 포함한다. ConversationBook은 회화 책에서 다루는 언어 명 정보를 포함한다. 객체 지향 개념에 부합하도록 적절한 접근 지정자, 멤버 변수 및 함수, 생성자 등을 작성하라. main()에서는 최대 100개의 상품을 관리하며, 모든 상품의 정보를 조회할 수 있다. 상품의 식별자는 상품을 등록할 때 자동으로 붙인다.

 

 

2. 결과

 

 

 

 

3. 코드

#include <iostream>
#include <string>
using namespace std;

class Product {
	int id;
	string info;
	string pro;
	string price;
public :
	Product(){;}
	Product(int id, string info, string pro, string price) {  
		this->id = id;
		this->info = info; this->pro = pro; this->price = price; 
	}
	int getId() { return id; }
	string getInfo() { return info; }
	string getPro() { return pro; }
	string getPrice() { return price; }
	virtual void show() = 0;
};

class Book : public Product {
	string ISBN;
	string writer;
	string BName;
public :
	Book(int id, string info, string pro, string price, string IS, string writer, string BN) : Product(id, info, pro, price) {
		ISBN = IS; this->writer= writer; BName= BN; }
	string getISBN() { return ISBN; }
	string getWriter() { return writer; }
	string getBName() { return BName; }
	void show();
};
void Book::show() {
	cout << "--- 상품ID : " << getId() << endl;
	cout << "상품설명 : " << getInfo() << endl;
	cout << "생산자 : " << getPro() << endl;
	cout << "가격 : " << getPrice() << endl;
	cout << "ISBN : " << ISBN << endl;
	cout << "책제목 : " << BName << endl;
	cout << "저자 : " << writer << endl;
}

class CompactDisc : public Product {
	string AName;
	string singer;
public :
	CompactDisc(int id, string info, string pro, string price, string AN, string singer) : Product(id, info, pro, price) {
		AName = AN; this->singer = singer; }
	void show();
};
void CompactDisc::show() {
	cout << "--- 상품ID : " << getId() << endl;
	cout << "상품설명 : " << getInfo() << endl;
	cout << "생산자 : " << getPro() << endl;
	cout << "가격 : " << getPrice() << endl;
	cout << "앨범제목 : " << AName << endl;
	cout << "가수 : " << singer << endl;
}

class ConversationBook : public Book {
	string lan;
public :
	ConversationBook(int id, string info, string pro, string price, string IS, string writer, string BN, string lan) 
		: Book(id, info, pro, price, IS, writer, BN)
	{ this->lan = lan; }
	void show();
};
void ConversationBook::show() {
	cout << "--- 상품ID : " << getId() << endl;
	cout << "상품설명 : " << getInfo() << endl;
	cout << "생산자 : " << getPro() << endl;
	cout << "가격 : " << getPrice() << endl;
	cout << "ISBN : " << getISBN() << endl;
	cout << "책제목 : " << getBName() << endl;
	cout << "저자 : " << getWriter() << endl;
	cout << "언어 : " << lan << endl;
}

int main() {
	
	int num;
	int id=-1;
	string info, pro, price, AN, singer, BN, writer, lan, ISBN;
	Product* p[100];
	bool exit = true;

	cout << "***** 상품 관리 프로그램을 작동합니다 *****" << endl;
	while( exit ) {
		cout << "상품 추가(1), 모든 상품 조회(2), 끝내기(3) ? ";
		cin >> num;
		switch( num ) 
		{
		case 1 :
			cout << "상품 종류 책(1), 음악CD(2), 회화책(3) ? ";
			cin >> num;
			cin.ignore(1);
			id++;
			if( id >= 100 ) break;
			if( num == 1) {
				cout << "상품설명>>"; getline(cin, info );
				cout << "생산자>>"; getline(cin, pro );
				cout << "가격>>"; getline(cin, price );
				cout << "책제목>>"; getline(cin, BN );
				cout << "저자>>"; getline(cin, writer );
				cout << "ISBN>>"; getline(cin, ISBN );
				Book* b = new Book(id, info, pro, price, BN, writer, ISBN);
				p[id] = b;
			}
			if( num == 2) {
				cout << "상품설명>>"; getline(cin, info);
				cout << "생산자>>"; getline(cin, pro );
				cout << "가격>>"; getline(cin, price );
				cout << "앨범제목>>"; getline(cin, AN);
				cout << "가수>>"; getline(cin, singer);
				CompactDisc* d = new CompactDisc(id, info, pro, price, AN, singer);
				p[id] = d;
			}
			if( num == 3) {
				cout << "상품설명>>"; getline(cin, info );
				cout << "생산자>>"; getline(cin, pro );
				cout << "가격>>"; getline(cin, price );
				cout << "책제목>>"; getline(cin, BN );
				cout << "저자>>"; getline(cin, writer );
				cout << "언어>>"; getline(cin, lan);
				cout << "ISBN>>"; getline(cin, ISBN );
				ConversationBook* cb = new ConversationBook(id, info, pro, price, BN, writer, ISBN, lan);
				p[id] = cb;
			}
			cout << endl;
			break;
		case 2 :
			for(int i=0; i<=id; i++)
				p[i]->show();
			cout << endl;
			break;
		case 3 : 
			exit = false;
			break;
		}
	}
}



 

4. 설명

 

 

show() 함수를 순수 가상 함수로 만들었습니다.

 

순수 가상 함수는 9장에서 배우지만 코드를 간단히 하기 위하여 사용하였습니다.

 

순수 가상 함수를 간단히 설명하자면 부모 클래스에는 선언만 한 후 자식 클래스에서 구현부를 입력하여 다른 자식 클래스에서는 각각 서로가 구현한 show()함수를 실행 시킵니다.

 

 

 

1. 문제

 

9. 비행기 예약 프로그램을 작성하라. 이 문제는 여러 개의 클래스와 객체들을 다루는 연습을 위한 것이다. 클래스 사이의 상속 관계는 없다. 항공사 이름은 '한성항공'이고, 8개의 좌석을 가진 3대의 비행기로 서울 부산 간 운항 사업을 한다. 각 비행기는 하루에 한 번만 운항하며 비행 시간은 7시, 12시, 17시이다. 비행기 예약 프로그램은 다음의 기능을 가진다.

-예약 : 비행 시간, 사용자의 이름, 좌석 번호를 입력받아 예약한다.

-취소 : 비행 시간, 사용자의 이름, 좌석 번호를 입력받고 예약을 취소한다.

-예약 보기 : 예약된 좌석 상황을 보여준다.

 

 

2. 결과

 

 

3. 코드

#include <iostream>
#include <string>
using namespace std;

class Console {
public:
	int menu() {
		int num;
		cout << "\n예약:1, 취소:2, 보기:3, 끝내기:4 >>";
		cin >> num;
		return num;
	}
	int time_menu() {
		int num;
		cout << "7시:1, 12시:2, 17시:3 >>";
		cin >> num;
		return num;
	}

};

class Seat {
	string name;
	int number;
public:
	Seat() { this->name = "---"; this->number = -1; }
	void setName(string name) { this->name = name; }
	string getName() { return name; }
};

class Schedule {
	Seat *seat;
public:
	Schedule() {
		seat = new Seat[8];
	}
	void show(int num) {
		if (num == 1) cout << "7시:";
		else if (num == 2) cout << "12시:";
		else if (num == 3) cout << "17시:";

		for (int i = 0; i<8; i++)
			cout << "\t" << seat[i].getName();
		cout << endl;
	}
	void setN(int num, string name) { seat[num - 1].setName(name); }
	string getN(int num) { return seat[num - 1].getName(); }
};

class AirlineBook {
	Schedule *s;
public:
	AirlineBook() {
		s = new Schedule[3];
	}
	void program() {
		bool exit = true;
		int num;
		Console c;
		int seat_num;
		string name;

		while (exit) {
			num = c.menu();
			if (num == 1) {
				num = c.time_menu();

				if (num == 1 || num == 2 || num == 3) {
					s[num - 1].show(num);
					cout << "좌석 번호 >>"; cin >> seat_num;
					cin.ignore(1);
					cout << "이름 입력 >>"; getline(cin, name);
					s[num - 1].setN(seat_num, name);
				}
				else
					cout << "숫자를 잘못 입력하셨습니다." << endl;
			}
			else if (num == 2) {
				num = c.time_menu();

				if (num == 1 || num == 2 || num == 3) {
					s[num - 1].show(num);
					cout << "좌석 번호 >>"; cin >> seat_num;
					cin.ignore(1);
					cout << "이름 입력 >>"; getline(cin, name);
					if (name != s[num - 1].getN(seat_num))
						cout << "해당 좌석에 예약되어 있는 이름과 일치하지 않습니다." << endl;
					else
						s[num - 1].setN(seat_num, "---");
				}
				else
					cout << "숫자를 잘못 입력하셨습니다." << endl;
			}
			else if (num == 3) {
				s[0].show(1);
				s[1].show(2);
				s[2].show(3);
			}
			else if (num == 4) {
				cout << "예약 시스템을 종료합니다." << endl;
				exit = false;
			}
			else
				cout << "숫자를 잘못 입력하셨습니다." << endl;
		}
	}
};



int main() {
	AirlineBook *Air = new AirlineBook();

	cout << "*** 한성한공에 오신것을 환영합니다. ***\n";
	Air->program();
}

 

 

4. 설명

 

 힌트에서 설명했듯이 AirlineBook 클래스, Schedule 클래스, Seat 클래스, Console 클래스, 이 4개의 클래스 함수를 작성하였습니다. 

 

 지금은 편의상 한 cpp 파일에 다 작성을 하였지만 본래 문제에서도 말하였듯이 여러 개의 클래스를 다루는 연습을 하기 위해서라도 각 클래스를 각각 다른 파일의 구현하는 것이 좋습니다. 여기서는 하나의 파일의 다 작성하였고, 어느 클래스의서는 다른 클래스 변수를 사용하기 때문에 클래스를 선언하는 순서가 중요합니다.

 

 

 

- Console 클래스 : 메뉴를 물어보고 선택한 숫자를 return 해주는 menu 멤버 함수와 시간 대를 물어보고 어느 시간 대를 선택하였는지 return 해주는 time_menu 멤버 함수를 구현하였습니다.

 

- Seat 클래스 : 좌석 클래스로서 name, number를 멤버 변수로 가집니다. name은 이름을, number은 각각 좌석 번호를 저장하는 변수 입니다. 또한 생성자에서 name = "---"로 초기화 해주므로서 예약되지 않은 좌석이 출력될 때 "---"가 출력되도록 합니다. 그 밖에 이름을 변경하는 setName 멤버 함수와 이름을 return하는 getName 멤버 함수를 가집니다.

 

- Schedule 클래스 : Seat 변수를 가지며, 생성자에서 크기가 8인 동적 배열을 선언합니다. 그리고 좌석을 예약할 시 또는 취소할 시 해당하는 시간 대의 좌석 상황을 보여주기 위한 show 멤버 함수를 가집니다. show 멤버 함수는 num 매개변수를 하나 입력 받아서 해당하는 시간 대의 좌석 현황만 보여줍니다. 그 밖에 좌석을 예약, 취소 시 이름을 수정하기 위한 setN 멤버 함수와 해당 좌석에 이름을 return하는 getN 멤버 함수를 가집니다.

 

- AirlineBook 클래스 : Schedule 변수를 가지며, 생성자에서 크기가 3인 동적 배열을 선언합니다. 전체적인 프로그램을 구현한 program 멤버 함수를 가지며, program 멤버 함수에서 전체 프로그램을 작성하였기 때문에 main 함수에서는 AirlineBook 변수를 동적으로 생성한 후 "->"를 사용하여서 program 멤버 함수를 실행하기만 하면 됩니다.

 

 

 

 이건 여담이지만 파일이 날라가서 코드를 다시 작성하였는데 문제를 안 읽고해서인지는 몰라도 상속관계로 구현하였다가 실패하고 잠시 해매면서 다시 작성하였내요 ㅎㅎ; 그래도 느낌상 처음보다 더 잘 만든 코드인 것 같습니다. 여러분들도 나중에 한번 씩 다시 해보시는 것이 좋을 것 같습니다.

 

 

 

1. 문제

 

8. 다음 그림과 같은 상속 구조를 갖는 클래스를 설계한다.

모든 프린터는 모델명 (model), 제조사 (manufacturer), 인쇄 매수 (prontedCount), 인쇄 종이 잔량 (availableCount)을 나타내는 정보와 print (int pages) 멤버 함수를 가지며, print()가 호출할 때마다 pages 매의 용지를 사용한다. 잉크젯 프린터는 잉크 잔량 (availableInk) 정보와 printInkJet (int pages) 멤버 함수를 추가적으로 가지며, 레이저 프린터는 토너 잔량 (availableToner) 정보와 역시 printLaser (int pages) 멤버 함수를 추가적으로 가진다. 각 클래스에 적절한 접근 지정으로 멤버 변수와 함수, 생성자, 소멸자를 작성하고, 다음과 같이 실행되도록 전체 프로그램을 완성하라. 잉크젯 프린터 객체와 레이저 프린터 객체를 각각 하나만 동적 생성하여 시작한다.

 

 

2. 결과

 

 

 

3. 코드

#include <iostream>
#include <string>
using namespace std;

class printer {
	string model;
	string manufacturer;
	int printedCount;
	int availableCount;
public :
	printer(string m, string ma, int a ) {
		model = m;
		manufacturer = ma;
		availableCount = a;
	}
	string getModel() { return model;}
	string getManu() { return manufacturer;}
	int getAvail() { return availableCount; }
	bool print(int pages) {
		printedCount = pages;
		if( availableCount >= printedCount ) {
			availableCount -= printedCount;
			return true;
		}
		else {
			cout << "용지가 부족하여 프린트할 수 없습니다." << endl;
			return false;
		}
	}
};

class Ink : public printer {
	int availableInk;
public :
	Ink(string m, string ma, int a, int aInk ) : printer( m,  ma,  a ) {
		availableInk = aInk;
	}
	void printInkJet(int pages) {
		if( print(pages) ) {
			if( availableInk >= pages ) {
				availableInk -= pages;
				cout << "프린트하였습니다." << endl;
			}
		}
	}
	void show() {
		cout << getModel() << " ," << getManu() << " ,남은 종이 " << getAvail() << "장 ,남은 잉크 " << availableInk << endl;
	}
};

class Laser : public printer {
	int availableToner;
public :
	Laser(string m, string ma, int a, int aToner ) : printer( m,  ma,  a ) {
		availableToner = aToner;
	}
	void printLaser(int pages) {
		if( print(pages) ) {
			if( availableToner >= pages ) {
			availableToner -= pages;
			cout << "프린트하였습니다." << endl;
			}
		}
	}
	void show() {
		cout << getModel() << " ," << getManu() << " ,남은 종이 " << getAvail() << "장 ,남은토너 " << availableToner << endl;
	}
};

int main() {
	Ink* IP = new Ink("Officejet V40", "HP", 5, 10);
	Laser* LP = new Laser("SCX-6x45", "삼성전자", 3, 20 );
	int n1, n2;
	char a;

	cout << "현재 작동중인 2 대의 프린터는 아래와 같다" << endl;
	cout << "잉크젯 : "; IP->show();
	cout << "레이저 : "; LP->show();

	while(1) {
		cout << endl << "프린터(1:잉크젯, 2:레이저)와 매수 입력>>";
		cin >> n1 >> n2;
		if( n1 == 1 ) 
		{
			IP->printInkJet( n2);
			IP->show();
			LP->show();
		}
		if( n1 == 2 )
		{
			LP->printLaser( n2);
			IP->show();
			LP->show();
		}
		cout << "계속 프린트 하시겠습니까(y/n)>>";
		cin >> a;
		if( a == 'n' ) break;
	}
}

 

4. 설명

 

 프린터 클래스와 프린터 클래스를 상속 받는 잉크젯 프린터 클래스, 레이저 프린터 클래스를 작성합니다.

 

문제 마지막 부분을 보면 잉크젯 프린터 객체와 레이저 프린터 객체를 각각 하나만 동적 생성하여 시작한다고 하였으므로 이에 따라 정보를 입력 받도록 생성자들을 생성 합니다.

 

Priter 클래스는 모델명, 제조사, 인쇄 종이 잔량을 매개변수로 가지는 생성자를 생성하고 Ink 와 Laser 클래스에서 각각 추가적으로 잉크 잔량과 토너 잔량을 입력 받아서 총 매개변수 갯수가 4개인 생성자를 생성합니다.

 

 

 

 Ink 클래스나 Laser 클래스의 생성자에서  ": Printer( m, ma, a )" 을 해준 것은 Printer 클래스에서 printer(string m, string ma, int a ) 생성자가 실행되도록 입니다. 이렇게 지정을 하지 않는다면 기본 생성자를 실행합니다.

 

 

 그 후 print 멤버 함수를 구현하면, print 멤버 함수는 입력받은 매개 변수와 인쇄 종이 잔량을 비교하여서 인쇄 종이 잔량이 같거나 더 많으면 True를 리턴 하고 그렇지 않다면 용지가 부족하다는 매세지를 출력 후 false를 리턴 합니다.

 

-> Ink 클래스나 Laser 클래스는 Printer의 자식 클래스이므로 Printer 클래스의 멤버 함수인 print를 사용할 수 있습니다.

 

  void printInkJet(int pages) 와 void printLaser(int pages) 에서 print 멤버 함수로 용지 잔량을 비교하여 참이였다면 각각 잉크 잔량과 토너 잔량을 비교하여서 잔량이 더 많다면 프린트를 성공 시키고, 그렇지 않으면 프린트를 실패 시킵니다.

 

 

 

 main 에서는 두 객체를 동적으로 생성한 후 while문과 if문을 사용하여서 프로그램을 진행시킵니다.

 

※ 동적으로 생성하였으므로 멤버 함수의 접근하기 위해서는 "->"를 사용하셔야 합니다.

 

1. 문제

 

7. 아래와 같은 BaseMemory 클래스를 상속받는 ROM( Read Only Memory ), RAM 클래스를 작성하라. BaseMemory 에 필요한 코드를 수정 추가하여 적절히 완성하라.

 

ROM은 읽기 전용 메모리이므로 작동 중에 값을 쓸 수가 없기 때문에, 공장에서 생산할 때 생산자가 요청한 데이터로 초기화하는데 이 작업을 굽는다( burn )라고 한다. 그러므로 ROM은 반드시 생성자에서 burn 작업이 일어나야 한다.

다음은 ROM과 RAM 메모리를 생성하고 사용하는 사례이다. ROM의 0번지에서 4번지까지 읽어 RAM 메모리의 0~4번지에 쓰고, 다시 RAM 메모리의 값을 화면에 출력한다. 전체 프로그램을 완성하라.

 

2. 결과

 

 

 

3. 코드

 

#include <iostream>
using namespace std;

class BaseMemory {
	char *mem;
protected:
	BaseMemory(int size) { mem = new char [size]; }
	~BaseMemory() { delete [] mem; }
	void setData(int index, char data) { mem[index] = data; }
	char getData(int index) { return mem[index]; }
};

class ROM : private BaseMemory {
	int length;
public :
	ROM( int size, char memory[], int len) : BaseMemory(size) {
		length = len;
		for(int i=0; i< len; i++)
			setData( i, memory[i] );
	}
	char read(int index) { return getData(index); }
};

class RAM : private BaseMemory {
public :
	RAM(int size) : BaseMemory(size) {;}
	void write(int index, int data) { setData( index, data); }
	char read(int index) { return getData(index); }
};

int main() {
	char x[5] = {'h', 'e', 'l', 'l', 'o'};
	ROM biosROM(1024*10, x, 5);
	RAM mainMemory( 1024*1024 );

	for(int i=0; i<5; i++) mainMemory.write(i, biosROM.read(i) );
	for(int i=0; i<5; i++) cout << mainMemory.read(i);
}

 

 

4. 설명

 

 ROM은 읽기 전용 메모리로서 매개변수로 입력받은 char형 배열을 메모리 (배열)의 저장하도록 합니다.

 

 

 

RAM 클래스 멤버는 생성자에서 size를 입력받고, 크기가 size인 배열을 동적으로 생성하도록 합니다.
 
main함수에서 보면 RAM 클래스 변수 mainMemory의 write 멤버 함수를 이용하여서 동적으로 생성했었던 배열의 해당하는 주소의 값을 저장합니다.
 
그 후 read 멤버함수로 출력을 해보면 hello가 출력되는 것을 알 수가 있습니다.

 

+ Recent posts