post-custom-banner

정보처리기사 실기 C언어 구조체 포인터 기출문제 정리 & 문제 풀이
🔗 포인터 문제 더 풀기 🔗 C언어 문제 풀기 🔗 파이썬 문제 풀기 🔗 자바 문제 풀기

C언어 > 문자열과 포인터

다음은 c언어의 코드이다. 알맞은 출력값을 작성하시오.

#include <stdio.h>
int main() {
   char *p="KOREA";
   printf("%s\n",p);      // Output: KOREA
   printf("%s\n",p+3);    // Output: EA
   printf("%c\n",*p);     // Output: K
   printf("%c\n",*(p+3)); // Output: E
   printf("%c\n",*p+2);   // Output: M
}

포인터 *가 헷갈릴 수 있으니 한 줄씩 풀어보자.

  1. 첫줄 char *p="KOREA";에서는 포인터 p를 선언한다. p는 포인터 *로 선언되었으므로 "KOREA"라는 문자열의 주소값을 가지는 변수이다.

    문자열 포인터*
    포인터는 주소를 바탕으로 이동하기 때문에 문자열 포인터의 경우 문자열을 이동하여 그 일부분을 가리킬 수 있게 된다.

    포인터 문제에서는 값과 주소를 떠올려야 하는데, 이 문제에서의 문자열 값과 그 값을 담은 주소를 그려보자면 아래와 같다.

    KOREA
    주소(p)100101102103104

    주소를 p라고 칭할 때, p의 대표 번지를 임의로 100이라고 하자.

    각 주소에는 순서가 매겨져 있다. 예를 들어 첫번째 값 'K'를 담은 주소지 100은 p의 0번 자리, 값 'O'를 담은 주소지 101은 p의 1번 자리... 이런 식이다.

  2. printf("%s\n",p);에서는 포인터 p를 출력하라고 했으므로 대표 주소지인 p의 0번째 자리 100번지부터 그대로 출력한다. 즉, "KOREA"가 출력된다.

  3. printf("%s\n",p+3);는 포인터 p에서 +3만큼 이동한 위치부터 문자열을 출력한다.

    p는 p의 0자리를 의미하므로 p의 0자리인 100번지 + 3으로 이해하면 된다. 즉 103번지로 포인터를 이동하라는 것이다. 따라서 103번지부터 "EA"가 출력된다.

  4. printf("%c\n",*p);역참조 연산자 *를 사용하여 포인터가 가리키는 값만 가져온다. 따라서 포인터 p가 가리키는 위치의 을 출력한다. 그러므로 'K'가 출력된다.

    포인터의 역참조란?
    포인터는 기본적으로 주소를 가리키는데, 그 포인터 변수에 포인터 *를 다시 줄 경우 그 주소지에 있는 '값'을 가리키게 되는데, 이것을 역참조라고 한다.

  5. printf("%c\n",*(p+3));는 포인터 p에서 +3만큼 이동한 위치의 을 출력한다. 'E'가 출력된다.

    앞선 3번과 다른 점은 괄호 (p+3) 안에서 주소지에 대한 계산이 p의 100번지에서 +3 하여 103번지가 되는 것으로 동일하게 이루어지지만,

    괄호 밖의 포인터 *로 인해 해당 103번지의 '값'을 가리킬 것을 명시받는다. 따라서 해당 103번지부터가 아닌 103번지만의 값이 출력값에 해당된다.

  6. printf("%c\n",*p+2);에서는 포인터 p 자체에 역참조를 붙임으로써 p 주소지의 에 2를 더할 것을 요구한다. 즉, 포인터 p의 값 'K'에서 2를 더한 값이 출력되어야 한다는 것이다.

'K'는 ASCII 코드로 75이므로 'M'이 출력되어야 한다. 하지만 ASCII 코드값을 몰라도 이 코드의 값들은 알파벳 순서로 코드값이 +1되고 있으므로 K의 다음다음 알파벳은 K - L - M이라고 유추할 수 있다. 결과적으로 출력은 'M'이 된다.

