22
일일일일일일 일일일일 WORKING WITH BATCHES OF DATA Chapter 3

일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

Embed Size (px)

DESCRIPTION

Chapter 3. 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA. 3 장에서는 …. 1-2 장에서는 하나의 문자열을 읽어 들이고 그것을 출력하고 , 약간의 장식을 추가한 정도 대부분 문제는 이보다 훨씬 복잡하다 . 복잡해지는 원인은 여러 개의 유사한 데이터를 처리해야 하기 때문 3 장에서 다루는 문제는 , 학생의 시험성적과 과제성적을 읽어 들여 , 최종성적을 계산 (3.1 절 ) 입력된 성적을 저장해야 하는 경우 , vector 클래스 사용 (3.2 절 ) - PowerPoint PPT Presentation

Citation preview

Page 1: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

일괄데이터로 작업하기WORKING WITH BATCHES OF DATA

Chapter 3

Page 2: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

3 장에서는…

1-2 장에서는 하나의 문자열을 읽어 들이고 그것을 출력하고 , 약간의 장식을

추가한 정도 대부분 문제는 이보다 훨씬 복잡하다 .

복잡해지는 원인은 여러 개의 유사한 데이터를 처리해야 하기 때문

3 장에서 다루는 문제는 , 학생의 시험성적과 과제성적을 읽어 들여 , 최종성적을 계산 (3.1

절 ) 입력된 성적을 저장해야 하는 경우 , vector 클래스 사용 (3.2 절 )

일련의 데이터를 처리하는 다양한 방법 얼마나 많은 성적들이 있는지 미리 알지 못해도 , 저장할 수 있는

방법 2

Page 3: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

3.1 학생 성적 계산하기

기말 40% 중간 20% 과제의 평균이 40% 일 때 최종 성적 계산하는 과정

1) 이름 읽어 들이기2) 중간고사와 기말고사 성적 읽어 들이기3) 과제성적 읽어 들이기

몇 개를 과제점수를 읽어 들였는지 저장 현재까지 읽어 들인 과제 점수의 합계 저장

4) 과제성적 평균 계산하기 5) 최종 성적 계산하기

최종 = 중간 * 0.2 + 기말 * 0.4 + 과제 평균 * 0.4

3

Page 4: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

학생 성적 계산 – 과제성적 평균

4

#include <iomanip>#include <ios>#include <iostream>#include <string>

using namespace std; // using std::setprecision; using std::streamsize;

int main(){

// ask for and read the student's namecout << "Please enter your first name: ";string name;cin >> name;cout << "Hello, " << name << "!" << endl;

// ask for and read the midterm and final gradescout << "Please enter your midterm and final exam grades: ";double midterm, final;cin >> midterm >> final;

Page 5: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

5

// ask for the homework gradescout << "Enter all your homework grades, " "followed by end-of-file: ";

// the number and sum of grades read so farint count = 0;double sum = 0;

// a variable into which to readdouble x;

// invariant: we have read `count' grades so far, and// `sum' is the sum of the first `count' gradeswhile (cin >> x) {

++count;sum += x;

}

// write the resultstreamsize 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;}

Page 6: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

성적 읽어 들이기

cout <<“Enter your midterm and final …: ”;double midterm, final;cin >> midterm >> final;

실수형 float ( 단일 정밀도 부동소수점 타입 ): 6 자리 유효 숫자 double (double-precision floating point): 최소 10 자리 유효

숫자 부동소수점 연산에는 항상 double 을 써라 .

보다 정확하고 , 하드웨어 발전으로 속도도 느리지 않다 .

입력 연산자 >> 읽어 들인 후 , 왼쪽 연산자를 결과 값으로 리턴함 cin>>midterm>>final; // cin>>midterm;

// cin>>final;

6

Page 7: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

문자열 리터럴

cout << "Enter all your homework grades, "

"followed by end-of-file: ";

공백문자만으로 구분된 둘 또는 그 이상의 문자열 리터럴은 자동적으로 합쳐진다

7

cout << "Enter all your homework grades, followed by end-of-file: ";

Page 8: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

초기화 하기

int count=0;double sum=0; // 자동으로 형 변환 일어남 : sum=0.0;

명시적으로 초기화하지 않으면 ,

기본 타입의 지역 변수들은 정의되지 않은 (undefined) 상태 쓰레기 값을 가지므로 , 이 상태로 사용하면 위험 초래

클래스 타입의 변수는 디폴트 초기화 (default-initialization)

