본문 바로가기
혼공단 12기(혼공C)

[혼공C] 5주차 배열

by 눈 떠 보니 공대생 2024. 8. 6.

주차 진도 기본 숙제 추가 숙제
5주차(8.5~8.11) Chapter 8 배열의 개념 정리하고 공유하기 널 문자의 정의, 용도와 표기법 공유하기

<기본 숙제:  배열의 개념 정리하고 공유하기  >

배열

① 같은 자료형의 데이터가 연속적으로 저장된 것. 같은 유형의 변수가 많이 필요할 때 사용

② 배열 요소(element): 배열의 나누어진 조각

③ 기본값: 쓰레기 값. 선언과 동시에 초기화 가능

④ 선언할 때 초기화하지 않으면, 각 배열 요소를 일일이 대입해야 함

각 배열 요소는 index(0~)로 접근

<추가 숙제: 널 문자의 정의, 용도와 표기법 공유하기>

널 문자(null character)

① char형 배열에 저장된 0(아스키 코드 값이 0인 문자)

'\0'으로 표기

문자열의 끝을 표시하는 용도로 사용됨배열의 길이 >= 문자열의 길이 + 1(널 문자) 이어야 함

④ 선언과 동시에 초기화하는 경우: 문자열을 저장하고 남는 공간은 널 문자로 채워짐

선언과 동시에 초기화하지 않는 경우: 마지막 문자 다음에 널 문자 대입 필요.

 

※ 널 문자 더 알아보기

널 문자가 없다면?

[코드]

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

int main() {
	char str[3];
	str[0] = 'A';
	printf("%s\n", str);

	return 0;
}

[실행 결과]

다른 메모리 침범, 쓰레기값 출력하고,(침범된 메모리의 값에 따라 실행 결과는 달라짐.)

메모리 어딘가에 저장되어 있던 널 문자를 만나면 출력을 종료한다.

 

중간에 널 문자를 넣으면?

[코드]

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

int main() {
	char str[3];
	str[0] = 'A';
	str[1] = '\0';
	printf("%s\n", str);

	return 0;
}

[실행 결과]

널 문자를 만나면 출력을 종료한다.


Chapter 8. 배열

1. 배열의 선언과 사용

배열(array): 메모리에 연속적으로 저장된 같은 자료형의 데이터 모음. 같은 유형의 변수가 많이 필요할 때 사용. 기본값은 쓰레기 값.

1) 배열의 선언

(1) 배열의 선언

자료형 배열명 [요소 개수]

*배열 요소(element): 배열의 나누어진 조각

e.g. int형 요소(element) 3개의 배열 선언: int arr[3];

 

※ 개별 변수 선언 vs. 배열 선언

int a, b, c;

4 bytes  
 ...
4 bytes  
 ...
4 bytes
a b c

int arr[3];

12 bytes
4 bytes 4 bytes 4 bytes
arr[0] arr[1] arr[2]

- 각 배열 요소는 배열명[index]로 접근 가능하며, 마치 하나의 변수처럼 사용됨

- index 0부터 시작, 만약 index가 배열의 사용 범위를 벗어날 경우, 배열에 할당되지 않은 메모리에 접근하게 됨. 침범된 메모리에 따라 실행 결과가 달라짐

2) 배열 초기화: 중괄호 {} 사용

- 배열 선언 시 최초 한 번만 가능

- 구체적인 데이터 값은 약간의 차이가 있으나, 어떤 자료형이든 기본적인 초기화 방법은 같음

(1) 기본적인 초기화 방법

왼쪽부터 차례로 채움

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

1 2 3
arr[0] arr[1] arr[2]

(2) 초깃값 개수 < 배열 요소 개수

int arr[3] = {1};

왼쪽부터 차례로 초기화. 남는 요소는 0으로 할당.

1 0 0
arr[0] arr[1] arr[2]

(3) 자동 초기화

int arr[3] = {0};

0 0 0
arr[0] arr[1] arr[2]

(4) 배열 요소 개수 생략된 형태 존재

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

컴파일러: 초깃값 개수만큼 메모리 할당

1 2 3
arr[0] arr[1] arr[2]

