[C] 혼공단_5주차_Chapter 08

Haeun Noh·2022년 8월 12일
0

0811


5주차 미션

기본 미션 : 직접 정리한 키워드 공유하기

선택 미션 : 널 문자의 정의, 용도와 표기법 공유하기

세상에 왜 벌써 방학이 일주일도 남지 않은거지..? 무사히 MOS 파워포인트도 합격을 하고 나니 혼공단 방학이 쥐도 새도 모르게 끝나버렸다.
Java도 그렇고 C언어도 그렇고 아직 프로그래밍을 몰라도 한참 모르는 나에게는 다 너무나도 어려운 것 같다... 그래도 하나하나 배우면서 얻는 재미와 성취감덕분에 쉬이 포기를 하지 않는 것 같기도 하다.
이번 Chapter 8에서는 C언어 선생님께서 우리에게 어렵다고 어렵다고 겁을 주셨던 배열을 드디어 배우게 되었다. 부모님은 내게 배열을 배우면 훨씬 코드를 다양하게 짤 수 있다고 해주셨다. 확실하게 더 성장할 수 있다는 기대와 어려울 것이라는 두려움을 가득 안고 정리를 시작해보겠다.



직접 정리한 키워드 공유하기

저번 4주차에서도 함수의 유형을 정리하여 공유하는 미션이 나왔었다. 이번에도 비슷한 미션인 것 같기도 하고, 아예 처음 배우는 내용이기 때문에 기억에 훨씬 잘 남기 위해서 Chapter 8을 전체적으로 정리해보는 시간을 갖도록 하겠다.


배열(Array)이란?

: 같은 형태의 많은 데이터를 반복문으로 처리하기 위해서 메모리에 연속적으로 저장해놓고 쪼개서 사용하는 방법
: 연관된 데이터를 모아서 관리하기 위해서 사용되는 데이터 타입

변수가 하나의 데이터를 저장하기 위한 것이라면 배열은 여러 개의 데이터를 저장하기 위한 것이라고 할 수 있다.


배열의 선언

기존에는 int형 변수, double형 변수등을 사용하기 위해서는 하나씩 선언해야 했다. 하지만 배열에서는 한 번에 변수를 여러 개 선언할 수 있는 장점이 있어서, 하나의 이름으로 한꺼번에 선언하여 저장공간을 확보할 수 있게 되었다.

배열의 선언은 원래 우리가 선언하던 방식과 거의 유사하다. 원래 방식에 요소 개수가 포함된다는 것이 조금 다를 뿐이다. 배열의 선언은 다음과 같다.

int ary[5];

위의 예시에서 각각 int자료형, ary배열명, [5]요소(element) 개수를 나타낸다.

✏️8-1 직접 해보는 손코딩_5명의 나이를 저장할 배열을 선언하고 사용하는 방법

소스코드 예제8-1.c

#include <stdio.h>

int main(void) {
	int ary[5];		//int형 요소 5개의 배열 선언
    
    ary[0] = 10;	//첫 번째 배열 요소에 10 대입
    ary[1] = 20;	//두 번째 배열 요소에 20 대입
    ary[2] = ary[0] + ary[1];	//첫 번째와 두 번째 요소를 더해 세 번째 요소에 저장
    scanf("%d", &ary[3]);		//키보드로 입력받아 네 번째 요소에 저장
    
    printf("%d\n", ary[2]);		//세 번째 배열 요소 출력
    printf("%d\n", ary[3]);		//네 번째 배열 요소 출력
    printf("%d\n", ary[4]);		//다섯 번째 배열 요소 출력, 이 요소 값은 쓰레기 값
    
    return 0;
}
    
실행결과

50
30
50
-858993460

배열을 사용하는 것과 변수를 사용하는 것의 전체 공간의 크기는 동일하다. 하지만 변수각각의 공간에 이름을 지정하고, 배열메모리에 연속된 공간이 할당되며, 하나의 이름을 사용한다는 차이점이 있다.

int a,b,c,d,e;	//개별 변수로 선언
int array[5];	//배열로 선언

