6장 배열
배열 배열(array) 예: 5명의 성적 표현 자료구조(data structure) 여러 개의 같은 자료형의 값들의 모임을 나타내는 자료형 예: 5명의 성적 표현 배열을 사용하지 않은 경우 int grade0, grade1, grade2, grade3, grade4; … 개별적으로 선언 배열을 사용한 경우 int grade[5]; … 변수 grade는 5원소로 구성된 배열 1개의 이름으로 5원소 나타냄 자료구조(data structure) 함수는 프로그램을 조직화하는 방법 제공 자료구조는 자료를 조직화하는 방법 제공 배열(array): 같은 자료형의 값들의 모임 구조체(structure): 임의의 자료형의 값들의 모임 C 프로그래밍
배열 선언과 원소 접근 배열 선언 배열 원소 접근 int grade[5]; … 정수 배열 선언 char s[80]; … 문자 배열 선언 int a[10], b[5], c; … 여러 개의 배열과 보통 자료형을 함께 선언 배열 원소 접근 grade[0], grade[1], … , grade[4] … 첨자는 0부터 N-1까지 (N: 배열의 원소개수) 첫원소 마지막원소 첨자, 인덱스 첨자는 정수식으로 표현 가능, 첨자가 유효한 범위 내에 있어야 함 grade[2] grade[k] grade[3*k+2] … k는 정수형 변수 배열 원소는 같은 자료형의 변수와 똑같이 사용 가능 data = 80; grade[4] = 80; total = total + data; total = total + grade[k]; scanf("%d", &data); scanf("%d", &grade[k]); C 프로그래밍
예제: 여러 사람의 성적의 총점 계산 배열을 사용하지 않은 예 배열을 사용한 예 int grade0, grade1, grade2, grade3, grade4, total; scanf("%d%d%d%d%d",&grade0,&grade1, &grade2, &grade3, &grade4); total = grade0 + grade1 + grade2 + grade3 + grade4; printf("총점 = %d\n", total); 배열을 사용한 예 int grade[5], total, i; for (i=0; i<5; i++) scanf("%d", &grade[i]); /* 성적 입력 */ total = 0; total = total + grade[i]; /* 총점 계산 */ printf("총점 = %d\n", total); /* 총점 출력 */ 개별적 변수 선언 일반화된 프로그램 작성 곤란 C 프로그래밍
예제: 여러 사람의 성적의 총점 계산 기호상수로 배열의 크기를 지정한 프로그램 #include <stdio.h> #define SIZE 5 /* 배열의 크기 */ main() { int grade[SIZE], total, i; for (i=0; i< SIZE; i++) scanf("%d", &grade[i]); /* 성적 입력 */ total = 0; total = total + grade[i]; /* 총점 계산 */ printf("총점 = %d\n", total); /* 총점 출력 */ } C 프로그래밍
배열의 치환과 비교 배열 전체를 비교하거나 치환할 수 없음 배열의 치환과 비교는 원소 단위로 수행해야 함 int a[10], b[10]; … a = b; … 틀렸음: 배열 치환 불가 if (a == b) printf("두 배열은 같습니다.\n"); … 틀렸음: 배열 비교 불가 배열의 치환과 비교는 원소 단위로 수행해야 함 for (i=0; i<10; i++) … 배열의 치환 a[i] = b[i] same = 1; … 배열의 비교 for (i=0; i<10; i++) if (a[i] != b[i]) { same = 0; break; } if (same==1) printf("두 배열은 같습니다.\n"); C 프로그래밍
배열의 초기화 배열 원소도 선언을 할 때에 초기화 할 수 있음 int a[4] = { 10, 20, 30, 40 }; … a[0]=10, a[1]=20, a[2]=30, a[3]=40 int a[4] = { 10, 20 }; … a[0]=10, a[1]=20, a[2]=0, a[3]=0 int a[4] = { 10, 20, 30, 40, 50 }; … 틀렸음(초기값의 개수가 많음) int a[ ] = { 10, 20, 30, 40 }; … 배열의 크기가 4로 지정됨 C 프로그래밍
예제: 가중치 평균 계산 중간, 기말, 퀴즈, 과제, 출석 점수가 모두 100점 만점으로 기재됨 각 점수의 반영 비율은 각각 30%, 30%, 10%, 10%, 20%이며 평균은 각 점수에 가중치를 곱하여 더한 값이다. int score[5]; /* 점수 */ float mean; /* 총점 */ float weight[5] = { 0.3, 0.3, 0.1, 0.1, 0.2 }; /* 가중치 */ int i; for (i=0; i<5; i++) scanf("%d", &score[i]); /* 점수 입력 */ mean = 0.0; for (i=0; i<5; i++) /* 가중치를 반영한 총점 계산 */ mean += score[i] * weight[i]; printf("mean score = %.1f\n", mean); C 프로그래밍
다차원 배열 다차원 배열 다차원 배열 선언 배열 원소 접근 1차원 배열: 1개의 첨자에 의해서 원소가 구분됨 2차원 배열: 2개의 첨자에 의해서 원소가 구분된 n차원 배열: n개의 첨자에 의해서 원소가 구분됨 다차원 배열 선언 int a[4]; … 1차원 배열, 4 원소 int b[2][4]; … 2차원 배열 (2행 4열), 2x4 = 8 원소 int c[3][2][4]; … 3차원 배열 (3면 2행 4열), 3x2x4 = 24원소 배열 원소 접근 b[0][3] … 첨자는 행 0~1, 열 0~3까지 사용 가능 c[p][q][r] … 첨자는 정수식 사용 가능 C 프로그래밍
배열의 기억장소 배치 배열의 기억장소 배치 배열의 각 원소는 연속적인 위치에 배치됨 다차원 배열은 행 우선 배치 (앞의 첨자가 작은 원소가 먼저 배치됨) a[0] 0열 b[0][0] c[0][0][0] a[1] 1열 b[0][1] c[0][0][1] 0행 c[1][0][0] a[2] 2열 b[0][2] c[0][0][2] c[1][0][1] a[3] 3열 b[0][3] c[0][0][3] c[2][0][0] c[1][0][2] b[1][0] c[0][1][0] c[2][0][1] c[1][0][3] b[1][1] c[0][1][1] 1행 c[2][0][2] c[1][1][0] b[1][2] c[0][1][2] c[2][0][3] c[1][1][1] b[1][3] c[0][1][3] c[2][1][0] c[1][1][2] 0면 각 행은 1차원 배열 (b[0], b[1]) c[2][1][1] c[1][1][3] c[2][1][2] 1면 c[2][1][3] 각 면은 2차원 배열 (c[0], c[1], c[2]) 2면 C 프로그래밍
다차원 배열 초기화 초기값은 기억장소 배치 순서대로 지정됨 int b[2][4] = { 1,2,3,4,5,6,7,8 }; … b[0][0]=1, b[0][1]=2, b[0][2]=3, b[0][3]=4 b[1][0]=5, b[1][1]=6, b[1][2]=7, b[1][3]=8 b[0][..] b[1][..] int b[2][4] = { 1,2,3,4,5,6 }; … (나머지원소=0) b[1][2], b[1][3]=0 int b[2][4] = { {1,2,3,4}, {5,6,7,8} }; … { }을 사용하여 행 구분 int b[2][4] = { {1,2,3}, {5,6} }; … (각 행의 나머지 원소=0) b[0][3], b[1][2], b[1][3]=0 int b[ ][4] = { 1,2,3,4,5,6,7,8 }; … 가장 첫 첨자를 제외한 나머지 첨자의 크기는 정의 되어야 함, 행 크기=2 C 프로그래밍
예제: 여러 명의 가중치 평균 계산 여러 명의 중간, 기말, 퀴즈, 과제, 출석 점수가 2차원 배열에 저장됨 가중치는 1차원 배열에 저장됨. 각 학생의 평균을 계산 int score[3][5] = { { 80, 70, 90, 80, 85}, {70, 85, 80, 60, 90}, {50, 80, 85, 70, 80} }; … 학생 성적 float weight[5] = { 0.3, 0.3, 0.1, 0.1, 0.2 }; … 가중치 float avg[3]; … 학생 평균 int sid, i; for (sid=0; sid<3; sid++) { avg[sid] = 0.0; for (i=0; i<5; i++) avg[sid] += score[sid][i]*weight[i]; } for (sid=0; sid<3; sid++) printf("student %d: average = %.1f\n", sid, avg[sid]); C 프로그래밍
배열과 함수 배열은 함수의 인수로 사용될 수 있다. 배열은 함수의 반환 값으로 사용할 수 없음 배열의 크기는 지정할 필요가 없음 double average(double data[ ]) … 배열의 크기 지정하지 않음 { … } 인수로 전달되는 배열은 호출하는 측에서 선언 되어 있음 배열의 크기를 함께 선언해도 무방하지만 아무런 의미가 없음 double average(double data[5]) … 임의의 크기의 배열에 사용 가능 배열은 함수의 반환 값으로 사용할 수 없음 C 프로그래밍
예제: 배열을 인수로 사용하는 함수 배열 원소의 평균을 계산하는 함수 배열과 배열의 크기(원소 개수)를 인수로 전달 받음 평균을 계산하여 반환. 원소 개수가 0이하이면 0을 반환 double average(double data[ ], int num) { double total = 0.0; int k; if (num <=0) return 0.0; for (k=0; k<num; k++) total = total + data[k]; return total / num; } C 프로그래밍
예제(계속) #include <stdio.h> double average(double data[ ], int num); main() { int i; double number[10], avg; printf("Input 10 numbers: "); for (i=0; i<10; i++) /* 자료 입력 */ scanf("%lf", &number[i]); avg = average(number, 10); /* 배열 number의 값의 평균 계산 */ printf("average = %.2f\n", avg); } C 프로그래밍
다차원 배열 인수 다차원 배열 인수 예: 2차원 배열의 원소의 최대값을 구하는 함수 첫번째 첨자를 제외한 나머지 첨자의 크기는 지정해야 함 double max_elem(int a[ ][3]) { … } 예: 2차원 배열의 원소의 최대값을 구하는 함수 int max_elem(int a[3][3]) … 이 함수는 3x3 배열에 대해서 수행됨 { 없어도 됨 int i, j, max; max = a[0][0]; for (i=0; i<3; i++) … 모든 원소에 대해서 현재의 max와 for (j=0; j<3; j++) 비교하여 더 크면 이 원소를 max로 지정 if (max < a[i][j]) max = a[i][j]; return max; C 프로그래밍
예제(계속) #include <stdio.h> int max_elem(int a[3][3]); main() { int b[3][3] = { 1, 22, 13, 4, 5, 16, 7, 8, 9 }; printf("max element = %d\n", max_elem(b); } 3x3 2차원 배열 이름 C 프로그래밍
배열 인수와 보통 인수의 차이 보통 인수 배열 인수 함수에서 형식 인수의 값이 바뀌더라도 이 함수를 호출한 측에서 실 인수로 사용된 변수에는 영향 없음 배열 인수 함수에서 사용되는 배열은 이 함수를 호출한 측에서 실 인수로 사용된 배열과 같은 배열임 따라서 함수에서 배열 원소가 변경되는 것은 호출한 측의 인수로 사용된 배열이 변경되는 것임 배열 인수의 사용에 주의를 요함 (자세한 내용은 포인터를 배울 때에) C 프로그래밍
예제: 함수에서 원소 값이 바뀌는 배열 인수 함수 double_first는 배열 인수의 첫 원소를 두 배로 증가시킴 #include <stdio.h> void double_first(int data[ ]); main() { int a[5] = { 3, 4, 5, 6, 7 }; printf("호출 전: %d", a[0]); /* 3이 출력 */ double_first(a); printf("호출 후: %d", a[0]); /* 6이 출력 */ } void double_first(int data[]) data[0] = data[0] * 2; /* 배열 data의 첫 원소 두 배로 */ C 프로그래밍
예제: 배열 원소를 반대로 배치하기 void rev_copy(int d[ ], int s[ ], int n) { int from, to; for (from=0, to=n-1; from<n; from++, to--) d[to] = s[from]; } void reverse(int s[ ], int n) int front, rear; int tmp; for (front=0, rear=n-1; front<n/2; front++, rear--) { tmp = s[front]; s[front] = s[rear]; s[rear] = tmp; 1 2 n-2 n-1 결과 저장용 배열 s d 1 2 n-2 n-1 s 인수로 받은 배열을 반대로 배치함 C 프로그래밍
예제 (계속) #include <stdio.h> void print_array(int s[ ], int n); void rev_copy(int d[ ], int s[ ], int n); void reverse(int s[ ], int n); main() { int a[5] = {1,2,3,4,5}; int b[5]; rev_copy(b, a, 5); print_array(b, 5); reverse(b, 5); } void print_array(int s[ ], int n) { int i; for (i=0; i<n; i++) printf("%d ", s[i]); printf("\n"); } … 출력: 5 4 3 2 1 … 출력: 1 2 3 4 5 C 프로그래밍
변수의 접근 수정자 접근 수정자 const 변수의 수정을 허용하지 않음(상수) const int n = 30; int array[n]; … 기호상수와 같이 배열 크기 지정에 사용 불가 배열에 사용하면 배열 원소의 수정을 허용하지 않음 배열을 인수로 사용할 때에 의도하지 않은 배열 원소의 수정을 방지 void copy_array(int d[ ], const int s[ ], int len) { … s[len] = d[len]; … 배열원소 수정시도 (잘못) } C 프로그래밍
변수의 접근 수정자(2) 접근 수정자 volatile 프로그램에 명시되지 않고 변수 값이 변경될 수 있음을 나타냄 주로 입출력 제어장치 접근에 사용됨 volatile char a; a = 10; … 최적화 적용 시 이 문장 삭제, 여기서는 그대로 둠 a = 20; C 프로그래밍
예제: 정렬(sorting) - 선택정렬 정렬 선택정렬(selection sort) 자료를 순서대로 나열하는 것 이러한 방식을 1개 자료가 남을 때까지 반복 수행 10 4 6 1 5 a[0] ~a[4]의 최소값 위치 찾은 후 a[0]와 교환 1 4 6 10 5 a[1] ~a[4]의 최소값 위치 찾은 후 a[1]와 교환 1 4 6 10 5 a[2] ~a[4]의 최소값 위치 찾은 후 a[2]와 교환 1 4 5 10 6 a[3] ~a[4]의 최소값 위치 찾은 후 a[3]와 교환 1 4 5 6 10 정렬된 결과 C 프로그래밍
예제 (계속) void select_sort(int data[ ], int n) … data : 정렬할 배열, n : 배열의크기 { int i; … 정렬되지 않은 시작 인덱스 int min_i; … 최소값의 인덱스 int j, temp; for (i = 0; i < n-1; i++) { /* data[i] ~ data[n-1]의 최소값의 인덱스 찾기 */ min_i = i; … data[i]가 최소값이라고 가정 for (j = i+1; j < n; j++) if (data[j] < data[min_i]) … data[j]가 현재 최소값보다 작으면 min_i = j; … 최소값 인덱스 변경 if (i != min_i) { … i가 최소값 인덱스가 아니면 두 위치의 자료 교환 temp = data[i]; data[i] = data[min_i]; data[min_i] = temp; } C 프로그래밍
예제 (계속) #include <stdio.h> #include <stdlib.h> … rand() 함수 사용을 위한 것 #define N 10 void select_sort(int data[ ], int n); void print_array(int s[ ], int n); … 21쪽에 정의됨 main() { int i, a[N]; for (i=0; i<N; i++) … N개의 0~999사이의 임의의 정수 생성 a[i] = rand() % 1000; print_array(a, N); … 정렬 전 출력 select_sort(a, N); … 정렬 print_array(a, N); … 정렬 후 출력 } C 프로그래밍
실습 문제 0부터 100점 사이에 분포된 성적 자료들을 입력 받아서 10점 단위로 빈도를 구하여 출력하는 프로그램을 작성 int freq[10]; … freq[k]는 10*k 점 대 성적 빈도, 100점은 90점 대에 포함 n차 다항식 의 값을 계산하는 함수를 작성하고 이 함수의 동작을 확인하는 프로그램 작성 double p(double a[ ], double x, int n); 차수 (배열의 크기는 n+1) (cf) Horner의 법칙: C 프로그래밍