7_ch09_vector

Download Report

Transcript 7_ch09_vector

Vectors and Arrays
Prof. Jung Guk Kim
HUFS,
[email protected]
목표
 객체의 집합으로서 벡터의 사용에 친숙해진다.
 벡터의 원소에 접근하는 것과 벡터 크기를 재조정한다.
 벡터를 함수 인자로 사용한다.
 자주 쓰는 배열 알고리즘에 대해 배운다.
 일차원과 이차원 배열의 사용 방법을 배운다.
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합 표현
 모든 급여를 읽어서 리스트를 출력하는 프로그램을 가정하자
프로그램은 최고 급여액을 아래와 같이 표시한다.
32000
54000
67500
29000
35000
80000
highest value => 115000
44500
100000
65000
 최고 급여액을 찾기 위해서는 먼저 프로그램은 급여를 읽어야 한다.
 만약 회사에 10명의 직원이 있다는 것을 알고 있다면 10개의 변수
salary1, salary2, ... , salary10. 연속적인 변수를 만들어 사용하는 것
은 실질적이지 못하다.
 직원이 100명 이상일 수도 있기 때문이다.
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합 표현
 벡터(vector)란 같은 타입의 데이터 아이템의 집합이다.
 vector<double> salaries(10);
 여기서 salaries는 연속된 double 타입의 값을 저장한다.
 또 (10) 벡터의 값을 10개 까지 저장한다는 것을 나타낸다.
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합표현
 구문 9.1 벡터 변수의 정의
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합 표현
 Salaries 속에 데이터를 넣으려면 벡터의 어느 칸에 넣는
지를 명시해 주어야 한다.
이를 위해 [] 연산자를 사용한다.
salaries[4] = 35000;
 그림의 숫자는 각 내부의 칸 를 나타내는 index이다.
 salaries 벡터(vector)는 double 타입의 값을 가진다, 따
라서 salaries[4]에는 오직 double타입의 값만을 가질 수
있다.
cout << salaries[4] << "\n";
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합 표현
 C++ 벡터의 칸은 0부터 시작하게 번호가 붙여진다.
RTDCS Lab.
벡터를 이용한 데이터 아이템 집합 표현
RTDCS Lab.
벡터 첨자
 벡터에서 존재하지 않는 칸에 접근(읽기/쓰기)한다면 오
류가 발생한다. .
vector<double> staff(10);
cout << staff[10]; /* legal subscripts are 0 until 9 */
 만양 index에러가 발생한다면, 잘못된 위치에서 값을 접
근(읽기/쓰기)한 경우가 발생한다.
 자주 발생하는 오류는 벡터의 크기를 명시하지 않을 경우
(no elements.)
vector<double> salaries; /* no size given */
salaries[0] = 35000;
RTDCS Lab.
벡터 첨자
 벡터의 크기는 size 함수를 이용하여 알아낼 수 있다.
for(i = 0; i < v.size(); i++)
do something with v[i];
 size 를 사용하는 것은 magic number사용하는 것 보다
좋은 생각이다. (see Quality Tip 2.3).
RTDCS Lab.
벡터 첨자
 push_back 함수는 벡터를 처음에는 빈 벡터를 만들고 직
원이 추가될 때마다 벡터가 늘어나게 한다.
vector<double> salaries;
...
double s;
cin >> s;
...
salaries.push_back(s);
RTDCS Lab.
벡터 첨자
 push_back 명령은 벡터의 크기를 틀려 한 원소를 벡터의
뒤에 추가한다.
 벡터에서 사용될 원소가 몇 개나 될지 미리 알 수 있다면
벡터를 정의할 때 크기를 명시하고 필요할 때 사용한다.
 또 다른 멤버 함수로 pop_back, 이 함수는 벡터의 마지막
원소를 없애고 크기를 하나 줄인다.
salaries.pop_back(); /* Now salaries has size 9 */
 ANSI 표준에서는 벡터와 관련해서 더 많은 유용한 함수