3) 배열과 반복문

배열 요소의 활용: index로 접근

e.g. 배열과 반복문을 사용한 성적 처리 프로그램

[코드]

#include <stdio.h>

int main() {
	int score[5];
	int total = 0; // 총점을 저장할 변수
	int avg = 0; // 성적의 평균을 저장할 변수

	for (int i = 0; i < 5; i++) {
		scanf("%d", &score[i]); // 입력 받은 데이터를 i번째 배열 요소에 저장
		total += score[i]; // 총점 변수에 i번째 데이터를 더하기
	}

	avg = total / 5; // 성적의 평균 구하기

	for (int i = 0; i < 5; i++) {
		printf("score[%d]: %d\n", i, score[i]); // i번째 배열 요소의 데이터 값 출력
	}

	printf("total score: %d\n", total); // 총점 출력
	printf("average score: %d\n", avg); // 평균 점수 출력

	return 0;
}

[실행 결과]

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

sizeof(x): x의 크기 알려줌

배열의 크기 = 배열 요소 개수 * 자료형 크기

e.g. int score[5]

20 bytes
4 bytes 4 bytes 4 bytes 4 bytes 4 bytes
score[0] score[1] score[2] score[3] score[4]

따라서 배열 요소의 개수 = 배열의 크기 / 자료형 크기

* 자료형 크기는 sizeof(int)와 같이 자료형 keyword를 사용해 구할 수도 있고, sizeof(score[0])와 같이 배열 요소를 이용해 구할 수도 있다.

 

배열 요소의 개수를 이용해 평균 점수 구하기.

[코드]

#include <stdio.h>

int main() {
	int score[5];
	int total = 0; // 총점을 저장할 변수
	int avg = 0; // 성적의 평균을 저장할 변수
	int num; // 배열 요소의 개수를 저장할 변수

	num = sizeof(score) / sizeof(int);
	printf("size of score: %d\n", sizeof(score));
	printf("the number of elements of score: %d\n", num);

	printf("성적을 입력하세요: ");
	for (int i = 0; i < 5; i++) {
		scanf("%d", &score[i]); // 입력 받은 데이터를 i번째 배열 요소에 저장
		total += score[i]; // 총점 변수에 i번째 데이터를 더하기
	}

	avg = total / num; // 성적의 평균 구하기

	for (int i = 0; i < 5; i++) {
		printf("score[%d]: %d\n", i, score[i]); // i번째 배열 요소의 데이터 값 출력
	}

	printf("total score: %d\n", total); // 총점 출력
	printf("average score: %d\n", avg); // 평균 점수 출력

	return 0;
}

[실행 결과]

2. 문자를 저장하는 배열

1) char형 배열의 선언과 초기화

※ char형 배열의 길이 >= 저장할 문자열의 길이 + 1

널 문자('\0')를 저장하기 위함.

** 널 문자의 용도

널 문자(null character): char형 배열에 저장된 0(아스키 코드 값이 0인 문자). 문자열의 끝을 표시하는 용도로 사용됨. 배열의 길이 > (문자열의 길이 + 1)일 경우, 남는 공간은 자동으로 널 문자로 채워 짐(초기화시)

선언과 동시에 초기화하지 않는 경우: 마지막 문자 다음에 널 문자 대입 필요.

e.g.

#include <stdio.h>

int main() {
	char str[10] = "pineapple";

	printf("최초 문자열: %s\n", str);

	printf("문자열을 입력하세요: ");
	scanf("%s", str);

	printf("입력 후 문자열: %s\n", str);

	return 0;
}

/* 결과 */
/* 최초 문자열: pineapple
문자열을 입력하세요: apple
입력 후 문자열: apple */

최초 문자열

p i n e a p p l e \0

printf(): \0가 나올 때까지만 출력

scanf(): 입력된 문자열 다음을 \0으로 채움

입력 후 문자열

a p p l e \0 \0 \0 \0 \0

※ char형 배열 선언 시 주의

① 문자열의 길이가 일정하지 않을 때: 배열의 크기 최대한 넉넉히 선언

② 배열 요소의 개수 >= 문자열 길이 + 1

