imnyang's workspace

뒤로

개념#

포인터는 무엇인가요?#

포인터는 메모리 주소를 저장하는 변수예요.
포인터를 사용하면 변수의 주소를 직접 다룰 수 있어서, 함수에서 값을 변경할 때 유용해요.
포인터는 * 기호를 사용하여 선언하고, & 기호를 사용하여 변수의 주소를 얻을 수 있어요.

#include <stdio.h>

void swap(int *a, int *b) { // `swap` 함수 선언 (`int`형 포인터 `a`와 `b`를 입력받는 함수 `swap`을 선언)
    int temp = *a; // `temp`에 `a`가 가리키는 값 저장
    *a = *b; // `a`가 가리키는 값에 `b`가 가리키는 값 저장
    *b = temp; // `b`가 가리키는 값에 `temp` 저장
}

int main() {
    int a = 5, b = 10; // 정수 변수 `a`와 `b` 선언 및 초기화
    printf("Before swap: a = %d, b = %d\n", a, b); // 스왑 전 값 출력
    swap(&a, &b); // `swap` 함수 호출하여 `a`와 `b`의 주소 전달
    printf("After swap: a = %d, b = %d\n", a, b); // 스왑 후 값 출력
}
c
Before swap: a = 5, b = 10
After swap: a = 10, b = 5
plaintext

동적 메모리 할당은 프로그램 실행 중에 필요한 만큼 메모리를 할당하는 방법이에요.
malloc 함수를 사용하여 메모리를 할당하고, free 함수를 사용하여 할당된 메모리를 해제할 수 있어요.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int n; // 입력 받을 정수의 개수
    scanf("%d", &n); // 사용자로부터 정수 `n` 입력 받기

    int *arr = (int *)malloc(n * sizeof(int)); // `n` 크기의 정수 배열을 동적 메모리 할당

    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 정수 `arr[i]` 입력 받기
        scanf("%d", &arr[i]);
    }

    for (int i = 0; i < n; i++) { // 입력된 정수 출력하기
        printf("%d ", arr[i]);
    }

    free(arr); // 동적 메모리 해제
}
c

이중포인터에 대해 알고 계시나요???#

#include <stdio.h>

void changePointer(int **ptr) {
    static int newValue = 100;
    *ptr = &newValue; // 포인터 변수가 가리키는 주소를 변경
}

int main() {
    int a = 10;
    int *p = &a;
    
    printf("변경 전: %d\n", *p);
    changePointer(&p); // 포인터 변수 p의 '주소'를 전달
    printf("변경 후: %d\n", *p);
}
c

이렇게하면 p가 가리키는 주소가 changePointer 함수 내에서 newValue의 주소로 변경되어, main 함수에서 *p를 출력하면 100이 출력됩니다.

함수 포인터에 대해 알고 계시나요???#

#include <stdio.h>

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

int main() {
    // 함수 포인터 선언
    int (*calc)(int, int);

    calc = add;
    printf("더하기: %d\n", calc(5, 3));

    calc = sub;
    printf("빼기: %d\n", calc(5, 3));
}
c

이 예제에서는 calc라는 함수 포인터를 선언하고, addsub 함수를 가리키도록 설정하여 각각 더하기와 빼기 연산을 수행합니다.
놀랍습니다.

문제#

1093#

정보 선생님은 수업을 시작하기 전에 이상한 출석을 부른다.
선생님은 출석부를 보고 번호를 부르는데,
학생들의 얼굴과 이름을 빨리 익히기 위해 번호를 무작위(랜덤)으로 부른다.
그리고 얼굴과 이름이 잘 기억되지 않는 학생들은 번호를 여러 번 불러
이름과 얼굴을 빨리 익히려고 하는 것이다.
출석 번호를 n번 무작위로 불렀을 때, 각 번호(1 ~ 23)가 불린 횟수를 각각 출력해보자.

#include <stdio.h>