를 정의하고 있다. 그러나 이 책에서는push_back 과
pop_back만을 사용하기로 한다.
RTDCS Lab.
벡터 첨자 (salvect.cpp)
RTDCS Lab.
벡터 첨자 (salvect.cpp)
RTDCS Lab.
벡터 인자와 반환값(Vector Parameters)
 함수나 프로시저는 벡터를 인자로 갖게 되는 경우가 종종
있다.
double average(vector<double> v)
{
if (v.size() == 0) return 0;
double sum = 0;
for (int i = 0; i < v.size(); i++)
sum = sum + v[i];
return sum / v.size();
}
RTDCS Lab.
벡터 인자와 반환값(Vector Parameters)
 벡터는 passed by value or by reference
 Pass by reference 를 사용한다면 벡터에 있는 개별원소
는 변경될 것이다.
void raise_by_percent(vector<double>& v, double p)
{
for (int i = 0; i < v.size(); i++)
v[i] =v[i] * (1 + p / 100);
}
RTDCS Lab.
벡터 인자와 반환값 (Return Values)
 함수는 벡터를 반환할 수 있다.
 이 함수는 특정 범위의 값을 포함하는 집합을 돌려준다
vector<double> between(vector<double> v,
double low, double high)
{
vector<double> result;
for (int i = 0; i < v.size(); i++)
if (low <= v[i] && v[i] <= high)
result.push_back(v[i]);
return result;
}
RTDCS Lab.
벡터 인자와 반환값 (Return Values)
 이 함수는 범위에 포함되는 값의 위치(index)값의 집합을 돌려
준다.
vector<int> find_all_between(vector<double> v,
double low, double high)
{
vector<int> pos;
for (int i = 0; i < v.size(); i++)
{
if (low <= v[i] && v[i] <= high)
pos.push_back(i);
}
return pos;
}
RTDCS Lab.
벡터 인자와 반환값(matches.cpp)
RTDCS Lab.
벡터 인자와 반환값(matches.cpp)
RTDCS Lab.
원소의 삭제와 삽입
 어떻게 벡터의 한 원소를 삭제할 것인가?
 만약 벡터 속에서 삭제하려는 원소가 특별한 순서에 따라
들어 있는 것이 아니라면 삭제는 간단하다.
void erase(vector<string>& v, int pos){
int last_pos - v.size() - 1;
v[pos] = v[last_pos];
v.pop_back();
}
RTDCS Lab.
원소의 삭제와 삽입
void erase(vector<string>& v, int pos)
{
for (int i = pos; i < v.size() - 1; i++)
v[i] = v[i+1];
v.pop_back();
}
RTDCS Lab.
원소의 삭제와 삽입
 원소를 삽입할 때 벡터의 중간에 삽입한다면, 새로운 벡터
의 원소를 벡터의 마지막에 추가한다.
그리고 모든 원소를 추가하는 원소 아래로 이동한다.
void insert(vector<string>& v int pos, string s)
{
int last = v.size() - 1;
v.push_back(v[last]);
for (int i = last; i > pos; i--)
v[i] = v[i - 1];
v[pos] = s;
}
RTDCS Lab.
원소의 삭제와 삽입
 원소를 삽입 할 때는 벡터의 제일 끝 원소부터 삽입하려는
위치까지 차례로 올라가면서 옮긴다.
RTDCS Lab.
병렬 벡터
 일련의 상품 데이터를 처리하고, 상품 정보와 상품 가치
(점수/가격비)가 가장 높은 상품을 표시해 보자
RTDCS Lab.
병렬 벡터
 동일 길이의 세개의 벡터를 생성(names, price, scores)
(See bestval1.cpp)
 이러한 벡터를 parallel vectors 함께 작업하기 때문이다.
 각 slice - names[i], prices[i], scores[i] - 언제나 함께 처
리된다.
RTDCS Lab.
병렬 벡터(bestval1.cpp)
RTDCS Lab.
병렬 벡터(bestval1.cpp)
RTDCS Lab.
병렬 벡터(bestval1.cpp)
RTDCS Lab.
병렬 벡터
 대형 프로그램에서 병렬 벡터는 많은 문제를 발생 시킨다.
 각 벡터의 길이가 같은지.
 같은 위치의 원소에 들어가는 값들이 실제로 한곳에서
나온 값인지
 모든 벡터의 같은 위치 원소를 처리하는 함수를 호출할
