본문으로 건너뛰기

단원 모의 문제

정보처리기사 목차프로그래밍 기초문제 15개

19단원 '프로그래밍 기초'의 열두 레슨에서 한 문제씩 12문제를 내고, 끝에 실기 꼴 3문제를 두었습니다. 3과목의 첫 단원이라 앞 단원에서 섞어 온 문제는 없습니다. 코드는 C이고, 출력은 clang(C 코드를 실행 파일로 바꾸는 프로그램)으로 돌린 결과입니다. 출력을 쓰는 문제는 줄바꿈까지 그대로 씁니다. 1~12번은 보기 넷 가운데 하나를 고른 뒤 정답을 펼쳐 맞춰 보고, 13~15번은 종이에 답을 끝까지 쓴 뒤 펼치세요. 띄어쓰기만 다르면 같은 답입니다.

문제 1

다음 (가)~(라) 가운데 C에서 변수 이름으로 쓸 수 있는 것만 모두 고른 것을 고르세요.

  • (가) Count

  • (나) count_2

  • (다) 2count

  • (라) for

  • ① (나)

  • ② (가)·(나)

  • ③ (가)·(나)·(다)

  • ④ (가)·(나)·(라)

정답

② — 변수 이름은 영문자·숫자·밑줄로 짓고, 숫자로 시작하지 않으며, 예약어를 쓰지 않습니다. 2count는 숫자로 시작하고, for는 반복문을 여는 예약어라 이름이 될 수 없습니다.

  • ① 대문자로 시작하는 이름은 안 된다고 봤습니다. 대문자도 영문자라 쓸 수 있고, Count와 count는 다른 이름으로 칩니다.
  • ③ 숫자가 들어가면 자리와 상관없이 된다고 봤습니다. 숫자는 둘째 글자부터 쓸 수 있고 첫 글자로는 쓰지 못합니다.
  • ④ 예약어도 이름으로 쓸 수 있다고 봤습니다. for는 C가 반복문에 쓰는 낱말이라 변수 이름이 될 수 없습니다.

다시 볼 레슨: 출력과 변수

문제 2

C에서 (가) char 하나·int 하나·double 하나의 크기를 모두 더한 바이트 수와 (나) (int)7.9 / 2의 값으로 알맞은 것을 고르세요. int는 4바이트, double은 8바이트입니다.

  • ① (가) 13 · (나) 3
  • ② (가) 13 · (나) 4
  • ③ (가) 14 · (나) 3
  • ④ (가) 14 · (나) 4
정답

① — C의 char는 1바이트, int는 4바이트, double은 8바이트라 모두 13바이트입니다. (int)7.9는 소수 부분을 버려 7이 되고, 정수끼리 나눈 7 / 2는 몫만 남아 3입니다.

  • ② (나)에서 7.9를 8로 반올림했습니다. 실수를 정수로 바꾸면 소수 부분을 버립니다.
  • ③ (가)에서 char를 2바이트로 셌습니다. char가 2바이트인 것은 Java이고, C의 char는 1바이트입니다.
  • ④ 두 오해가 겹쳤습니다. C의 char는 1바이트이고, 정수로 바꿀 때 소수 부분은 버립니다.

다시 볼 레슨: 자료형과 형 변환

문제 3

다음 코드가 찍는 값을 고르세요.

#include <stdio.h>

int main(void) {
  int a = 10, b = 3, c = 0;
  int x = a + b * 6 % 4;
  int y = a < b && (c = 7);
  printf("%d %d %d\n", x, y, c);
  return 0;
}
  • ① 12 0 0
  • ② 12 0 7
  • ③ 16 0 0
  • ④ 16 0 7
정답

① — 실행 결과는 이렇습니다.

실행 결과
12 0 0

*와 %는 같은 순위라 왼쪽부터 묶어, b * 6의 18을 먼저 셈하고 18 % 4의 2를 10에 더해 x는 12입니다. y는 a < b가 0이라 &&의 오른쪽 (c = 7)을 셈하지 않아 0이고, c는 0 그대로입니다.

  • ② c에 7이 들어간다고 봤습니다. &&의 왼쪽이 0이면 결과가 0으로 정해져 오른쪽의 대입은 실행되지 않습니다.
  • ③ %를 *보다 먼저 셈해 6 % 4의 2에 3을 곱했습니다. *·/·%는 같은 순위라 왼쪽부터 묶습니다.
  • ④ 두 오해가 겹쳤습니다. 같은 순위는 왼쪽부터 묶고, 왼쪽이 0인 &&는 오른쪽을 건너뜁니다.

