|| ["AcceleratedC++/Chapter2"] || ["AcceleratedC++/Chapter4"] || = 목차 = ||[[TableOfContents]]|| = Chapter 3 Working with batches of data = 여태까지의 기초적인 입출력 문제를 넘어서서 본격적인 작업을 다루기 시작하는 장이다. 학생들의 성적 관리 프로그램으로 작업을 하면서, 뭔가를 저장하는 방법 등등을 논의할 것이다. == 3.1 Computing student grades == * 먼저 우리가 가지고 놀 코드를 보자. {{{~cpp #include #include #include using std::cin; using std::setprecision; using std::streamsize; using std::cout; using std::string; using std::endl; int main() { // ask for and read the students's name cout << "Please enter your first name: "; string name; cin >> name; const string greeting = "Hello, " + name + "!"; // ask for and read the midterm and final grades cout << "Please enter your midterm and final exam grades: "; double midterm, final; cin >> midterm >> final; // ask for the homework grades cout << "Enter all your homework grades, " "follewd by end-of-file: "; // the number and sum of grades read so far int count = 0; double sum = 0; // a variable into which to read double x; // invariant: // we hava read count grades so far, and // sum is the sum of the first count grades while(cin >> x) { ++count; sum += x; } // write the result streamsize prec = cout.precision(); cout << "Your final grade is " << setprecision(3) << 0.2 * midterm + 0.4 * final + 0.4 * sum / count << setprecision(prec) << endl; return 0; } }}} * cin {{{~cpp cin >> a >> b; // 이 문장은 다음과 같다. cin >> a; cin >> b; // >> 연산자는 left operand를 리턴한다. }}} * 변수 선언에 관해서.. {{{~cpp string insu("insu"); // 요건 string형 변수 insu에 "insu"라는 문자열이 들어간다. string insu; // 요건 디폴트 생성자(그냥 넘어가자. 책에는 Default Initialization이라고 써있다.)에 의해 그냥 비어있게 된다. int num = 0; // num을 0으로 초기화해준다. int num; // num에는 무슨 값이 들어갈까? 책에는 undefined라고 써있다. 메모리에 있던 쓰레기값이 들어가게 된다. // -8437535 이거 비슷한 이상한 숫자가 들어가게 되는걸 보게 될 것이다. }}} * while(cin >> x) {{{~cpp // 다음과 같은 코드는 cin >> x를 만족할 동안 돌게 된다. 이게 무슨 말인지는 일단 넘어가자.(3.1.1) while (cin >> x) { ++count; // count에 1을 더한다. sum += x; // sum에 x를 더한다. } }}} * setprecision {{{~cpp // 숫자의 정밀도를 조절해준다. setprecision(3); // 유효숫자는 3자리가 되고, 일반적으로 소숫점 앞의(정수부분의) 2자리, 소수보분의 1자리로 채워지게 된다. }}} === 3.1.1 Testing for end of input === 위에서 살펴본 while(cin>>x)구문을 살펴보도록 하자. 위에 써놓은 바에 의하면 cin >> x가 성공할동안 계속 루프를 돈다고 했다. 그러면 언제 실패할까? 1. 입력 작업 빠져 나갈때 2. x의 타입에 맞지 않는 값이 들어올때 * >> {{{~cpp if (cin >> x) ... // 이 문장은 다음과 같다. cin >> x; if(cin) ... // istream 내부의 복잡한 작업이 있긴 하지만 12장까진 몰라도 된다. 그냥 이것마 알아도 충분히 쓸수 있다. }}} * bool과 숫자 : 조건문 내에서 0이외의 숫자는 모두 true로 변환, 0은 false로 변환된다. * bool과 cin : 역시 cin도 조건문 내에서 쓸수 있게 변환된다. 지금은 자세히 알 필요 없다. * stream으로부터 읽어들이는데 실패할 경우 * 입력파일의 끝에 도달했을때 * type이 맞지 않을때 * 입력 하드웨어 상에 문제가 생길때 * 실패했을 경우에는 stream 초기화를 시켜줘야 한다.(4장에서 보자) == 3.2 Using medians instead of averages == * 평균값 대신에 중간값을 사용하는 프로그램으로 변경한다. * 평균값보다 중간값이 좋을 때도 있다. * 평균값은 그냥 다 더해서 나눠주면 되니까 하나하나의 값을 저장할 필요가 없었다. * 하지만.. 중간값은 그렇지가 못하다. 다 저장해놔야 한다. 그리고 sort를 해야할 것이다. * 이제부터 그 방법들을 살펴보도록 하자. === 3.2.1. Storing a collection of data in a vector === * vector란? - 주어진 타입의 값들의 모음을 가지고 있는 컨테이너이다. 확장요청이 있을때 커진다. * 이러한 것들을 Telplate Classes 라고 한다. 11장에서 자세히 보도록 하자. * vector 사용하기 {{{~cpp // 다음과 같은 코드를 int count = 0; double sum = 0; double x; while(cin >> x) { ++count; sum += x; } // 다음과 같은 코드로 바꿀수 있다. vector homework; // double값들을 저장할 vector double x; while(cin >> x) // while루프는 값들을 읽어들이면서 homework에 저장한다. homework.push_back(x); }}} * push_back : vector의 멤버 함수. vector의 끝에다 집어넣는 역할을 한다. 그러면서 벡터의 크기를 하나 증가시킨다. === 3.2.2 Generating the output === * size() 멤버 함수 : vector가 소지하고 있는 값들의 갯수를 리턴해준다. {{{~cpp typedef vector::size_type vec_sz; vec_sz size = homework.size(); }}} * typedef : vector::size_type이라고 일일히 쳐주기엔 너무 길기 ㅤㄸㅒㅤ문에 vec_sz로 줄여쓴 것이다. * 또한 vector의 크기가 0이면 아무것도 안들어있다는 것이므로 중간값의 의미가 없다. 0일때 처리 {{{~cpp if(size == 0) { cout << endl << "you must enter your grades. " "Please try again." << endl; return 1; // main함수가 0을 리턴하면 성공적으로 끝난것이고, 그 외의 숫자는 실패적으로 끝난것이다. } }}} * 중간값을 찾기 위해 먼저 해야할 작업 sort : algorithm 헤더에 정의되어 있다. {{{~cpp // sort the grades sort(homework.begin(),homework.end()); }}} * begin() 메소드와, end() 메소드 * begin() : 컨테이너의 맨 처음 값을 가리킨다. * end() : 컨테이너의 맨 마지막 원소에서 한칸 지난 값을 가리킨다. * 5장에선 이 둘을 자세하게 살펴볼것이며, 8장에서는 한칸 지난다는 것의 의미를 살펴볼 것이다. * find a median {{{~cpp median = size % 2 == 0 ? (homework[mid] + homework[mid-1]) / 2 : homework[mid]; // 개수가 홀수이면 딱 가운데꺼, 짝수개면 가운데 두개의 평균을 median 변수에 넣어준다. }}} * % : 나머지 연산 * ? : : ? 앞의 문장이 참이면 ?와 :사이의 문장을 수행, 거짓이면 : 뒤의 문장을 수행 * etc : vector의 맨 처음 인덱스는 [0]이다. 마지막은 [size-1] * 최종 소스 {{{~cpp #include #include #include #include #include #include // 원래 책에는 위 소스 처럼 각각 이름공간을 주었지만 이제부터 무난한 std로 쓰겠습니다. using namespace std; int main() { // ask for and read the students's name cout << "Please enter your first name: "; string name; cin >> name; const string greeting = "Hello, " + name + "!"; // ask for and read the midterm and final grades cout << "Please enter your midterm and final exam grades: "; double midterm, final; cin >> midterm >> final; // ask for the homework grades cout << "Enter all your homework grades, " "follewd by end-of-file: "; vector homework; double x; // invariant: homework contains all the homework grades read so far while(cin >> x) homework.push_back(x); // check that the student entered some homework // 바로 밑에 소스가 이상합니다. // 원래 책에는 "typedef vector::size_type vec_sz;" 이렇게 되어있지만 // 컴파일시 에러가 나서 같은 의미인 unsigned int형을 써서 vec_sz을 표현했습니다. typedef unsigned int vec_sz; vec_sz size = homework.size(); if(size == 0) { cout << endl << "you must enter your grades. " "Please try again." << endl; return 1; } // sort the grades sort(homework.begin(),homework.end()); // compute the median homework grade vec_sz mid = size / 2; double median; median = size % 2 == 0 ? (homework[mid] + homework[mid-1]) / 2 : homework[mid]; // compute and write the final grade streamsize prec = cout.precision(); cout << "Your final grade is " << setprecision(3) << 0.2 * midterm + 0.4 * final + 0.4 * median << setprecision(prec) << endl; return 0; } }}} === 3.2.3 Some additional observations === * homework가 비어있을때 왜 프로그램을 끝내야 할까? * 끝내지 않는다면, size/2=0 이다. homework[0]은 정의되어 있지 않다. 그런 것이다. * size_type은 unsigned int 이다. * vector와 sort의 수행성능에 관해 * vector에다 값을 새로 추가하는 데에는 Θ(n)의 시간이 걸린다. * sort 작업은 Θ(nlog(n))의 시간이 걸린다. * C++의 스탠다드 라이브러리들은 걱정하지 말고 써도 된다. C++은 performance-critical한 애플리케이션 제작을 위해 만들어졌기 때문이다. ---- SeeAlso [STL/vector] ---- ["AcceleratedC++"]