2025년도 1회, 2회, 3회의 정보처리기사 실기 기출문제 속 C 언어 문제를 정리하였다.
2025년 1회 정보처리기사 실기
문제 1. 문자의 ASCII 값
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| #include <stdio.h>
char Data[5] = {'B', 'A', 'D', 'E'};
char c;
int main() {
int i, temp, temp2;
c = 'C';
printf("%d\n", Data[3] - Data[1]);
for (i = 0; i < 5; ++i) {
if (Data[i] > c)
break;
}
temp = Data[i];
Data[i] = c;
i++;
for (; i < 5; ++i) {
temp2 = Data[i];
Data[i] = temp;
temp = temp2;
}
for (i = 0; i < 5; i++) {
printf("%c", Data[i]);
}
}
|
더보기
[정답]
4
BACDE
[풀이]
문자의 ASCII 값 : A=65, B=66, C=67, D=68, E=69
char Data[5] = {'B', 'A', 'D', 'E'};의 초기상태
1
2
3
4
5
6
7
| Data[0] = 'B' (66)
Data[1] = 'A' (65)
Data[2] = 'D' (68)
Data[3] = 'E' (69)
Data[4] = '\0' (0) ← 배열 끝을 나타내는 null 문
c = 'C' (67)
|
1
| printf("%d\n", Data[3] - Data[1]);
|
Data[3] = ‘E’ (69)
Data[1] = ‘A’ (65)
Data[3] - Data[1] = 69 - 65 = 4
printf("%d\n")이므로, 4를 출력 후, 줄바꿈을 한다.
1
2
3
4
| for (i = 0; i < 5; ++i) {
if (Data[i] > c)
break;
}
|
1
2
3
| i = 0; Data[0] = 'B' (66) > c = 'C' (67) ➔ false
i = 1; Data[1] = 'A' (65) > c = 'C' (67) ➔ false
i = 2; Data[2] = 'D' (68) > c = 'C' (67) ➔ true ➔ break; 실행
|
반복문에서의 break문을 만나면, 바로 그 반복문에서 빠져나온다.
따라서 i = 2에서 멈춘다.
1
2
3
| temp = Data[i];
Data[i] = c;
i++;
|
temp = Data[i]; 여기서 i = 2이므로,
temp = Data[2] = ‘D’
Data[i] = c; c값은 ‘C’이므로,
Data[2] = ‘C’
i++이므로, i값은 3이 된다.
정리해보면 현재 배열은 아래와 같다.
1
2
3
| Data = ['B', 'A', 'C', 'E', '\0']
temp = 'D'
i = 3
|
1
2
3
4
5
| for (; i < 5; ++i) {
temp2 = Data[i];
Data[i] = temp;
temp = temp2;
}
|
i = 3일때,
temp2 = Data[3] = ‘E’
Data[3] = temp = ‘D’
temp = temp2 = ‘E’
1
2
3
4
| Data = ['B', 'A', 'C', 'D', '\0']
temp = 'E'
temp2 = 'E'
i = 3
|
i = 4일때,
temp2 = Data[4] = ‘\0’
Data[4] = temp = ‘E’
temp = temp2 = ‘\0’
1
2
3
4
| Data = ['B', 'A', 'C', 'D', 'E']
temp = '\0'
temp = '\0'
i = 4
|
반복문 끝.
1
2
3
4
| // 한글자씩 출력
for (i = 0; i < 5; i++) {
printf("%c", Data[i]);
}
|
BACDE가 출력된다.
따라서 최종 답은 아래와 같다.
C언어의 printf 함수는 기본적으로 출력 후 자동 줄바꿈을 하지 않는다.
따라서 줄바꿈을 하고 싶다면, 출력 내용 끝 부분에 \0을 작성해주어야 한다.
문제 2. 포인터 배열 동적 할당
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| #include <stdio.h>
#include <stdlib.h>
void set(int** arr, int* data, int rows, int cols) {
for (int i = 0; i < rows * cols; ++i) {
arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
}
}
int main() {
int rows = 3, cols = 3, sum = 0;
int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9};
int** arr;
arr = (int**) malloc(sizeof(int*) * rows);
for (int i = 0; i < cols; i++) {
arr[i] = (int*) malloc(sizeof(int) * cols);
}
set(arr, data, rows, cols);
for (int i = 0; i < rows * cols; i++) {
sum += arr[i / rows][i % cols] * (i % 2 == 0 ? 1 : -1);
}
for (int i = 0; i < rows; i++) {
free(arr[i]);
}
free(arr);
printf("%d", sum);
}
|
더보기
[정답]
13
[풀이]
참고
malloc(sizeof(int*) * rows) : int 포인터 배열 동적 할당free() : malloc으로 할당한 메모리 해제
1
2
3
4
5
6
7
8
9
10
| int rows = 3, cols = 3, sum = 0;
int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9};
int** arr;
// rows 개수만큼 int 포인터 배열을 동적 할당
arr = (int**) malloc(sizeof(int*) * rows);
for (int i = 0; i < cols; i++) {
// 각 포인터가 cols 개수만큼 int 배열을 가리키도록 생성
arr[i] = (int*) malloc(sizeof(int) * cols);
}
|
메모리 구조는 아래와 같다.
1
2
3
4
5
| arr
↓
[ptr0] → [int][int][int]
[ptr1] → [int][int][int]
[ptr2] → [int][int][int]
|
set(arr, data, rows, cols); 호출
1
2
3
4
5
| void set(int** arr, int* data, int rows, int cols) {
for (int i = 0; i < rows * cols; ++i) {
arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
}
}
|
| i | data[i] | (i + 1) / rows | % rows | (i + 1) % cols | 위치 |
|---|
| 0 | 5 | 0 | 0 | 1 | arr[0][1] = 5 |
| 1 | 2 | 0 | 0 | 2 | arr[0][2] = 2 |
| 2 | 7 | 1 | 1 | 0 | arr[1][0] = 7 |
| 3 | 4 | 1 | 1 | 1 | arr[1][1] = 4 |
| 4 | 1 | 1 | 1 | 2 | arr[1][2] = 1 |
| 5 | 8 | 2 | 2 | 0 | arr[2][0] = 8 |
| 6 | 3 | 2 | 2 | 1 | arr[2][1] = 3 |
| 7 | 6 | 2 | 2 | 2 | arr[2][2] = 6 |
| 8 | 9 | 3 | 0 | 0 | arr[0][0] = 9 |
완성된 배열
1
2
3
| arr[0] = {9, 5, 2}
arr[1] = {7, 4, 1}
arr[2] = {8, 3, 6}
|
1
2
3
| for (int i = 0; i < rows * cols; i++) {
sum += arr[i / rows][i % cols] * (i % 2 == 0 ? 1 : -1);
}
|
| i | i / rows | i % cols | arr[i / rows][i % cols] | i % 2 == 0 | sum |
|---|
| 0 | 0 | 0 | arr[0][0] = 9 | 1 | 9 |
| 1 | 0 | 1 | arr[0][1] = 5 | -1 | -5 |
| 2 | 0 | 2 | arr[0][2] = 2 | 1 | 2 |
| 3 | 1 | 0 | arr[1][0] = 7 | -1 | -7 |
| 4 | 1 | 1 | arr[1][1] = 4 | 1 | 4 |
| 5 | 1 | 2 | arr[1][2] = 1 | -1 | -1 |
| 6 | 2 | 0 | arr[2][0] = 8 | 1 | 8 |
| 7 | 2 | 1 | arr[2][1] = 3 | -1 | -3 |
| 8 | 2 | 2 | arr[2][2] = 6 | 1 | 6 |
sum = 9 - 5 + 2 - 7 + 4 -1 + 8 -3 + 6
sum = 13
따라서 출력되는 결과는 13이다.
문제 3. 연결 리스트 (Linked List)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
| #include <stdio.h>
#include <stdlib.h>
typedef struct Data {
int value;
struct Data* next;
} Data;
Data* insert(Data* head, int value) {
Data* new_node = (Data*)malloc(sizeof(Data));
new_node->value = value;
new_node->next = head;
return new_node;
}
Data* reconnect(Data* head, int value) {
if (head == NULL || head->value == value) return head;
Data* prev = NULL, *curr = head;
while(curr != NULL && curr->value != value) {
prev = curr;
curr = curr->next;
}
if (curr != NULL && prev != NULL) {
prev->next = curr->next;
curr->next = head;
head = curr;
}
return head;
}
int main() {
Data* head = NULL, *curr;
for(int i = 1; i <= 5; i++)
head = insert(head, i);
head = reconnect(head, 3);
for (curr = head; curr != NULL; curr = curr->next)
printf("%d", curr->value);
return 0;
}
|
더보기
[정답]
35421
[풀이]
구조체 정의
1
2
3
4
| typedef struct Data {
int value;
struct Data* next;
} Data;
|
연결 리스트(Linked List)의 노드를 정의한 것이다.
value : 노드의 값next : 다음 노드를 가리키는 포인터
insert() 함수 - 맨 앞에 노드 추가
1
2
3
4
5
6
| Data* insert(Data* head, int value) {
Data* new_node = (Data*)malloc(sizeof(Data));
new_node->value = value;
new_node->next = head;
return new_node;
}
|
새로운 노드를 생성한 뒤, 값을 넣고
기존 리스트의 맨 앞(head)에 삽입하는 함수이다.
1
2
| for(int i = 1; i <= 5; i++)
head = insert(head, i);
|
1
2
3
4
5
| i=1 -> 1 -> NULL
i=2 -> 2 -> 1 -> NULL
i=3 -> 3 -> 2 -> 1 -> NULL
i=4 -> 4 -> 3 -> 2 -> 1 -> NULL
i=5 -> 5 -> 4 -> 3 -> 2 -> 1 -> NULL
|
reconnect() 함수 - 특정 값을 가진 노드를 찾아 맨 앞으로 이동
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| Data* reconnect(Data* head, int value) {
// 예외 처리
// 리스트가 비어있거나 이미 찾는 값이 맨 앞에 있는 경우 "그대로 반환"
if (head == NULL || head->value == value) return head;
// 노드 탐색 (curr = 현재 탐색 중인 노드, prev = curr의 이전 노드)
Data* prev = NULL, *curr = head;
while(curr != NULL && curr->value != value) {
prev = curr;
curr = curr->next;
}
// 위치 변경
if (curr != NULL && prev != NULL) {
prev->next = curr->next; // 기존 위치에서 제거 (->5->4->2->1)
// 맨 앞으로 이동 (3->5->4->2->1)
curr->next = head;
head = curr;
}
return head;
}
|
최종 출력
1
2
3
4
5
6
7
8
9
10
11
12
| int main() {
Data* head = NULL, *curr;
for(int i = 1; i <= 5; i++)
head = insert(head, i); // 5->4->3->2->1
head = reconnect(head, 3); // 3->5->4->2->1
for (curr = head; curr != NULL; curr = curr->next)
printf("%d", curr->value);
return 0;
}
|
아래와 같이 띄어쓰기 없이 출력된다.
연결 리스트(Linked List)
장점
- 동적 크기 : 필요에 따라 크기 조절 가능
- 삽입/삭제 용이 : 중간에 노드 추가/제거가 쉬움
- 메모리 효율 : 필요한 만큼만 메모리 사용
단점
- 순차 접근 : 특정 위치에 바로 접근 불가능
- 추가 메모리 : 포인터 저장을 위한 추가 메모리가 필요
- 캐시 효율성 : 데이터가 메모리에 연속적으로 저장되지 않음
문제 4. 16진수 ➔ 2진수, &(AND) 연산
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| #include <stdio.h>
typedef struct student {
char* name;
int score[3];
} Student;
int dec(int enc) {
return enc & 0xA5;
}
int sum(Student* p) {
return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}
int main() {
Student s[2] = { "Kim", {0xA0, 0xA5, 0xDB}, "Lee", {0xA0, 0xED, 0x81} };
Student* p = s;
int result = 0;
for (int i = 0; i < 2; i++) {
result += sum(&s[i]);
}
printf("%d", result);
return 0;
}
|
더보기
[정답]
908
[풀이]
1
2
3
| int dec(int enc) {
return enc & 0xA5;
}
|
& (AND 연산)
- 두 비트가 모두 1일 때, 결과는 1이 된다.
하나라도 0이면 결과는 0이 된다. 0xA5가 특정 비트만 골라내는 역할이라고 보면 된다.
🤔 0xA5가 뭐야?
c언어에서 16진수를 표현할 때, 앞에 0x를 붙인다.
1
| 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ➔ 총 16개
|
- A = 10
- A5 = (10 × 16^1) + (5 × 16^0)
= 160 + 5
= 165
165를 2진수로 바꾸면?
1010 0101이 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| /*
dec 함수는 점수(enc)에 대해 0xA5와 AND 연산을 수행하여
특정 비트만 추출한 값을 반환한다.
*/
int dec(int enc) {
return enc & 0xA5;
}
/*
sum 함수는 한 학생의 score 배열에 있는 3개의 값을 각각 dec() 함수로 처리한 후,
그 결과를 모두 더한 값을 반환한다.
*/
int sum(Student* p) {
return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}
|
(1) Kim
- 0xA0
- A = 1010
0 = 0000 - 1010 0000
1
2
3
4
| 1010 0000 (0xA0)
& 1010 0101 (0xA5)
------------
1010 0000 = 0xA0 = 160
|
- 0xA5
- 0xDB
- D = 1101
B = 1011 - 1101 1011
1
2
3
4
| 1101 1011 (0xDB)
& 1010 0101 (0xA5)
------------
1000 0001 = 0x81 = 129
|
총 합계
160 + 165 + 129 = 454
(2) Lee
- 0xA0
- 0xED
- E = 1110
D = 1101 - 1110 1101
1
2
3
4
| 1110 1101 (0xED)
& 1010 0101 (0xA5)
------------
1010 0101 = 0xA5 = 165
|
- 0x81
- 8 = 1000
1 = 0001 - 1000 0001
1
2
3
4
| 1000 0001 (0x81)
& 1010 0101 (0xA5)
------------
1000 0001 = 0x81 = 129
|
총 합계
160 + 165 + 129 = 454
(최종 결과)
454 + 454 = 908
2025년 2회 정보처리기사 실기
문제 5. 원형 큐 (Circular Queue) 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| #include <stdio.h>
#define SIZE 3
typedef struct {
int a[SIZE];
int front;
int rear;
} Queue;
void enq(Queue* q, int val) {
q->a[q->rear] = val;
q->rear = (q->rear + 1) % SIZE;
}
int deq(Queue* q) {
int val = q->a[q->front];
q->front = (q->front + 1) % SIZE;
return val;
}
int main() {
Queue q = { {0}, 0, 0 };
enq(&q,1); enq(&q,2); deq(&q); enq(&q,3);
int first = deq(&q);
int second = deq(&q);
printf("%d 그리고 %d", first, second);
return 0;
}
|
더보기
[정답]
2 그리고 3
[풀이]
1
2
3
4
5
| typedef struct {
int a[SIZE];
int front; // 꺼내는 위치
int rear; // 넣는 위치
} Queue;
|
Queue 자료구조 특징
- FIFO (First In First Out)
- 넣게 되면 뒤에 붙이고, 꺼내게 되면 앞에서 제거한다.
1
2
3
4
5
6
7
8
9
10
11
12
| // 데이터 넣기
void enq(Queue* q, int val) {
q->a[q->rear] = val;
q->rear = (q->rear + 1) % SIZE;
}
// 데이터 꺼내기
int deq(Queue* q) {
int val = q->a[q->front];
q->front = (q->front + 1) % SIZE;
return val;
}
|
1
2
3
4
5
6
7
8
9
10
11
| int main() {
Queue q = { {0}, 0, 0 };
enq(&q,1); enq(&q,2); deq(&q); enq(&q,3);
int first = deq(&q);
int second = deq(&q);
printf("%d 그리고 %d", first, second);
return 0;
}
|
- 초기 상태 (
Queue q = { {0}, 0, 0 };)
1
2
3
| rear = 0
a[0] = 1
rear = (0 + 1) % 3 ⟹ 1
|
1
2
3
| rear = 1
a[1] = 2
rear = (1 + 1) % 3 ⟹ 2
|
1
2
| val = a[front] ⟹ a[0] ⟹ 1
front = (0 + 1) % 3 ⟹ 1
|
1
2
| a[2] = 3
rear = (2 + 1) % 3 ⟹ 0
|
int first = deq(&q); ⟹ 2deq(&q) ⟹ 2- int val = a[1] ⟹ 2
- front = (1 + 1) % 3 ⟹ 2
int second = deq(&q); ⟹ 3deq(&q) ⟹ 3- int val = a[2] ⟹ 3
- front = (2 + 1) % 3 ⟹ 0
1
| printf("%d 그리고 %d", first, second);
|
현재 first 값과 second 값은 다음과 같다.
first = 2, second = 3
따라서 2 그리고 3이 출력된다.
문제 6. 이중 포인터 (Double Pointer)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| #include <stdio.h>
struct dat {
int x;
int y;
};
int main() {
struct dat a[] = { {1,2}, {3,4}, {5,6} };
struct dat* ptr = a;
struct dat** pptr = &ptr;
(*pptr)[1] = (*pptr)[2];
printf("%d 그리고 %d", a[1].x, a[1].y);
return 0;
}
|
더보기
[정답]
5 그리고 6
[풀이]
1
| struct dat a[] = { {1,2}, {3,4}, {5,6} };
|
배열 a 안에 구조체 3개가 들어있다.
| index | x | y |
|---|
| a[0] | 1 | 2 |
| a[1] | 3 | 4 |
| a[2] | 5 | 6 |
1
2
| struct dat* ptr = a; // ptr = a[0]의 주소, ptr ➔ a[0]
struct dat** pptr = &ptr; // pptr ➔ ptr ➔ a[0]
|
1
| (*pptr)[1] = (*pptr)[2];
|
1
2
3
4
5
6
7
| *pptr = ptr
(*pptr)[1] = ptr[1] = a[1]
(*pptr)[2] = ptr[2] = a[2]
(*pptr)[1] = (*pptr)[2]
➔ a[1] = a[2] // 값이 복사되어 아래와 같이 바뀐다.
|
| index | x | y |
|---|
| a[0] | 1 | 2 |
| a[1] | 5 | 6 |
| a[2] | 5 | 6 |
1
| printf("%d 그리고 %d", a[1].x, a[1].y);
|
1
2
| a[1].x = 5
a[1].y = 6
|
따라서 5 그리고 6이 출력된다.
이중 포인터란,
포인터를 가리키는 포인터이다.
1
2
| struct dat* ptr = a; // ptr → a[0]
struct dat** pptr = &ptr; // pptr → ptr
|
문제 7. node 구조체
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #include <stdio.h>
#include <stdlib.h>
struct node {
int p;
struct node* n;
};
int main() {
struct node a = {1, NULL};
struct node b = {2, NULL};
struct node c = {3, NULL};
a.n = &b; b.n = &c; c.n = NULL;
c.n = &a; a.n = &b; b.n = NULL;
struct node* head = &c;
printf("%d %d %d", head->p, head->n->p, head->n->n->p);
return 0;
}
|
더보기
[정답]
3 1 2
[풀이]
1
| printf("%d %d %d", head->p, head->n->p, head->n->n->p);
|
따라서 3 1 2가 출력된다.
문제 8. 단일 연결 리스트 - head 삽입
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| #include <stdio.h>
#include <stlib.h>
struct node {
char c;
struct node* p;
};
struct node* func(char* s) {
struct node* h = NULL, *n;
while (*s) {
n = malloc(sizeof(struct node));
n->c = *s++;
n->p = h;
h = n;
}
return h;
}
int main() {
struct node* n = func("BEST");
while (n) {
putchar(n->c);
struct node* t = n;
n = n->p;
free(t);
}
return 0;
}
|
더보기
[정답]
TSEB
[풀이]
1
2
3
4
| struct node {
char c; // 문자 저장
struct node* p; // 다음 노드를 가리키는 포인터
};
|
1
2
3
4
5
6
7
8
9
10
11
12
| struct node* func(char* s) {
struct node* h = NULL, *n;
while (*s) {
n = malloc(sizeof(struct node)); // 새 노드 동적 할당
n->c = *s++;
/* 아래 두 코드 ➔ 새 노드가 항상 맨 앞에 삽입되도록 함 */
n->p = h; // 새 노드가 기존 리스트를 가리키게 함
h = n; // 새 노드를 리스트의 시작(head)으로 변경
}
return h;
}
|
1
| struct node* n = func("BEST");
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| (1) n = 1
n -> [? | ?]
n -> c = B, n -> [B | ?]
s++; ➔ E, s -> E
n -> p = NULL, n -> [B | NULL]
h = n = B
h -> B (head로 이동됨)
⟹ 현재 : h -> B -> NULL
(2) n = 2
n -> [? | ?]
n -> c = E, n -> [E | ?]
s++; ➔ S, s-> S
n -> p = h, h -> B이므로, n -> [E | B]
h = n = E
h -> E
⟹ 현재 : h -> E -> B -> NULL
(3) n = 3
n -> [? | ?]
n -> c = S, n -> [S | ?]
s++; ➔ T, s-> T
n -> p = h, h -> E이므로, n -> [S | E]
h = n = S
h -> S
⟹ 현재 : h -> S -> E -> B -> NULL
(4) n = 4
n -> [? | ?]
n -> c = T, n -> [T | ?]
s++; ➔ \0
n -> p = h, h -> S이므로, n -> [T | S]
h = n = T
h -> T
⟹ 현재 : h -> T -> S -> E -> B -> NULL
|
반환되는 리스트 : T -> S -> E -> B -> NULL
1
2
3
4
5
6
7
8
9
10
11
| int main() {
// ...
while (n) {
putchar(n->c); // 문자 하나를 출력하는 함수
struct node* t = n;
n = n->p; // 다음 노드로 이동
free(t); // malloc으로 만든 메모리를 삭제하는 함수
}
return 0;
}
|
순회하며 문자열 출력하면 된다.
따라서 TSEB가 출력된다.
2025년 3회 정보처리기사 실기
문제 9. 문자열 포인터 연산
1
2
3
4
5
6
7
8
9
10
11
12
13
| #include <stdio.h>
struct Test {
int i;
const char *g;
};
int main() {
struct Test test[] = { {1, "AB"}, {2, "DC"}, {3, "EB"} };
struct Test *p = &test[1];
printf("%s", p->g + (p->i - 1));
return 0;
}
|
더보기
[정답]
C
[풀이]
1
2
3
4
| struct Test {
int i;
const char *g; // 문자열의 시작 주소를 가리키는 포인터
};
|
1
| struct Test test[] = { {1, "AB"}, {2, "DC"}, {3, "EB"} };
|
1
2
3
| struct Test *p = &test[1]; // test[1] = {2, "DC"}
// p->i = 2
// p->g = "DC"를 가리킴
|
1
| printf("%s", p->g + (p->i - 1));
|
- p->i - 1 = 2 - 1 = 1
- p->g + 1
%s는 해당 위치부터 문자열 끝(\0)까지 출력하므로
“C”가 출력된다.
따라서 출력 결과는 C이다.
문제 10. 후위연산, 전위연산
1
2
3
4
5
6
7
8
9
10
| #include <stdio.h>
int main(void) {
char str[] = "REPUBLICOFKOREA";
int a = 0;
while (str[a] != '\0')
++a;
putchar(str[a-2]);
return 0;
}
|
더보기
[정답]
E
[풀이]
먼저 짚고 가기
a++ (후위연산) : 현재 값을 사용 후 증가
++a (전위연산) : 먼저 증가 후 사용
Tip. 이 문제의 경우, 후위연산/전위연산 둘 다 최종 a = 15가 나온다.
1
2
| while (str[a] != '\0')
++a;
|
| str[a] | a |
|---|
| str[0] = R | a = 1 |
| str[1] = E | a = 2 |
| str[2] = P | a = 3 |
| str[3] = U | a = 4 |
| str[4] = B | a = 5 |
| str[5] = L | a = 6 |
| str[6] = I | a = 7 |
| str[7] = C | a = 8 |
| str[8] = O | a = 9 |
| str[9] = F | a = 10 |
| str[10] = K | a = 11 |
| str[11] = O | a = 12 |
| str[12] = R | a = 13 |
| str[13] = E | a = 14 |
| str[14] = A | a = 15 |
str[15] = '\0'이므로, 반복문 종료
putchar() : 하나의 문자를 콘솔화면에 출력
따라서 str[13]은 “E”이므로,
“E” 가 최종적으로 출력된다.
문제 11. 비트 연산자 (XOR, OR, AND)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #include <stdio.h>
struct Node {
struct Node* next;
unsigned int x;
};
int main() {
struct Node t1 = {0, 5u};
struct Node t2 = {0, 7u};
struct Node t3 = {0, 11u};
t3.next = &t2;
t2.next = &t1;
struct Node* curr = &t3;
int sum = 0;
while (curr) {
sum = sum * 3 + curr->x;
curr = curr->next;
}
sum = (sum^42u) + 100u;
printf("%u\n", sum);
}
|
더보기
[정답]
187
[풀이]
1
2
3
4
5
6
| struct Node {
struct Node* next;
// int의 범위를 양의 정수 범위로만 사용한 자료형 (unsigned int) ⟹ 음수 제외
// 0 ~ 4,294,967,295까지 표현함
unsigned int x;
};
|
1
2
| t3.next = &t2;
t2.next = &t1;
|
t3 -> t2 -> t1 연결된다.
1
2
3
4
5
6
7
| struct Node* curr = &t3;
int sum = 0;
while (curr) {
sum = sum * 3 + curr->x;
curr = curr->next;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| (1) &t3
sum = sum * 3 + curr->x;
sum = (0 * 3) + (11u) = 11u
curr = curr -> next;
curr = &t2
---------------------------
(2) &t2
sum = sum * 3 + curr->x;
sum = (11u * 3) + (7u)
= 33u + 7u = 40u
curr = curr -> next;
curr = &t1
---------------------------
(3) &t1
sum = sum * 3 + curr->x;
sum = (40u * 3) + (5u)
= 120u + 5u = 125u
curr = curr -> next;
curr = null
|
1
2
| sum = (sum^42u) + 100u;
printf("%u\n", sum);
|
비트 연산자
- ^(XOR)
두 비트가 다를 때는 1
두 비트가 같으면 0 - | (OR)
두 비트 중 하나만 1이면 ➔ 1
두 비트 모두 0이면 ➔ 0 - & (AND)
두 비트 모두 1이면 ➔ 1
두 비트 중 하나라도 0이면 ➔ 0
이 문제에서는 ^(XOR) 비트 연산자를 사용하고 있다.
두 비트가 다를 때는 1, 두 비트가 같으면 0이다.
1
| sum = (sum^42u) + 100u;
|
현재 sum값은 125u이다.
(125u^42u) + 100u
- 125u (10진수인 125를 2진수로 바꿔야한다.)
1
2
3
4
5
6
7
8
| 125 ÷ 2 = 62 --- 1
62 ÷ 2 = 31 --- 0
31 ÷ 2 = 15 --- 1
15 ÷ 2 = 7 --- 1
7 ÷ 2 = 3 --- 1
3 ÷ 2 = 1 --- 1
1111101
|
- 42u (10진수인 42를 2진수로 바꿔야한다.)
1
2
3
4
5
6
7
| 42 ÷ 2 = 21 --- 0
21 ÷ 2 = 10 --- 1
10 ÷ 2 = 5 --- 0
5 ÷ 2 = 2 --- 1
2 ÷ 2 = 1 --- 0
101010
|
^(XOR) 비트 연산자 : 두 비트가 다를 때는 1, 두 비트가 같으면 0
1
2
3
4
| 0111 1101
^ 0010 1010
------------
0101 0111
|
0101 0111이 나온다.
이제 이 2진수 값을 10진수로 다시 바꾸면 된다.
1
2
3
4
5
6
| 0101 0111
= (2^7 * 0) + (2^6 * 1) + (2^5 * 0) + (2^4 * 1) + (2^3 * 0) + (2^2 * 1) + (2^1 * 1) + (2^0 * 1)
= 0 + 64 + 0 + 16 + 0 + 4 + 2 + 1
= 64 + 16 + 4 + 2 + 1
= 80 + 7
= 87
|
125u^42u 값은 87이다!
그럼 최종 sum값을 구해보자.
sum = (125u^42u) + 100u
= 87u + 100u
= 187u
따라서 최종 답은 187이다.
187u ← 여기서 u는 무엇일까?
u는 숫자를 unsigned int로 만들어주는 표시이다. (음수 제외)
문제 12. 비트 시프트 연산자
1
2
3
4
5
6
7
8
9
10
| #include <stdio.h>
int main() {
int x = 7, y = 4, z;
z = y % 3 < 3 ? 2 : 1;
z = z & z >> 1;
z = x > 5 && z <= 3 ? z * x : z / x;
printf("%d", z);
return 0;
}
|
더보기
[정답]
0
[풀이]
1
| int x = 7, y = 4, z; // 초기 변수
|
1
| z = y % 3 < 3 ? 2 : 1; // z = 2
|
1
| z = z & z >> 1; // z = 0
|
» (비트 시프트 연산자) : 오른쪽으로 지정한 비트 수만큼 밀어준다.
& (비트 연산자) : 두 비트 모두 1이면 1, 하나라도 0이면 0
시프트 연산자가 비트 연산자보다 우선순위가 높다.
- z » 1 부터 실행
- z = 2 (2를 2진수로 바꾸면? 2진수 값 :
10) 10을 오른쪽으로 1만큼 밀어주면, 01이 된다.
- z & z » 1
1
2
3
4
| 10
& 01
------------
00 = (2^1 * 0 + 2^0 * 0) = 0 + 0 = 0
|
따라서 z값은 0이 된다.
1
| z = x > 5 && z <= 3 ? z * x : z / x; // z = 0
|
- x > 5 && z <= 3
- x > 5 ⟹ x = 7 이므로
true 반환 - z <= 3 ⟹ z = 0 이므로
true 반환 true && true이므로 true이다.
true에 해당하는 z * x를 실행
현재 z값인 0이 출력된다.
정리
printf함수
기본적으로 출력 후 자동 줄바꿈을 하지 않는다.
줄바꿈을 하고 싶다면, 출력 내용 끝 부분에 \0을 작성해주어야 한다.
비트 연산자 (XOR, AND, OR)
1. ^(XOR)
- 두 비트가 다를 때는 1
두 비트가 같으면 0
2. & (AND)
- 두 비트가 모두 1이면 1
두 비트 중 하나라도 0이면 0
3. | (OR)
- 두 비트 중 하나만 1이면 1
두 비트 모두 0이면 0
비트 시프트 연산자
1
| z >> 1 // 오른쪽으로 1 만큼 밀어준다.
|
16진수
c언어에서 16진수를 표현할 때, 앞에 0x를 붙인다.
또한 16진수로 표현하기 위해선 숫자가 16개가 필요하다.
1
| 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ➔ 총 16개
|
printf() 주요 서식 지정자
서식 지정자는 printf(), scanf() 등의 함수에서 데이터의 자료형과 출력 및 입력 형식을 지정하는 역할을 한다.
(printf() : 출력 형식을 지정, scanf() : 입력 형식을 지정)
정수
| 서식 지정자 | 자료형 | 의미 |
|---|
| %d | int | 10진수 정수 출력 |
| %i | int | 10진수 정수 출력 (%d와 동일하게 동작) |
| %u | unsigned int | 부호 없는 int 타입 정수 출력 (10진수) |
문자/문자열
| 서식 지정자 | 자료형 | 의미 |
|---|
| %c | char | 문자 하나 출력 |
| %s | char*, char[] | 문자열 출력 (\0까지) |
[예시 코드]
1
2
3
4
5
6
7
8
9
10
| printf("%d", 10); // 10
// u는 이 숫자를 unsigned int로 만드는 접미사이다.
// 따라서 10이 출력된다.
printf("%u", 10u); // 10
char *str = "ABC";
printf("%c", str[0]); // A
printf("%s", str); // ABC
|