본문 바로가기
Development/C

(C언어 기초) 13. 배열(2)

by eoieiie 2023. 9. 10.

문자를 저장하는 배열


메모리에 문자를 순서에 맞게 연속으로 저장하기 때문에 결국 순서를 다루는 배열은 주로 문자열을 저장하는 데 가장 많이 사용됩니다. 모든 알파벳 문자는 한 바이트로 충분히 사용될 수 있으니 char형 배열을 사용하는 것이 좋습니다. 

 

char형 배열을 선언할 때 꼭 기억해야 할 점은 저장할 문자열의 길이보다 최소한 하나 이상 크게 배열을 선언해야 한다는 것입니다. 예를 들어 문자열 "apple"을 저장할 배열은 배열 요소 개수가 최소한 6개 이상이어야 합니다. 

 

a p p l e  

 

이 여분의 공간이 필요한 이유는 널 문자(\0)를 저장하기 위해서입니다. 널 문자의 기능은 다음 예제를 통해 확인해보겠습니다. 

 

#include <stdio.h>

int main(void)
{
    char str[80] = "applejam"; //문자열 초기화

    printf("최초 문자열 : %s\n", str); // 초기화 문자열 출력
    printf("문자열 입력");
    scanf("%s", &str); //새로운 문자열 출력
    printf("입력 후 문자열 : %s\n", str); //입력된 문자열 출력

    return 0;
}


//실행 결과

최초 문자열 : applejam
문자열 입력 : grape
입력 후 문자열 : grape

 

널 문자의 용도


 초기화한 문자는 배열의 처음부터 차례로 저장되어 문자열을 만듭니다. 이때 남는 배열 요소에는 자동으로 0이 채워집니다. 이렇게 char형 배열에 저장된 0을 특별히 널 문자(null character)라고 부릅니다. 모든 문자는 아스키 값으로 저장되므로 결국 널 문자는 아스키 코드 값이 0인 문자를 말하며 문자 상수로는 \0으로 표현됩니다. 

 

a p p l e j a m \0 \0 ...

 

 아스키 코드 값이 0인 문자를 널 문자라는 이름으로 지정한 이유는, 널 문자가 문자열의 끝을 표시하는 용도로 쓰이기 때문입니다. 첫 printf가 배열의 크기와 상관없이 초기화된 문자열만을 정확히 출력하는 것도 널 문자가 있기 때문입니다. printf함수는 char형 배열에서 널 문자가 나올 때까지만 출력하도록 만들어졌습니다. 이런 규칙은 문자열을 처리하는 모든 함수에 적용됩니다. 

 

 scanf 함수로 문자열을 입력받을 때도 널 문자가 사용됩니다. scanf 함수가 배열의 처음터 grape만 입력했다면, "입력 후 문자열 : " 다음 출력 결과는 grapejam 이어야 합니다. 그러나 scanf함수는 사용자가 입력한 문자열 다음에 자동으로 널 문자를 추가해 문자열의 끝을 표시합니다. 따라서 마지막의 printf함수는 grape 까지만 출력됩니다. 

 

a p p l e j a m \0 \0
g r a p e \0 그 다음은 출력 안 됨

 

char형 배열을 선언할 때 주의할 점을 정리하고 넘어가겠습니다. 

 

  • 배열의 크기는 최대한 넉넉하게 선언해야 합니다. 나중에 다른 문자열을 저장하게 될 일이 생길지도 모르니까요. 
  • 배열 요소의 개수는 최소한 '문자열 길이 + 1'이어야 합니다. 널 문자를 저장할 공간을 지정해주어야 합니다. 

 

