Description
– Inheritance & polymorphism –
주의사항
● 클래스선언및정의를 main.cpp 파일에작성하는것을금지합니다. 그외에선언및정의의 위치에대한제약은없습니다.
● STL 사용이가능합니다.
● 모든 C++ 문법이사용가능합니다.
● 문제에서제공한형식을준수해야합니다.
● 문제에명시되어있지않더라도소멸자(Destructor)와같은메모리누수방지를위해필요한 멤버함수는필수적으로구현되어야합니다.
● 문제조건이복잡합니다. 모든문제의세부조건을꼼꼼히읽어보시기바랍니다.
● 과제관련질문은 PLMS를통해문의바랍니다.
감점
● 제출기한에서하루(24시간) 늦을때마다 20%씩감점
○ 1일(20%) , 2일(40%), … 5일(100%)
● 컴파일이정상적으로이루어지지않을경우 0점
● 제출형식위반 (파일이름등)
제출방식
(맥사용자의경우) 환경에서이루어집니다. VS 로작업했을경우작업하신환경이있는 visual studio 프로젝트폴더에 Report 를포함하여 zip 파일로압축후제출해주시기를바랍니다. (x64 및 .vs 폴더는 전부지워주십시오) 마찬가지로, 맥이용자의경우소스코드, 보고서, Makefile을포함한폴더를 압축해서제출해주시면됩니다. 폴더명은 ‘학번’으로만들어주시고, Report는 docx 나 pdf 형식으로 제출해주세요. 반드시 PLMS 를통해제출해주시기를바랍니다. 이메일제출은인정되지않습니다. 폴더
이름과압축파일은 “Assign3_학번”으로만드시면됩니다 (e.g., Assign3_20229999).
공통채점기준
1. 프로그램기능
● 프로그램이요구사항을모두만족하면서올바로실행되는가?
2. 프로그램설계및구현
● 요구사항을만족하기위한변수및알고리즘설계가잘되었는가?
● 문제에서제시된세부조건을모두만족하였는가?
● 설계된내용이요구된언어를이용하여적절히구현되었는가?
3. 프로그램가독성
● 프로그램이읽기쉽고이해하기쉽게작성되었는가?
● 변수명이무엇을의미하는지이해하기쉬운가?
● 프로그램의소스코드를이해하기쉽도록주석을잘붙였는가?
4. 보고서구성및내용, 양식
● 보고서는적절한내용으로이해하기쉽고보기좋게잘작성되었는가?
● 보고서의양식을잘따랐는가?
다른사람의프로그램이나인터넷에있는프로그램을복사(copy)하거나간단히수정해서제출하면 학점은무조건 ‘F’가됩니다. 이러한부정행위가발견되면학과에서정한기준에따라추가적인불이익이 있을수있습니다.
ASCII Art
ASCII art는 ASCII 문자만을사용하여그림이나도형을만드는예술형식이다. 예를들어서, 그림 1과 같이임의의사진에서어두운부분에해당하는위치에복잡한글자를위치시키고밝은부분에는단순한 글자를위치시키면문자로만이뤄진그림이아래와같이보이게된다. 본과제에서는클래스상속과 다형성을사용해서간단한 ASCII Art를생성하는프로그램을만드는것을목적으로한다.
[ 그림1. ASCII art example]
문제해결을위해사용되는 class와상속관계는아래그림 2과같다. 화살표는상속을의미하고
방향표시가있는 class가부모 class다. 예를들어서 classic class는 artist class를상속받는다.
[ 그림2. Class diagram ]
프로그램을구현에아래와같은제약사항들이따른다.
● 그림2에명시된멤버변수및함수는반드시구현되고사용되어야한다.
● 그림2에명시된멤버함수의인자와 return type이준수되어야한다.
● 그림2에명시된 class 외에다른 class를정의해서사용할수없다.
● 제공된함수(function) 외에함수를정의해서사용할수없다.
● class diagram에명시된멤버함수(method)와멤버변수외에도필요한멤버함수및멤버변수를 자유롭게추가할수있다.
● 주어진 main 함수는절대로수정할수없다.
그림 2에표현된클래스및 main 함수에대한자세한설명은아래와같다.
int main(int argc, char *argv[])
C++ main 함수에 int 와 char*[] 를 argument로정의한경우, 첫번째인자는프로그램실행시입력받은 argument의수, 두번째인자는실제 argument 값들을갖는다. 예를들어서임의의 compile된프로그램
hello 를
./hello 2 world 1234
라는명령어로실행시킬경우 argc 는 4, argv[1] 는 2 argv[2] 는 world, argv[3] 는 1234가된다. 참고로 argv[0]에는실행파일경로가자동으로할당되며, 따라서 argc 는 3이아닌 4가된다.
본과제에서최종 compile된프로그램은실행시 3개의인자를받는다. 첫번째인자는 input파일의경로,
두번째인자는 configuration 파일의경로, 세번째인자는 output 파일의경로다. 주어진 main함수는아래와같으며절대수정을불가한다.
int main(int argc, char *argv[]) {
if (argc != 4) {
cout << “argc is not 4, but ” << argc << endl; throw;
}
// CREATE PARSER parser p;
// LOAD IMAGE AND CONFIG
vector<int> tokens = p.load_image(argv[1]); vector<string> configs = p.load_config(argv[2]);
string style_target = configs[0]; string drawer_target = configs[1]; char *path_output = argv[3];
int width = tokens[0]; int height = tokens[1];
vector<int> vals = {tokens.begin() + 2, tokens.end()};
// CREATE ARTIST artist *style;
if (style_target == “classic”) { style = new classic(width, height, vals);
} else if (style_target == “iclassic”) { style = new iclassic(width, height, vals);
} else if (style_target == “sobelx”) { style = new sobelx(width, height, vals);
} else if (style_target == “sobely”) { style = new sobely(width, height, vals);
} else if (style_target == “gradient”) { style = new gradient(width, height, vals);
} else { throw;
}
// CREATE DRAWER drawer *d;
if (drawer_target == “drawer”) {
d = new drawer(style);
} else if (drawer_target == “upsample”) { d = new upsample(style);
} else if (drawer_target == “downsample”) { d = new downsample(style);
} else if (drawer_target == “scale”) { int scale_x = stoi(configs[2]); int scale_y = stoi(configs[3]); d = new scale(style, scale_x, scale_y);
} else { throw;
}
// PERFORM DRAWING string output = d->draw(); cout << output;
// WRITE OUTPUT
p.write_result(path_output, output); delete d; return 0;
}
vector<int> parser::load_image(const char*)
인자로 input file의경로를받고해당파일의정보를불러온다. input 파일의내용은일련의숫자들이 delimiter ‘|’ 을통해나눠져있다. 예를들어서 input 파일의내용이
3|2|101|102|103|104|105|106
와같다면, 해당함수의 return 값은
vector<int> { 3 ,2, 101, 102, 103, 104, 105, 106 }
이된다. 여기서처음두값은그려질그림의 width와 height를의미하고나머지값은각좌표에해당되는 pixel 값이다. 예를들어서위정보는
101
(0,0) 102
(1,0) 103
(2,0)
104
(0,1) 105
(1,1) 106
(2,1)
와같이시각화될수있다. 여기서괄호안의정보는 x,y 좌표를의미한다. 이후 artist와 drawer class를 통해서해당값이특정 ASCII 문자로변환되며그림을그리게된다.
vector<string> parser::load_config(const char*)
인자로 config file의경로를받고해당정보를불러온다. config 파일의내용은일련의 text들이 delimiter ‘|’ 을통해나눠져있다. 첫번째값은사용될 artist class의이름, 두번째값은사용될 drawer class의 이름을의미한다. 예를들어서 config 파일의내용이
iclassic|upsample
와같다면, 해당함수의 return 값은
vector<string> { “iclassic”, “upsample”}
이된다.
void parser::write_result(const char*, const string&)
첫번째인자로저장할파일경로, 두번째인자로저장할내용이들어온다. 예를들어서
p.write_result(“output.txt”,”hello world”)
를호출하면 output.txt파일이 “hello world”라는내용이담겨서생성된다. 해당함수로최종결과를 저장하게된다. 예시는아래와같으며예시를그대로사용해도무방하다.
void parser::write_result(const char *path, const string& contents) {
ofstream myfile; myfile.open(path); myfile << contents; myfile.close();
}
artist(int, int, const std::vector<int>&)
artist class는그림의스타일을정의하는 class다. 다양한스타일 class들이 artist class를상속받아서 자신만의스타일을정의하게될것이다. 그리고이후설명할 drawer class가 artist class의 instance를 인자로받아서최종적인그림을그리게된다.
생성자는첫번째인자로그림의 width, 두번째인자로그림의 height, 세번째인자로그림의각좌표에
해당하는 pixel 값을받는다. 즉, input 파일 parsing 결과를인자로받는다.
virtual char mapper(int, int)
첫번째인자로 x coordinate, 두번째인자로 y coordinate을받고, 사용될 ASCII 문자를 return한다. 다형성을구현하기위한 virtual method이기때문에해당 class에서는구현되지않고상속받는 class에서 구현된다.
char classic::mapper(int, int)
classic class의 mapper는가장일반적인 ASCII Art의 mapping을구현한다. 이미지는 display에표현될 때 pixel값이작을수록어둡게나타난다. 이관찰에근거해서 pixel 값이낮을수록시각적으로 dense한 ASCII 문자를대입시켜그림을표현한다. 구체적으로 classic::mapper는 pixel을표현하기위해서
15개의 ASCII 문자
‘@’ ‘&’ ‘%’ ‘W’ ‘X’ ‘A’ ‘H’ ‘O’ ‘T’ ‘*’ ‘^’ ‘+’ ‘-’ ‘.’ ‘ ‘
를사용한다. 왼쪽부터 pixel 값이낮은경우에대응되고각문자는 [0, 254] 사이의값을 17개씩균일하게 커버한다. 예를들어서 ‘@’는 [0, 16], ‘&’ 는 [17, 33]를커버한다. 예외적으로마지막문자만 18개, [238,
255]의범위를커버한다. 각 pixel이 ASCII 문자로변하는예시는
2 18 @ &
18 37 & %
와같다. 참고로그림1의 ASCII art는 classic::mapper를통해그려진결과다.
char iclassic::mapper(int, int)
iclassic은 inverted classic의약자다. iclassic::mapper는사용되는 ASCII문자의순서를반대로사용한
것외에 classic::mapper와모든 logic이동일하다. 예를들어서 ‘ ‘가 [0, 16]을커버하고 ‘@’가 [238, 255]를커버한다.
char sobelx::mapper(int, int)
sobel operation은영상에서 edge성분을검출할때사용되는연산이다. 본과제에서 sobelx::mapper는 임의의 pixel에서 x축양의방향으로인접한 pixel과의차이가 50이상인경우 ‘|’를, 그렇지않은경우 공백문자 ‘ ‘를리턴한다. 예를들어서
100 160 120 |
100 30 100 | |
100 100 170 |
와같이왼쪽의 pixel 값에대해서오른쪽같은 ASCII 문자가그려진다.
char sobely::mapper(int, int)
sobelx에서사용된 logic과두가지세부사항이다르다. 먼저 x축이아닌 y축의방향을고려한다. 그리고
리턴되는문자가 ‘|’가아닌 ‘-’이다.
char gradient::mapper(int, int)
gradient::mapper는 sobelx::mapper와 sobely::mapper의 logic을그대로반영한다. 추가적으로 x,y축
양의방향모두인접한 pixel과의차이가 50이상인경우 ‘+’를리턴한다. 예를들어서
100 160 120 | –
100 30 100 | + –
100 100 170 |
와같이왼쪽의 pixel 값이오른쪽과같은 ASCII 문자로그려진다.
drawer(artist *)
drawer class는 artist가갖는 method를사용해서최종적으로그려지는 string을만들어낸다. 따라서
drawer 생성자는첫번째인자로 artist pointer instance를받는다.
string drawer::draw()
최종 ASCII 문자로구성된그림을하나의 string으로리턴한다.
string downsample::draw()
upsample과 downsample은이미지크기를키우고줄이는데사용되는방법이다. 본과제에서는
Nearest-neighbor 기반의 upsample과 downsample을 downsample::draw와 upsample::draw를통해서 모방한다.
downsample::draw()는 drawer::draw()로그려지는그림의크기를절반으로줄인다. 구체적으로좌표 (0,
0)은반드시그려지고, 해당좌표를기준으로홀수값을갖는좌표의문자들은무시된다. 예시는
와같으며왼쪽이원본이고오른쪽이 downsample 결과다.
string upsample::draw()
downsample::draw()와반대로그림의크기를두배로키운다. 키우는과정에서각문자를반복한다. 예시는
와같으며왼쪽이원본이고오른쪽이 upsapmle 결과다.
scale(artist *, int, int)
scale class의생성자는예외적으로 artist*외에추가적인두개의 int 인자를받는다. 두 int 인자는각각 x, y축으로확장및축소될값을의미한다. 이경우예외적으로 config 파일에 2개가아닌 4개의정보가 포함되어야하며 3,4 번째정보가해당 scale 생성자의인자로들어간다. 해당내용은 main 함수에이미 작성되어있다.
string scale::draw()
downsample::draw()와 upsample::draw()이축을구분하지않고단순히 2배확장및축소를했다면, scale::draw()는각축에대해서정해진배율의확장축소를수행한다. 배율이자연수인경우해당값의 배율로그림을확장한다. 배율이음의정수인경우해당값의음의역수를배율로사용한다. 마지막으로 0 인경우는허용하지않는다. 예를들어서 x축과 y축배율이 3, -2 인경우 x축으로 3배, y 축으로 1/2배 확장및축소한다. 아래이어지는예시는프로그램의 input과이에대응되는 output예시들이다.
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
@@@@%%%WWXXXHHHOOTTT***++—….
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
….—++***TTTOOHHHXXXWW%%%@@@@
output using input1.txt and confit1.txt
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@&^–+^..^.HHX@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@*–…–.–. .+.*^^^+-@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@.-^.-…-++^^-.+.-+-.—.-.@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@&-.*…… ….. ..+… …+.+.@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@…-..-..-+.. …………+…….-@@@@@@@@@@@@@@@@
@@@@@@@@@@@@…..^HAXXXXAH*.+-^*++-+^*TOHO^……&@@@@@@@@@@@@@@
@@@@@@@@@@@-..-*HAAXXXXWXWWWXWWWWWWWXWXXXAHHO^..-+%@@@@@@@@@@@@@
@@@@@@@@@@….*OHAXXXWXW%%%%%&&&&&%%%WWWXXAHHAH+…@@@@@@@@@@@@@
@@@@@@@@@@-..+HHAAXXWW%&&&&&&&&&&&&&%%WWXXAAHOOH^…@@@@@@@@@@@@
@@@@@@@@@T-..HOOHAXXW%%%%%&&&&&&&&&&%%WWXAHAHHHHA..^@@@@@@@@@@@@
@@@@@@@@@+.-+HOHHAXWW%%%%%%&@&&@&&&%%%WXXAHHHOHHA-+^@@@@@@@@@@@@
@@@@@@@@@+..+AHHAAXWWWWW%%%%&&&&&&%%%WWXAAHHOOOHXT.*@@@@@@@@@@@@
@@@@@@@@@^…*AHOAXWXWW%%%%&%%%%%%%WWWXXAHHOOTOAW+-^@@@@@@@@@@@@
@@@@@@@@@@-.^*OTOAXXWWWWWW%WWWWWXWWWXXAAAHHOTOHXHT-+@@@@@@@@@@@@
@@@@@@@@@@T.-OXX*+—–..-^HXXAAAH*.-……-^AW%T.+@@@@@@@@@@@@@
@@@@@@@@@@&..X%%OTOHT—+^^*OHHHT-+-+-+-++^^O%&X-.A@@@@@@@@@@@@@
@@@@@@@@@@X+**&WT^..A-. *HT*TWWX^.**W….O+.+H%*+^A*@@@@@@@@@@@@
@@@@@@@@@@@HX+@WAXWWXW%%WX%WXW%X**THHXWXXXAAHAW^HO-%@@@@@@@@@@@@
@@@@@@@@@@@AAO&%AAXXWWWXXWXXX%%XT*OHAXXXWWWXAHW^-WH@@@@@@@@@@@@@
@@@@@@@@@@@&X%&%WAHAAXXXXAXXX%%WO^*THAXXXXXXHH%*+H&@@@@@@@@@@@@@
@@@@@@@@@@@@%%X@WHHHHAXXXWAXAW%WX^TOHAAAAHHOOAWTHA@@@@@@@@@@@@@@
@@@@@@@@@@@@@AX%WOHOHAAXAHXAAW%WHAT*HAHHHHOTOXX*O@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@WHHHHAAXWWWXHO^^+-^TOHHHOOTOAX@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@HHHHAXXXXXWXXHAOOTOOOOOOOOHW@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@AHHHHAAXWWO**HT*^THOOHOOOAX@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@XOOHOAXXXWAXXXHHHTOAAAHTHTO@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@WOT^OOOAHHOT*^^*TOHHOOOOTTO@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@%AO*^-*OHHAAHAAAAAHOT****OH@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@AXAO*^^++*OTOTOTT^^^^^^TOHA@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@HXWWAHOT^+++++^^+++^^^*TOHHAX@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@OAAWWXXAHOO*^++^+++^^**TOOHHHXXA@@@@@@@@@@@@@@@@@
output using input2.txt and confit2.txt
최종적으로풀어야하는문제는아래와같다. 문제 1,2,3은코드구현문제로 test case를통해서채점 되고, 문제 4,5는보고서에작성한다.
문제1> parser 클래스를구현하라
문제2> artist class 및 artist를상속받는 class 그리고 drawer class를구현하라 문제3> drawer class를상속받는 class들을구현하라 문제4> drawer 생성자가 artist가아닌 artist*를인자로받는이유를설명하라 (보고서에작성) 문제5> artist 클래스를상속받아서자신만의 style을정의하고그림을출력하라 (보고서에작성) 문제6> 제시된클래스들을객체지향프로그래밍관점에서개선할수있다면어떤점을더개선할수 있을지토의하라 (보고서에작성)
Reviews
There are no reviews yet.