때 모든 벡터의 원소를 인자로 잡아 주어야 한다.
 같은 원소를 함께 묶어 그 것이 나타내는 의미(개념)을 찾
는다. 그 의미(개념)을 클래스로 만든다.
 병렬 벡터 집합에서의 집합은 한 벡터로 대치될 수 있다.
RTDCS Lab.
병렬 벡터
RTDCS Lab.
병렬 벡터(bestval2.cpp)
RTDCS Lab.
병렬 벡터(bestval2.cpp)
RTDCS Lab.
병렬 벡터(bestval2.cpp)
RTDCS Lab.
병렬 벡터(bestval2.cpp)
RTDCS Lab.
배열(array)
 같은 타입의 원소를 모아 두는 두 번째 방법으로 배열
(arrays)이 있다.
 배열은 벡터에 비해 저수준의 추상화 개념으로 그만큼 사
용하기 불편하다.
 배열은 크기 재조정이 불가능하다.
 벡터는 최근에 C++에 추가된 개념이고, 예전의 많은 프로
그램들이 배열을 사용하고 있다.
 배열은 벡터에 비해 빠르고 효율적이다.
RTDCS Lab.
배열(array)
 배열의 정의는 벡터의 정의와 유사하다.
double salaries[10]; /* array */
/* compare to.... */
vector<double> salaries(10);
 배열은 크기를 변경시킬 수 없다.
 배열의 크기는 반드시 컴파일 할 때 설정되어 있어야 한다.
RTDCS Lab.
배열(array)
 배열을 사용할 때는 프로그램에서 저장하게 될 최대 원소
수를 잘 예측하여야 한다.
const int SALARIES_CAPACITY = 100;
double salaries[SALARIES_CAPACITY];
 여기서 상수는 배열의 용량(capacity)을 나타낸다.
RTDCS Lab.
배열(array)
 얼마나 많은 원소가 사용되고 있는가를 알려면짝 변수(companion
variable) 를 가지고 있어야 한다.
int salaries_size = 0;
while (more && salaries_size < SALARIES_CAPACITY)
{
cout << "Enter salary or 0 to quit: ";
double x;
cin >> x;
if (cin.fail() || x == 0) more = false;
else
{
salaries[salaries_size] = x;
salaries_size++;
}
}
RTDCS Lab.
배열(array)
RTDCS Lab.
배열 인자(Array Parameters)
 배열 인자를 갖는 함수를 만들 때는 비어 있는 괄호 []를
인자 이름 뒤에 오게 한다.
double maximum(double a[], int a_size);
 배열의 크기도 함수에 인자로 보낼 필요가 있다. 배열에는
size()와 같은 멤버 함수가 없기 때문에 함수에서 배열의
크기를 알 수 없다.
RTDCS Lab.
배열 인자(Array Parameters)
 다른 인자와는 달리 배열 인자는 항상 참조에 의한 전달
passed by reference로 보내진다.
void raise_by_percent(double s[], double s_size, double p)
{
int i;
for (i = 0; i < s_size; i++)
s[i] = s[i] * (1 + p / 100);
}
 배열 인자를 정의할 때는 &부호를 사용하지 않는다.
 함수가 배열을 수정하지 않는다면 const키워드를 추가하
는 것이 좋다.
double maximum(const double a[], int a_size)
RTDCS Lab.
배열 인자(Array Parameters)
 함수에서 배열에 원소를 추가하려면, 함수에 배열, 배열의
최대 크기, 현재 크기 세개의 인자를 보내야 한다.
 현재의 크기는 함수가 수정할 수 있게 참조 인자로 전달되
어야 한다.
void read_data(double a[], int a_capacity, int& a_size)
{
a_size = 0;
while (a_size < a_capacity) {
double x;
cin >> x;
if (cin.fail()) return;
a[a_size] = x;
a_size++;
}
}
RTDCS Lab.
배열 인자(Array Parameters)
 배열이 함수의 반환 타입은 될 수 없다.
 함수에서 여러 값을 계산하려면 함수 호출 프로그램은 결