int main() {
    int count; // 입력 받을 정수의 개수
    scanf("%d", &count); // 사용자로부터 정수 `count` 입력 받기

    int n[count]; // `count` 크기의 정수 배열 `n` 선언
    int said_n[23] = {0}; // 1부터 23까지의 숫자가 몇 번 나왔는지 세기 위한 배열 `said_n` 선언 및 초기화

    for (int i = 0; i < count; i++) { // `count`만큼 반복하여 정수 입력 받기
        scanf("%d", &n[i]); // 사용자로부터 정수 `n[i]` 입력 받기
        if (n[i] >= 1 && n[i] <= 23) { // 입력된 정수가 1에서 23 사이인지 확인
            said_n[n[i]-1]++; // 해당 숫자가 나온 횟수를 세기 위해 `said_n` 배열의 해당 인덱스 증가 
        }
    }

    for (int i = 0; i < 23; i++) { // 1부터 23까지의 숫자에 대해 반복하여 결과 출력
        printf("%d ", said_n[i]);
    }
}
c
  1. 사용자로부터 정수 count를 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. n 배열을 선언하여 입력받은 정수들을 저장하고, said_n 배열을 선언하여 1부터 23까지의 숫자가 몇 번 나왔는지 세기 위한 배열을 초기화해요.
  3. for 루프를 사용하여 count만큼 정수를 입력받고, 입력된 정수가 1에서 23 사이인지 확인하여 해당 숫자가 나온 횟수를 said_n 배열에 저장해요.
  4. 마지막으로, 1부터 23까지의 숫자에 대해 said_n 배열의 값을 출력하여 각 숫자가 몇 번 나왔는지 보여줘요.

1093

1094#

정보 선생님은 수업을 시작하기 전에 이상한 출석을 부른다.
학생들의 얼굴과 이름을 빨리 익히기 위해 번호를 무작위(랜덤)으로 부르는데,
영일이는 선생님이 부른 번호들을 기억하고 있다가 거꾸로 불러보는 것을 해보고 싶어졌다.
출석 번호를 n번 무작위로 불렀을 때, 부른 번호를 거꾸로 출력해 보자.

#include <stdio.h>

int main() {
    int count; // 입력 받을 정수의 개수
    scanf("%d", &count); // 사용자로부터 정수 `count` 입력 받기

    int n[count]; // `count` 크기의 정수 배열 `n` 선언

    for (int i = 0; i < count; i++) { // `count`만큼 반복하여 정수 `n[i]` 입력 받기
        scanf("%d", &n[i]);
    }

    for (int i = count - 1; i >= 0; i--) {
        printf("%d ", n[i]);
    }

    return 0;
}
c
  1. 사용자로부터 정수 count를 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. n 배열을 선언하여 입력받은 정수들을 저장해요.
  3. for 루프를 사용하여 count만큼 정수를 입력받고, 입력된 정수를 거꾸로 출력하기 위해 역순으로 반복해서 출력해요.

1094

1095#

정보 선생님은 오늘도 이상한 출석을 부른다.
영일이는 오늘도 다른 생각을 해보았다.
출석 번호를 다 부르지는 않은 것 같은데… 가장 빠른 번호가 뭐였지?
출석 번호를 n번 무작위로 불렀을 때, 가장 빠른 번호를 출력해 보자.

#include <stdio.h>

int main() {
    int count; // 입력 받을 정수의 개수
    scanf("%d", &count); // 사용자로부터 정수 `count` 입력 받기

    int n[count]; // `count` 크기의 정수 배열 `n` 선언

    for (int i = 0; i < count; i++) { // `count`만큼 반복하여 정수 `n[i]` 입력 받기
        scanf("%d", &n[i]);
    }

    int min = n[0]; // `min` 변수를 첫 번째 입력된 값으로 초기화

    for (int i = 1; i < count; i++) { // 나머지 입력된 값들과 비교하여 가장 작은 값을 찾기 위해 반복
        if (n[i] < min) { // 현재 값이 `min`보다 작은 경우 `min`을 현재 값으로 업데이트
            min = n[i];
        }
    }

    printf("%d", min); // 가장 작은 값 출력
}
c
  1. 사용자로부터 정수 count를 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. n 배열을 선언하여 입력받은 정수들을 저장해요.
  3. for 루프를 사용하여 count만큼 정수를 입력받고, 입력된 정수들 중에서 가장 작은 값을 찾기 위해 또 다른 for 루프를 사용하여 비교해요.
  4. 가장 작은 값을 출력해요.