문자열 대입


 char형 배열이 문자열을 저장하는 변수의 역할을 하므로 초기화된 이후에도 얼마든지 새로운 문자열을 저장할 수 있습니다. 단, 문자열의 길이가 다를 수 있으므로 일반 변수처럼 대입 연산자를 사용하는 것은 불가능합니다. 이때는 strcpy함수를 사용합니다. 

 

 strcpy함수는 char형 배열에 새로운 문자열을 저장하는 함수로, 저장할 문자열의 길이를 파악해 딱 그 길이마나큼만 char형 배열에 문자열을 복사합니다. 물론 문자열 끝에 널 문자도 자동으로 붙여 줍니다. 예제를 통해 확인해보겠습니다.

 

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str1[80] = "cat";
    char str2[80];

    strcpy(str1, "tiger"); // str1배열에 문자열 "tiger" 대입
    strcpy(str2, str1); // str2배열에 str1배열에 저장된 문자열을 복사
    printf("%s, %s\n", str1, str2); // 

    return 0;

}


//실행결과

tiger, tiger

 

우리가 지금까지 못 보던 헤더 파일이 등장했습니다. sting.h는 문자열을 다루는 함수들의 원형을 모아 놓은 것으로, strcpy 함수에 접근하기 위해 사용됩니다. strcpy의 기본 사용법은 다음과 같습니다. 

 

strcpy(저장될 배열명, 저장할 문자열)

 

문자열 전용 입출력 함수 : gets, puts


char형 배열에 문자열을 대입하는 일은 strcpy 함수가 훌륭히 수행합니다. 이제 키보드로 문자열을 입력하는 문제를 생각해 보겠습니다. scanf함수는 char형 배열에 문자열을 입력할 수 있으나 중간에 빈칸이 있는 경우 빈칸 전까지만 입력합니다. 따라서 빈칸을 포함해서 문자열을 입력할 수 있는 새로운 방식이 필요합니다. 

 

gets 함수는 빈칸을 포함해 한 줄 전체를 문자열로 입력합니다. 또한 이 함수와 짝을 이루는 문자열 출력 함수 puts도 있습니다. 예제를 통해 puts와 gets함수의 사용법과 특징을 알아보겠습니다. 

 

#include <stdio.h>

int main(void)
{
    char str[80];

    printf("문자열 입력 : "); //입력 안내메시지 출력
    gets(str); //빈칸을 포함한 문자열 입력
    puts("입력된 문자열 : "); //문자열 상수 출력
    puts(str); //배열에 저장된 문자열 출력

    return 0;
}


//실행결과

문자열 입력 : love is in your eyes
입력된 문자열 :
love is in your eyes

 

gets함수의 사용법은 간단합니다. 인수로 char형 배열의 배열명을 줍니다. 

 

gets(char형 배열명)

 

gets함수는 문자열 입력 중간에 빈칸이나 탭 문자를 활용할 수 있으며, enter를 누르기 전까지 전체를 하나의 문자열로 배열에 저장합니다. 물론 마지막에 널 문자를 붙여서 문자열의 끝을 표기합니다. 

 

puts 함수는 문자열 상수나 char형 배열의 배열명을 주면 문자열을 화면에 출력합니다. printf와 기능이 같지만 문자열을 출력한 후에 자동으로 줄을 바꿔준다는 차이점이 있습니다. 경우에 따라 더 편할 수도 있지만, 문자열을 출력한 후에 바로 이어서 입력하는 것은 불가능합니다. 

 

printf("문자열 입력 : ") // 입력 안내 메시지를 출력하고 줄이 바뀌지 않음
gets(str); // 출력한 문자열 바로 앞에서 입력. 입력 후 자동으로 줄바꿈

 

문자열 처리에서 핵심 포인트를 정리해보겠습니다. 

구분 사용 예 기능
char형 배열 초기화 char str[80] = "apple"; char형 배열은 문자열로 초기화한다. 문자열의 끝에는 널 문자가 있다. 
문자열 대입 char str[80];
strcpy(str, "apple");
문자열 대입은 대입 연산자 대신 strcpy함수를 사용한다. str배열에 문자열 "apple"저장
문자열 입출력 char str[80];
scanf("%s",str);
gets(str);
printf("%s", str);
puts(str);
scanf 함수는 하나의 단어만 입력
gets 함수는 한 줄 입력