과를 저장할 배열 인자를 함수에 보내야 한다.
RTDCS Lab.
배열 인자(salarray.cpp)
RTDCS Lab.
배열 인자(salarray.cpp)
RTDCS Lab.
배열 인자(salarray.cpp)
RTDCS Lab.
문자 배열(Character Arrays)
 C++에 string class가 없었다.
 모든 문자열 처리는 char타입의 배열을 이용하여 이루어
졌다.
 한 문자 상수는 다음과 같이 작은 따옴표(single quotes)
로 표시한다.
char input = 'y'; /* don't confuse with "y" */
 문자열(string)을 저장하는 배열의 정의이다.
char greeting[] = "Hello";
/* same as greeting[6] = "Hello"; */
RTDCS Lab.
문자 배열(Character Arrays)
 이 배열에는 '\0'(zero terminator)라는 문자가 들어 있다.
 문자 배열 변수를 문자 배열 상수로 초기화 할 때는 문자
배열의 크기를 생략해도 된다.
RTDCS Lab.
문자 배열(Character Arrays)
 표준 라이브러리의 문자열 함수에게는 종료표시(zero
terminators)가 매우 중요하다.
int strlen(const char s[])
{
int i = 0;
while (s[i] != '\0')
i++;
return i;
}
RTDCS Lab.
문자 배열(Character Arrays)
 이 종료표시 문자를 빼먹는 것은 아주 자주 발생하는 오류
이다.
 문자배열을 선언할때 배열 길이에 추가되는 공간("extra
space")을 좀 더 확실히 표현하는 것이 도움이 된다.
const int MYSTRING_MAXLENGTH = 4;
char mystring[MYSTRING_MAXLENGTH + 1];
RTDCS Lab.
문자 배열(append.cpp)
RTDCS Lab.
문자 배열(append.cpp)
RTDCS Lab.
문자 배열(append.cpp)
 일반적으로 문자 배열을 사용하지 않는 것이 가장 좋은 방
법이다.
 string 클래스가 더 안전하고 편리하다.
 때때로 string 클래스가 생기기 이전에 만들어진 함수를
사용하는 경우처럼 문자열(string)을 문자배열로 변환해
야 할 때가 있다.
 정수로 이루어진 문자 배열을 정수 값으로 변환시켜준다.
int atoi(const char s[])
 c_str 멤버 함수 c_str 이용하면 문자열(string)를 문자배
열로 변환할수 있다.
string year = "1999";
int y = atoi(year.c_str());
RTDCS Lab.
이차원 배열 (Two-Dimensional Arrays)
 경우에 따라서는 숫자의 집합을 이차원으로 배치해야 할
때도 있다.
 이러한 배치를 값들의 행과 열이 있는 이차원(twodimensional) 배열(array)또는 행렬(matrix)이라고 한다.
 C++ 에서는 이차원 배열에 저장하기 위해 두 개의 첨자
(two subscripts)가 있는 배열을 사용한다.
const int BALANCE_ROWS = 11;
const int BALANCE_COLS = 6;
double balances[BALANCE_ROWS][BALANCE_COLS];
RTDCS Lab.
이차원 배열 (Two-Dimensional Arrays)
 이 차원 배열에서 특정 원소에 값을 저장하려면 두 개의
대괄호로 행과 열을 표시해 주어야 한다.
RTDCS Lab.
이차원 배열 (Two-Dimensional Arrays)
RTDCS Lab.
이차원 배열 (Two-Dimensional Arrays)
 이차원 배열을 함수의 인자로 전달할 때는 열의 개수를 상수로 인자
타입과 함께 명시해야 한다.
 행의 개수는 변수일수도 있다.
void print_table(const double table[][BALANCE_COLS], int
table_rows)
{
const int WIDTH = 10;
cout << fixed << setprecision(2);
for (int i = 0; i < table_rows; i++) {
for (int j = 0; j < BALANCES_COLS; j++)
cout << setw(WIDTH) << table[i][j]; cout << "\n";
}
}
RTDCS Lab.
이차원 배열 (matrix.cpp)
RTDCS Lab.
이차원 배열 (matrix.cpp)
RTDCS Lab.
이차원 배열 (matrix.cpp)
RTDCS Lab.