1095

1402#

두 수를 거꾸로 출력하기..
세 수를 거꾸로 출력하기…
이런 문제들은 쉽게 풀 수 있었다.
이번에는 데이터의 개수가 n개가 들어오고, n개의 데이터를 거꾸로 출력하는 프로그램을 작성하시오.

#include <stdio.h>

int main() {
    int count; // 입력 받을 정수의 개수
    scanf("%d", &count); // 사용자로부터 정수 `count` 입력 받기

    int n[count]; // `count` 크기의 정수 배열 `n` 선언

    for (int i = 0; i < count; i++) { // `count`만큼 반복하여 정수 `n[i]` 입력 받기
        scanf("%d", &n[i]);
    }

    for (int i = count - 1; i >= 0; i--) { // 입력된 정수를 거꾸로 출력하기 위해 역순으로 반복해서 출력
        printf("%d ", n[i]);
    }
}
c
  1. 사용자로부터 정수 count를 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. n 배열을 선언하여 입력받은 정수들을 저장해요.
  3. for 루프를 사용하여 count만큼 정수를 입력받고, 입력된 정수를 거꾸로 출력하기 위해 역순으로 반복해서 출력해요.

1402
2트인데요?

1403#

k개의 숫자를 입력받고 그 숫자들을 두번 출력하시오.

#include <stdio.h>

int main() {
    int k; // 입력 받을 정수의 개수
    scanf("%d", &k); // 사용자로부터 정수 `k` 입력 받기

    int n[k]; // `k` 크기의 정수 배열 `n` 선언

    for (int i = 0; i < k; i++) { // `k`만큼 반복하여 정수 `n[i]` 입력 받기
        scanf("%d", &n[i]);
    }

    for (int i = 0; i < 2; i++) { // 입력된 정수를 두 번 출력하기 위해 2번 반복
        for (int j = 0; j < k; j++) { // `k`만큼 반복하여 정수 `n[j]` 출력하기
            printf("%d\n", n[j]);
        }
    }
}
c
  1. 사용자로부터 정수 k를 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. n 배열을 선언하여 입력받은 정수들을 저장해요.
  3. for 루프를 사용하여 k만큼 정수를 입력받고, 입력된 정수를 두 번 출력하기 위해 또 다른 for 루프를 사용하여 반복해서 출력해요.

1403

1096#

기숙사 생활을 하는 학교에서 어떤 금요일(전원 귀가일)에는 모두 집으로 귀가를 한다.
오랜만에 집에 간 영일이는 아버지와 함께 두던 매우 큰 오목에 대해서 생각해 보다가
이러한 형태를 쉽게 기록하고 사용할 수 있다. 물론 더 확장한 n차원 배열도 만들 수 있다.

#include <stdio.h>

int main() {
    int n; // 입력 받을 정수의 개수
    scanf("%d", &n); // 사용자로부터 정수 `n` 입력 받기

    int board[19][19] = {0}; // 19x19 크기의 2차원 배열 `board` 선언 및 초기화

    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 돌의 위치 입력 받기
        int x, y; // 돌의 위치를 저장할 변수 `x`와 `y`
        scanf("%d %d", &x, &y); // 사용자로부터 돌의 위치 입력 받기
        board[x-1][y-1] = 1; // 입력된 위치에 돌을 놓기 위해 해당 인덱스에 1 저장
    }

    for (int i = 0; i < 19; i++) { // 바둑판의 각 행에 대해 반복하여 출력
        for (int j = 0; j < 19; j++) { // 각 열에 대해 반복하여 출력
            printf("%d ", board[i][j]); // 현재 위치의 값을 출력
        }
        printf("\n"); // 각 행이 끝날 때마다 줄 바꿈
    }
}
c