printf 함수는 문자열 출력
puts 함수는 문자열 출력 후 줄 바꿈

 

확인 문제 


다음 중 char형 배열이 바르게 초기화된 것을 고르세요.

  1. char str[80] = {'p', 'i', 'g'};
  2. char str[ ] = "elephant";
  3. char str[5] = "apple";
  4. char str[2] = {"sun", "moon"};
더보기

1 - O. 남는 배열 요소에는 자동으로 0이 채워집니다 

2 - O. 문자열 끝의 널 문자를 포함해 9개의 배열 요소를 할당합니다.

3 - X. 널 문자를 저장할 공간이 없습니다. 

4 - X. 배열의 크기가 작고, 중괄호 없이 하나의 문자열만 초기화할 수 있습니다. 

 

 

2개의 문자열을 입력받아 위치를 바꾼 후 출력하는 프로그램을 작성하세요. 

 

5개의 정수 중 최댓값과 최솟값의 위치를 출력하는 프로그램을 작성하세요. 

더보기
#include <stdio.h>
#define NUMBER 5

int main(void)
{
    int i, max, min, index1,  index2; 
    int ary1[NUMBER]; //arry[0] ~ arry[4]
    int ary2[NUMBER]; //arry[0] ~ arry[4]
    int ary[NUMBER]; //arry[0] ~ arry[4]
    max = 0;
    min = ary[0];
  

    for (i = 0; i < NUMBER; i++)
    {
        scanf("%d", &ary[i]);
        

        ary1[i] = ary[i]; 
        ary2[i] = ary[i]; 
        

        if(max <= ary1[i])
        {
            max = ary1[i]; // max에다가 최댓값 저장
            index1 = i + 1; // 위치
        }

        if(min >= ary2[i])
        {
            min = ary2[i]; // min 에다가 최솟값 저장
            index2 = i + 1; // 위치
        }

        

    }
    printf("가장 큰 값은 %d입니다.%d번째에 있습니다.\n", max, index1);
    printf("가장 작은 값은 %d입니다.%d번째에 있습니다.", min, index2);

    return 0;
}


3
6
8
4
6
가장 큰 값은 8입니다. 그리고 3번째에 있습니다.
가장 작은 값은 3입니다. 그리고 1번째에 있습니다.

 

 

5개의 정수 중 짝수인 최댓값과 홀수인 최솟값의 위치를 출력하는 프로그램을 작성하세요. 

더보기
#include <stdio.h>
#define NUMBER 5

int main(void)
{
    int i, max, min, index1,  index2; 
    int ary1[NUMBER]; //arry[0] ~ arry[4]
    int ary2[NUMBER]; //arry[0] ~ arry[4]
    int ary[NUMBER]; //arry[0] ~ arry[4]
    max = 0;
  

    for (i = 0; i < NUMBER; i++)
    {
        scanf("%d", &ary[i]);
        

        ary1[i] = ary[i]; 
        ary2[i] = ary[i]; 
        

        if(max <= ary1[i] && (int)ary1[i] % 2 == 0)
        {
            max = ary1[i]; // max에다가 최댓값 저장
            index1 = i + 1; // 위치
        }

        if((int)ary2[i] % 2 == 1) //홀수일 경우를 먼저 
        {
            if(min >= ary2[i])
            {
                min = ary2[i]; // min 에다가 최솟값 저장
                index2 = i + 1; // 위치
            }

        }

    }
    printf("가장 큰 값은 %d입니다.%d번째에 있습니다.\n", max, index1);
    printf("가장 작은 값은 %d입니다.%d번째에 있습니다.", min, index2);

    return 0;
}


//실행결과

2
3
4
55
44
가장 큰 값은 44입니다.5번째에 있습니다.
가장 작은 값은 3입니다.2번째에 있습니다.

 

 

댓글