배열의 나누어진 조각, [ ]안에 있는 수를 배열 요소(element)라고 한다.
배열은 각 저장 공간을 이름첨자(index)로 구분하고 첨자0부터 시작한다. int ary[2];에서 배열 요소가 두 번째 배열 요소가 아니라 세 번째 배열 요소라는 점을 명심하라.

ary[2]

위의 예시에서 ary이름, 즉 배열명이고, [2]첨자(index)이다.


배열의 사용

이제 배열을 선언할 수 있으니 배열을 사용해보도록 하자.

앞에서 우리는 [ ] (대괄호)안에 숫자를 넣었고, 이 숫자는 배열 요소의 전체 갯수를 뜻한다고 배웠다. 하지만 배열을 사용할 때에는 [ ]안의 숫자의 의미가 달라진다.

배열 선언에서는 [ ]안의 숫자가 배열 요소의 전체 갯수를 의미하지만, 배열 사용에서는 [ ]안의 숫자가 각 요소가 배열에서 몇 번째에 있는지를 의미하는 배열에서의 위치(첨자)를 의미하게 된다.

배열을 선언할 때 
int ary[5];		// 배열 요소의 개수 : 5개
배열 요소를 사용할 때
ary[0] = 10;	// 배열에서의 위치(첨자) : 첫 번째 배열 요소

이러한 차이점을 분명히 알고 넘어가도록 하자.


배열 요소는 값을 대입하거나 연산할 때 마치 하나의 변수처럼 사용한다.

int ary[4];			// 배열 선언

ary[0] = 10;		// 배열 사용
ary[1] = 20;
ary[2] = ary[0] + ary[1];

위와 같은 코드를 보고 우리는 배열에 다음과 같은 값이 저장되어 있다고 예상할 수 있다.

ary[0]ary[1]ary[2]ary[3]
102030

이제 위에서 대입한 값들을 출력해보도록 하자.

printf("%d\n", ary[1]);		
printf("%d\n", ary[2]);	
printf("%d\n", ary[3]);	

이렇게 출력하게 되면 ary[3]을 출력한 값이 요상하게 나오게 되는데 이것은 위의 표에서도 보았다시피 저장된 값이 없으므로 쓰레기 값이 출력되게 되는 것이다.


💡여기서 잠깐_배열의 첨자가 사용 범위를 벗어난다면?

만약 int ary[5];를 선언했는데 ary[5]를 사용하게 되면 어떨까?
요소가 5개뿐인데 여섯 번째의 요소를 사용한다는 것은 말도 안 되는 일이다.

이 경우에는 컴파일러가 경고 메시지로 알려주기도 하지만 확실한 에러 메시지를 표시하지는 않는다. 이렇게 범위를 벗어난 영역에 접근하는 배열코드는 실행 단계에서 문제를 일으킬 때나 발견할 수 있기 때문에 버그를 찾아내기가 쉽지 않다. 따라서 사용 범위를 벗어나지 않도록 주의해주는 수 밖에 없다.
꼭 주의하도록 하자.


배열 초기화

우리가 변수를 사용하려면 초기화를 했어야 하는 것처럼 배열을 사용하기 위해서도 초기화가 꼭 필요하다. 배열에서는 선언과 동시에 { }로 묶어서 초기화를 한다.

다양한 초기화의 형태에 대해서 알아보도록 하자

1. 기본적인 초기화 방법

int ary[5] = {1,2,3,4,5};

초깃값은 첫 번째 요소부터 차례로 초기화된다.

ary1[0]ary1[1]ary1[2]ary1[3]ary1[4]
12345

2. 초깃값이 배열 요소의 개수보다 적은 경우

int ary2[5] = {1,2,3};

왼쪽부터 차례로 초기화하고 남은 배열 요소는 모두 0으로 채운다.

ary2[0]ary2[1]ary2[2]ary2[3]ary2[4]
12300

3. 자동 초기화 기능

int ary2[1000] = {0};

자동 초기화 기능을 사용하면 배열 요소의 개수가 아무리 많아도 모든 요소를 쉽게 0으로 초기화할 수 있다.

ary2[0]ary2[1]ary2[2]...ary2[1000]
000...0