다시 볼 레슨: 산술·관계·논리 연산자와 우선순위

문제 4

다음 코드가 찍는 값을 고르세요.

#include <stdio.h>

int main(void) {
  int i = 5, j;
  j = i-- + 2;
  i += j % 3;
  int k = i > j ? i++ : --j;
  printf("%d %d %d\n", i, j, k);
  return 0;
}
  • ① 4 5 5
  • ② 4 5 6
  • ③ 5 6 6
  • ④ 5 6 7
정답

③ — 실행 결과는 이렇습니다.

실행 결과
5 6 6

5번 줄은 후위라 i의 지금 값 5에 2를 더한 7이 j에 들고, 그다음 i가 4가 됩니다. 6번 줄은 7 % 3의 1을 더해 i가 5입니다. 7번 줄은 5 > 7이 거짓이라 : 뒤의 --j를 셈합니다. 전위라 j가 먼저 6이 되고 그 6이 k에 듭니다. 고르지 않은 i++는 실행되지 않습니다.

  • ① 5번 줄에서 줄인 뒤의 4에 2를 더했습니다. 후위 i--는 줄이기 전 값 5를 씁니다. j를 6으로 두면 i는 4 + 0, k는 줄인 j의 5가 됩니다.
  • ② 두 오해가 겹쳤습니다. 후위 i--는 줄이기 전 값을, 전위 --j는 줄인 뒤 값을 씁니다.
  • ④ --j가 줄이기 전 값 7을 k에 넣는다고 봤습니다. 전위는 먼저 줄이고 줄인 값 6을 씁니다.

다시 볼 레슨: 증감·대입·조건 연산자

문제 5

다음 코드가 찍는 것을 고르세요.

#include <stdio.h>

int main(void) {
  int t = 15;
  if (t > 10) {
    printf("A");
  } else if (t > 5) {
    printf("B");
  }
  if (t % 5) {
    printf("C");
  }
  printf("D\n");
  return 0;
}
  • ① ABCD
  • ② ABD
  • ③ ACD
  • ④ AD
정답

④ — 실행 결과는 이렇습니다.

실행 결과
AD

첫 if는 t > 10이 참이라 A를 찍고, else if는 앞 갈래가 참이었으니 조건을 보지 않습니다. 둘째 if는 15 % 5가 0이라 거짓이어서 C를 찍지 않고, 그 아래 줄이 D를 찍습니다.

  • ① 두 오해가 겹쳤습니다. else if는 앞 갈래가 참이면 건너뛰고, 나머지 0은 거짓입니다.
  • ② else if도 조건이 참이면 실행된다고 봤습니다. else if는 앞 갈래가 모두 거짓일 때만 조건을 봅니다.
  • ③ t % 5를 '5로 나누어떨어지는가'로 읽어 참으로 봤습니다. 식의 값이 나머지 0이라 거짓이고, 0이 아닌 나머지일 때 참입니다.

다시 볼 레슨: 조건문

문제 6

다음 코드가 찍는 값을 고르세요.

#include <stdio.h>

int main(void) {
  int i, c = 0;
  for (i = 1; i < 50; i *= 3) {
    c++;
  }
  printf("%d %d\n", i, c);
  return 0;
}
  • ① 27 4
  • ② 27 5
  • ③ 81 4
  • ④ 81 5
정답

③ — 실행 결과는 이렇습니다.

실행 결과
81 4

i가 1, 3, 9, 27일 때 몸을 실행해 c는 4입니다. 27에 3을 곱한 81에서 i < 50이 거짓이 되어 반복이 끝나므로, 끝난 뒤 i는 조건을 처음 어긴 값 81입니다.

  • ① 끝난 뒤 i를 마지막으로 몸을 실행한 값 27로 봤습니다. 한 바퀴 뒤 i *= 3을 한 다음에 조건을 보고 끝나므로 i는 81입니다.
  • ② 두 오해가 겹쳤습니다. 끝난 뒤 i는 조건을 어긴 81이고, 몸은 조건이 참인 네 번만 실행됩니다.
  • ④ 조건을 본 횟수 5(1·3·9·27·81)를 몸이 실행된 횟수로 셌습니다. 81에서는 조건이 거짓이라 몸을 실행하지 않습니다.

다시 볼 레슨: 반복문과 추적 표

문제 7

C에서 int g[3][4];의 칸을 메모리에 놓인 차례로 셉니다. g[0][0]을 첫째 칸으로 세면 g[2][1]은 몇째 칸인지 고르세요.

  • ① 다섯째
  • ② 여섯째
  • ③ 아홉째
  • ④ 열째
