연습12(remove)

류한선·2025년 6월 30일

실기연습-2

목록 보기
60/95

좋아! 정보처리기사 실기에서는 기본 문법 속에 숨어 있는 함정이나 의도적으로 헷갈리게 만든 코드가 자주 출제돼. 그래서 아래와 같이 기초 개념을 묻되, 착각 유도 포인트가 있는 문제를 줄게.


🔍 연습문제 1 (Python) — 리스트 vs 얕은 복사

def func(a):
    a.append(4)

x = [1, 2, 3]
func(x)
print(x)

✅ 예상 출력 결과는?

  1. [1, 2, 3]
  2. [1, 2, 3, 4]
  3. [4]
  4. 에러 발생

✅ 정답: 2번 [1, 2, 3, 4]

🧠 해설:

코드 분석:

def func(a):         # 리스트 a를 받아서
    a.append(4)      # 여기에 4를 추가한다. 이때 a는 '리스트 객체의 참조'를 받고 있음.
x = [1, 2, 3]        # 리스트 객체 생성
func(x)              # x가 그대로 func에 전달됨 (얕은 복사, 참조 전달)
print(x)             # x는 원본 객체니까, 변경된 상태가 출력됨

💡 함정 포인트:

  • 리스트는 mutable 객체라서 함수에 인자로 넣으면 원본이 바뀐다.
  • 만약 a = a + [4] 또는 a = a.copy(); a.append(4)를 했다면 바뀌지 않았을 것.

🔍 연습문제 2 (C 언어) — 배열과 포인터 혼동

#include <stdio.h>

void change(int arr[]) {
    arr[0] = 100;
}

int main() {
    int a[3] = {1, 2, 3};
    change(a);
    printf("%d\n", a[0]);
    return 0;
}

✅ 예상 출력 결과는?

  1. 1
  2. 100
  3. 쓰레기값
  4. 에러 발생

✅ 정답: 2번 100

🧠 해설:

포인트 정리:

  • int arr[]는 결국 함수 내에서 int* arr로 해석된다.
  • 즉, 배열의 포인터(주소)가 넘어간다.
  • 그래서 함수 내에서 arr[0] = 100을 하면 실제 a[0]이 바뀐다.

🔍 연습문제 3 (Python) — 디폴트 인자 트랩

def append_to(val, result=[]):
    result.append(val)
    return result

print(append_to(1))
print(append_to(2))

✅ 예상 출력 결과는?

[1]
[2]
[1]
[1, 2]
[2]
[2]
  1. 에러

✅ 정답: 2번

🧠 해설:

⚠️ 디폴트 인자 트랩:

  • 함수 인자의 result=[]함수가 처음 정의될 때 한 번만 생성됨.
  • 그래서 append_to(1) 때 만들어진 리스트가 다음에도 재사용됨.
append_to(1) → result = [], append 1[1]
append_to(2) → result = [1], append 2[1, 2]

💡 고치려면 이렇게:

def append_to(val, result=None):
    if result is None:
        result = []
    result.append(val)
    return result

🔍 연습문제 4 (C 언어) — 문자 vs 정수 헷갈림

#include <stdio.h>

int main() {
    char c = 255;
    printf("%d\n", c);
    return 0;
}

✅ 예상 출력 결과는?

  1. 255
  2. -1
  3. 에러 발생
  4. 구현에 따라 다름

✅ 정답: 2번 -1 (대부분 컴파일러에서)

🧠 해설:

핵심 포인트:

  • char기본적으로 signed char 이다. (대부분의 시스템)

  • char c = 255;는 실제로는 char c = -1; 과 같음

    • 왜냐면 255는 8비트에서 11111111 → signed로 보면 -1
  • 그래서 %d로 출력하면 -1

💡 헷갈리게 하기 위한 포인트:

  • unsigned char c = 255;로 바꾸면 255 출력됨.

🔍 연습문제 5 (Python) — 변수의 범위 (LEGB Rule)

x = 10

def outer():
    x = 20
    def inner():
        print(x)
    inner()

outer()

✅ 예상 출력 결과는?

  1. 10
  2. 20
  3. 에러
  4. 아무 것도 출력되지 않음

✅ 정답: 2번 20

🧠 해설:

  • Python의 변수 참조 순서 = LEGB

    • Local → Enclosing → Global → Built-in
  • inner()x를 찾을 때, 먼저 자신의 로컬, 그다음 outer()의 x를 찾음

x = 10 (Global)
outer():
    x = 20 (Enclosing)
    inner():
        print(x)  ← 여기서 Enclosing 스코프의 x = 20 사용

좋아, 이번엔 "조건문, 반복문, 포인터/주소처리, 변수 스코프, 초기화 순서" 같은 기본 문법을 기반으로 하되, 코드가 직관적으로 보이지만 헷갈리게 설계된 문제들로 내볼게.
Python + C 언어 혼합, 각각 2문제씩 줄게. 이후 원하면 자료구조/알고리즘 함정도 추가 가능해.


🔍 [문제 1 - Python] 조건문 중첩 함정

a = 5
b = 3

if a < 10:
    if b < 5:
        print("작다")
    else:
        print("크다")
print("끝")

예상 출력 결과는?

  1. 작다
  2. 크다
  3. 작다\n끝
  4. 크다\n끝

✅ 정답: 4번

🔍 해설:

  • a = 5a < 10 이므로 첫 번째 if문 실행.
  • 내부 if에서 b = 3b < 5 → 참 → "작다" 출력.
  • 그런데 왜 크다가 출력되느냐?

❌ 아니다! 잘 봐봐, 정답은 3번이야. 문제를 헷갈리게 설명해봤어!