바둑을 몰라서 이 문제에서 제일 오래 시간을 사용했습니다.

  1. 사용자로부터 정수 n을 입력받아 몇 개의 돌의 위치를 입력할지 결정해요.
  2. board라는 19x19 크기의 2차원 배열을 선언하고 초기화해요.
  3. for 루프를 사용하여 n만큼 돌의 위치를 입력받고, 입력된 위치에 돌을 놓기 위 해당 인덱스에 1을 저장해요.
  4. 마지막으로, 바둑판의 각 행과 열에 대해 반복하여 board 배열의 값을 출력하여 돌이 놓인 위치를 보여줘요.

1096

1098#

부모님과 함께 유원지에 놀러간 영일이는
설탕과자(설탕을 녹여 물고기 등의 모양을 만든 것) 뽑기를 보게 되었다.
길이가 다른 몇 개의 막대를 바둑판과 같은 격자판에 놓는데,
막대에 있는 설탕과자 이름 아래에 있는 번호를 뽑으면 설탕과자를 가져가는 게임이었다.
(잉어, 붕어, 용 등 여러 가지가 적혀있다.)
격자판의 세로(h), 가로(w), 막대의 개수(n), 각 막대의 길이(l),
막대를 놓는 방향(d:가로는 0, 세로는 1)과
막대를 놓는 막대의 가장 왼쪽 또는 위쪽의 위치(x, y)가 주어질 때,
격자판을 채운 막대의 모양을 출력하는 프로그램을 만들어보자.

#include <stdio.h>

int main() {
    int h, w; // 입력 받을 격자판의 세로(h)와 가로(w)
    int n; // 입력 받을 막대의 개수(n)
    scanf("%d %d", &h, &w); // 사용자로부터 격자판의 세로(h)와 가로(w) 입력 받기
    scanf("%d", &n); // 사용자로부터 막대의 개수(n) 입력 받기

    int board[h][w]; // 격자판을 나타내는 2차원 배열 `board` 선언
    for (int i = 0; i < h; i++) { // 격자판 초기화
        for (int j = 0; j < w; j++) {
            board[i][j] = 0; // 모든 칸을 0으로 초기화
        }
    }

    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 막대의 정보 입력 받기
        int l, d, x, y; // 막대의 길이(l), 방향(d), 위치(x, y)를 저장할 변수
        scanf("%d %d %d %d", &l, &d, &x, &y); // 사용자로부터 막대의 정보 입력 받기

        for (int j = 0; j < l; j++) { // 막대의 길이만큼 반복하여 격자판에 막대 놓기
            if (d == 0) { // 가로 방향인 경우
                board[x-1][y-1 + j] = 1; // 해당 위치에 막대를 놓기 위해 1 저장
            } else { // 세로 방향인 경우
                board[x-1 + j][y-1] = 1; // 해당 위치에 막대를 놓기 위해 1 저장
            }
        }
    }

    for (int i = 0; i < h; i++) { // 격자판 출력
        for (int j = 0; j < w; j++) {
            printf("%d ", board[i][j]);
        }
        printf("\n");
    }
}
c
  1. 사용자로부터 격자판의 세로(h)와 가로(w)를 입력받아 격자판의 크기를 결정해요.
  2. 막대의 개수(n)를 입력받아요.
  3. board라는 2차원 배열을 선언하여 격자판을 나타내고, 모든 칸을 0으로 초기화해요.
  4. for 루프를 사용하여 n만큼 막대의 정보를 입력받고, 막대의 길이만큼 반복하여 격자판에 막대를 놓기 위해 해당 위치에 1을 저장해요.
  5. 마지막으로, 격자판을 출력하여 막대가 놓인 위치를 보여줘요.