printf의 결과값은 문제 코드의 주석에 적혀있다.


C언어 > 포인터와 출력

다음은 c언어의 코드이다. 보기의 조건에 맞추어 알맞은 출력값을 작성하시오.
보기: 입력값은 홍길동, 김철수, 박영희 순서로 주어진다.

    #include<stdlio.h> 
    #include<stdlib.h> 
    char n[30];
    char *test() {
        printf(입력하세요 : );
        gets(n);
        return n;
    }

    int main()
    {
        char *test1;
        char *test2;
        char *test3;

        test1 = test();
        test2 = test();
        test3 = test();

        printf(%s\n,test1);
        printf(%s\n,test2);
        printf(%s,test3);
    }

main() 함수 확인 전 참고할 것은, 맨 윗 줄의 char n[30]전역 변수이고, 주소값을 가진다는 것이다.

C언어는 무조건 main() 함수부터 실행되므로 main() 함수를 보자.

main() 함수 안에 각 test1, 2, 3은 * 즉 포인터(주소값이 담김)이다.

test1

test1test()함수를 호출하니 test()함수로 가자.

test()함수 내의 gets() 함수는 문자열을 저장해주는 함수이다. 이는 개행 기준으로 저장하는데, 개행 없는 문자열이 들어와도 자동으로 문자열 끝에 개행을 넣어준다.

따라서 test()함수의 리턴값은 전역변수 n에 ‘홍길동’으로 저장되며 test1의 주소값은 100번지라고 하자.

test1의 포인터n의 주소(번지)n의 값
n의 주소100‘홍길동’

test2

test2도 마찬가지로 test()함수를 실행한다. 이때 gets() 함수를 사용해 n에 집어넣는데, 개행 기준으로 저장하는 함수의 특성상 전역변수 n의 값은 ‘홍길동’에서 ‘김철수’로 overwrite된다.

따라서 test()함수의 리턴값은 ‘김철수’이고 test2의 주소값은 100번지다.

test2의 포인터n의 주소(번지)n의 값
n의 주소100‘김철수’

test3

test3test()함수를 실행한다.

gets() 함수에서 overwrite을 통해 ‘김철수’ → ‘박영희’가 되므로 리턴값은 ‘박영희’, 주소값은 100번지다.

test3의 포인터n의 주소(번지)n의 값
n의 주소100‘박영희’

따라서 main() 함수에서 test() 함수를 세 번 돌고나서 printf()로 내려가면 test1, 2, 3 모두 같은 주소지의 같은 값, 즉 ‘박영희’를 가지고 있다.

printf()를 보면 \n을 통해 개행할 것을 요구하고 있으므로 정답은 아래와 같다.

박영희
박영희
박영희


C언어 > 스택과 포인터

다음은 C언어 문제이다. 알맞은 출력값을 작성하시오.

#include <stdio.h>
#define MAX_SIZE 10
 
int isWhat[MAX_SIZE];
int point= -1; 
 
void into(int num) {
    if (point >= 10) printf("Full");
    isWhat[++point] = num;
}
 
int take() {
    if (isEmpty() == 1) printf("Empty");
    return isWhat[point--];
}
 
int isEmpty() {
    if (point == -1) return 1;
    return 0;
}
 
int isFull() {
    if (point == 10) return 1;
    return 0;
}
 
int main(int argc, char const *argv[]){
    int e;
    into(5); into(2);
    while(!isEmpty()){
        printf("%d", take());
        into(4); into(1); printf("%d", take()); 
        into(3); printf("%d", take()); printf("%d", take()); 
        into(6); printf("%d", take()); printf("%d", take()); 
    }
    return 0;
}

코드가 길어도 일단 main() 함수 먼저 보자.

into(), take() 함수는 stack 자료구조의 push(), pop()과 동일한 역할을 하고 있다. 따라서 stack 자료구조에 관한 문제라고 볼 수 있다.

