[C] 배열

JOOYEUN SEO·2023년 8월 18일

C 언어

목록 보기
7/13
post-thumbnail

1. 배열의 선언과 초기화

배열(array)은 동일한 자료형의 값을 여러 개 저장할 수 있는 "연속적으로 할당된 공간"을 묶어 하나의 이름을 갖는 변수로 된 것이다.
배열의 각 요소는 배열명과 첨자로 구분할 수 있으며, 첨자는 대괄호([])로 나타낸다.

⌨️ 예제 1

// 배열의 선언과 초기화 방법 1 : 배열 선언 후, 각 요소에 하나씩 초깃값 할당
#include <stdio.h>

int main() {
    int a[5];   // 크기가 5인 int형 배열 a 선언
    
    a[0] = 2;   // 초기화하기
    a[1] = 3;
    a[2] = 5;
    a[3] = 9;
    a[4] = 4;   // 마지막 첨자는 "배열의 크기 - 1"

    printf("%d ", a[0]); // 배열 요소를 하나의 변수명처럼 사용 가능
    printf("%d ", a[1]);
    printf("%d ", a[2]);
    printf("%d ", a[3]);
    printf("%d\n", a[4]);
}

🖥️ 실행 결과

2 3 5 9 4

배열을 선언하면 변수의 개수만큼 연속된 기억공간을 할당받은 후 초기화한다.
이 기억공간(배열의 요소)을 변수명처럼 사용하기 위해선 배열명[첨자(배열에서의 위치)]를 사용해야 한다.
❗️배열의 첨자는 0부터 시작한다

⌨️ 예제 2

// 배열의 선언과 초기화 방법 2 : 배열 선언과 동시에 초깃값 할당
#include <stdio.h>

int main() {
    int arr[5] = {6, 7, 2, 1, 3};   // 배열 안에 순차적으로 초깃값 할당

    for(int i = 0; i <= 4; i++)     // 반복문 사용
        printf("%d ", arr[i]);
    printf("\n");
}

🖥️ 실행 결과

6 7 2 1 3 

일일히 각 요소에 초깃값을 할당하는 것은 번거로우므로, 이 방법이 주로 사용된다. 또한 모든 배열 요소는 같은 배열명을 갖고 있고 첨자가 하나씩 증가하는 규칙이 있으므로 반복문을 사용하면 깔끔하게 작성할 수 있다.


⌨️ 예제 3

// 배열 선언과 초기화가 동시에 이뤄질 경우 활용 가능한 자동 기능
#include <stdio.h>

int main() {
    // 자동 기능 1
    int arr1[] = {5, 8, 2, 3};  // 배열의 크기를 생략하면 주어지는 값의 개수에 따라 결정됨

    for(int i = 0; i < sizeof(arr1) / sizeof(int); i++) {   // sizeof 연산자 사용
        printf("%d ", arr1[i]);			// arr1의 원소 출력
    }
    printf("\n\n");
    // 자동 기능 2
    int arr2[3] = {1, 2};   // 배열 크기보다 초기화 값의 개수가 적으면 남는 공간이 0으로 채워짐
    for(int i = 0; i < 3; i++) {
        printf("arr2[%d] = %d\t", i, arr2[i]);
    }
    printf("\n");
    
    int arr3[3] = {0};      // 0만 입력하면 모든 요소의 값을 0으로 초기화할 수 있음
    for(int i = 0; i < 3; i++) {
        printf("arr3[%d] = %d\t", i, arr3[i]);
    }
    printf("\n");
}

🖥️ 실행 결과

5 8 2 3 

arr2[0] = 1     arr2[1] = 2     arr2[2] = 0
arr3[0] = 0     arr3[1] = 0     arr3[2] = 0

배열 요소의 개수를 생략한 경우, 나중에 초깃값을 계속 추가하거나 삭제할 수 있다는 장점이 있다. 그러나 반복문을 사용해서 배열의 값을 출력할 때 매번 다시 배열 요소의 개수를 세서 수정해야 하기 때문에 불편하다. 이를 보완하기 위해 반복문의 조건에 배열의 크기 대신 sizeof 연산자를 사용하면 자동으로 크기가 계산된다.

[배열 요소의 개수 = 배열 전체의 크기 ÷ 배열 요소 하나의 크기] 이기 때문에

  • 방법 1 : sizeof(배열명) ÷ sizeof(배열명[0])
  • 방법 2 : sizeof(배열명) ÷ sizeof(자료형)

