950 likes | 1.67k Views
CHAPTER 07. 배열. 배열의 필요성과 편리성을 공부한다 . 1 차원 , 2 차원 , 다차원 배열의 선언과 사용법을 공부한다 . char 형 배열을 이용한 문자열 처리를 공부한다 . 배열을 이용한 다양한 프로그래밍을 공부한다 . 배열의 평균 구하기 배열의 최솟값 구하기 배열 정렬하기 설문 조사 결과 통계치 구하기 2 차원 행렬의 덧셈 학생 정보 조회 시스템 3 차원 배열을 이용한 텍스트 그래픽 처리. 7.0 개요 p. 254. 배열 (array) 동일한 구조의 많은 자료를 다룰 때 사용
E N D
배열의 필요성과 편리성을 공부한다. • 1차원, 2차원, 다차원 배열의 선언과 사용법을 공부한다. • char형 배열을 이용한 문자열 처리를 공부한다. • 배열을 이용한 다양한 프로그래밍을 공부한다. • 배열의 평균 구하기 • 배열의 최솟값 구하기 • 배열 정렬하기 • 설문 조사 결과 통계치 구하기 • 2차원 행렬의 덧셈 • 학생 정보 조회 시스템 • 3차원 배열을 이용한 텍스트 그래픽 처리
7.0 개요 p. 254 • 배열(array) • 동일한 구조의 많은 자료를 다룰 때 사용 • 학생 1000명의 성적, 책 만권의 도서명, 직원 30명의 급여 등 • 변수는 한 개의 자료를 저장하는 데 사용하므로배열은 자료 개수만큼의 변수를 모아 둔 것으로 볼 수 있다.
7.1 1차원 배열 p.255 • 배열이란 • 자료형이 같은 값 여러 개를 연속된 기억장소에 같은 이름(배열명)으로 저장한 것 즉 같은 자료형의 여러 변수들을 연속적으로 모아 둔 것 • 배열의 원소(element) • 배열에 포함된 값 한 개 • 배열원소 한 개를 구분할 때는 첨자(index)를 사용 • 배열의 차원 • 1차원,2차원, 3차원 등의 다차원 배열 • 배열의 첨자의 개수와 동일
7.1 1차원 배열 • 일렬로 연속된 구조로 자료를 저장한 것 • 특정 원소 한 개를 명시하기 위해 1씩 증가하는 첨자 한 개를 사용. 첨자
7.1.1 1차원 배열의 선언과 배열 원소 p.255 • int age[1000];// 1000명의 나이를 저장하기 위한 배열 • int quiz[5]; // 5명의 퀴즈 점수를 저장하기 위한 배열 • double average[100]; // 100명의 평균을 저장하기 위한 배열 • char name[10]; // 10개의 문자를 저장하기 위한 배열 • 주의) • 배열 원소수와 상관없이 배열에 저장되는 모든 값의 자료형은 같아야 한다. • 배열 원소수는 배열의 크기를 의미하며 정수형 상수만 가능하다. 매크로 상수는 가능하나 int n=10; int data[n];는 에러
7.1.1 1차원 배열의 선언과 배열 원소 p.256 • int quiz[5] = {8, 9, 10, 8, 7};// [그림 7-2] 참조 • int sum[100] = {0}; • {} 안의 초깃값 개수가 배열 원소수보다 적으면 나머지 원소는 0으로 초기화된다. • int error[] = {0, 1, 0, 2, 3, 0, 1}; • 배열 원소수를 명시하지 않으면 {} 안의 값 개수가 배열 원소수로 결정된다. 즉 int error[7] = {0, 1, 0, 2, 3, 0, 1};과 같다.
7.1.1 1차원 배열의 선언과 배열 원소 p.256 • quiz[0] = 1; • printf("%d", quiz[1]); • quiz[4]++; • 주의) int a[3] = {21, 25, 20};으로 선언한 배열에서 세 번째 원소를 a[3]으로 참조한다면?에러는 발생하지 않으나 실제로 a[3]은 a 배열에 포함된 기억장소가 아니므로 프로그램 실행 결과를 예측할 수 없게 된다.
7.1.2 1차원 배열과 반복문 p.257 • 배열 원소의 참조(사용) 배열명만으로 모든 배열 원소를 한번에 입출력하거나 저장할 수 없으며, 배열 원소 단위로 입출력하거나 저장해야 한다. • scanf("%d", &quiz[0]); 표준 입력 함수에서는 입력된 자료를 저장할 기억장소의 주소를 명시해야 하므로 배열 원소 앞에 ‘&’를 붙인다. • quiz[0] = 8; quiz[1] = 9; quiz[2] = 10; quiz[3] = 8; quiz[4] = 7; • printf("%d", quiz[0]); • 배열 원소 전체에 대한 처리 선언과 동시에 초기화하는 경우를 제외하고는 배열명에 배열 원소를 바로 입력하거나 저장하는 것이 불가능하다. 배열 원소수가 100개라면 대입문이나 입력문을 100개 사용해야 할까?
7.1.2 1차원 배열과 반복문 p.257 • 배열의 편리성은 배열 원소수와 상관없이 반복문을 이용해 편리하게 코드화할 수 있다는 것
7.2.1 5명 퀴즈 점수의 평균 및 평균 미만 학생 수 구하기 p.258 • 학생 다섯 명의 퀴즈 점수를 입력받은 후, 전체 평균과 퀴즈 점수가 평균보다 낮은 학생 수를 구하고, 각 학생마다 자신의 점수와 평균 점수와의 차이를 구하여 출력하시오. • 퀴즈 점수 5개를 1차원 배열 quiz에 입력하기 (for문) • 배열 quiz의 평균을 avg에 구하기 • 배열 quiz의 원소 5개의 합을 sum에 구하기 (for문) • avg← sum/5 • 2.에서 구한 avg와 각 학생의 점수를 비교하여 학생의 점수가 더 낮을 때마다 count를 1 증가시키는 방식으로 평균 미만인 학생 수를 count에 구하기 (for문) • 각 학생마다 평균과의 차이 점수 quiz [i]-avg를 출력하기 (for문)
7.2.1 5명 퀴즈 점수의 평균 및 평균 미만 학생 수 구하기 • 퀴즈 점수 5개를 1차원 배열 quiz에 입력하기 (for문) • 배열 quiz의 평균을 avg에 구하기 • 배열 quiz의 원소 5개의 합을 sum에 구하기 (for문) • avg← sum/5 • 2.에서 구한 avg와 각 학생의 점수를 비교하여 학생의 점수가 더 낮을 때마다 count를 1 증가시키는 방식으로 평균 미만인 학생 수를 count에 구하기 (for문) • 각 학생마다 평균과의 차이 점수 quiz [i]-avg를 출력하기 (for문)
7.2.1 5명 퀴즈 점수의 평균 및 평균 미만 학생 수 구하기 퀴즈 점수 5개를 1차원 배열 quiz에 입력하기 (for문)
7.2.1 5명 퀴즈 점수의 평균 및 평균 미만 학생 수 구하기 배열 quiz의 평균을 avg에 구하기 • 3. 2.에서 구한 avg와 각 학생의 점수를 비교하여 학생의 점수가 더 낮을 때마다 count를 1 증가시키는 방식으로 평균 미만인 학생 수를 count에 구하기 (for문)
7.2.1 5명 퀴즈 점수의 평균 및 평균 미만 학생 수 구하기 4. 각 학생마다 평균과의 차이 점수 quiz [i]-avg를 출력하기 (for문)
7.2.2 배열의 최솟값 구하기 p.261 • 다섯 가지 물질의 어는 점 3, 0, -30, -20, -1 중 가장 낮은 어는 점(최솟값)을 구하여 출력하시오. • 배열에 저장된 최솟값은 [그림 7-5]의 ①~⑤ 과정을 통해 min 변수에 구할 수 있다. • 1. 최솟값은 배열 원소 중 하나이므로 min을 배열의 첫 원소로 초기화한다(①). • 2. min이 배열 첫 원소로 초기화되어 있으므로 두 번째 원소부터 마지막 원소까지 차례로 다음 확인 과정을 반복해 최종적으로 min에 최솟값이 저장되게 한다(②~⑤). • 현재 min에 저장된 값과 배열 원소의 값을 비교해 min보다 더 작다면 min을 이 배열 원소의 값으로 수정한다. 이 같은 과정을 통해 현재까지 구한 min보다 작은 배열 원소 값이 나타날 때마다 min 값이 새로 수정되고, 마지막 원소까지 비교하면 min에는 배열 원소 중 최소의 값이 저장된다.
7.2.2 배열의 최솟값 구하기 p.262 • min = 배열의 첫 원소; • 나머지 원소에 대해 min과 비교해 작은 값으로 min을 변경하기 (for문) • if (min > 배열 원소) • min = 배열 원소;
7.2.3 설문 조사 결과 구하기 p.263 • 30명에게 5명의 연예인에 대한 선호도를 설문 조사한 결과로부터 각 연예인 번호별로 총 득표수를 구해 출력하시오. • 설문 조사 응답 정보를 저장하는 배열 survey는프로그램이 완성되기까지는 survey 배열을 선언하면서 초기화하여 프로그램을 실행할 때 직접 입력하는 번거로움을 없앤다 • intsurvey[30] = {1, 3, 2, 5, 3, 2, 1, …, 1, 4, 2, 3};
7.2.3 설문 조사 결과 구하기 • 해당 연예인의 득표수 누적 • 설문 조사 응답이 3이라면 3번 연예인의 득표수를 1 증가시켜야 한다. • vote[3]++ • 응답자가 답한 연예인 번호 3은 survey 배열에 저장되어 있으므로 survey[i]가 3일 때 vote[survey[i]]++;로 표현할 수 있다. • 각 연예인의 득표수를 저장하는 배열 vote • - 해당 연예인의 번호와 첨자를 통일하기 위해 6개의 원소를 갖는 배열로 선언 • - 각 원소는 득표수를 누적하기 위해 0으로 초기화
연습문제 7-8 • 열 가지 물질의 어는 점 15, 0, -20, -30, 50, -5, -120, -5, 10, -12를 freeze 배열에 저장한 후 가장 높은 어는 점(최댓값)을 구하여 다음과 같이 출력하시오. • [힌트] • - 배열에 저장된 값 중에서 최솟값을 구하는 7.3을 참고하여 최댓값 max를 구한다. • - 배열의 최댓값에 해당하는 배열 원소의 첨자 index를 구하기 위해 max를 배열의 첫 원소로 초기화할 때 index 또한 첫 원소의 첨자 0으로 초기화한다. 그 다음 max와 배열 원소의 값을 차례대로 비교할 때 max가 새로운 배열 원소 값으로 바뀔 때마다 index 또한 이 배열 원소의 첨자로 수정한다.
연습문제 7-9 • 표준편차는 각 자료들이 평균에 얼마나 근접하게 분포되어 있는지 알려주는 값으로 표준편차가 0이라면 모든 자료가 동일한 값임을 의미한다. 실행 결과와 같이 5개의 자료에 대해 표준편차를 구하여 출력하시오. • [힌트] • sum의 제곱근은 sqrt(sum) • 표준편차 std_D = sqrt(sum); • sqrt함수를 사용하려면 #include <math.h>를 프로그램에 추가해야 한다. printf 함수를 사용하기 위해서 #include <stdio.h>를 포함하는 것과 같은 의미이다.
7.2.4 버블 정렬(오름차순) p.264 • 정렬(sort) • 프로그램에서가장 많이 처리하는 기능 중 하나 • 도서명을 가나다순으로 정렬하기 • 도서를 최근 출판년도 순으로 정렬하기 • 수능 성적을 내림차순으로 정렬하기 • 주소록의 이름을 가나다순으로 정렬하기 등 • 원소수 증가 시 실행 시간이 급격히 증가(원소수의 제곱에 비례)하는 문제 발생실행 시간을 줄이기 위해 많은 정렬 알고리즘이 개발되었다.그 중 하나로 아주 빠른 ‘퀵 정렬’이 있지만 알고리즘 자체가 쉽지 않다.여기서는 가장 단순한 버블 정렬 알고리즘을 소개한다.
7.2.4 버블 정렬(오름차순) p.264 • 버블 정렬(bubblesort) • 버블 정렬의 원리 • 이웃하는 두 원소씩 차례대로 정렬하는 작업을 반복함으로써 배열 전체를 정렬 [그림 7-6]처럼 이웃하는 두 원소를 정렬하는 과정을 [그림 7-7]과 같이(배열 원소수-1)만큼 반복한다.
7.2.4 버블 정렬(오름차순) • 두 변수의 값을 교환하기: 잘못된 예 p.266 x와 y 둘 다 y의 값이 저장된다. • 눈으로 보기에는 2행과 3행의 x가 같은 변수명이지만 실제의 값은 상황에 따라 달라진다. • 2행에서 x의 값이 1로 수정됨으로써 x의 원래 값 3이 사라졌고, 현재 x에 저장된 1이 새로 저장된다.
7.2.4 버블 정렬(오름차순) • 두 변수의 값을 교환하기: 바른 방법 p.267 x의 값을 수정하기 전에 임시 저장소에 보관
7.2.4 버블 정렬(오름차순): [프로그램7-4]의 개선 p.268
7.2.4 버블 정렬(오름차순): [프로그램7-4]의 개선 p.268 • 불필요한 비교를 제거하기 위한 repeat와 i의 상관관계 분석 • repeat가 1 i가 0~3일 때까지 a[i]와 a[i+1]을 비교 (a[0],a[1]) (a[1],a[2]) (a[2],a[3]) (a[3],a[4]) • repeat가 2 i가 0~2일 때까지 (a[0],a[1]) (a[1],a[2]) (a[2],a[3]) • - repeat가 3 i가 0~1일 때까지 (a[0],a[1]) (a[1],a[2])) • repeat가 4 i가 0~0일 때까지 (a[0],a[1]) • repeat가 1씩 증가할 때마다 i의 마지막 값은 1씩 감소 • 12행의 for문을 for (i=0; i<SIZE-repeat; i++)로 수정하면불필요한 비교를 제거할 수 있다.
7.2.4 버블 정렬(오름차순): [프로그램7-5]의 개선 p.270 • 최적화한 버블 정렬 프로그램 p.270 • [프로그램 7-5]는 아직까지 개선할 내용이 있다. b[5] = {1, 2, 3, 5, 4};라면? • 그러나 [프로그램 7-5]는 무조건 repeat가 2일 때부터 4일 때까지 계속 안쪽 for문을 실행함 배열이 완전히 정렬된 상태라면 더 이상 바깥 for문을 실행하지 않게 하자.
7.2.4 버블 정렬(오름차순): [프로그램7-5]의 개선 • 배열의 정렬 완료 여부를 어떻게 알 수 있을까? • 안쪽 for문에서 두 원소 간의 교환이 발생했다. 두 원소가 정렬되지 않았기 때문이므로 아직 정렬 완료 여부를 알 수 없다. • 안쪽 for문에서 이웃 원소 간의 교환이 발생한 적이 없다 • 정렬이 완료된 상태기 때문이므로 정렬 작업을 끝낸다. • 플래그(flag) 변수 • 프로그램에서 특정 상태를 표시하고 상태 변화를 확인하는 데 사용하는 변수 예) 정렬이 완료된 상태인지 아닌지, 두 원소 간에 값의 교환이 발생했는지 아닌지, 입력이 완료되었는지 아닌지를 표시 또는 확인
7.2.4 버블 정렬(오름차순): [프로그램7-5]의 개선 • 버블 정렬에서 플래그 변수의 사용법 • 안쪽 for문 시작 전에 두 원소 간의 교환이 발생한 적이 없는 상태를 나타내게 함 swap = ‘N’; • 안쪽 for문에서 두 원소의 교환이 일어난다면 상태 변화를 저장 swap = ‘Y’; • 안쪽 for문을 마쳤을 때 swap의 값이 ‘N’ 그대로라면 교환이 일어난 적이 없으므로 정렬이 완료되었다는 뜻이다. 따라서 더 이상 정렬 과정을 진행하지 않고 break를 통해 바깥 for문을 완전히 끝낸다. if(swap == ‘N’) break;
7.2.4 버블 정렬(오름차순): [프로그램7-5]의 개선 p.271
7.3 2차원 배열 p.272 • 2차원 배열 • 1차원 배열이 여러 개 모인 배열 • 표 형태의 구조로 표현되는 자료들을 저장하는 데 사용
7.3.1 2차원 배열의 선언과 배열 원소 p.273 • 2차원 배열의 선언 • 전체 행의 개수를 먼저 명시하고 그 다음에 각 행에 들어 있는 열의 개수를 명시 • 배열에 저장되는 모든 값의 자료형이 같아야 한다.
7.3.2 2차원 배열과 반복문 p.273 • 배열 원소 처리 • 2차원 배열도 입출력이나 대입문에서 배열 원소 단위로 처리해야 한다. • 2차원 배열은 1차원 배열의 배열이므로 일반적으로 이중으로 중첩된 반복문으로 처리한다.
7.3.2 2차원 배열과 반복문 p.274 첫 행 둘째 행
7.3.3 2차원 배열의 입력: 행 단위 입력과 열 단위 입력 p.275 • 2차원 배열의 입력 학생들의 여러 과목 점수를 과목별로 입력하거나 학생별로 입력하는 것처럼 [그림 7-16]의 (a)처럼 한 행씩 차례로 입력하거나 (b)처럼 한 열씩 차례로 입력할 수 있다.
7.3.3 2차원 배열의 입력: 행 단위 입력 p.275 한 행을 입력받을 때 행 첨자는 같고 열 첨자만 변한다.