stack의 포인터
stack 알고리즘에서 포인터 p는 맨 처음 -1 이다. 값이 쌓일 때 p = 0 이 된다.

stack은 우선 값을 넣거나 빼고나서 p를 + 또는 - 한다. 예를 들어 위의 main() 함수에서 into(5)가 수행될 때, stack 구조에 5가 먼저 들어가고 p가 -1에서 0이 된다. 빼는 경우에도 마찬가지로 stack 구조에서 n이 먼저 나오고 포인터 p가 -1된다.

into 즉 push 되는 것은 파란색, pop 되는 take는 빨간색으로 표시해보자.

printf()함수에서 나가는 take()마다 출력하고 있으므로 빨간색이 답이 된다. 따라서 답은 아래와 같다.

2 1 3 4 6 5


C언어 > 단순 포인터

💡 단순 포인터는 1차원이고, 단순히 주소값만 가진다

int data[0][3] = {1, 3, 4, 5, 2, 9, 6, 8, 7}; // 3열
int *p = data[1];
int x, y;
x = *p;
y = *(p + 2);
printf("%d, %d", x, y);

data를 아래와 같은 주소지와 값으로 입력한다.

포인터 p는 data[1]의 주소지를 가리키므로 data[1]의 주소지는 103번지이다. 따라서 x = 103

y는 x의 번지수 + 2 이므로 y = 105 가 된다.

printf에 각 x, y 값을 적으면 되므로 103번지의 값, 105번지의 값을 적자면 아래와 같다.

5, 9


C언어 > 배열 포인터

💡 배열 포인터는 2차원 배열의 주소, 대표 주소가 있다

int arr[2][3] = {1, 2, 3, 4, 5, 6}; // 2행3열
int (*p)[2] = NULL; // 2열로 만들어라
p = arr;
printf("%d,", *(p[0] + 1) + *(p[1] + 2));
printf("%d,", *(*(p + 1) + 0) + *(*(p + 1) + 1));

위 코드에 주석으로 적어놓았듯 arr은 최초에 2행 3열로 선언된 2차원 배열이다. 이를 그림으로 나타내면 아래와 같다.

그 아래 줄에서는 포인터 (*p)[2], 즉 p라는 변수가 2열짜리 포인터로 선언된다.

세번째 줄 p = arr;에서는 2열짜리 포인터 p에 arr이 담기게 되면서 기존 arr은 2열짜리 배열로 재구성된다.

재구성된 arr, 즉 p를 그려보자.

p는 포인터이므로 주소와 값을 함께 그리면 아래와 같다. 참고로 대표주소 p는 100번지이다.

이제 printf() 포인터 연산을 해보자.

  1. (p[0]+1)+(p[1]+2)*(p[0] + 1) + *(p[1] + 2)

    위의 그림을 참고하면 어렵지 않게 풀 수 있다.

    *(p의 0자리 주소 + 1) + *(p의 1자리 주소 + 2)

    = ( 100 + 1 ) + ( 102 + 2 ) 가 된다.

    그리고 각 괄호의 밖에 *가 있으므로 역참조되어 해당 주소지의 을 데려온다.

    그러면 101번지의 값 + 104번지의 값, 즉 2 + 5 = 7 이 된다.

  1. ((p+1)+0)+((p+1)+1)*(*(p + 1) + 0) + *(*(p + 1) + 1)

    주의할 것은 식의 (p+1)은 101+1 아니라 행을 1 넘기는 것이라는 점이다. p의 값과 주소를 담은 그림을 참고하면 이해가 쉽다.

    즉, p[0]이 p[1]로 행을 이동하게 된다. 행을 이동한다는 것은 주소가 바뀐다는 뜻이다. p[1]의 주소는 102번지이다.

    그러므로 (p+1)은 102 + 0 = 102

    그 뒤의 괄호 연산도 마찬가지로 계산한다.

    p[0]이 p[1]로 행을 이동하고, 거기에 +1 하면 102 + 1 = 103 이다.

    최종적으로는 *(102번지의 값) + *(103번지의 값)을 계산하게 되어 해당 번지의 각 값들을 더하면 3 + 4 = 7 이 된다.

    printf()에 정수 뒤에 콤마(,)가 있으므로 콤마를 포함하여 아래와 같이 답안을 작성해야 한다.

    7, 7,