둘 중 하나를 사용해 개수를 계산할 수 있다.

예제를 보면 i 값이 0부터 시작하므로 "i <= sizeof(arr1) / sizeof(int) - 1" 라고 할 수 있지만,
"i < sizeof(arr1) / sizeof(int)"로 변경하면 더 간단해진다.



⌨️ 예제 4

// 입력받은 숫자들을 거꾸로 출력하는 프로그램
#include <stdio.h>

int main() {
    int n;
    int arr[100];                       // 배열의 크기를 미리 넉넉하게 지정
    
    printf("입력할 숫자의 개수 입력 : ");
    scanf("%d", &n);                    // 100을 넘지 않는 임의의 숫자 입력

    for(int i = 0; i < n; i++) {        // 배열 앞에서부터 값 채우기
        scanf("%d", &arr[i]);
    }
    for(int i = n - 1; i >= 0; i--) {   // 배열 맨 뒤에서부터 앞까지 값을 거꾸로 출력
        printf("%d ", arr[i]);
    }
    printf("\n");
}

🖥️ 실행 결과

입력할 숫자의 개수 입력 : 4  [Enter↵]
1 5 9 2  [Enter↵]
2 9 5 1 

⌨️ 예제 5

// 입력받은 숫자들의 최대값, 최소값을 구하는 프로그램
#include <stdio.h>