4. 배열 요소 개수가 생략된 형태

int ary3[] = {1,2,3};

이 경우, 컴파일러는 초깃값 개수만큼 배열 요소 개수를 정하고 저장 공간을 할당한다. 즉, ary3은 다음과 같이 메모리에 저장 공간이 할당되고 초기화된다.

ary3[0]ary3[1]ary3[2]
123

5. double형 배열과 char형 배열의 선언과 초기화

double ary4[5] = {1.0,2.1,3.2,4.3,5.4};
char ary5[5] = {'a','p','p','l','e'};

각각의 자료형에 맞게 double형 배열은 실수 값으로 초기화하고, char형 배열은 문자로 초기화한다. char형 배열은 주로 문자열을 저장하는 용도로 사용된다.


배열의 초기화는 선언 시 최초 한 번만 가능하다. 그 이후에는 배열 요소에 일일이 값을 대입해야한다. 다시 말해 배열을 선언할 때만 한 번에 배열을 초기화할 수 있다는 것이다.
배열의 값은 다음과 같이 바꿀 수 있다.

ary1[0] = 10;
ary1[1] = 20;
ary1[2] = 30;
ary1[3] = 40;
ary1[4] = 50;

배열과 반복문

우리가 배열을 사용하는 이유 중 하나가 무엇인가?
배열은 연속된 저장 공간을 할당하고 초기화할 수 있어 같은 유형의 변수가 많이 필요할 때 사용한다고 했었다. 만약 당신이 연속된 배열 요소를 일일이 변수처럼 하나씩 떼어서 사용하고 있다면 그냥 변수를 사용하는 것이 나을지도 모른다. 우리는 배열을 제대로 활용하기 위해 배열과 반복문을 함께 쓰는 방법을 알아야 할 필요가 있다.

배열 요소가 5개인 배열에 정수를 입력하는 다음 예시를 살펴보자.

int score[5];		//배열 선언

scanf("%d", &score[0]);
scanf("%d", &score[1]);
scanf("%d", &score[2]);
scanf("%d", &score[3]);
scanf("%d", &score[4]);

언뜻 보아도 같은 작업 반복에 첨자만 바뀌는 것을 알 수 있었다. 이것을 반복문으로 간단히 나타낼 수 있다. 한 번 예제를 통해 확인해보자.

✏️8-2 직접 해보는 손코딩_배열과 반복문을 사용한 성적 처리 프로그램

소스코드 예제8-2.c

#include <stdio.h>

