쉽게 풀어쓴 C언어 Express 제10장 배열 C Express
배열을 사용하면 한 번에 여러 개의 값을 저장할 수 있는 공간을 할당받을 수 있다. 이번 장에서 학습할 내용 배열을 사용하면 한 번에 여러 개의 값을 저장할 수 있는 공간을 할당받을 수 있다. 배열의 개념 배열의 선언과 초기화 일차원 배열 다차원 배열
배열의 필요성 학생이 10명 있고 성적의 평균을 계산할 경우 방법 #1 : 개별 변수 사용 int s0; int s1; … 개별변수를 사용하는 방법은 학생수가 많아지면 번거로워집니다. 방법 #1 : 개별 변수 사용 int s0; int s1; … int s9; 방법 #2 : 배열 사용 int s[10];
배열이란? 배열(array): 동일한 타입의 데이터를 여러 개 저장할 수 있는 데이터 저장 장소 배열 안에 들어있는 데이터는 정수형의 번호(첨자)를 사용하여 접근 배열을 이용하면 여러 개의 값을 하나의 이름으로 처리 가능
배열 원소와 인덱스 인덱스(index): 배열 원소의 번호 (첨자) 첨자 또는 인덱스
배열의 선언 자료형: 배열 원소들이 int형 배열 이름: 배열을 사용할 때 이름이 grade 배열 크기: 배열 원소 수가 10개 인덱스는 0부터 시작 int score[60]; // 60개의 int형 값을 가지는 배열 score float cost[12]; // 12개의 float형 값을 가지는 배열 cost char name[50]; // 50개의 char형 값을 가지는 배열 name char src[10], dst[10]; // 2개의 문자형 배열을 동시에 선언 int index, days[7]; // 일반 변수와 배열을 동시에 선언
배열 원소 접근 grade[5] = 80 grade[5] = 80; grade[1] = grade[0]; grade[0] grade[1] grade[2] grade[3] grade[4] grade[5] grade[6] grade[7] grade[8] grade[9] 80 grade[5] = 80 grade[5] = 80; grade[1] = grade[0]; grade[i] = 100; // i는 정수 변수 grade[i + 2] = 100; // 인덱스가 수식 grade[index[3]] = 100; // index는 정수 배열
배열 선언 예제 #include <stdio.h> grade[0] = 10 grade[1] = 20 int main(void) { int i; int grade[5]; grade[0] = 10; grade[1] = 20; grade[2] = 30; grade[3] = 40; grade[4] = 50; for (i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 10 grade[1] = 20 grade[2] = 30 grade[3] = 40 grade[4] = 50
배열과 반복문 배열은 반복문을 사용하여 간편하게 처리 가능 #define SIZE 5 ... grade[0] = 0; int grade [SIZE]; for (i = 0; i < SIZE; i++) grade[i] = 0; grade[0] = 0; grade[1] = 0; grade[2] = 0; grade[3] = 0; grade[4] = 0;
배열 사용 예제 #include <stdio.h> #include <stdlib.h> #define SIZE 5 int main(void) { int i; int grade[SIZE]; for (i = 0; i < SIZE; i++) grade[i] = rand() % 100; printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 41 grade[1] = 67 grade[2] = 34 grade[3] = 0 grade[4] = 69
배열 입력 예제 #include <stdio.h> #define SIZE 5 int main(void) { int i, grade[SIZE]; printf("5명의 점수를 입력하시오\n"); for (i = 0; i < SIZE; i++) scanf("%d", &grade[i]); printf("grade[%d]=%d\n", i, grade[i]); return 0; } 5명의 점수를 입력하시오 23 35 67 45 21 grade[0]=23 grade[1]=35 grade[2]=67 grade[3]=45 grade[4]=21
배열 사용 예제 #include <stdio.h> #define STUDENTS 5 int main() { int grade[STUDENTS]; int sum = 0, i, average; for (i = 0; i < STUDENTS; i++) { printf("학생들의 성적을 입력하시오: "); scanf("%d", &grade[i]); } for (i = 0; i < STUDENTS; i++) sum += grade[i]; average = sum / STUDENTS; printf("성적 평균= %d\n", average); return 0; 학생들의 성적을 입력하시오: 10 학생들의 성적을 입력하시오: 20 학생들의 성적을 입력하시오: 30 학생들의 성적을 입력하시오: 40 학생들의 성적을 입력하시오: 50 성적 평균 = 30
잘못된 인덱스 문제 인덱스가 배열의 범위를 벗어나게 되면 치명적인 오류 발생 int grade[5]; …
배열의 초기화 int grade[5] = { 10, 20, 30, 40, 50 }; grade[0] grade[1] grade[2] grade[3] grade[4] 50 40 30 20 10 초깃값을 일부만 주면 나머지 원소들은 0으로 초기화됩니다. grade[0] grade[1] grade[2] grade[3] grade[4] 10 20 30
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] = { 31, 63, 62, 87, 14 }; int i; for (i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 31 grade[1] = 63 grade[2] = 62 grade[3] = 87 grade[4] = 14
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] = { 31, 63 }; int i; for (i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0] = 31 grade[1] = 63 grade[2] = 0 grade[3] = 0 grade[4] = 0
배열 초기화 예제 #include <stdio.h> int main(void) { int grade[5] ; int i; for (i = 0; i < 5; i++) printf("grade[%d] = %d\n", i, grade[i]); return 0; } grade[0]=4206620 grade[1]=0 grade[2]=4206636 grade[3]=2018779649 grade[4]=1
배열의 초기화: 크기 생략 배열의 크기를 생략하면 배열의 크기는 초깃값의 개수 10 20 30 40 50 60 6 int grade[ ] = { 10 , 20 , 30 , 40 , 50 , 60 };
배열의 크기 계산 int grade[ ] = { 1, 2, 3, 4, 5, 6 }; int i, size; size = sizeof grade / sizeof grade[0]; for (i = 0; i < size; i++) printf("%d ", grade[i]); 배열 원소 개수 자동 계산
배열의 복사 int grade[SIZE]; int score[SIZE]; score = grade; // 컴파일 오류! 잘못된 방법 #include <stdio.h> #define SIZE 5 int main(void) { int i; int a[SIZE] = { 1, 2, 3, 4, 5 }; int b[SIZE]; for (i = 0; i < SIZE; i++) b[i] = a[i]; return 0; } 올바른 방법 원소를 하나씩 복사
배열의 비교 #include <stdio.h> #define SIZE 5 int main(void) { int i; int a[SIZE] = { 1, 2, 3, 4, 5 }; int b[SIZE] = { 1, 2, 3, 4, 5 }; if (a == b) // ① 올바르지 않은 배열 비교 printf("잘못된 결과입니다.\n"); else for (i = 0; i < SIZE; i++) // ② 올바른 배열 비교 if (a[i] != b[i]) { printf("a와 b는 같지 않습니다.\n"); return 0; } printf("a와 b는 같습니다.\n"); return 0; } 원소를 하나씩 비교
최솟값 찾기 #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10 int main(void) { int prices[SIZE]; int i, minimum; printf("--------------------------------------\n"); printf(" 1 2 3 4 5 6 7 8 9 10\n"); srand(time(NULL)); for (i = 0; i < SIZE; i++) { prices[i] = rand() % 100 + 1; printf("%-3d ", prices[i]); } printf("\n\n"); 첫 번째 원소를 최솟값 minimum이라고 가정 for (i = 1; i < 배열의 크기; i++) if (prices[i] < minimum) minimum = prices[i] 반복이 종료되면 minimum에 최솟값이 저장됨
최솟값 찾기 minimum = prices[0]; for (i = 1; i < SIZE; i++) if (prices[i] < minimum) minimum = prices[i]; printf("최솟값은 %d입니다.\n", minimum); return 0; } -------------------------------------- 1 2 3 4 5 6 7 8 9 10 44 24 78 51 20 90 74 76 99 82 최솟값은 20입니다.
빈도 계산: 투표 집계 #include <stdio.h> #define SIZE 11 int main(void) { int freq[SIZE] = { 0 }; // 빈도 저장 배열 int i, candidate; while (1) { printf("후보자 선택(1~%d): ", SIZE - 1); scanf("%d", &candidate); if (candidate <= 0 || candidate >= SIZE) break; freq[candidate]++; } printf(" 값 득표수\n"); for (i = 1; i < SIZE; i++) printf("%3d %3d \n", i, freq[i]); return 0; 후보자 선택(1~10): 1 후보자 선택(1~10): 2 후보자 선택(1~10): -1 값 득표수 1 2 2 1 3 0 4 0 5 0 6 0 7 0 8 0 9 0 10 0
배열 역순 출력 #include <stdio.h> #define SIZE 5 int main(void) { int data[SIZE]; int i; for (i = 0; i < SIZE; i++) { printf("정수를 입력하시오: "); scanf("%d", &data[i]); } // 역순 출력 루프 for (i = SIZE - 1; i >= 0; i--) printf("%d\n", data[i]); return 0; } 정수를 입력하시오: 10 정수를 입력하시오: 20 정수를 입력하시오: 30 정수를 입력하시오: 40 정수를 입력하시오: 50 50 40 30 20 10
막대 그래프 #include <stdio.h> #define STUDENTS 5 int main(void) { int grade[STUDENTS] = { 30, 20, 10, 40, 50 }; int i, s; for (i = 0; i < STUDENTS; i++) { printf("번호 %d: ", i); for (s = 0; s < grade[i]; s++) printf("*"); printf("\n"); } return 0; } 번호 0: ****************************** 번호 1: ******************** 번호 2: ********** 번호 3: **************************************** 번호 4: **************************************************
주사위 면의 빈도 계산 #include <stdio.h> #include <stdlib.h> #define SIZE 6 int main(void) { int i, freq[SIZE] = { 0 }; // 주사위 면의 빈도를 0으로 초기화 for (i = 0; i < 10000; i++) // 주사위를 10000번 굴림 ++freq[rand() % 6]; // 해당 면의 빈도 증가 printf("====================\n"); printf(" 면 빈도\n"); for (i = 0; i < SIZE; i++) printf("%3d %5d \n", i + 1, freq[i]); return 0; } ==================== 면 빈도 1 1657 2 1679 3 1656 4 1694 5 1652 6 1662
배열과 함수 인자 전달에서 배열은 사본이 아닌 원본이 전달됨 #include <stdio.h> #define STUDENTS 5 int get_average(int score[ ], int n); int main(void) { int grade[STUDENTS] = { 1, 2, 3, 4, 5 }; int avg; avg = get_average(grade, STUDENTS); printf("평균은 %d입니다.\n", avg); return 0; } int get_average(int score[ ], int n) int i, sum = 0; for (i = 0; i < n; i++) sum += score[i]; return sum / n; 인자 전달에서 배열은 사본이 아닌 원본이 전달됨 배열의 원본이 score로 전달됨
배열 인자 #include <stdio.h> #define SIZE 7 void square_array(int a[ ], int size); void print_array(int a[ ], int size); int main(void) { int list[SIZE] = { 1, 2, 3, 4, 5, 6, 7 }; print_array(list, SIZE); square_array(list, SIZE); print_array(list, SIZE); return 0; } void square_array(int a[ ], int size) { int i; for (i = 0; i < size; i++) a[i] = a[i] * a[i]; } void print_array(int a[ ], int size) { printf("%3d ", a[i]); printf("\n"); 1 2 3 4 5 6 7 1 4 9 16 25 36 49
원본 배열의 변경을 금지하는 방법 void print_array(const int a[], int size) { ... a[0] = 100; // 컴파일 오류 -- a를 변경할 수 없음 }
선택정렬(selection sort) 정렬이 안 된 구간에서 최솟값/최댓값을 선택하여 배열의 첫 번째 원소와 교환
선택 정렬 #include <stdio.h> #define SIZE 10 int main(void) { int list[SIZE] = { 3, 2, 9, 7, 1, 4, 8, 0, 6, 5 }; int i, j, temp, least; for (i = 0; i < SIZE - 1; i++) { least = i; for (j = i + 1; j < SIZE; j++) if (list[j] < list[least]) least = j; temp = list[i]; list[i] = list[least]; list[least] = temp; } for (i = 0;i < SIZE; i++) printf("%d ", list[i]); printf("\n"); return 0; 0 1 2 3 4 5 6 7 8 9
순차 탐색 배열의 원소를 순서대로 탐색키와 비교 #include <stdio.h> #define SIZE 10 int main(void) { int key, i; int list[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; printf("탐색할 값을 입력하시오: "); scanf("%d", &key); for (i = 0; i < SIZE; i++) if (list[i] == key) printf("탐색 성공 인덱스 = %d\n", i); printf("탐색 종료\n"); return 0; } 배열의 원소를 순서대로 탐색키와 비교 탐색할 값을 입력하시오: 7 탐색 성공 인덱스 = 6 탐색 종료
이진 탐색(binary search) 정렬된 배열에서 구간의 중앙에 위치한 원소와 비교
이진 탐색 #include <stdio.h> int binary_search(int list[], int n, int key); int main(void) { int grade[] = { 2,6,11,13,18,20,22,27,29,30,34,38,41,42,45,47 }; int key, size = sizeof grade / sizeof grade[0]; printf("탐색할 값을 입력하시오: "); scanf("%d", &key); printf("탐색 결과 = %d\n", binary_search(grade, size, key)); return 0; }
이진 탐색 int binary_search(int list[], int n, int key) { int low = 0, high = n - 1, middle; while (low <= high) { printf("[%d %d]\n", low, high); // 테스트용으로 구간 출력 middle = (low + high) / 2; // 중간 위치 계산 if (key == list[middle]) // 탐색 성공 return middle; else if (key > list[middle]) // 중간 원소보다 크면 low = middle + 1; // 새로운 값으로 low 설정 else // 중간 원소보다 작으면 high = middle - 1; // 새로운 값으로 high 설정 } return -1; // 탐색 실패 탐색할 값을 입력하시오: 34 [0 15] [8 15] [8 10] [10 10] 탐색 결과 = 10
다차원 배열 int s[10]; // 1차원 배열 int s[3][5]; // 2차원 배열
2차원 배열 #include <stdio.h> int main(void) { int s[3][5]; int i, j; int value = 0; for (i = 0; i < 3; i++) for (j = 0; j < 5; j++) s[i][j] = value++; printf("%d\n", s[i][j]); return 0; } 1 2 3 ... 13 14
다차원 배열의 초기화 int s[3][5] = { { 0, 1, 2, 3, 4 }, { 10, 11, 12, 13, 14 }, { 0, 1, 2, 3, 4 }, { 10, 11, 12, 13, 14 }, { 20, 21, 22, 23, 24 } }; int s[ ][5] = { { 0, 1, 2, 3, 4 }, { 10, 11, 12, 13, 14 }, { 20, 21, 22, 23, 24 } }; int s[ ][5] = { { 0, 1, 2 }, { 10, 11, 12 }, { 20, 21, 22 } };
다차원 배열의 초기화 3 4 3 4 a a int a[2][3] = { { 1, 2 }, { 3, 4 } }; 1 2 3 4 a 1 2 3 4
3차원 배열 #include <stdio.h> int main(void) { int s[6][3][5]; int x, y, z; int i = 1; for (z = 0; z < 6; z++) for (y = 0; y < 3; y++) for (x = 0; x < 5; x++) s[z][y][x] = i++; return 0; }
다차원 배열 인자 #include <stdio.h> #define YEARS 3 #define PRODUCTS 5 int sum(int sales[ ][PRODUCTS]); int main(void) { int sales[YEARS][PRODUCTS] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; int total_sale = sum(sales); printf("총매출은 %d입니다.\n", total_sale); return 0; } int sum(int sales[ ][PRODUCTS]) { int y, p, total = 0; for (y = 0; y < YEARS; y++) for (p = 0; p < PRODUCTS; p++) total += sales[y][p]; return total; 총매출은 45입니다.
다차원 배열 예제 #include <stdio.h> #define CLASSES 3 #define STUDENTS 5 int main(void) { int s[CLASSES][STUDENTS] = { { 0, 1, 2, 3, 4 }, { 10, 11, 12, 13, 14 }, { 20, 21, 22, 23, 24 }, }; int clas, student, subtotal, total = 0; for (clas = 0; clas < CLASSES; clas++) { subtotal = 0; for (student = 0; student < STUDENTS; student++) subtotal += s[clas][student]; printf("학급 %d의 평균 성적 = %d\n", clas, subtotal / STUDENTS); total += subtotal; } printf("전체 학생들의 평균 성적 = %d\n", total / (CLASSES * STUDENTS)); return 0; } 학급 0의 평균 성적 = 2 학급 1의 평균 성적 = 12 학급 2의 평균 성적 = 22 전체 학생들의 평균 성적 = 12
행렬(matrix) #include <stdio.h> #define ROWS 3 #define COLS 3 int main(void) { int A[ROWS][COLS] = { { 2, 3, 0 }, { 8, 9, 1 }, { 7, 0, 5 } }; int B[ROWS][COLS] = { { 1, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 } int C[ROWS][COLS]; int r,c; // C = A + B for (r = 0; r < ROWS; r++) for (c = 0; c < COLS; c++) C[r][c] = A[r][c] + B[r][c]; for (r = 0; r < ROWS; r++) { printf("%d ", C[r][c]); printf("\n"); } return 0; } 3 3 0 9 9 1 8 0 5