int main() {
    int n;
    int arr[100];
    
    printf("입력할 숫자의 개수 입력 : ");
    scanf("%d", &n);

    for(int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    // 최대값 구하기
    int max = arr[0];           // 배열 맨 첫번째부터 최대값으로 지정
    for(int i = 1; i < n; i++) {
        if(max < arr[i]) {      // 이전까지 최대값이었던 숫자와 그 다음 숫자를 비교
            max = arr[i];       // 둘 중 더 큰 값이 최대값이 됨
        }   
    }
    printf("가장 큰 숫자는 %d\n", max);

    // 최소값 구하기
    int min = arr[0];
    for(int i = 1; i < n; i++) {
        if(min > arr[i]) {
            min = arr[i];
        }
    }
    printf("가장 작은 숫자는 %d\n", min);
}

🖥️ 실행 결과

입력할 숫자의 개수 입력 : 5  [Enter↵]
2 45 7 1 34  [Enter↵]
가장 큰 숫자는 45
가장 작은 숫자는 1

⌨️ 예제 6

// 입력받은 숫자들 중 짝수의 개수를 알려주는 프로그램
#include <stdio.h>

int main() {
    int n;
    int arr[100];
    
    printf("입력할 숫자의 개수 입력 : ");
    scanf("%d", &n);

    for(int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    int cnt = 0;        // 카운트 횟수를 0에서부터 시작
    for(int i = 0; i < n; i++) {
        if(arr[i] % 2 == 0) {
            cnt++;      // 짝수일 때만 카운트에 1 추가
        }
    }
    printf("짝수는 총 %d개\n", cnt);
}

🖥️ 실행 결과

입력할 숫자의 개수 입력 : 6  [Enter↵]
23 9 36 82 44 7  [Enter↵]
짝수는 총 3개

⌨️ 예제 7

/* 100개 이하의 정수들을 입력하면
첫 줄에 짝수 번째 숫자들을 순서대로 출력하고,
다음 줄에 홀수 번째 숫자들을 순서대로 출력하는 프로그램 */
#include <stdio.h>

int main() {
    int n;          // 입력될 숫자의 개수를 저장할 변수
    int arr[105];   // 문제에서 지정한 100개보다 좀 더 넉넉한 숫자 사용 추천

    printf("입력할 숫자의 개수 입력 : ");
    scanf("%d", &n);

    for(int i = 0; i < n; i++) {
        scanf("%d", &arr[i]);           // 배열에 숫자를 하나씩 입력
    }
    for(int i = 1; i < n; i += 2) {     // 짝수 번째 숫자 출력
        printf("%d ", arr[i]);
    }
    printf("\n");
    for(int i = 0; i < n; i += 2) {     // 홀수 번째 숫자 출력
        printf("%d ", arr[i]);
    } 
    printf("\n");
}

🖥️ 실행 결과

입력할 숫자의 개수 입력 : 6  [Enter↵]
8 4 1 7 16 3  [Enter↵]
4 7 3
8 1 16

2. 2차원 배열

1차원 배열 : 첨자가 하나만 있는 배열로, 1개의 열로만 구성되어 있다.
2차원 배열 : 2개의 첨자를 가지며, 표처럼 행과 열로 구성되어 있다. (1차원)배열의 (1차원)배열이라고도 부른다.
3차원 배열 : 3개의 첨자를 가지며, 면, 행, 그리고 열로 구성되어 있다. 3차원 부터는 실무에서 거의 쓰이지 않는다.

⌨️ 예제 8

// 2차원 배열 선언과 초기화
#include <stdio.h>

int main() {
    // 방법 1
    int arr1[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    // 방법 2
    int arr2[3][4] = {
        {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}
    };
    // 방법 3(가장 가독성이 좋음)
    int arr3[3][4] = {
        {1, 2, 3, 4},       // 0행
        {5, 6, 7, 8},       // 1행
        {9, 10, 11, 12}     // 2행
    };
    // 방법 3의 모양대로 출력하기
    for(int i = 0; i < 3; i++) {        // 3개의 행
        for(int j = 0; j < 4; j++) {    // 4개의 열
            printf("%d ", arr3[i][j]);
        }
        printf("\n");
    }
}

🖥️ 실행 결과

1 2 3 4 
5 6 7 8 
9 10 11 12 

⌨️ 예제 9

// 파스칼의 삼각형을 왼쪽 정렬해서 출력하는 프로그램
#include <stdio.h>

int main() {
    int p[8][8];

    for(int i = 0; i < 8; i++) {
        for(int j = 0; j <= i; j++) {
            if(j == 0 || j == i) {
                p[i][j] = 1;
            }
            else {
                p[i][j] = p[i - 1][j - 1] + p[i - 1][j];
            }
            printf("%d ", p[i][j]);
        }
        printf("\n");
    }
}

🖥️ 실행 결과

1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
1 5 10 10 5 1 
1 6 15 20 15 6 1 
1 7 21 35 35 21 7 1 


⌨️ 예제 10

/* 10 × 10 이하의 정수형 이차원 배열을 입력받으면,
그 배열의 각 행마다 요소들의 합을 출력하는 프로그램 */
#include <stdio.h>

int main() {
    int row, col;
    int arr[12][12];

    printf("이차원 배열의 행과 열 개수를 차례로 입력 : ");
    scanf("%d%d", &row, &col);

    for(int i = 0; i < row; i++) {
        for(int j = 0; j < col; j++) {
            scanf("%d", &arr[i][j]);
        }
    }    
    for(int i = 0; i < row; i++) {
        int rowSum = 0;
        for(int j = 0; j < col; j++) {
            rowSum += arr[i][j];
        }
        printf("%d\n", rowSum);
    }
}

🖥️ 실행 결과

이차원 배열의 행과 열 개수를 차례로 입력 : 3 4  [Enter↵]
3 8 4 6  [Enter↵]
1 2 0 9  [Enter↵]
3 5 2 1  [Enter↵]
21
12
11

3. 문자열

C 언어에서는 문자열(string)에 대한 자료형이 없다. 대신 문자열은 문자들의 열거이므로, char형 배열로 문자열을 처리할 수 있다.

⌨️ 예제 11

// char형 배열의 선언과 초기화
#include <stdio.h>

int main() {
    // 방법 1 : 문자열 단위로 초기화
    char arr1[] = "Hello, world!";
    printf("%s\n", arr1);    	// %s를 사용하여 문자열 전체를 한번에 출력 가능
    printf("배열의 크기 : %d\n", sizeof(arr1) / sizeof(char));
    
    // 방법 2 : 문자 단위로 초기화(이 때는 뒤에 \0을 직접 삽입해야 함)
    char arr2[] = {'S', 'e', 'o', 'u', 'l', '\0'};
    printf("%s\n", arr2);
    printf("배열의 크기 : %d\n", sizeof(arr2) / sizeof(char));
}

🖥️ 실행 결과

Hello, world!
배열의 크기 : 14
Seoul
배열의 크기 : 6

"Hello, world!"는 실제로 {'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\0'} 로 저장된다. 마지막 부분에 자동으로 삽입된 \0은 null 문자로, 문자열의 끝을 알려주는 역할을 한다. 때문에 문자열의 크기가 13이 아닌 14가 된다.


⌨️ 예제 12

// 문자열을 입력받을 시 주의할 점
#include <stdio.h>

int main() {
    char s[100];    // 입력되는 문자열을 모두 저장할 수 있는 넉넉한 크기로 배열 선언
    scanf("%s", s); // 배열명 앞에는 기호 &을 붙이지 않음!
    printf("%s\n", s);
}

🖥️ 실행 결과

문자열  [Enter↵]
문자열

문자열을 scanf 함수로 입력할 때 중간에 빈칸, 탭, 엔터 등으로 공백을 넣으면, 공백 이전까지만 입력이 된다. 왜냐하면 scanf 함수에서는 입력 데이터의 구분을 공백 문자로 하기 때문이다.

문자열  입력하기  [Enter↵]
문자열

만약 이런 식으로 중간을 띄우면, 공백 앞의 "문자열"만 출력된다. 이를 해결하기 위해선 scanf 대신 문자열만 전용으로 입력받는 입력 함수를 사용해야 한다.
참고 : [C] 표준입출력함수


(1) 문자열 처리 함수

<string.h> : 문자열을 처리하는 함수가 정의된 헤더 파일

strlen(배열1)
배열1의 문자열의 길이를 반환하는 함수(null 문자 미포함)
리턴값이 항상 양수이므로 unsigned int형이 가장 적합하다.

strcpy(배열1, 배열2)
배열2의 문자열을 복사해서 배열1에 붙여넣는 함수(null 문자 포함)
strcpy 함수를 이용하면 일반 변수의 값을 교환하는 것과 같은 원리로 두 개의 문자열을 교환할 수 있다(임시 배열을 생성한 후 문자열을 옮기면서 바꿈).

strcat(배열1, "문자열" 또는 배열2)
배열1에 다른 문자열 또는 배열2를 이어서 붙이는 함수
이 때 배열1은 이어붙여질 문자열이나 배열도 함께 저장될 수 있을 만큼 넉넉하게 길어야 한다.

strcmp(배열1, 배열2)
두 배열의 문자열을 사전순으로 비교하는 함수(대소문자 구분)
strcmp 함수의 반환값의 의미는 다음과 같다.

  • 반환값이 0 : 두 문자열은 같음
  • 반환값이 양수 : 앞의 문자열이 뒤의 문자열보다 사전순으로 뒤에 위치
  • 반환값이 음수 : 앞의 문자열이 뒤의 문자열보다 사전순으로 앞에 위치

⌨️ 예제 13

#include <stdio.h>
#include <string.h> // 헤더 파일 포함

int main() {
    char str1[] = "Hello, ";
    int len;
    len = strlen(str1);
    printf("문자열의 길이는 %d\n\n", len);

    char str2[100];
    strcpy(str2, str1);  // str1의 문자열을 str2로 복사
    printf("str2의 값 : %s\n\n", str2);

    strcat(str2, "world!"); // str2의 문자열 뒤에 다른 문자열을 이어붙임
    printf("str2의 새로운 값 : %s\n\n", str2);

    char str3[] = "sample";
    char str4[] = "simple";
    int cmp = strcmp(str3, str4);   // str3과 str4의 두 문자열 비교
    printf("%d\n", cmp);
}

🖥️ 실행 결과

문자열의 길이는 7

str2의 값 : Hello, 

str2의 새로운 값 : Hello, world!

-8

strcmp 함수에서 "sample"과 "simple"의 1번째 문자 's'는 동일하므로 그 다음 'i'와 'a'를 비교하게 된다. ASCII 코드 값으로 'i'는 105이고 'a'는 97이므로 두 문자는 8만큼 차이가 나서 -8이라는 결과가 나왔다.




▷ 김형근·곽덕훈·정재화, 『C프로그래밍』, 한국방송통신대학교출판문화원, 2020
▷ 서현우, 『뇌를 자극하는 C 프로그래밍』, 한빛미디어, 2005
▷ 두들낙서, “두들낙서의 C/C++ 강좌”, https://youtube.com/playlist?list=PLlJhQXcLQBJqywc5dweQ75GBRubzPxhAk&si=s8RNpRcpJTi_Lz8M

2개의 댓글

comment-user-thumbnail
2023년 8월 18일

많은 것을 배웠습니다, 감사합니다.

1개의 답글