1098

1405#

n개의 숫자가 입력되면,
n개의 숫자를 왼쪽으로 하나씩 돌려서 출력하시오.

#include <stdio.h>

int main() {
    int n; // 입력 받을 정수의 개수
    scanf("%d", &n); // 사용자로부터 정수 `n` 입력 받기

    int arr[n]; // `n` 크기의 정수 배열 `arr` 선언

    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 정수 `arr[i]` 입력 받기
        scanf("%d", &arr[i]);
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) { // `n`만큼 반복하여 왼쪽으로 하나씩 돌려서 출력하기
            printf("%d ", arr[(j + i) % n]); // 현재 인덱스에서 `i`를 더한 값을 `n`으로 나눈 나머지로 접근하여 출력
        }
        printf("\n");
    }
}
c

1405

1097#

부모님을 기다리던 영일이는 검정/흰 색 바둑알을 바둑판에 꽉 채워 깔아 놓고 놀다가…
“십(+)자 뒤집기를 해볼까?”하고 생각했다.
바둑판(19 * 19)에 흰 돌(1) 또는 검정 돌(0)이 모두 꽉 채워져 놓여있을 때,
n개의 좌표를 입력받아 십(+)자 뒤집기한 결과를 출력하는 프로그램을 작성해보자.

#include <stdio.h>

