Chapter 12 배열
2 배열 의미 배열은 연속적인 항목들이 동일한 크기로 메모리에 저장되는 구조로 그 사용이 간편 배열은 동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는 자료 구조 일반 변수가 단독주택이라면 배열은 아파트 크기 배열의 선언은 다음과 같은 구문을 이용 주요 요소는 배열 변수명 ( 이름 ), 자료형, 그리고 배열의 크기 배열이름 score 로 정수 int 형의 저장 공간이 메모리에 연속적으로 할당된다.
3 배열의 크기와 첨자 배열 score 에서 10 개의 자료형 int 가 저장되는 항목 각각을 배열 원 소 (array element) 배열 원소는 첨자 (index) 를 사용하여 참조되는데, 유효한 첨자의 범 위는 0 부터 배열크기 -1 배열을 선언하는 경우, 대괄호 사이에 기술되는 수는 배열의 크기를 의미하 지만, 각각의 배열 원소를 참조하는 대괄호 사이의 수는 배열 원소를 표현 하는 첨자 즉 첫 배열 원소는 항상 첨자가 0 이며, 차례로 1 씩 증가 배열 첨자는 유효한 값의 범위를 벗어나는 경우, 문제 발생 항상 배열 첨자의 사용에 주의해야 한다. 첨자 범위 : 0 ~ size-1
4 예제 소스 score.c 10 개의 성적을 배열에 저장하여 이들 값 중에서 가장 높은 성적을 찾 아 출력하는 프로그램 정수 10 개를 저장할 배열 score 를 선언하여 다음 10 개의 성적을 저 장
5 배열의 초기화 값의 초기화 배열을 선언한 후 배열의 각 원소에 값을 저장하려면 첨자를 이용하 여 각 원소에 값을 대입 위의 방법보다 손쉽게 배열을 선언하면서 각 원소의 값을 지정하는 구문을 제공, 이 방법이 배열 초기화 (initialization) 구문 이 구문은 반드시 선언에서만 이용 가능 그러므로 다음 문장은 잘못된 문장 int a[4]; a[0] = 10; a[1] = 30; a[2] = 40; a[3] = 50; int a[4] = {10, 30, 40, 50}; 배열의 초기화는 중괄호를 이용한다. 순서대로 10 은 a[0] 의 저장 값으로 저장된다. int a[4]; a = {10, 30, 40, 50};
6 배열 초기화의 배열 크기 배열의 초기화에서 배열의 크기 4 는 생략 가능 배열의 크기를 생략하는 경우, 초기값을 넣는 개수에 따라 배열의 크기가 결정 또한 배열의 크기를 지정하는 경우, 지정된 배열의 크기가 초기 값 개수보다 크면 나머지 지정되지 않은 원소의 초기 값은 자동으로 모두 0 으로 저장
7 예제 소스 initialize.c 정수 int 형 배열 a, double 형 배열 b, char 형 배열 c 를 선언한 후 아래와 같이 초기값을 저장하여 출력하는 프로그램을 작성 저장된 배열 a 의 각 원소를 출력하는 구문으로 조건연산자를 이용 하여 원소를 모두 출력한 이후에 개행 문자 두 개를 출력하도록 int a[5] = {10, 20, 33, 35, 13}; double b[4] = {1.2, 2.4}; char c[] = {'$', '&', '*'}; for (i=0; i<5; i++) { printf("%d%s", a[i], (i==4) ? "\n\n" : ", "); };
8 소스와 결과
9 이차원 배열 2X4 의 이차원 배열의 선언과 구조 이차원 배열에서 각 원소를 참조하기 위해서는 2 개의 첨자를 이용 이차원 배열을 행과 열로 취급하는 것은 좀 더 이해를 쉽게 하기 위한 방법 실제로 이차원 배열이 메모리에 저장되는 모습은 행과 열의 개념이 아니라 일차원과 같은 연속적인 메모리에 저장 이차원 배열의 행과 열에서 처음 행의 모든 원소가 메모리에 할당된 이후에 계속해서 연속된 메모리에 두 번째 행의 원소가 할당 배열의 이러한 특징을 행 우선 (row major) 개념적인 행과 열의 2 차원 배열은 실제 메모리에서 행 우선으로 연속적인 메모리에 저장공간이 확보된다.
10 초기화 주의 이차원 배열을 선언하는 경우, 초기화를 하지 않고 선언만 한다면 배 열의 크기는 행과 열, 두 개 모두 반드시 지정되어야 한다. 그러나 이차원 배열인 경우, 선언을 하면서 초기 값을 저장하면 첫 번 째 크기는 지정하지 않을 수 있다. 중괄호 하나를 이용한 방법도 가능하고, 중괄호를 중첩하여 이차원 구조표현도 가능 배열의 초기화 구문에서는 지정하지 않은 원소의 값은 0 이 저장되므 로 다음 구문도 위와 동일한 구문
11 삼차원 배열 이차원 배열을 확장하면 3 차원 배열 2X2X2 의 3 차원 배열의 선언과 구조 3 차원 배열의 각 원소를 참조하기 위해 3 개의 첨자를 이용 다음과 같은 초기값을 저장한 경우, 각 원소의 값은 다음과 같다. int a[2][2][2]; int a[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
12 예제 소스 dimension.c 이차원 2 X 5 배열에 초기 값을 저장하여 출력하는 프로그램 이차원 배열 grade[][5] 에서 열은 5 로 지정되고, 행은 지정되지 않으나, 초 기 값을 보고 행은 2 로 결정 중복된 for 반복문을 이용하여 이차원 배열의 각 원소를 출력
13 문자열 처리 문자열 프로그램 언어에서 자주 다루는 계속된 일련의 문자를 문자열 (string) 문자열은 일련의 문자를 앞 뒤로 인용부호 “” 로 둘러싸서 표기 이러한 상수를 문자열 상수 문자열 자료형은 없고 문자열을 저장하기 위해서는 1 차원 문자 배열을 이용 C 언어에서는 문자열을 지원하는 자료형이 따로 없고 문자열을 저장하는 배열의 크기는 반드시 저장되는 문자의 갯수보다 1 이 커야 함 “ c language ” char s[] = “C Language!”; char s[12] = “C Language!”;
14 문자열 저장 문자열은 널 (null) 문자 (\0) 가 문자 배열의 마지막에 저장 문자열을 저장하는 배열의 크기는 반드시 저장되는 문자의 갯수보다 1 이 커야 함 항상 널 문자가 문자열의 마지막에 있어야 함 만일 널 문자가 없는 경우는 문제가 발생 ( 문자열로 취급하지 않음 ) 위 문장은 아래 문장과 같이 문자 하나 하나를 배열에 저장하여 문자열을 표현 가능 이러한 경우, 반드시 프로그래머가 알아서 널 문자를 문자열의 마지막에 \0 저장 char c[4] = {‘a’, ‘b’, ‘c’, ‘\0’};
15 문자열 출력 문자열이 저장된 배열 이름을 이용하여 printf() 문을 이용 배열 이름이 문자열 자체를 나타낸다고 생각 문자열을 출력하는 또 다른 방법은 다음과 같이 문자열을 구성하는 각 각의 문자를 출력하는 방법 출력의 제한을 널 (\0) 문자로 검사하면 편리 char s[] = “C Language!”; printf(“%s”, s);
16 예제 소스 string.c 문자열 “C Language!”, “ABC”, “java” 를 여러 방법 으로 저장한 후, 출력하는 프로그램
17 배열의 합 배열 합 모듈 정수나 실수의 자료형 배열인 경우, 모든 원소의 합을 구하는 방법 배열을 함수 인자로 배열의 모든 원소의 합을 구하는 함수를 만든다면 함수의 인자로 배열 을 이용 융통성 있는 함수를 만들자면 배열의 크기도 하나의 인자로 사용
18 배열 합 함수 원형 배열의 합을 구하여 반환하는 함수 원형을 기술하면 다음과 같다. 함수 원형에서 변수 이름은 생략 가능, 그러나 함수 정의 부분에서는 생략 할 수 없음 함수의 인자로서 정수 int 형 배열을 기술하는 경우, 일반적으로 배열의 크기를 지정하지 않음 배열의 크기에 관계없이 배열 원소의 합을 구할 수 있는 함수
19 배열 합 구현 함수 함수 sum() 은 함수 내부에서 선언한 변수 total 에 모든 원소의 합을 구하여 반환 하는 함수 함수 호출 (call) 문장 함수 sum() 을 기술하고 필요한 인자 2 개를 기술하는데, 첫 번째 인자인 배열은 배열 이름인 grade 로, 두 번째 인자는 이 배열의 크기인 7 로 기 술하여 호출 반드시 배열의 이름으로 호출해야 한다. grade[] 는 컴파일 에러가 발생 함수 sum() 의 반환 값을 출력하므로 정수의 변환명세인 %d 를 기술 int sum(int g[], int n) { int i = 0, total = 0; for (i = 0; i < n; i++) { total += g[i]; }; return total; } printf(" 함수에서 구한 합은 %d 이다. \n", sum(grade, 7));
20 예제 소스 Arraysum.c 정수 int 형 배열을 구성하 는 모든 원소의 합을 구하 는 프로그램 배열을 인자로 갖는 함수 를 정의하고 호출
21 이차원 배열 성적 처리, 이차원 배열 이용 프로그램 주어진 4 명에 대한 중간, 기말 성적을 가지고 개인 성적의 합과 중간, 기말고사 각각 모든 학생의 합을 구하는 프로그램 주어진 성적 점수와 프로그램에서 구할 합을 저장할 공간으로 배열 grade 를 이용 이차원 배열이름 grade 로 선언한 후, 초기 값으로 각 학생의 점수를 입 력 중간고사기말고사합 1020 행합 3335 행합 1379 행합 6045 행합 열합 int grade[][3] = { {10, 20}, {33, 35}, {13, 79}, {60, 45}, {0, 0 } }; 배열 grade 는 옆 테이블의 값을 저장하는 변수로 열의 크기는 중간, 기말, 합의 저 장인 3 으로 지정한다. 배열의 크기는 [ 학생수 +1][3] 이 면 가능하다.
22 합을 구하는 함수 이차원 배열에서 행과 열의 합을 구하는 모듈을 함수 함수 이름을 calcgrade() 로 하고 인자는 이차원 배열 다차원 배열을 인자로 이용하는 경우, 배열의 첫 번째 크기를 제외한 다른 모든 크기는 반드 시 기술되어야 함 이차원 배열의 행 내부에서 열을 차례로 참조하여 행의 합을 구하고, 행을 참조할 때 마다 중간고사와 기말고사의 합을 계속 합해 나가면서 행과 열의 합을 구한 다. void calcgrade(int g[][3]);
23 구현 함수와 헤더 파일 성적처리가 끝난 배열을 적당히 출력하는 모듈도 함수로 구현 위의 성적처리 함수를 참고로 다음과 같은 출력이 되도록 함수를 작성 프로그램에서 배열의 크기 및 각 첨자를 쉽게 처리하기 위하여 다음과 같이 전처리 지시자 #define 을 이용하여 상수기호를 정의 void printgrade(int g[][3]); #define NUM_STUDENT 4 // 학생 수 #define MID_INDEX 0 // 배열에서 개인의 중간고사가 저장되는 첨자 #define FINAL_INDEX 1 // 배열에서 개인의 기말고사가 저장되는 첨자 #define SUM_INDEX 2 // 배열에서 개인의 합이 저장되는 첨자
24 예제 소스 Arraygrade.c 함수 main() 에서는 이차원 배열 grade[][] 를 선언하면서 초기 값을 저장하자. 그리고 함수 calcgrade() 와 printgrade() 를 호출
25 문자열의 입력 함수 scanf 표준입력으로 문자열을 입력 받으려면 문자 배열의 변수에 입력된 문 자열을 저장 함수 scanf() 를 이용하여 공백 ( 스페이스 ) 이 없는 문자열을 표준입력으 로 받아 문자 배열에 저장 아래의 예에서 이름을 “ 홍 길동 ” 으로 입력하면 배열 name 에는 “ 홍 ” 만 이 저장되는 문제가 발생 함수 scanf() 에서 %s 의 변환 명세로 입력 받는 문자열은 문자가 시작 되고 공백이 나오기 이전까지의 문자열 한글을 입력하려면 2 바이트가 필요하므로 충분한 저장공간을 확보
26 한 줄의 입출력 함수 gets, puts 한 줄에 입력되는 모든 문자열을 입력하고 출력하기 위한 함수가 gets() 와 puts() 함수를 이용하려면 헤더 파일 stdio.h 파일을 포함 함수 gets() 는 입력 받은 한 줄을 인자로 기술하는 문자 배열에 저장하 는 함수 그러므로 인자 배열의 크기는 표준입력 한 줄의 문자가 모두 입력되고 마지 막에 널 문자가 입력되도록 충분히 커야 한다. char line[81]; gets(line); puts(line);
27 예제 소스 Inputstring.c 함수 gets() 를 이용하여 표 준입력 한 줄을 입력 받고, 함수 scanf() 를 이용하여 공 백이 없는 하나의 문자열을 입력 받은 후, 각각 이들 문 자열을 출력하는 프로그램
28 프로그램 연습 프로그램 목적 이 단원에서 배운 배열을 이용하 여 배열 원소의 총합과 평균, 그리 고 원소의 출현 빈도수를 계산하 는 프로그램 0 에서부터 9 까지의 60 개의 수를 배열에 저장, 이 배열을 적당히 출 력 배열 원소 60 개 수의 평균을 구 하여 출력 배열 원소 60 개에서 각 수가 저 장된 빈도 수를 세어서 이를 다음 결과 그림과 같이 막대 그래프 형 식으로 출력 가장 빈도 수가 많은 수와 빈도 횟 수를 출력 함수는 main() 과 함수 printArray(), mean(), mode() 로 구성
29 구현 함수 구성 이 프로그램은 함수 main() 과 printArray(), mean(), mode() 로 구성 배열의 출력을 위한 함수 printArray() 와 배열의 총합과 평균을 구하는 함수 mean(), 그리고 분포를 조사하여 히스토그램을 그리는 함수 mode() 를 구현 이용 배열 함수 main() 에서 배열 변수 frequency[] 와 response[] 를 선언 int frequency[10] = { 0 }; int response[SIZE] = { 5, 6, 7, 2, 5, 3, 9, 4, 6, 4, 4, 8, 0, 6, 3, 7, 0, 2, 0, 8, 7, 8, 0, 5, 8, 7, 3, 9, 7, 8, 3, 5, 2, 9, 7, 5, 3, 8, 7, 2, 7, 4, 7, 2, 5, 3, 8, 7, 5, 6, 4, 7, 6, 1, 6, 5, 7, 7, 7, 6 };
30 구현 함수 main() 에서 함수 세 개를 호출하면 프로그램은 완성 함수 mean() 은 인자로 받은 배열에서 원소를 모두 더해 출력하는 함수 void mean(int answer[]) { int j, total = 0; … for (j = 0; j < SIZE; j++) total += answer[j]; … } mean(response); mode(frequency, response); void mean(int answer[])
31 구현 0 에서 9 의 분포를 히스토그램을 그리는 함수 mode() 이 함수에서는 인자 answer[] 에 저장된 여러 정수를 조사하여 인자 freq[] 에 그 결과를 저장 변수 modevalue 에는 빈도 수가 가장 많은 수가 저장되며, 변수 largest 에는 그 때의 빈도 수가 저장 void mode(int freq[], int answer[]) { int rating, j, h, largest = 0, modeValue = 0; … for ( j=0; j <= SIZE - 1; j++ ) ++freq[answer[j]]; … for (rating = 0; rating <= 9; rating++) { printf("%10d%10d%8s", rating, freq[rating], " "); if (freq[rating] > largest) { largest = freq[ rating ]; modeValue = rating; } for (h = 1; h <= freq[rating]; h++) printf( "*" ); printf( "\n" ); } … }
32 소스와 결과