정답

④ — C는 행 우선이라 g[0]의 네 칸과 g[1]의 네 칸을 놓은 뒤 g[2][0], g[2][1] 차례입니다. g[0][0]에서 떨어진 칸 수가 2 × 4 + 1 = 9이고, 첫째 칸에서 아홉 칸 떨어졌으니 열째 칸입니다.

  • ① 두 오해가 겹쳤습니다. 열을 먼저 채우는 차례로 떨어진 칸 수를 1 × 3 + 2 = 5로 셈했고, 그 5를 그대로 다섯째로 읽었습니다.
  • ② 열을 먼저 채우는 열 우선으로 봤습니다. C는 g[0]의 네 칸을 다 놓은 뒤에 g[1]로 가는 행 우선입니다.
  • ③ 떨어진 칸 수 9를 그대로 아홉째로 읽었습니다. g[0][0]은 떨어진 칸 수가 0인 첫째 칸이라, 떨어진 칸 수에 1을 더해야 몇째 칸인지 나옵니다.

다시 볼 레슨: 배열

문제 8

다음 코드가 찍는 값을 고르세요.

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

int main(void) {
  char s[] = "planet";
  s[4] = '\0';
  int n = strlen(s);
  int k = sizeof s;
  printf("%s %d %d\n", s, n, k);
  return 0;
}
  • ① plan 4 6
  • ② plan 4 7
  • ③ plan 6 6
  • ④ plan 6 7
정답

② — 실행 결과는 이렇습니다.

실행 결과
plan 4 7

"planet"은 글자 여섯 뒤에 널 문자가 붙어 칸이 7개입니다. s[4]에 '\0'을 넣으면 문자열은 s[0]~s[3]의 plan에서 끝나, %s는 plan을 찍고 strlen은 4를 돌려줍니다. sizeof는 배열의 바이트 수(char라 칸 수와 같음)라 널 문자를 넣어도 7 그대로입니다.

  • ① sizeof에서 끝의 널 문자 칸을 빼고 셌습니다. 크기를 비우고 큰따옴표 문자열로 만든 배열은 글자 수 + 1칸입니다.
  • ③ 두 오해가 겹쳤습니다. strlen은 처음 만나는 '\0' 앞까지 세고, sizeof는 끝의 널 문자 칸까지 셉니다.
  • ④ strlen이 처음 넣은 글자 수를 센다고 봤습니다. strlen은 처음 만나는 '\0' 앞까지 세므로 s[4]에서 멈춰 4입니다.

다시 볼 레슨: 문자열

문제 9

다음 코드가 찍는 값을 고르세요.

#include <stdio.h>

int g(int *p, int n) {
  *p = *p * n;
  n = 0;
  return *p + 1;
}
int main(void) {
  int a = 3, k = 2;
  int r = g(&a, k);
  printf("%d %d %d\n", a, k, r);
  return 0;
}
  • ① 3 0 7
  • ② 3 2 7
  • ③ 6 0 7
  • ④ 6 2 7
정답

④ — 실행 결과는 이렇습니다.

실행 결과
6 2 7

g는 a의 주소와 k의 사본을 받습니다. *p는 main의 a 칸이라 a가 3 × 2 = 6이 되고(참조 전달), 사본 n에 0을 넣어도 main의 k는 2 그대로입니다(값 전달). 돌려준 6 + 1 = 7이 g(&a, k) 자리에 들어가 r은 7입니다.

  • ① 두 오해가 겹쳤습니다. 주소로 받은 *p를 바꾸면 a가 바뀌고, 사본 n을 바꿔도 k는 그대로입니다.
  • ② 주소를 넘겨도 a가 바뀌지 않는다고 봤습니다. *p는 p가 가리키는 main의 a 칸 자체라, 넣은 6이 a에 남습니다.
  • ③ 매개변수 n에 넣은 0이 k에 남는다고 봤습니다. n은 k를 복사한 g의 칸이라, 바꿔도 main의 k는 2 그대로입니다.

다시 볼 레슨: 함수 호출과 값·참조 전달

문제 10

다음 코드가 찍는 것을 고르세요.

#include <stdio.h>

int r(int n) {
  if (n <= 1) {
    return 1;
  }
  printf("%d ", n);
  return r(n - 2) * n;
}
int main(void) {
  printf("%d\n", r(6));
  return 0;
}
  • ① 2 4 6 48
  • ② 6 4 2 48
  • ③ 48 2 4 6
  • ④ 48 6 4 2
정답

② — 실행 결과는 이렇습니다.

실행 결과
6 4 2 48

