1. C언어 코드 분석 연습
- 언어와 마찬가지로 프로그래밍 코드 역시 작성 능력뿐만 아니라 읽는 능력도 중요하다.
- 코드를 읽는 능력은 프로그래밍 과정에서 발생하는 버그를 발견하고, 코드의 동작을 미리 예측하는 분석 능력의 기초가 된다.
- 아래에 제시된 코드를 컴파일하지 않고 직접 분석하여 실행 결과를 예측해 보자.
- 이를 통해 코드 이해 능력을 기르고, 논리적으로 사고하는 연습을 할 수 있다.
1.1. 초급 난이도
1.1.1. ex01_low_if.c
if/else 조건문의 제어 흐름을 이해한다.
a + b > c * 3 식에서 연산자 우선순위를 확인한다.
const로 선언된 상수 값이 조건 판단에 어떻게 사용되는지를 추적한다.
#include <stdio.h>
int main(void)
{
const int a = 3;
const int b = 5;
const int c = 2;
int result = 0;
if (a + b > c * 3) {
result = 1;
} else {
result = 2;
}
printf("%d\n", result);
return 0;
}
1.1.2. ex02_low_while_sum.c
while 반복문을 이용하여 값을 누적하는 과정을 이해한다.
#define MAX_NUM으로 정의된 반복 종료 조건을 확인한다.
- 각 반복 회차에서
sum 값이 어떻게 증가하는지를 추적한다.
#include <stdio.h>
#define MAX_NUM 5
int main(void)
{
int i = 1;
int sum = 0;
while (i <= MAX_NUM) {
sum = sum + i;
i = i + 1;
}
printf("%d\n", sum);
return 0;
}
1.1.3. ex03_low_switch.c
switch/case 문과 이후에 실행되는 if/else 문의 흐름을 이해한다.
const로 정의된 n 값에 따라 선택되는 case와, 이후 score 값의 변경 과정을 추적한다.
#include <stdio.h>
int main(void) {
const int n = 4;
int score = 0;
switch (n % 3) {
case 0:
score = 10;
break;
case 1:
score = 20;
break;
default:
score = 30;
break;
}
if (score > 15) {
score = score - 5;
} else {
score = score + 5;
}
printf("%d\n", score);
return 0;
}
1.1.4. ex04_low_nested_if.c
- 중첩 반복문 구조와 이를 이용한 약수 개수 계산 과정을 이해한다.
count == 2 조건을 통해 소수를 판별하는 방식과 sum 값의 누적 변화를 추적한다.
#include <stdio.h>
int main(void)
{
const int x = 7;
const int y = 4;
int out = 0;
if (x > y) {
if ((x - y) % 2 == 1) {
out = 9;
} else {
out = 6;
}
} else {
out = 3;
}
printf("%d\n", out);
return 0;
}
1.2. 중급 난이도
1.2.1. ex05_mid_for_break.c
break 문에 의해 for 반복문이 중단되는 흐름을 이해한다.
#define LOOP_MAX, #define THRESHOLD 상수를 사용한 조건 판단 과정을 확인한다.
#include <stdio.h>
#define LOOP_MAX 10
#define THRESHOLD 20
int main(void)
{
int i;
int answer = 0;
for (i = 1; i <= LOOP_MAX; i = i + 1) {
if (i * i > THRESHOLD) {
answer = i;
break;
}
}
printf("%d\n", answer);
return 0;
}
1.2.2. ex06_mid_function_chain.c
- 함수 호출에 따른 값의 변환 과정을 이해한다.
transform() 함수를 두 번 연속 호출할 때, 입력 값과 반환 값이 어떻게 변화하는지를 추적한다.
#include <stdio.h>
int transform(int n)
{
int v = n;
if (v % 2 == 0) {
v = v / 2;
} else {
v = v * 3 + 1;
}
return v - 1;
}
int main(void)
{
int x = 6;
x = transform(x);
x = transform(x);
printf("%d\n", x);
return 0;
}
1.2.3. ex07_mid_do_while_reverse.c
do/while 반복문과 숫자 자릿수 처리 방식을 이해한다.
init_n 값에서 시작하여, 오른쪽 자릿수부터 처리되며 reversed 값이 갱신되는 과정을 추적한다.
#include <stdio.h>
int main(void)
{
const int init_n = 321;
int n = init_n;
int reversed = 0;
do {
reversed = reversed * 10 + (n % 10);
n = n / 10;
} while (n > 0);
printf("%d\n", reversed);
return 0;
}
1.3. 고급 난이도
1.3.1. ex08_high_prime_sum.c
- 중첩된 반복문 구조와 이를 이용한 약수 개수 계산 과정을 이해한다.
count == 2일 때(소수를 판별하는 조건)와 sum 변수의 변화를 추적한다.
#include <stdio.h>
int main(void)
{
int n;
int sum = 0;
for (n = 1; n <= 6; n = n + 1) {
int d;
int count = 0;
for (d = 1; d <= n; d = d + 1) {
if (n % d == 0) {
count = count + 1;
}
}
if (count == 2) {
sum = sum + n;
}
}
printf("%d\n", sum);
return 0;
}
1.3.2. ex09_high_recursion.c
- 재귀 함수의 호출 방식을 이해한다.
INITIAL_VAL에서 시작하여 calc() 호출 시 콜 스택의 흐름과 짝수/홀수 분기 동작을 추적한다.
#include <stdio.h>
#define INITIAL_VAL 6
int calc(int n)
{
if (n <= 1) {
return 1;
}
if (n % 2 == 0) {
return n + calc(n - 1);
}
return calc(n - 1);
}
int main(void)
{
printf("%d\n", calc(INITIAL_VAL));
return 0;
}
1.3.3. ex10_high_state_flow.c
- 상태 기반 제어 흐름(State-based Control Flow)을 이해한다.
- 반복문 내부에서
state 값의 전환에 따라 n 값이 어떻게 변화하는지를 추적한다.
#include <stdio.h>
int main(void)
{
int n = 23;
int state = 0;
int steps = 0;
while (n > 0) {
if (state == 0) {
n = n - 2;
state = 1;
} else if (state == 1) {
n = n / 2;
state = 2;
} else {
n = n - 1;
state = 0;
}
steps = steps + 1;
}
printf("%d\n", steps);
return 0;
}