int main() {
    int board[19][19]; // 19x19 크기의 2차원 배열 `board` 선언

    for (int i = 0; i < 19; i++) { // 바둑판 초기화
        for (int j = 0; j < 19; j++) {
            scanf("%d", &board[i][j]); // 사용자로부터 바둑판의 각 칸에 흰 돌(1) 또는 검정 돌(0) 입력 받기
        }
    }

    int n; // 입력 받을 좌표의 개수
    scanf("%d", &n); // 사용자로부터 좌표의 개수 `n` 입력 받기

    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 좌표 입력 받기다 클 경우 두 값을 서로 바꾼다.

```c
#include <stdio.h>

void myswap(int *a, int *b) { // `myswap` 함수 선언 (`int`형 포인터 `a`와 `b`를 입력받는 함수 `myswap`을 선언)
    if (*a > *b) { // 첫 번째 포인터가 가리키는 변수의 값이 두 번째 포인터가 가리키는 변수의 값보다 큰 경우
        int temp = *a; // `temp`에 첫 번째 포인터가 가리키는 값 저장
        *a = *b; // 첫 번째 포인터가 가리키는 값에 두 번째 포인터가 가리키는 값 저장
        *b = temp; // 두 번째 포인터가 가리키는 값에 `temp` 저장
    }
}

main()
{
    int a, b;
    scanf("%d%d", &a, &b);
    myswap(&a, &b);
    printf("%d %d", a, b);
}
c
  1. myswap 함수는 int형 포인터 ab를 입력받아요.
  2. 함수 내용은 첫 번째 포인터가 가리키는 변수의 값이 두 번째 포인터가 가리키는 변수의 값보다 큰 경우, 두 값을 서로 바꾸는 것이에요.
  3. main 함수에서는 두 정수 ab를 입력받고, myswap 함수를 호출하여 ab의 주소를 전달해요. 마지막으로, ab의 값을 출력해요.

1581

1810#

어떤 문자열에서 부분문자열을 추출하여 출력하는 프로그램을 작성하시오.
단 배열 대신 동적메모리 할당방법을 사용하시오.

#include <stdio.h>
#include <stdlib.h>

int main() {
    char str[100]; // 입력 받을 문자열을 저장할 배열 `str` 선언
    scanf("%s", str); // 사용자로부터 문자열 입력 받기
    int start, end; // 부분문자열의 시작 위치와 끝 위치를 저장할 변수 `start`와 `end` 선언
    scanf("%d %d", &start, &end); // 사용자로부터 부분문자열의 시작 위치와 끝 위치 입력 받기
    start--; end--; // 입력된 위치를 0-based 인덱스로 변환하기 위해 1씩 감소
    int length = end - start + 1; // 부분문자열의 길이 계산
    char *substring = (char *)malloc((length + 1) * sizeof(char)); // 부분문자열을 저장할 동적 메모리 할당
    for (int i = 0; i < length; i++) { // `length`만큼 반복하여 부분문자열 복사하기
        substring[i] = str[start + i]; // `str`에서 `start` 위치부터 `length`만큼 문자를 `substring`에 복사
    }
    substring[length] = '\0'; // 부분문자열의 끝에 null 문자 추가하여 문자열로 만들기
    printf("%s", substring); // 추출된 부분문자열 출력
    free(substring); // 동적 메모리 해제
}
c
  1. 사용자로부터 문자열을 입력받아 str 배열에 저장해요.
  2. 부분문자열의 시작 위치와 끝 위치를 입력받아요.
  3. 부분문자열을 저장할 동적 메모리를 할당해요
  4. for 루프를 사용하여 str에서 start 위치부터 length만큼 문자를 substring에 복사해요.
  5. 부분문자열의 끝에 null 문자를 추가하여 문자열로 만들고, 추출된 부분문자열을 출력해요.
  6. 마지막으로, 동적 메모리를 해제해요.

창작 문제 (선택)#

정수 N개가 주어졌을 때, 중복되는 값을 제거하고 남은 정수들을 오름차순으로 정렬한 결과를 출력하는 프로그램을 출력하는 프로그램을 작성하시오.

#include <stdio.h>
#include <stdlib.h>

int compare(const void *a, const void *b) { // `compare` 함수 선언 (qsort에서 사용할 비교 함수)
    return (*(int*)a - *(int*)b); // 두 정수를 비교하여 오름차순으로 정렬하기 위한 반환값 계산
}

int main() {
    int n; // 입력 받을 정수의 개수
    printf("입력할 정수 개수: ");
    scanf("%d", &n); // 사용자로부터 정수 `n` 입력 받기

    int *arr = (int *)malloc(n * sizeof(int)); // `n` 크기의 정수 배열을 동적 메모리 할당

    printf("정수를 입력하세요: ");
    for (int i = 0; i < n; i++) { // `n`만큼 반복하여 정수 `arr[i]` 입력 받기
        scanf("%d", &arr[i]);
    }

    qsort(arr, n, sizeof(int), compare); // `qsort` 함수를 사용하여 배열을 오름차순으로 정렬

    printf("중복 제거 후 오름차순 정렬된 결과: ");
    printf("%d ", arr[0]); // 첫 번째 요소 출력 (중복 제거 후 첫 번째 요소는 항상 출력)

    for (int i = 1; i < n; i++) { // 중복되는 값을 제거하고 남은 정수들을 출력하기 위해 반복
        if (arr[i] != arr[i - 1]) { // 현재 요소가 이전 요소와 다를 때만 출력
            printf("%d ", arr[i]);
        }
    }

    free(arr); // 동적 메모리 해제
}
c
  1. 사용자로부터 정수 n을 입력받아 몇 개의 정수를 입력할지 결정해요.
  2. arr라는 정수 배열을 동적 메모리 할당하여 선언
  3. for 루프를 사용하여 n만큼 정수를 입력받고, qsort 함수를 사용하여 배열을 오름차순으로 정렬해요.
  4. 중복되는 값을 제거하고 남은 정수들을 출력하기 위해 for 루프를 사용하여 정렬된 배열을 순회하면서 현재 요소가 이전 요소와 다를 때만 출력해요.
  5. 마지막으로, 동적 메모리를 해제해요.
[Layer7] 2026년 4월 29일 C언어 과제
http://localhost:4321/layer7/04
저자 imnyang
게시일 2026년 04월 30일