printf가 재귀 호출보다 앞에 있어, 부르러 들어가며 r(6)·r(4)·r(2)가 6·4·2를 차례로 찍습니다. r(0)이 1을 돌려준 뒤 2 × 1 = 2, 4 × 2 = 8, 6 × 8 = 48이 차례로 돌아옵니다. main의 printf는 r(6)이 다 끝나 48을 돌려받은 뒤에야 맨 끝에 찍습니다.

  • ① 찍는 줄이 돌아오며 실행된다고 봤습니다. printf가 return r(n - 2) * n;보다 앞에 있어 더 깊이 부르기 전에 찍습니다.
  • ③ 두 오해가 겹쳤습니다. 바깥 printf는 r(6)이 다 끝난 뒤에 찍고, 안의 printf는 부르러 들어가며 찍습니다.
  • ④ main의 printf가 먼저 찍힌다고 봤습니다. printf는 괄호 안 r(6)을 다 셈해 돌려받은 값을 찍으므로, r 안의 출력이 모두 나온 뒤입니다.

다시 볼 레슨: 재귀

문제 11

8진수 157을 16진수로 바꾼 것을 고르세요.

  • ① 6F
  • ② 9D
  • ③ D7
  • ④ 157
정답

① — 8진수 한 자리를 2진수 세 자리로 풀면 1 → 001, 5 → 101, 7 → 111이라 001101111입니다. 오른쪽 끝부터 넷씩 묶으면 0110 · 1111이라 16진수 6F입니다. 10진수로는 64 + 40 + 7 = 111입니다.

  • ② 157을 10진수로 읽고 16진수로 바꿨습니다. 9D는 10진수 157이고, 8진수 157은 10진수 111입니다.
  • ③ 2진수 1101111을 왼쪽부터 넷씩 묶었습니다(1101 · 111). 오른쪽 끝부터 묶고 모자란 왼쪽 자리에 0을 채웁니다.
  • ④ 8진수 한 자리를 2진수 네 자리로 풀었습니다(0001 · 0101 · 0111). 8진수 한 자리는 0~7이라 세 자리로 풉니다.

다시 볼 레슨: 진법 변환

문제 12

다음 코드가 찍는 값을 고르세요.

#include <stdio.h>

int main(void) {
  int x = 0x1A;
  printf("%d %d\n", x << 2, ~x);
  return 0;
}
  • ① 52 -27
  • ② 52 -26
  • ③ 104 -27
  • ④ 104 -26
정답

③ — 실행 결과는 이렇습니다.

실행 결과
104 -27

0x1A는 2진수 0001 1010, 10진수 26입니다. << 2는 비트를 왼쪽으로 두 칸 옮겨 2² = 4를 곱하므로 104입니다. ~는 모든 비트를 뒤집어, 2의 보수로 읽으면 −x − 1이라 −27입니다.

  • ① << 2를 2를 곱하는 것으로 봤습니다. << n은 2ⁿ을 곱해, 두 칸이면 4를 곱합니다.
  • ② 두 오해가 겹쳤습니다. << 2는 4를 곱하고, ~x는 −x − 1입니다.
  • ④ ~를 부호만 바꾸는 것으로 봤습니다. 비트를 모두 뒤집은 1의 보수는 −26보다 1 작은 −27입니다.

다시 볼 레슨: 비트 연산과 2의 보수 · 진법 변환

문제 13 (실기)

(가)·(나)의 이름을 한글로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

  • (가) if (n != 0 && 100 / n > 5)⁠는 n이 0이면 100 / n을 셈하지 않아, 0으로 나누는 일 없이 거짓이 됩니다. &&·||가 왼쪽 값만으로 결과가 정해지면 오른쪽을 건너뛰는 이 셈 방식의 이름입니다.
  • (나) sign = n < 0 ? -1 : 1;⁠처럼 if·else 문 없이 식 하나 안에서, 앞의 식이 참이면 ? 뒤의 값을, 거짓이면 : 뒤의 값을 그 식의 값으로 내는 연산자입니다.
정답

받는 답: (가) 단락 평가 또는 단축 평가 · (나) 조건 연산자 또는 삼항 연산자