2) 문자열 대입: strcpy함수 사용(string.h 필요)

strcpy(저장될 배열명, 저장할 문자열/배열명): char형 배열에 새로운 문자열 저장. 저장할 문자열의 길이 + null 문자를 char형 배열에 복사

e.g.

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

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

	strcpy(str1, "dog"); // str1에 "dog" 복사
	strcpy(str2, str1); //str2에 str1 복사
	printf("%s %s\n", str1, str2);

	return 0;
}

/* 결과 */
/* dog dog */

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

scanf(): 빈칸 전까지만 입력 가능

gets(): 빈칸을 포함, 한 줄 전체를 문자열로 입력 + 널 문자 붙이기. 입력할 배열의 크기 검사 X → 메모리 침범 위험(scanf, strcpy 함수도 해당됨)

puts(): 문자열 출력하고 자동으로 줄바꿈

e.g.

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

int main() {
	char str[20];
	printf("문자열 입력: ");
	gets(str);
	puts("입력된 문자열: ");
	puts(str);

	return 0;
}

/* 결과 */
/* 문자열 입력: Hello, World!
입력된 문자열:
Hello, World! */

확인 문제 3

2개의 문자열을 받아 위치를 바꾼 후 출력하는 프로그램 완성하기

[코드]

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

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

	printf("두 문자열 입력 : ");
	scanf("%s %s", str1, str2);
	printf("바꾸기 전 : %s, %s\n", str1, str2);

	strcpy(temp, str1);
	strcpy(str1, str2);
	strcpy(str2, temp);

	printf("바꾼 후: %s, %s\n", str1, str2);

	return 0;
}

[실행 결과]

도전 실전 예제: 대소문자 변환 프로그램

키보드로부터 문장을 입력받은 후, 대문자를 찾아 소문자로 바꾸는 프로그램 작성하기.

바뀐 문장과 바뀐 문자의 수도 함께 출력하기

[코드]

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

int main() {
	char str[100] = { '\0' }; // 문자열 초기화

	printf("문장 입력 : ");
	gets(str); // 빈칸을 포함한 문자열 입력 받기

	int i = 0; // index를 나타내는 변수
	int cnt = 0; // 바뀐 문자의 수를 저장하는 변수

	while (str[i] != '\0') { // 문자열의 길이를 모르므로, 널 문자 전까지 반복
		if ('A' <= str[i] && str[i]  < 'a') { // 대문자 알파벳인지 확인
			str[i] += 'a' - 'A'; // 소문자로 전환
			cnt++; // 바뀐 문자 수 증가
		}
		i++; // 인덱스 증가
	}

	printf("바뀐 문장 : %s\n", str);
	printf("바뀐 문자 수: %d\n", cnt);
	
	return 0;
}

[실행 결과]

+) 소문자 → 대문자의 경우: 대문자인지 확인하는 부분과 str[i]를 변환하는 부분만 수정하면 된다.

[코드]

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

int main() {
	char str[100] = { '\0' }; // 문자열 초기화

	printf("문장 입력 : ");
	gets(str); // 빈칸을 포함한 문자열 입력 받기

	int i = 0; // index를 나타내는 변수
	int cnt = 0; // 바뀐 문자의 수를 저장하는 변수

	while (str[i] != '\0') {
		if ('a' <= str[i] && str[i] <= 'z') { // 소문자 알파벳인지 확인
			str[i] += 'A' - 'a'; // 대문자 전환
			cnt++; // 바뀐 문자 수 증가
		}
		i++; // 인덱스 증가
	}

	printf("바뀐 문장 : %s\n", str);
	printf("바뀐 문자 수: %d\n", cnt);
	
	return 0;
}

[실행 결과]

'혼공단 12기(혼공C)' 카테고리의 다른 글

[혼공C] 회고록  (0) 2024.08.18
[혼공C] 6주차 포인터  (0) 2024.08.18
[혼공C] 4주차 함수  (0) 2024.07.28
[혼공C] 3주차 선택문, 반복문  (3) 2024.07.20
[혼공C] 2주차 변수와 데이터 입력, 연산자  (2) 2024.07.14