정보처리기사 실기 프로그래밍 기출 C언어 구조체 문제 풀이

C언어 > 구조체와 포인터

🔗 구조체 struct
구조체는 여러 형의 데이터를 묶을 때 사용한다. 데이터를 넘길 때 해당 구조체만 넘겨주면 되므로 함수에 파라미터가 추가되더라도 변경이 용이하다.

#include <stdio.h>
struct jsu {
  char name[12];
  int os, db, hab, hhab;
};
 
int main(){
struct jsu st[3] = {{"데이터1", 95, 88}, 
                    {"데이터2", 84, 91}, 
                    {"데이터3", 86, 75}};
struct jsu* p; 
 
p = &st[0];
 
(p + 1)->hab = (p + 1)->os + (p + 2)->db;
(p + 1)->hhab = (p+1)->hab + p->os + p->db;
 
printf("%d\n", (p+1)->hab + (p+1)->hhab);
}

구조체 문제도 결국은 포인터와 같이 해당 주소지에 있는 올바른 값을 찾아가는 게 중요하다.

따라서 대표주소 p를 기준으로 주소지와 값을 그려보면 아래와 같다.

struct jsu를 담은 변수 st에 name, os, db는 값이 채워져 있고, hab, hhab 자리는 비어있는 상태다.

struct jsu* p;에서 구조체의 포인터 p가 선언되고, p = &st[0];에서 대표주소가 0번지로 설정됐다.

이제 그 아랫줄 hab과 hhab에 넣어줄 연산식으로 가보자.

  1. (p + 1)->hab = (p + 1)->os + (p + 2)->db;

    위의 코드에서 (p + 1) 이 식은 p에서 +1 만큼 행 이동을 하겠다는 뜻이다.

    따라서 대표주소 p[0]에서 p[1]로 옮겨간다.

    위 그림의 1) 행 이동 부분을 참고하자.

    그러면 p +1 행이동한 p[1]의 os 자리와 p +2 행이동한 p[2]의 db 자리를 더하라는 뜻이 되고, 그 값이 p +1한 p[1]의 hab 자리에 들어간다.

    값으로 보자면 84 + 75 = 159 가 p[1]의 hab 자리에 들어간다.

  1. (p + 1)->hhab = (p+1)->hab + p->os + p->db;

    이것도 방식은 같다.

    p +1한 자리의 hhab 자리를 채우기 위해 위의 1번에서 구했던 (p+1)->hab의 값 159에 p의 os, db 자리를 더하라고 되어있다.

    p는 대표주소 0번이므로 각 95와 88이 들어간다. 따라서 159 + 95 + 88 = 342 가 p[1]의 hhab이 된다.

  2. printf("%d\n", (p+1)->hab + (p+1)->hhab);

    출력값은 위에서 구한 값들을 전부 더하는 것이므로 159 + 342 가 되어야 하고, 정답은 아래와 같다.

    501


🙋🏻‍ 참고한 곳
🔗 홍달쌤 유튜브 🔗 홍달쌤의 정보처리기사 실기 책

post-custom-banner

4개의 댓글

comment-user-thumbnail
2024년 7월 15일

일단 좋은 자료 감사합니다. 선생님. 잘 참고하고 있습니다.
다름 아니라 C언어 > 배열 포인터 관련해서 정답관련해서 질문이 있어서요.
정답이 8, 9 아닌가요?
123
456이 왜
12
34
56으로 변하는지 이해가 안가서요.

2개의 답글