글자는 숫자이고, 구조체는 칸의 묶음이고, 재귀는 되감기다. 세 원리로 C 기출 16문항이 풀린다
왜 이 장을 하나
C 의 나머지 절반이다. 문자열 문제는 글자가 곧 코드 값이라는 것에서, 구조체 · 연결 리스트 문제는 화살표를 따라가는 그림에서, 재귀 문제는 가장 깊은 호출부터 되감는 표에서 답이 나온다. 11회 중 10회에 나온 장이라 3회에도 나온다고 보고 만든다.
다루는 것문자 코드 · 문자열 함수 · 구조체 · 연결 리스트 · 큐 · 재귀 · 트리
문항기출 16 · 예상 2 · 훈련 10
끝나면연결 리스트를 화살표로 그려 순회한다
01왜 이 장인가
왜 이걸 하나 — C 42문항 중 16문항이 이 장이고, 2025년에는 세 회 연속 연결 리스트가 나왔다.
11회분 220문항 중 이 장의 기출은 16문항이다. 11회 중 10회에 나왔고(2023년 2회만 빠짐), 2025년 2회에는 4문항(환형 큐 · 이중 포인터 구조체 · 연결 리스트 · 동적 문자열 역순)이 몰렸다. 훈련 C 10문항(7~13 · 17~19)이 붙는다.
꼴
몇 문항
무엇을 적나
보기
문자열 · 문자 코드
5
글자 순회 · 대소문자 변환 · 역순 · 시저 암호
2023-1회 3번 · 2024-1회 4번 · 19번 · 2025-2회 18번 · 2025-3회 7번
→ 연결 리스트가 5문항이다. 2024년 3회부터 2025년 2회까지 세 회 연속이었고, 2026년 2회 7번의 트리도 구조체 포인터 둘(a · b)이 자식을 가리키는 같은 꼴이다. 노드를 그리고 화살표를 따라가는 절차 하나로 여섯 문항이 풀린다.
E01 진단의 7번(트리 후위 순회, 답 12)이 이 장이다. 「재귀」와 「구조체 포인터」가 한 문제에 있어 어렵게 보이지만, 03절의 되감기 표와 화살표 그림을 합치면 순서가 하나로 정해진다.
문항 수는 이 노트의 문제 데이터에서 ch=E03 인 것을 센 값이다(2026-09-14). 기출 코드는 grandlife.co.kr 복원에서 옮겼고, 16문항 전부 gcc(도커 alpine)로 실행해 정답을 확인했다.
02한눈에
왜 이걸 하나 — 시험 전날 규칙 8개를 다시 본다.
글자는 숫자다'A' = 65, 'a' = 97, '0' = 48. 대문자 ↔ 소문자는 32 차이. c + 1 은 다음 글자, c - 'a' 는 알파벳 몇 번째. %c 로 찍으면 글자, %d 로 찍으면 숫자.
문자열의 끝\0 이 끝. while (s[i] != '\0') · while (*p) 가 끝까지 순회. strlen 은 \0 앞까지 개수, sizeof 는 \0 포함 바이트.
문자열 함수strcpy(a, b) 복사 · strcat(a, b) 이어 붙임 · strcmp(a, b) 같으면 0, 앞이 크면 양수 · strlen 길이 · toupper · tolower · isalpha · isdigit.
구조체 접근변수면 s.member, 포인터면 p->member(= (*p).member). typedef struct { … } Name; 로 이름을 만든다. 구조체 배열은 arr[i].member.
연결 리스트노드 = 값 + 다음 노드 주소(next). 순회는 for (p = head; p != NULL; p = p->next). 삽입 · 교환은 화살표를 다시 잇는 것. malloc 으로 노드를 만들면 free 로 돌려준다.
환형 큐front(꺼낼 자리) · rear(넣을 자리)가 (x + 1) % SIZE 로 돈다. 넣으면 rear 가, 꺼내면 front 가 움직인다. 두 값을 매 연산마다 적는다.
재귀종료 조건(if (n <= 1) return …)까지 내려간 뒤 되감으며 계산. 표를 아래(가장 깊은 호출)부터 채운다. 팩토리얼 · 피보나치 · 자릿수 합 · 트리 순회.
트리 순회전위(자기 → 왼 → 오른) · 중위(왼 → 자기 → 오른) · 후위(왼 → 오른 → 자기). 코드에서 func(n->a); func(n->b); 뒤에 자기 처리가 있으면 후위다.
03밑바닥
왜 이걸 하나 — 세 원리가 왜 그런지를 알면, 함수 이름이 낯설어도 코드가 무엇을 하는지 읽힌다.
3-1. 글자는 숫자라서 더하고 뺄 수 있다
C 의 char 는 8비트 정수다. 'A' 는 65, 'a' 는 97, '0' 은 48 이고 그 차이가 규칙을 만든다. 대문자에 32 를 더하면 소문자, c - '0' 은 글자 숫자를 진짜 숫자로, c + 3 은 알파벳 세 칸 뒤다. 2024년 1회 19번의 시저 암호가 이 덧셈이고, 범위를 넘으면 % 26 으로 돌린다.
순회는 \0 을 만날 때까지다. while (s[i] != '\0') 든 while (*p) 든 같은 뜻이고, 2023년 1회 3번은 두 문자열을 이중 반복문으로 대조해 있는 글자만(qwe) 찍는다. 2024년 1회 4번은 마지막 첨자부터 두 칸씩 건너뛰어(6 · 4 · 2 · 0) GECA 를 만든다 — 첨자를 종이에 0 1 2 … 로 적고 조건을 대 보면 된다.
역순 출력은 두 가지 꼴로 나온다. 첨자를 len - 1 부터 내려오거나(훈련 8번), malloc 으로 새 칸을 잡아 거꾸로 복사하거나(2025년 2회 18번, TSEB). 어느 쪽이든 strlen 으로 길이를 먼저 재고 마지막 첨자가 len − 1 이라는 것이 출발점이다.
3-2. 구조체는 칸의 묶음이고 화살표는 「포인터가 가리키는 묶음의 칸」이다
struct Item { int price; int count; }; 는 두 칸을 한 묶음으로 만든 새 자료형이다. 변수면 item.price 로, 포인터면 p->price 로 칸을 연다 — 화살표는 (*p).price 의 줄임이고, 2023년 3회 4번의 빈칸이 바로 -> 다. 2024년 1회 11번은 구조체의 잔액에서 100 을 빼고 1.1 을 세 번 곱해 %.2f 로 2795.10 을 찍으므로 소수 둘째 자리까지 그대로 적는다.
2026년 1회 8번은 구조체 멤버가 함수 포인터다. int *(*fn)(int *) 는 「int 포인터를 받아 int 포인터를 돌려주는 함수」를 가리키는 포인터이고, s.fn(&x) 로 부른다. 선언이 낯설어도 괄호 안의 * 가 함수 포인터, 밖의 것이 반환형으로 읽으면 된다.
3-3. 연결 리스트는 화살표를 따라가고, 바꾸는 것은 화살표다
노드는 값 하나와 next 주소 하나로 된 구조체다. 순회는 head 에서 시작해 p = p->next 로 화살표를 따라가다 NULL 에서 멈춘다. 2025년 1회 18번은 노드 5개를 잇고 순회해 35421 을 찍는데, 이어 붙인 순서와 값의 순서가 다르다는 것이 함정이다 — 코드가 next 를 어디에 꽂는지를 그림에 그려야 한다.
교환 문제(2024년 3회 12번, 312)는 값을 바꾸는지 화살표를 바꾸는지를 먼저 본다. 값을 바꾸면 노드는 그대로이고 값만 오가고, 화살표를 바꾸면 노드의 순서가 바뀐다. 2025년 2회 16번(3 1 2)은 화살표를 두 번 다시 이은 뒤 head 를 c 로 잡는 꼴이라, 마지막에 이은 화살표가 순서를 정한다.
환형 큐(2025년 2회 12번, 2 그리고 3)는 배열에 front · rear 두 첨자를 두고 (x + 1) % SIZE 로 돌린다. 넣을 때 rear 가, 꺼낼 때 front 가 움직이므로 연산마다 두 값을 표로 적으면 무엇이 남는지 보인다. 이중 포인터 구조체(2025년 2회 14번, 5 그리고 6)는 **pp 가 「포인터의 포인터」라 두 번 따라가 원본 구조체에 닿는다.
3-4. 재귀는 내려갔다 되감는 표다
재귀 함수는 자기를 부르며 내려가다 종료 조건에서 멈추고, 거기서부터 값을 돌려주며 되감는다. 표를 아래부터 채운다 — factorial(1) = 1, (2) = 2, (3) = 6 … (7) = 5040(2023년 3회 15번). 자릿수 합(예상 1회 3번)은 n % 10 + f(n / 10) 로 뒤 자리부터 더한다.
트리 순회는 재귀와 구조체 포인터가 합쳐진 것이다. 2026년 2회 7번의 func(n->a); func(n->b); if (++c == 3) result = n->v; 는 왼쪽 → 오른쪽 → 자기 순서라 후위 순회이고, 방문 순서 35 → 53 → 12 → 64 → 21 에서 세 번째인 12 가 답이다. 자기 처리가 두 재귀 호출 앞에 있으면 전위, 사이에 있으면 중위다.
통과 기준은 넷이다. 첫째, 'A' 65 · 'a' 97 · '0' 48 과 대소문자 32 차이로 글자 덧셈 문제를 푼다. 둘째, . 과 -> 를 가르고 구조체 멤버 값을 계산한다. 셋째, 연결 리스트 · 환형 큐를 그림과 표로 순회한다. 넷째, 재귀를 되감기 표로 계산하고 트리 순회 3종을 코드에서 구분한다. 기출 16문항이 이 넷 안에 있다.
연결 리스트는 노드를 만든 순서대로 출력된다.next 를 어디에 꽂았느냐가 순서다. 2025년 2회 16번은 화살표를 다시 이어 head 를 c 로 잡아 3 1 2 가 되고, 2025년 1회 18번은 앞에 끼워 넣은 뒤 3 을 맨 앞으로 옮겨 35421 이다. 화살표를 그리지 않으면 틀린다.
재귀는 위에서부터 계산하면 된다.종료 조건까지 내려간 뒤 아래부터 되감아야 값이 정해진다. 2026년 2회 14번(Java)처럼 음수까지 내려가는 재귀는 가장 깊은 호출의 반환값(음수)이 위로 올라오며 답을 바꾼다.
04기출
왜 이걸 하나 — 그림(노드 · 화살표)과 표(재귀 되감기)를 종이에 그리며 푸는 연습이다.
문자열 문제는 첨자를 0 부터 적어 두고, 구조체 · 리스트는 노드를 상자로 그려 화살표를 잇고, 재귀는 아래부터 표를 채운다. 세 가지 종이 도구가 이 장의 답이다.
2023-1회 · 3번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
int main(void) {
char *left = "qwer";
char *right = "qwtety";
for (int i = 0; left[i] != '\0'; i++) {
for (int j = 0; right[j] != '\0'; j++) {
if (left[i] == right[j]) {
printf("%c", left[i]);
}
}
}
return 0;
}
정답qwe
a의 q,w,e,r을 하나씩 들고 b에서 찾습니다. q(있음), w(있음), e(있음), r(없음) → "qwe". 이중 반복문은 "명단 대조 작업"으로 생각하면 됩니다. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「qwe」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-3회 · 4번C
다음 C 코드에서 구조체 포인터가 멤버에 접근하도록 ①에 들어갈 기호를 쓰시오.
#include <stdio.h>
struct Member {
int score;
};
int main(void) {
struct Member data = {
90
};
struct Member *pointer = &data;
printf("%d", pointer ( ① ) score);
return 0;
}
정답->
직접 접근은 점(.), 포인터 경유는 화살표(->). "쪽지(포인터)로 찾아가려면 화살표 이정표를 따라간다". 빈칸에 답을 넣어 실행하면 출력이 「90」 로 나오는 것을 확인했다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「->」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2023-3회 · 15번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
int factorial(int number) {
if (number <= 1) {
return 1;
}
return number * factorial(number - 1);
}
int main(void) {
printf("%d", factorial(7));
return 0;
}
정답5040
7! = 7×6×5×4×3×2×1 = 5040. 5!=120, 6!=720, 7!=5040은 외워두면 시간 절약. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「5040」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2024-1회 · 4번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
#include <string.h>
int main(void) {
char word[] = "ABCDEFG";
int n = (int)strlen(word);
for (int i = n - 1; i >= 0; i -= 2)
putchar(word[i]);
return 0;
}
정답GECA
역순 뒤집기 + 한 칸 건너뛰기의 조합. "GFEDCBA"에서 짝수 인덱스만 → G, E, C, A. 문자열 조작은 종이에 인덱스 표를 그려 추적하세요. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「GECA」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
✔ 재검증 완료: 2200−100=2100 → 2100×1.1³=2795.1 → %.2f로 2795.10 (뉴비티·기사퍼스트 일치). ※ 실제 시험지에서는 return 누락 논란으로 전원 정답 처리됐다는 설이 유력 — 학습 포인트는 구조체 멤버 접근과 %.2f 서식. 복원된 코드를 실행해 위 출력을 그대로 얻었다. (gcc(도커 alpine)) 그랜드라이프 가답안 표기는 「9981 and 2795.10」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
문자 = 숫자(아스키코드)라는 것이 핵심. 'A'+n으로 밀고, 'Z'를 넘으면 %26으로 되돌리는 패턴. 'A'=65, 'a'=97, '0'=48 암기 필수. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「Nd sc 1」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
연결리스트 = "보물찾기 쪽지" — 각 노드에 다음 장소(next)가 적혀 있습니다. 노드를 상자 그림으로 그리고 화살표를 따라가며 값을 확인하세요. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「20」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
노드 상자 + next 화살표 그림을 그리고, 교환 후 화살표(또는 값)가 어떻게 바뀌었는지 갱신한 다음 처음부터 순회. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「312」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2025-1회 · 18번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node *next;
} Node;
Node *push(Node *head, int value) {
Node *node = malloc(sizeof(Node));
node->value = value;
node->next = head;
return node;
}
Node *move_front(Node *head, int target) {
if (head == NULL || head->value == target)
return head;
Node *previous = NULL;
Node *current = head;
while (current != NULL && current->value != target) {
previous = current;
current = current->next;
}
if (current != NULL) {
previous->next = current->next;
current->next = head;
head = current;
}
return head;
}
int main(void) {
Node *head = NULL;
for (int i = 1; i <= 5; i++)
head = push(head, i);
head = move_front(head, 3);
for (Node *p = head; p != NULL; p = p->next) {
printf("%d", p->value);
}
return 0;
}
정답35421
삽입/교환으로 화살표(next)가 바뀐 최종 상태를 그린 뒤 head부터 순회. 화살표 갱신을 놓치는 것이 최다 실수. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「35421」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2025-2회 · 12번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
#define SIZE 3
typedef struct {
int data[SIZE];
int front;
int rear;
} Queue;
void enqueue(Queue *queue, int value) {
queue->data[queue->rear] = value;
queue->rear = (queue->rear + 1) % SIZE;
}
int dequeue(Queue *queue) {
int value = queue->data[queue->front];
queue->front = (queue->front + 1) % SIZE;
return value;
}
int main(void) {
Queue queue = {
{0},
0, 0
};
enqueue(&queue, 1);
enqueue(&queue, 2);
dequeue(&queue);
enqueue(&queue, 3);
int first = dequeue(&queue);
int second = dequeue(&queue);
printf("%d 그리고 %d", first, second);
return 0;
}
정답2 그리고 3
원형 큐 = "회전초밥 레일". front(꺼낼 위치)와 rear(넣을 위치)가 (x+1)%크기로 회전합니다. front/rear 값을 매 연산마다 기록하며 추적. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「2 그리고 3」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
이중 포인터(쪽지의 쪽지) + 구조체 화살표(->) 조합. 메모리 그림을 3단(변수→포인터→이중 포인터)으로 그리는 습관이 유일한 해법. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「5 그리고 6」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
✔ 재검증 완료: 기사퍼스트·정처기감자 일치로 확정 (일부 페이지의 "2003 1 2" 표기는 렌더링 오류로 판정 — 해당 페이지 자체 해설도 head→3→1→2로 유도). head가 어디를 가리키는지부터 확정하고 화살표를 따라가세요. 복원된 코드를 gcc(도커 alpine) 로 실행해 위 출력을 그대로 얻었다. 그랜드라이프 가답안 표기는 「3 1 2」. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
make_list 는 글자마다 노드를 만들어 head 앞에 끼우므로 B E S T 를 넣으면 T → S → E → B 순서의 리스트가 되고, 순회하며 찍으면 TSEB. malloc 으로 만든 노드는 free 로 돌려준다. 앞에 끼우는 삽입이 역순을 만드는 것이 이 문제의 전부다. 복원된 코드를 gcc(도커 alpine)로 실행해 TSEB 를 얻었다. 복원 출처는 grandlife.co.kr 회차별 복원 페이지(2026-09-14 대조). 공식 원문이 아니라 문장·변수명·값이 실제와 다를 수 있고, 문항 번호도 복원본마다 다르다.
2025-3회 · 7번C
다음 C 프로그램의 실행 결과를 쓰시오.
#include <stdio.h>
int main(void) {
char word[] = "REPUBLICOFKOREA";
int n = 0;
while (word[n] != '\0')
++n;
putchar(word[n - 2]);
return 0;
}
정답E
while 로 끝( )까지 세면 n = 15(REPUBLICOFKOREA 의 길이)이고, word[n − 2] 는 끝에서 둘째 글자 E 다. n 이