(가)의 실마리는 '왼쪽만으로 결과가 정해지면 오른쪽을 건너뛴다', (나)는 '?와 :로 두 값 가운데 하나를 식의 값으로 낸다'입니다. 단축 평가·삼항 연산자는 자료에 따라 부르는 이름이라 함께 받습니다.

  • 같은 이름의 다른 꼴: (가) Short-Circuit Evaluation · (나) Conditional Operator — 영문입니다. 문제가 한글로 물었습니다.
  • 틀리는 꼴 논리 연산자 — (가)에: &&·||·!라는 연산자 갈래의 이름입니다. 묻는 것은 그 연산자가 오른쪽을 건너뛰는 셈 방식입니다.
  • 틀리는 꼴 조건문 — (나)에: if·switch처럼 실행할 문장 덩어리를 고르는 문입니다. 식 안에서 두 값 가운데 하나를 골라 값으로 내는 것은 조건 연산자입니다.

다시 볼 레슨: 산술·관계·논리 연산자와 우선순위 · 증감·대입·조건 연산자

문제 14 (실기)

함수에 인자를 넘기는 두 방식 가운데 (가)·(나)에 맞는 이름을 영문으로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

  • (가) void reset(int n)을 reset(score);로 불렀습니다. 함수 안에서 n에 0을 넣었지만, 돌아온 뒤 main의 score는 원래 점수 그대로입니다.
  • (나) void reset2(int *p)를 reset2(&score);로 불렀습니다. 함수 안에서 *p에 0을 넣자, 돌아온 뒤 main의 score도 0입니다.
정답

받는 답: (가) Call by Value · (나) Call by Reference

(가)의 실마리는 'n은 score를 복사한 함수의 칸이라 바꿔도 score가 그대로', (나)는 '변수의 주소를 넘겨 함수가 main의 칸을 직접 고친다'입니다.

  • 같은 이름의 다른 꼴: (가) 값 전달 · (나) 참조 전달 — 한글 이름입니다. 문제가 영문으로 물었습니다.
  • 틀리는 꼴 Call by Reference — (가)에: 부른 쪽 변수의 자리를 넘겨 그 변수를 고치는 방식입니다. (가)는 사본만 받아 score가 그대로입니다.
  • 틀리는 꼴 Call by Value — (나)에: C가 주소도 복사해 넘기는 것은 맞지만, 주소를 넘겨 부른 쪽 변수를 고치는 방식은 참조 전달이라 부릅니다.

다시 볼 레슨: 함수 호출과 값·참조 전달

문제 15 (실기)

다음 코드는 한 파일을 세 덩이로 나눠 보인 것입니다. 실행 결과를 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

#include <stdio.h>

int grade(int s) {
  int g = -1;
  switch (s / 10) {
    case 10:
    case 9:
      g += 2;
    case 8:
      g += 2;
  }
  return g;
}
int top;
int total(int a[], int n) {
  int i, s = 0;
  for (i = 0; i < n; i++) {
    int g = grade(a[i]);
    if (g < 0) {
      continue;
    }
    s += g;
    if (a[i] > a[top]) {
      top = i;
    }
  }
  return s;
}
int main(void) {
  int a[5] = {
      95, 80, 100, 72, 88,
  };
  int t = total(a, 5);
  printf("%d %d\n", t, top);
  printf("%d\n", grade(a[top]));
  return 0;
}
정답

받는 답:

실행 결과
8 2
3

grade는 점수를 10으로 나눈 몫으로 들어갈 case를 고르고, break가 없어 아래 case까지 흘러내립니다. 95는 case 9에서 2, case 8에서 다시 2를 더해 −1 + 4 = 3입니다. 100은 비어 있는 case 10에서 case 9로 흘러 3, 80·88은 case 8만 거쳐 1, 72는 맞는 case가 없어 −1 그대로입니다.

total에서 72는 g가 음수라 continue가 그 바퀴의 남은 줄을 건너뛰어, s는 3 + 1 + 3 + 1 = 8입니다. top은 전역 변수라 0에서 시작하고, 더 큰 점수를 만날 때 그 번호로 바뀌어 100의 번호 2가 됩니다. 둘째 줄은 grade(100)의 3입니다.

  • 틀리는 꼴 4 2와 1: case 9에서 멈춘다고 봤습니다. break가 없으면 아래 case 8의 g += 2까지 실행해 95와 100은 3입니다.
  • 틀리는 꼴 5 0과 3: 비어 있는 case 10에서 멈춰 100이 −1이라고 봤습니다. 빈 case는 아래 case 9로 흘러내려 100도 3이고, top은 2가 됩니다.
  • 틀리는 꼴 7 2와 3: continue를 break처럼 읽어 72에서 반복을 끝냈습니다. continue는 그 바퀴만 건너뛰고 다음 바퀴의 88로 갑니다.

다시 볼 레슨: 조건문 · 반복문과 추적 표 · 배열 · 함수 호출과 값·참조 전달

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

정보처리기사 목차로