예 , string 타입 변수는 빈 문자열로 초기화 됨

초기화 할지 말지 어떻게 판단 ? 프로그래머의 책임 위 프로그램에서 , 왜 name 과 x 는 초기화 안하지 ?

왜 count 와 sum 은 초기화 하지 ?

8

Page 9: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

입력의 끝 테스트하기// 불변식 : 지금까지 count 개의 성적을 읽어 들였고// sum 은 처음 count 개의 성적의 합이다 .while ( cin>>x ) { ++count; sum += x;}

while 문의 condition 에 cin>>x 등장 가장 최근의 입력 요청 ( 즉 , cin >> x ) 이 성공하면 , 조건식이 성공 cin>>x 에서 >> 연산자는 왼쪽 피연산자 cin 을 리턴하는데 , cin

값은 true/false 로 자동 변환 아래 경우에 cin>> x 가 false 가 됨 ( 보다 구체적인 원리는 12.5

절 ) 파일 끝 입력 ( 키보드에서 Ctrl-Z 또는 Ctrl-D) 변수 형과 호환되지 않는 값 입력 . 예 ) int 형 입력에 숫자외 입력 입력장치에 대한 하드웨어 오류 감지

9

Page 10: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

출력에서 정밀도 정해주기 streamsize prec = cout.precision();cout << "Your final grade is " << setprecision(3) << 0.2*midterm + 0.4*final + 0.4*sum / count << setprecision(prec) << endl;

setprecision(3) 주요 자리수 세자리 출력 : 소수점 앞에 두 자리 , 뒤에 한 자리

출력 후 cout 의 정밀도를 바꾸기 이전 상태로 돌려주기 정밀도 바꾸기 이전 상태 보관 : streamsize prec = cout.precision();

정밀도를 바꾸기 이전 상태로 돌려주기 : setprecision(prec);

10

Page 11: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

3.2 평균 대신 중앙 값 사용하기

중앙값 (median) 과 평균값 (average) 입력이 55 80 12 70 65 라면 ,

평균값 : (55+80+12+70+65)/5=56.4 중앙값 : 65

중앙값은 어떻게 구할까 ? Sorting( 오름차순 또는 내림차순 ) 후 가운데 있는 값을 취함 입력 값들의 개수가 짝수이면 : 가운데 두 개의 평균

중앙값을 사용하기로 한다면 프로그램은 ? 앞의 프로그램처럼 , 읽은 값을 저장하지 않아도 될까 ? 저장해야 한다면 어디에 어떻게 ?

중앙값을 계산하기 위해 값을 한번에 하나씩 읽어 저장 , 끝까지 다 읽은 후에 값들을

정렬 , 중간에 위치한 값 ( 들 ) 을 구함

11

Page 12: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

vector 에 일련의 데이터 저장

표준 라이브러리는 vector 타입을 제공 vector 타입은 주어진 타입에 대한 여러 개의 값들을 저장 필요한 때에 크기가 커지며 , 개별 값들을 효과적으로 접근

가능

vector 타입의 객체에 저장하기

12

double x;vector<double> homework;

while (cin>>x) homework.push_back(x);

// 이전 것과 비교해보자 .int count=0;double sum=0;double x;

while(cin>>x) { ++count; sum+=x;}

Page 13: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

vector 타입vector<double> homework;homework.push_back(x);

vector 는 일련의 값을 저장하는 컨테이너 (container) 값을 여러 개 저장할 수 있는 타입을 컨테이너라 한다 . vector 타입은 템플릿 클래스 (template class) 로 정의되어 있음

‘ 객체’의 타입이 매개변수화 되어 있음 . <> 안에 명시 vector<double> 은 double 타입의 객체를 담는다 vector<string> 은 string 타입의 객체를 담는다

push_back(x) 멤버 함수 vector 의 끝에 새로운 요소를 추가하는 함수

즉 , vector 의 뒤 (back) 에 밀어 넣음 (push) 자연히 vector 의 크기는 하나 증가됨 몇 개의 요소를 담고 있는지는 어떻게 알지 ? vector 의 효율 : 요소가 많아지면 효율이 떨어지나 ?

13

템플릿 클래스를 정의하는 방법은 11

장에서 !!

Page 14: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

vector 크기

vector<double>::size_type size = homework.size();

vector 크기 알아내기 size() 라는 멤버함수 사용 . homework.size();

vector 의 크기를 저장할 변수 vector 의 size_type 을 사용 . vector<double>::size_type

