610 likes | 794 Views
Vectors and Arrays. Prof. Jung Guk Kim HUFS, jgkim@hufs.ac.kr. 목표. 객체의 집합으로서 벡터의 사용에 친숙해진다 . 벡터의 원소에 접근하는 것과 벡터 크기를 재조정한다 . 벡터를 함수 인자로 사용한다 . 자주 쓰는 배열 알고리즘에 대해 배운다 . 일차원과 이차원 배열의 사용 방법을 배운다. 벡터를 이용한 데이터 아이템 집합 표현. 모든 급여를 읽어서 리스트를 출력하는 프로그램을 가정하자 프로그램은 최고 급여액을 아래와 같이 표시한다 . 32000
E N D
Vectors and Arrays Prof. Jung Guk Kim HUFS, jgkim@hufs.ac.kr
목표 • 객체의 집합으로서 벡터의 사용에 친숙해진다. • 벡터의 원소에 접근하는 것과 벡터 크기를 재조정한다. • 벡터를 함수 인자로 사용한다. • 자주 쓰는 배열 알고리즘에 대해 배운다. • 일차원과 이차원 배열의 사용 방법을 배운다.
벡터를 이용한 데이터 아이템 집합 표현 • 모든 급여를 읽어서 리스트를 출력하는 프로그램을 가정하자 프로그램은 최고 급여액을 아래와 같이 표시한다. 32000 54000 67500 29000 35000 80000 highest value => 115000 44500 100000 65000 • 최고 급여액을 찾기 위해서는 먼저 프로그램은 급여를 읽어야 한다. • 만약 회사에 10명의 직원이 있다는 것을 알고 있다면 10개의 변수 salary1, salary2, ... , salary10. 연속적인 변수를 만들어 사용하는 것은 실질적이지 못하다. • 직원이 100명 이상일 수도 있기 때문이다.
벡터를 이용한 데이터 아이템 집합 표현 • 벡터(vector)란 같은 타입의 데이터 아이템의 집합이다. • vector<double> salaries(10); • 여기서 salaries는 연속된 double 타입의 값을 저장한다. • 또 (10) 벡터의 값을 10개 까지 저장한다는 것을 나타낸다.
벡터를 이용한 데이터 아이템 집합표현 • 구문 9.1 벡터 변수의 정의
벡터를 이용한 데이터 아이템 집합 표현 • Salaries 속에 데이터를 넣으려면 벡터의 어느 칸에 넣는지를 명시해 주어야 한다. 이를 위해 [] 연산자를 사용한다. salaries[4] = 35000; • 그림의 숫자는 각 내부의 칸 를 나타내는 index이다. • salaries 벡터(vector)는 double 타입의 값을 가진다, 따라서 salaries[4]에는 오직 double타입의 값만을 가질 수 있다. cout << salaries[4] << "\n";
벡터를 이용한 데이터 아이템 집합 표현 • C++ 벡터의 칸은 0부터 시작하게 번호가 붙여진다.
벡터 첨자 • 벡터에서 존재하지 않는 칸에 접근(읽기/쓰기)한다면 오류가 발생한다. . 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;
벡터 첨자 • 벡터의 크기는 size 함수를 이용하여 알아낼 수 있다. for(i = 0; i < v.size(); i++) do something withv[i]; • size 를 사용하는 것은 magic number사용하는 것 보다 좋은 생각이다. (see Quality Tip 2.3).
벡터 첨자 • push_back 함수는 벡터를 처음에는 빈 벡터를 만들고 직원이 추가될 때마다 벡터가 늘어나게 한다. vector<double> salaries; . . . double s; cin >> s; . . . salaries.push_back(s);
벡터 첨자 • push_back 명령은 벡터의 크기를 틀려 한 원소를 벡터의 뒤에 추가한다. • 벡터에서 사용될 원소가 몇 개나 될지 미리 알 수 있다면 벡터를 정의할 때 크기를 명시하고 필요할 때 사용한다. • 또 다른 멤버 함수로 pop_back, 이 함수는 벡터의 마지막 원소를 없애고 크기를 하나 줄인다. salaries.pop_back(); /* Now salaries has size 9 */ • ANSI 표준에서는 벡터와 관련해서 더 많은 유용한 함수를 정의하고 있다. 그러나 이 책에서는push_back 과 pop_back만을 사용하기로 한다.
벡터 인자와 반환값(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(); }
벡터 인자와 반환값(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); }
벡터 인자와 반환값 (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; }
벡터 인자와 반환값 (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; }
원소의 삭제와 삽입 • 어떻게 벡터의 한 원소를 삭제할 것인가? • 만약 벡터 속에서 삭제하려는 원소가 특별한 순서에 따라 들어 있는 것이 아니라면 삭제는 간단하다. void erase(vector<string>& v, int pos){ int last_pos - v.size() - 1; v[pos] = v[last_pos]; v.pop_back(); }
원소의 삭제와 삽입 void erase(vector<string>& v, int pos) { for (int i = pos; i < v.size() - 1; i++) v[i] = v[i+1]; v.pop_back(); }
원소의 삭제와 삽입 • 원소를 삽입할 때 벡터의 중간에 삽입한다면, 새로운 벡터의 원소를 벡터의 마지막에 추가한다. 그리고 모든 원소를 추가하는 원소 아래로 이동한다. 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; }
원소의 삭제와 삽입 • 원소를 삽입 할 때는 벡터의 제일 끝 원소부터 삽입하려는 위치까지 차례로 올라가면서 옮긴다.
병렬 벡터 • 일련의 상품 데이터를 처리하고, 상품 정보와 상품 가치(점수/가격비)가 가장 높은 상품을 표시해 보자
병렬 벡터 • 동일 길이의 세개의 벡터를 생성(names, price, scores) (See bestval1.cpp) • 이러한 벡터를 parallelvectors함께 작업하기 때문이다. • 각 slice - names[i], prices[i], scores[i] - 언제나 함께 처리된다.
병렬 벡터 • 대형 프로그램에서 병렬 벡터는 많은 문제를 발생 시킨다. • 각 벡터의 길이가 같은지. • 같은 위치의 원소에 들어가는 값들이 실제로 한곳에서 나온 값인지 • 모든 벡터의 같은 위치 원소를 처리하는 함수를 호출할 때 모든 벡터의 원소를 인자로 잡아 주어야 한다. • 같은 원소를 함께 묶어 그 것이 나타내는 의미(개념)을 찾는다. 그 의미(개념)을 클래스로 만든다. • 병렬 벡터 집합에서의 집합은 한 벡터로 대치될 수 있다.
배열(array) • 같은 타입의 원소를 모아 두는 두 번째 방법으로 배열(arrays)이 있다. • 배열은 벡터에 비해 저수준의 추상화 개념으로 그만큼 사용하기 불편하다. • 배열은 크기 재조정이 불가능하다. • 벡터는 최근에 C++에 추가된 개념이고, 예전의 많은 프로그램들이 배열을 사용하고 있다. • 배열은 벡터에 비해 빠르고 효율적이다.
배열(array) • 배열의 정의는 벡터의 정의와 유사하다. double salaries[10]; /* array */ /* compare to.... */ vector<double> salaries(10); • 배열은 크기를 변경시킬 수 없다. • 배열의 크기는 반드시 컴파일 할 때 설정되어 있어야 한다.
배열(array) • 배열을 사용할 때는 프로그램에서 저장하게 될 최대 원소 수를 잘 예측하여야 한다. const int SALARIES_CAPACITY = 100; double salaries[SALARIES_CAPACITY]; • 여기서 상수는 배열의 용량(capacity)을 나타낸다.
배열(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++; } }
배열 인자(Array Parameters) • 배열 인자를 갖는 함수를 만들 때는 비어 있는 괄호 []를 인자 이름 뒤에 오게 한다. double maximum(double a[], int a_size); • 배열의 크기도 함수에 인자로 보낼 필요가 있다. 배열에는 size()와 같은 멤버 함수가 없기 때문에 함수에서 배열의 크기를 알 수 없다.
배열 인자(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)
배열 인자(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++; } }
배열 인자(Array Parameters) • 배열이 함수의 반환 타입은 될 수 없다. • 함수에서 여러 값을 계산하려면 함수 호출 프로그램은 결과를 저장할 배열 인자를 함수에 보내야 한다.
문자 배열(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"; */
문자 배열(Character Arrays) • 이 배열에는 '\0'(zeroterminator)라는 문자가 들어 있다. • 문자 배열 변수를 문자 배열 상수로 초기화 할 때는 문자 배열의 크기를 생략해도 된다.
문자 배열(Character Arrays) • 표준 라이브러리의 문자열 함수에게는 종료표시(zero terminators)가 매우 중요하다. int strlen(const char s[]) { int i = 0; while (s[i] != '\0') i++; return i; }