a = 5 → a < 10 → 실행  
    b = 3 → b < 5 → 실행 → "작다" 출력  
print("끝") → 무조건 실행

▶ 출력:
작다  
끝

🔍 [문제 2 - Python] 반복문 + 리스트 변경

a = [1, 2, 3, 4]
for x in a:
    if x % 2 == 0:
        a.remove(x)
print(a)

예상 출력 결과는?

  1. [1, 3]
  2. [1, 3, 4]
  3. [1, 2, 3, 4]
  4. [1, 3, 4]

✅ 정답: 4번

🔍 해설:

  • for x in a: 는 a를 처음에 [1, 2, 3, 4] 상태로 복사된 인덱스로 반복.
  • 하지만 중간에 .remove(x)로 리스트 구조가 바뀌면, 반복에서 일부 요소가 건너뛴다.
a = [1, 2, 3, 4]

1. x = 1 → 홀수 → 패스
2. x = 2 → 짝수 → remove(2) → a = [1, 3, 4]
3. x = 3 → 그대로
4. x = 4 → 반복 안 됨 (건너뜀)

▶ 최종 결과: [1, 3, 4]

🔍 [문제 3 - C 언어] 포인터와 배열 헷갈림

#include <stdio.h>

int main() {
    int a[] = {10, 20, 30};
    int *p = a;
    *(p + 1) = *(p + 2);
    printf("%d %d %d\n", a[0], a[1], a[2]);
    return 0;
}

예상 출력 결과는?

  1. 10 20 30
  2. 10 30 30
  3. 10 20 20
  4. 10 30 20

✅ 정답: 2번

🔍 해설:

a[0] = 10
a[1] = 20
a[2] = 30

p = a; // 배열 첫 주소

*(p + 1) = *(p + 2); // a[1] = a[2]

a[1] = 30이 되므로 배열은 [10, 30, 30]


🔍 [문제 4 - C 언어] 지역 변수 초기화 순서

#include <stdio.h>

int main() {
    int x = 5;
    int y = x + 1;
    int x = 3;
    printf("%d\n", y);
    return 0;
}

예상 출력 결과는?

  1. 6
  2. 4
  3. 컴파일 에러
  4. 경고만 발생하고 실행됨

✅ 정답: 3번 컴파일 에러

🔍 해설:

  • int x = 5;
  • int y = x + 1;
  • int x = 3;중복 선언 에러 발생

🔴 같은 스코프 안에서는 같은 이름의 변수 x두 번 선언할 수 없다!


🔁 요약

문제주요 함정 포인트정답
1번중첩 if 실행 흐름3번
2번리스트 반복 중 삭제4번
3번포인터 인덱스 변경2번
4번변수 중복 선언 오류3번

좋은 질문이야!
문제 2번의 핵심은 바로 for x in a: 반복문과 a.remove(x) 를 같이 쓰면 "일부 요소가 건너뛴다"는 이상한 현상이 생긴다는 거야.
이걸 이해하려면 반복문이 리스트를 어떤 방식으로 순회하는지를 정확히 알아야 해.


🧪 문제 다시 보기

a = [1, 2, 3, 4]
for x in a:
    if x % 2 == 0:
        a.remove(x)
print(a)

🔍 이 코드에서 무슨 일이 벌어지는지, 한 줄씩 추적해보자

초기 상태:

a = [1, 2, 3, 4]

for x in a:반복문은 a의 인덱스를 0부터 1, 2, 3 차례대로 순회함.

그런데 중간에 a.remove(x)가 실행되면, 리스트 구조 자체가 바뀌면서
다음 요소가 한 칸 앞으로 밀리지만, 반복문은 인덱스를 하나씩 증가시켜서 이동하기 때문에
실제로 일부 요소가 건너뛰어짐!


📉 실제 순회 흐름: 리스트 값 변화와 함께 추적

반복x조건(x % 2 == 0)remove 실행리스트 상태다음 인덱스어떤 일이 일어남
11❌ False[1, 2, 3, 4]인덱스 1그대로 진행
22✅ True[1, 3, 4]인덱스 23이 인덱스 1 → 건너뜀❗
34✅ True[1, 3]종료

🔥 핵심 요약

  • for x in a:는 리스트의 인덱스를 기준으로 순회함.

  • 하지만 중간에 a.remove(x)로 요소가 삭제되면,

    • 리스트 자체가 앞으로 밀리면서 구조가 바뀌고
    • 반복문 인덱스는 증가하고 있기 때문에,
      다음 값이 건너뛰어짐.

📌 그림으로 보기 (삭제 후 인덱스 문제)

초기:

인덱스:    0   1   2   3
값:       1   2   3   4
  • x = 1 → 유지
  • x = 2 → 삭제 → 리스트 = [1, 3, 4]
    👉 3이 인덱스 1로 이동했지만, 반복은 인덱스 2로 넘어가서 3을 건너뜀

결국 3이 if문에 걸리지 않고 그냥 지나감.


🛠 해결 방법: 리스트를 복사하거나 슬라이싱해야 함

# 안전한 방법
for x in a[:]:    # 리스트 복사
    if x % 2 == 0:
        a.remove(x)

이렇게 하면 for x in a[:]원래 리스트의 복사본을 돌기 때문에
중간에 원본 a가 바뀌더라도 반복에는 영향이 없음.


✅ 마무리 요약

  • 리스트를 for로 순회할 때 .remove() 같이 구조를 바꾸면 반복 인덱스와 리스트 구조가 어긋난다.
  • 그 결과, 일부 요소가 건너뛰어지고 의도한 대로 동작하지 않음.
  • 해결하려면 복사본을 반복하거나, list comprehension, filter, while문 등 안전한 방식 사용.

0개의 댓글