int main(void) {
	int score[5];		//5과목의 성적을 입력할 int형 배열 선언
    int i;				//반복 제어 변수
    int total = 0;		//총점을 누적할 변수
    double avg;			//평균을 저장할 변수
    
    for(i = 0; i < 5; i++) {	//i가 0부터 4까지 5번 반복
    	scanf("%d", &score[i];	//각 배열 요소에 성적 입력
    }
    
    for (i = 0; i < 5; i++) {
    	total += score[i];		//성적을 누적하여 총점 계산
    }
    avg = total / 5.0;			//평균 계산
    
    for (i = 0; i < 5; i++) {
    	printf("%5d", score[i]);	//성적 출력	
    }
    printf("\n");
    
    printf("평균 : %.1f\n", avg);		//평균 출력
    
    return 0;
}
실행결과

80 95 77 84 100
80 95 77 84 100
평균 : 87.2

아무리 많은 데이터라도 배열과 반복문만 잘 사용하면 데이터의 양에 따라 유연하고 손쉬운 대응이 가능하다. 데이터 수가 늘어도 반복 횟수만 간단히 수정하면 그만이기 때문이다.


sizeof 연산자를 활용한 배열 처리

배열은 보통 많은 양의 데이터를 처리하기 때문에 반복문 사용은 필수다. 그래서 배열 요소의 개수가 바뀌면 배열을 처리하는 반복문을 모두 수정해야 한다는 번거로움이 있는데, 이 경우에는 배열 요소의 개수를 직접 계산하여 반복문에 사용하는 방법을 쓸 수 있다.

배열 요소의 개수를 구하는 방법은 다음과 같다.

sizeof(배열명) / sizeof(배열 요소)

✏️직접 해보는 손코딩_sizeof 연산자를 사용한 배열

소스코드 예제8-3.c

#include <stdio.h>

int main(void) {
	int score[5];
    int i;
    int total = 0;
    double avg;
    int count;		//배열 요소의 개수를 저장할 변수
    
    count = sizeof(score) / sizeof(score[0]);	//배열 요소의 개수 계산
    
    for (i=0;i<count;i++) {
    	scanf("%d", &score[i]);
    }
    
    for (i=0;i<count;i++) {
		total += score[i];
    }
    avg = total / (double)count;	//총합을 count로 나누어 평균 계산
    
    for (i=0;i<count;i++) {			//11행에서 계산한 배열 요소(count)만큼 반복
		printf("%5d", score[i];
    }
    printf("\n");
    
    printf("평균 : %.1\n", avg);
    
    return 0;
}
실행결과

80 95 77 84 100
80 95 77 84 100
평균 : 87.2

11행에서 배열 요소의 개수를 계산한다. 어떻게 계산되었는지 바로 확인해보자.

count = sizeof(score) / sizeof(score[0]);	//11행

sizeof(score)은 배열 전체 크기, 즉 20byte를 나타낸다.
sizeof(score[0])은 배열 요소 하나의 크기, 즉 4byte를 나타낸다.
그렇다면 위의 식은 count = 20 / 4;가 되므로 count에는 배열 요소의 개수, 즉 5가 대입되는 거다.

이렇게 구한 배열 요소의 개수를 각 반복문의 반복 횟수로 사용하면, 나중에 배열 선언문에서 요소의 개수를 바꾸더라도 나머지 코드를 수정할 번거로움을 없앨 수 있는 것이다.


마무리 정리

  • 배열선언하면 많은 변수를 한 번에 선언하는 효과를 볼 수 있다.
  • 배열초기화할 때는 중괄호( { } )를 사용한다.
  • 배열은 주로 반복문으로 처리한다.
  • 배열 전체의 크기를 구할 때 sizeof 연산자를 사용한다.

배열의 선언과 요소의 사용

구분사용 예기능
배열 선언int ary[5];int형 변수 5개를 한 번에 확보한다.
요소 사용ary[0], ary[1],ary[2],ary[3],ary[4]배열 요소를 사용할 때는 첨자를 0부터 시작하여 요소 개수-1까지 사용한다.
초기화int ary[5] = {1,2,3,4,5};초기화는 중괄호 안에 값을 나열한다.

확인 문제

1. 다음 설명에 따라 배열을 선언해보세요.

  1. 정수 5개를 저장할 배열
    int ary[5];
  2. 실수 10개를 저장할 배열
    double ary[10];
  3. 배열 요소 개수가 3개인 int형 배열
    int ary[2];
  4. 첨자의 최댓값이 4인 char형 배열
    char ary[5];

2. 다음 표와 일치하도록 배열을 선언하고 초기화해보세요.

int형int형int형int형int형int형
123000
int ary[6] = {1,2,3};

3. 다음과 같이 초기화된 A배열의 값을 복사하여 B배열을 채운 후 출력하는 프로그램을 작성해보세요.

A배열의 값이 복사된 B배열의 상태

1231231231
#include <stdio.h>

int main(void) {
	int A[3] = { 1,2,3 };	//초기화된 A 배열
	int B[10];				//초기화되지 않은 B 배열
	int i;

	int countA = sizeof(A) / sizeof(A[0]) + 1;		//A배열 요소의 개수
	int countB = sizeof(B) / sizeof(B[0]);		//B배열 요소의 개수
	int count = 1;								//배열 요소의 개수 카운트

	for (i = 0; i < countB; i++) {
		B[i] = count++;
		if (count == countA ) {
			count = 1;
		}
	}

	for (i = 0; i < countB; i++) {
		printf("%d  ", B[i]);
	}

	return 0;
}
실행결과

1  2  3  1  2  3  1  2  3  1


들어가며..

우리는 평소에 의미를 전달하기 위해 어떠한 단어를 사용한다. 이러한 단어들은 한글, 또는 알파벳을 연속으로 적고 그 순서에 따라 뜻이 달라진다.

무언가 키워드가 보이지 않는가? 바로 연속이라는 키워드이다. 배열은 메모리에 연속적으로 저장해놓고 쪼개서 사용하는 방법이라고 앞에서 나왔었다. 바로 이런 점에서 배열은 단어를 저장하기 위한 가장 좋은 방법이라는 것을 유추할 수 있는 것이다.

그리고 모든 알파벳 문자는 한 바이트로 충분히 표현할 수 있으니 char 배열을 사용하는 것이 좋다. 바로 지금, 우리는 이 char형 배열에 대해서 다뤄볼 것이다.


char형 배열의 선언과 초기화

들어가기에 앞서 char형 배열을 선언할 때 반드시 기억해두어야 할 것이 있다. 바로 저장할 문자열의 길이보다 최소한 하나 이항 크게 배열을 선언하는 것이다.

예를 들어보도록 하자.
문자열 apple을 배열에 저장할 때, 배열 요소 개수가 최소한 6개 이상이어야 한다는 것이다.

apple남는 공간이 하나 이상 있어야 한다.

이렇게 여분의 공간이 필요한 이유는 널 문자(\0)(null)를 저장하기 위해서이다. 그렇다면 null문자는 대체 무슨 기능을 하는 것일까?

✏️직접 해보는 손코딩_문자열을 저장하는 char형 배열

소스코드 예제8-4.c

#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

char형 배열은 배열 요소의 형태가 char일 뿐 다른 타입의 배열과 다르지 않다. 따라서 초기화 방법도 중괄호를 이용하여 문자를 차례로 나열해도 되긴 하나 번거로움이 있기 때문에 문자열 상수로 초기화하는 방법을 많이 사용한다.

문자 상수로 하나씩 초기화

char str[80] = {'a','p','p','l','e','j','a','m'};

문자열 상수로 한 번에 초기화

char str[80] = "applejam";


널 문자의 정의, 용도와 표기법 공유하기

널 문자가 무엇이고 어떻게 사용되는지, 어떻게 사용하는지에 대해 정리한다.


널 문자 (null charater)란?

: 아스키 코드 값이 0인 문자

우리가 주어진 배열 요소를 다 사용하지 않는다면 배열 요소가 남을 것이다. 이 때에 남은 배열 요소에 채워지는 0이 있는데 이 것을 널 문자라고 한다.

널 문자의 표기법

  • 아스키 코드 값 : 0
  • 문자 상수 : \0

널 문자의 용도

아스키 코드 값이 0인 문자를 널 문자라는 이름으로 특별히 대접하는 이유는, 널 문자가 문자열의 끝을 표시하는 용도로 쓰이기 때문이다.

7행의 printf 함수가 배열의 크기와 관계없이 초기화된 문자열만을 정확히 출력하는 것도 널 문자가 있기 때문이다. 이게 무슨 말인가?
printf 함수char형 배열에서 널 문자가 나올 때까지만 출력하도록 만들어졌다. 이러한 규칙은 문자열을 처리하는 모든 함수에 적용된다.

printf("최초 문자열 : %s\n", str);		//7행. 초기화 문자열 출력



💡여기서 잠깐_char형 배열 선언 시 초기화하지 않은 경우에는?

초기화를 하지 않고 배열 요소에 문자를 직접 대입한다면 동일하게 마지막 문자 다음에는 널 문자를 대입해야 한다. 꼭 기억하자!


char형 배열 선언 시 주의할 점

  1. 배열의 크기는 최대한 넉넉하게 선언해야 한다.
  2. 배열 요소의 개수는 최소한 문자열 길이+1 이어야 한다.
    널 문자로 그 끝을 표시하므로 최소한 널 문자까지 저장할 수 있도록 한다.

문자열 대입

char형 배열도 문자열을 저장하는 엄연한 변수의 역할을 하기 때문에 초기화 이후에도 얼마든지 새로운 문자열을 저장할 수 있다.

그런데 만약 ary[5] = "jam";배열에 ary[100] = "schoolbus"을 대입하려 하면 어떻게 될까? 문자열의 길이가 다르므로 일반적인 변수처럼 대입 연산자를 사용하여 대입하는 것은 불가능할 것이다.
이 때에 사용하는 함수가 바로 strcpy 함수이다.

strcpy 함수란?

: char형 배열에 새로운 문자열을 저장하는 함수

strcpy 함수는 앞의 문제점을 해결할 수 있는 함수로, 저장할 문자열의 길이를 파악하여 딱 그 길이만큼만 char형 배열에 복사해준다. 물론 문자열 끝에 들어갈 널 문자도 자동으로 붙여준다.

strcpy 함수를 사용하기 위해서는 함수에 접근해야 할 것이다. strcpy 함수에 접근하기 위해서는 string.h를 사용해야 한다. string.h는 문자열을 다루는 함수들의 원형을 모아놓은 것이다.

strcpy 함수의 기본 사용법은 다음과 같다.

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

다음 예제를 통해 더 자세히 알아보자.


💡여기서 잠깐_strcpy 함수를 사용한 코드가 컴파일되지 않을 때는?

간혹 strcpy 함수를 사용한 코드가 컴파일되지 않을 때가 있을 것이다. 이 때에는 소스 코드 첫 줄에 #define_CRT_SECURE_NO_WARNINGS 문장을 추가해줍시다.


✏️직접 해보는 손코딩_문자열을 대입하는 strcpy 함수

소스코드 예제8-5.c

#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

strcpy 함수로 문자열 상수를 char형 배열에 대입

strcpy(첫 번째 인수, 두 번째 인수);

위의 식은 첫 번째 인수에 두 번째 인수가 대입된다고 생각해도 될 것 같다.

아울러 첫 번째 인수에는 문자열 상수를 사용할 수 없다. 상수는 변하지 않는 값이기 때문이다. 대입 연산자의 왼쪽에 상수가 올 수 없는 것과 같은 이유이지 않겠는가?


char형 배열에 저장된 문자열을 다른 char형 배열에 대입

strcpy(첫 번째 인수, 두 번째 인수);

위의 식에서 두 번째 인수에는 문자열 상수뿐만 아니라, char형 배열의 배열명도 사용할 수 있다. 이 때는 배열에 저장된 문자열을 다른 char형 배열에 복사하는 방식이다.


💡여기서 잠깐_배열에 대입 연산자는 왜 사용할 수 없을까?

한 번쯤은 이러한 코드를 작성해봤을 것이다.

char str[80];		//배열 선언
str = "apple";		//배열에 문자열 대입

이 대입 연산식은 컴파일 단계에서 에러가 발생한다.

그 이유는 대입 연산자 왼쪽에 사용한 배열명이 컴파일 과정에서 배열이 할당된 메모리의 주소 값으로 바뀌기 때문이다.
예를 들어보자. str 배열메모리 100번지부터 할당되었다면 다음과 같이 대입하는 꼴이 된다.

100 = "apple";		//배열명 str은 100으로 바뀜
//주의! 실제로 이렇게 대입하지는 않는다.

100상수로 대입 연산자의 왼쪽에 올 수 없으므로 컴파일 과정에서 에러가 발생한다. 여기서는 대입 연산자 왼쪽에 배열명이 올 수 없음을 기억하자.


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

char형 배열에 문자열을 대입하는 일은 strcpy 함수가 수행한다고 우리는 알고 있다. 이제 키보드로 문자열을 입력하는 문제를 생각해보자.

scanf 함수char형 배열에 문자열을 입력할 수 있다. 하지만 중간에 빈칸이 있는 경우 빈칸 전까지만 입력한다. 따라서 우리에게는 빈칸을 포함한 새로운 문자열 입력 방식이 필요하고 그 역할을 지금 배울 gets 함수puts 함수가 해 줄 것이다.

예제를 통해 putsgets의 사용법과 특징을 알아보자.

✏️직접 해보는 손코딩_빈칸을 포함한 문자열 입력

소스코드 예제8-6.c

#include <stdio.h>

int main(void) {
	char str[80];
    
    printf("문자열 입력 : ");	//입력 안내 메시지 출력
    gets(str);					//빈칸을 포함한 문자열 입력
    puts("입력된 문자열 : ");		//문자열 상수 출력
    puts(str);					//배열에 저장된 문자열 출력
    
    return 0;
}
실행결과

문자열 입력 : Love is belief...
입력된 문자열 :
Love is belief...

빈칸을 포함하여 문자열을 입력하는 gets 함수

gets 함수의 사용법은 다음과 같다.

gets(char형 배열명);

gets 함수는 문자열 입력 중간에 빈칸이나 문자를 사용할 수 있으며, Enter를 누르기 전까지 전체를 하나의 문자열로 배열에 저장한다.

gets 함수를 사용할 때에 주의사항이 있다.
입력할 배열의 크기를 검사하지 않기 때문에 배열의 크기보다 긴 문자열을 입력할 경우 배열을 벗어난 메모리 영역을 침범할 가능성이 있다. 따라서 입력 할 때는 항상 배열의 크기를 고려해야 한다.
이 문제는 scanf 함수strcpy 함수에도 해당된다.


gets와 짝을 이뤄 문자열을 출력하는 puts 함수

puts 함수 : 문자열 상수나 char형 배열의 배열명을 주면 문자열을 화면에 출력

puts 함수printf 함수의 문자열 출력 기능과 같다. 단 문자열을 출력한 후에 자동으로 줄을 바꾸는 차이가 있다. 이 기능은 경우에 따라 편할 수도 있지만 문자열을 출력한 후에 바로 이어서 입력하는 것은 불가하다.


마무리 정리

  • char형 배열은 문자열을 저장하는 변수의 역할을 하는 것으로 문자열로 직접 초기화할 수 있다.
  • char형 배열에 문자열을 저장할 때는 대입 연산자 대신 strcpy 함수를 사용한다.
  • char형 배열에 문자열을 입출력할 때는 scanf gets printf puts등의 함수를 사용한다.

문자열 처리

구분사용 예기능
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 함수는 문자열 출력 후 줄 바꿈

확인 문제

1. 다음 중 char형 배열이 바르게 초기화된 것은 O , 그렇지 않은 것은 X 하세요.

  1. char str [ 80 ] = { ' p ', ' i ', ' g ' }; - O
  2. char str [ ] = " elephant "; - O
  3. char str [ 5 ] = "apple"; - X 널 문자의 공간이 없다.
  4. char str [ 2 ] = { " sun ", " moon " }; - X 알파벳 하나씩 해야 한다.

2. 다음 중 널 문자의 상수 표현법으로 맞는 것을 고르세요.

  1. NULL - X
  2. /0 - X
  3. '0' - X
  4. '\0' - O

3. 다음 코드는 2개의 문자열을 입력받아 위치를 바꾼 후에 출력합니다. 빈칸을 채워 프로그램을 완성하세요.

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

int main(void) {
	char str1[80], str2[80];
	char temp[80];

	printf("두 문자열 입력 : ");
	scanf_s("%s %s", str1, 80, str2, 80);	//공간을 써줘야 오류가 생기지 않음
	printf("바꾸기 전 : %s, %s", str1, str2);
	strcpy(temp, str1);
	strcpy(str1, str2);
	strcpy(str2, temp);
	printf("바꾼 후 : %s, %s\n", str1, str2);

	return 0;
}
실행결과

두 문자열 입력 : apple banana
바꾸기 전 : apple, banana
바꾼 후 : banana, apple

처음에는 첫 번째 문자열이 str1이고 두 번째 문자열이 str2다.
두 문자열의 위치를 바꿔야 하므로 str2의 값이 먼저 나와야 한다.
먼저 str1의 값을 temp에 저장한다.
그 후 str1str2의 값을 대입한다.
마지막으로 str2str1의 값이 들어있는 temp의 값을 대입해준다.
그대로 str1 str2 순서로 출력하면 위치가 바뀌어 출력된다.



profile
기록의 힘을 믿는 개발자, 노하은입니다!

0개의 댓글