size;

typedef 은 해당 타입에 대한 동의어를 정의

typedef vector<double>::size_type vec_szvec_sz size = homework.size();

typedef 에 의해 size_type 과 vec_sz 는 동의어가 됨 size_type 을 여러 군데에서 사용하는 경우 유용함

14

Page 15: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

오류 처리

오류 처리는 매우 중요하다 .“ 어제까지는 됐는데…”“ 컴퓨터가 이상하네 . 되다 안되다 하네 .”

모든 입력 사례 (instance) 를 고려해라 !

현재 문제에서는 , size 가 0 일 경우와 그렇지 않은 경우

if(size==0) { cout << endl <<“You must enter your grades, ” “Please try again.” << endl;

return 1;} 운영체제에게 1 을 리턴 하여 실행 실패를 알림 main 이 0 을 리턴하면 프로그램이 성공했다고 가정함 오류 처리를 해주지 않으면 어떤 일이 생길까 ?

15

Page 16: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

정렬하기

sort(homework.begin(), homework.end());

sort() 함수 컨테이너에 들어있는 값들을 오름차순 (nondecreasing) 으로

정렬 정렬된 결과를 담을 새 컨테이너를 생성하는 것이 아니라 , 원래

컨테이너의 요소들의 값을 서로 바꿈 효율 : n log(n) 알고리즘 사용 . C++ 의 표준 라이브러리는 꽤 효율적이다

begin() 과 end() 는 vector 의 멤버 함수 homework.begin() 는 첫번째 요소 , homework.end() 는

마지막 요소를 나타냄 . homework 의 첫 번째와 마지막 요소는 homework[0] 과 homework[size-1]

16

Page 17: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

중앙값 찾기 vec_sz mid = size/2;double median;median = size%2==0?(homework[mid]+homework[mid-1])/2: homework[mid];

나머지 연산자 %, 조건부 연산자 ?:

size 가 짝수일 때 ,

size 가 홀수일 때 ,

17

// 홀수 개 일 때

// 짝수 개 일 때

Page 18: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

학생 성적 계산 – 과제성적 중앙값

18

#include <algorithm>#include <iomanip>#include <ios>#include <iostream>#include <string>#include <vector>

using namespace std;int main(){ // ask for and read the student's name cout << "Please enter your first name: "; string name; cin >> name; cout << "Hello, " << name << "!" << endl;

// 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 and read the homework grades cout << "Enter all your homework grades, “ "followed by end-of-file: “;

Page 19: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

19

vector<double> homework;double x;// invariant: `homework' contains all the homework grades read

so farwhile (cin >> x)

homework.push_back(x);

// check that the student entered some homework gradestypedef vector<double>::size_type 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 gradessort(homework.begin(), homework.end());

// compute the median homework gradevec_sz mid = size/2;double median;median = size%2==0 ? (homework[mid] + homework[mid-

1])/2 : homework[mid];

// compute and write the final gradestreamsize prec = cout.precision();cout << "Your final grade is " << setprecision(3) << 0.2 * midterm + 0.4 * final + 0.4 * median << setprecision(prec) << endl;

return 0;}

Page 20: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

벡터의 원소 접근하기

vector<int> v;v.push_back(100); // 100v.push_back(10); // 100 10v.push_back(1); // 100 10 1

cout << v[0] << endl; // prints 100cout << v[1] << endl; // prints 10cout << v[2] << end; // prints 1cout << v[3] << endl; // ERROR! No element at this

position.

for(unsigned int i=0; i != v.size(); ++i){cout << v[i] << endl;

}

20

Page 21: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

출력 : 소수점 3자리 지정

소수점 3자리까지 출력하는 방법cout.setf(ios::fixed, ios::floatfield); cout.precision(3);

21

Page 22: 일괄데이터로 작업하기 WORKING WITH BATCHES OF DATA

벡터 초기화 정수형의 빈 벡터 (empty vector) 생성

vector<int> a;

100 개의 double 형 벡터 생성 , 각 요소의 초기값은 3.14 로 설정int n = 100;vector<double> b( 100, 3.14 );

10,000 개의 정수를 저장하는 벡터 생성vector<int> c( n*n );

벡터 b 를 복사한 벡터 d 생성vector<double> d( b );vector<double> e( b ); // ERROR; e 는 double 형 , b는 int 형

22

cout << a.size() << endl << b.size() << endl << c.size() << endl << d.size() << endl;