주차 | 진도 | 기본 숙제 | 추가 숙제 |
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 |