Layer7 4차시 과제

이동규·2026년 5월 3일

Layer7과제

목록 보기
4/22

수업내용 정리

Pointer

pointer 란?

메모리의 특정 주소값을 저장하는 변수

pointer 변수를 선언해 보자

int *ptr = &a;// ptr 이라는 포인터 변수에 a의 주소값이 들어가 있다

a의 주소 -> ptr의 값

(& :주소 연산자로 변수의 메모리의 주소를 알려준다)

역참조

거슬러 올라가 알 수 있다
->

int *ptr = 67
printf("%d",*ptr);

결과: 67

주의 (서로 같지 않습니다)

위 코드에서 포인터 변수 ptr을 선언할떄의 에스터리스크(*)는 포인터
역참조 할때 사용한 에스터리스크는 간접 참조 연산자라 한다

인자로 사용가능

void 함수명(int *a){
	*a=바꾸려는 정수
}

이렇게 작성하면 main의 a가 실제로 바뀐다

주의 (매개변수가 pointer 일때)

인자에 주소를 넣는다(그대로)

array 와 string

배열의 이름은 곧 포인터
string은 비슷한 성질을 공유
arr은 배열의 맨 첫번째 주소다
arr[0] 은 (arr)
arr[1] 은
(arr+1)같이 이용할 수 있다


Dynamic Allocation

문제상황

배열의 크기를 정해두면 크기가 초과될 수 있다

기초문법

(자료형*) malloc(sizeof(자료형) *개수)

예시

char *sen = (char*) malloc(sizeof(char));
    scanf("%s",sen); 
free(sen);

malloc으로 메모리 할당 free로 할당된 메모리 해제


심화

이중 포인터

int *numptr1;
int **numptr2;
int num = 10
numptr1 = #
numptr2 = &numptr1;
printf("%d",**numptr2);

포인터의 포인터를 표현 할 때는 포인터를 2개 쓴다
-> 원래 값을 찾으려면 역참조 2개를 해주어야 한다는 말이다

어디에 쓸까?

(아직도 정확히 사용사례가 이해가 되지 않습니다)

int **matrix = (int **)malloc(3 * sizeof(int *));
for (int i = 0; i < 3; i++) {
    matrix[i] = (int *)malloc(4 * sizeof(int));
}

배열 matrix[3][4]를 만들려고 한다
하지만 우리는 이것을 굳이 이중포인터로 만들려 한다 int *는 아래 반복문에서 만든 1차원 배열의 시작주소를 집어 넣으려고 한 것이다.

굳이 왜?

1. 공간 절약: 필요한 만큼만 쓰고 버릴 수 있다.

주소록을 한 곳에 잘 만들면 실제 데이터들을 빈틈들에 저장할 수 있다고 한다(뭔소리지)

2. 유연함: 행마다 크기가 달라도 상관없다.

행마다 길이를 다르게 할 수 있다 예) 학생수 1반 13명, 2반 15명

3. 효율성: 데이터 덩어리를 직접 옮기지 않고 '주소'만 바꿔서 관리할 수 있다.

행을 바꿀때 일반적인 배열은 일일이 옮겨야 하지만 이중 포인터와 malloc으로 배열을 만들면 행의 주소값만 temp를 이용해서 swap해주면 된므로 아주 빠르다!


문제풀이

1093

문제

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

문제풀이

  1. 정수 변수 2개와 배열을 선언한다
  2. 변수 2개로 실행할 횟수를 스캔해 그만큼 스캔하는 반복문을 만든다
  3. 반복문 안에서 스캔하고 스캔한 값의 주소에 1을 더한다
  4. 배열을 출력한다

1093 코드

#include <stdio.h>
int main(){
    int a,b,arr[23]={};
    scanf("%d",&a);
    for(int i = 0;i<a;i++){
        scanf("%d",&b);
        *(arr+b-1) += 1;
    }
    for(int i=0;i<23;i++){
        printf("%d ",*(arr+i));
    }

    return 0;
}

1094

문제

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

문제풀이

  1. 입력횟수를 입력받는다
  2. 반복문으로 입력받은 값을 차례로 배열에 넣는다
  3. 거꾸로 출력한다

1094 코드

#include <stdio.h>
int main(){
    int a, b[10000]={};
    scanf("%d",&a);
    for(int i=0;i<a;i++){
        scanf("%d",&b[i]);
    }
    for(int i = a-1;i>=0;i--){
        printf("%d ",b[i]);
    }

}

1095

문제

정보 선생님은 오늘도 이상한 출석을 부른다.
영일이는 오늘도 다른 생각을 해보았다.
출석 번호를 다 부르지는 않은 것 같은데... 가장 빠른 번호가 뭐였지?
출석 번호를 n번 무작위로 불렀을 때, 가장 빠른 번호를 출력해 보자.
참고
배열에 순서대로 기록해 두면, 기록된 내용을 모두 검사해 가장 작은 값을 찾아내면 된다.
그런데, 가장 작은 값은 어떻게 어떤 것과 비교하고 찾아야 할까?

문제풀이

  1. 배열에 입력을 받는다
  2. min이라는 변수를 크게 잡고 배열 값들을 차례로 비교해 최솟값을 구하고 출력한다

1095 코드

#include <stdio.h>
int main(){
    int a, b[10000]={},min = 100000;
    scanf("%d",&a);
    for(int i=0;i<a;i++){
        scanf("%d",&b[i]);
    }
    for(int i = a-1;i>=0;i--){
        if(b[i]<min){
            min = b[i];
        }
    }
    printf("%d",min);

}

1402

문제

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

문제풀이

  1. 배열값들을 입력받는다
  2. 입력횟수를 이용하여 for문을 작성해 거꾸로 출력한다

1402 코드

#include <stdio.h>
int main(){
    int a = 0,b[100] = {0};
    scanf("%d",&a);
    for(int i=0;i<a;i++){
        scanf("%d",&b[i]);
    }
    for(a;0<a;a--){
        printf("%d ",*(b+a-1));
    }
    return 0;
}

1403

문제

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

문제풀이

  1. 숫자 갯수를 입력받는다
  2. 배열을 입력받는다
  3. 배열을 출력하는 for문을 2번 반복하는 for문에 넣는다

1403 코드

#include <stdio.h>
int main(){
    int a,b[100];
    scanf("%d",&a);
    for(int i = 0;i<a;i++){
        scanf("%d",&b[i]);
    }
    for(int i=0;i<2;i++){
        for(int j=0;j<a;j++){
            printf("%d\n",*(b+j));
        }
    }
}

1069

1096을 1069로 읽고 풀어버린 놀라운 지능!
우린 이 유인원의 행보를 축하해야합니다!!!

(아까워서 넣었습니다)

문제

평가를 문자(A, B, C, D, ...)로 입력받아 내용을 다르게 출력해보자.
평가 내용
평가 : 내용
A : best!!!
B : good!!
C : run!
D : slowly~
나머지 문자들 : what?
참고
조건/선택문을 복합적으로 구성해 출력할 수도 있지만,
switch(정수값)
{
case 'A': //문자 'A'가 정수값 65('A'의 아스키 값)로 저장되기 때문에 가능하다.
...;
break;
case 'B':
...;
break;
case 'C':
...;
break;
default:
...;
}
위와 같은 switch( ) ... case... break; 제어문을 사용할 수 있다.
** break; 를 사용하지 않으면 이후의 명령들도 계속 실행된다.
default: 는 제시된 case 를 제외한 나머지 모든 경우에 실행된다.
switch( ) 에 주어지는 값은 “정수"값만 가능하며,
문자도 아스키코드 정수값이기 때문에 가능하다.

문제풀이

1.스위치 case에 입력받은 문자에 따라 다르게 출력하는 내용을 작성

1069 코드

#include <stdio.h>
int main(){
    char a;
    scanf("%c",&a);
    switch (a)
    {
    case 'A':
        printf("best!!!");
        break;
    case 'B':
        printf("good!!");
        break;
    case 'C':
        printf("run!");
        break;
    case 'D':
        printf("slowly~");
        break;
    default:
        printf("what?");
        break;
    }
}

1096

문제

기숙사 생활을 하는 학교에서 어떤 금요일(전원 귀가일)에는 모두 집으로 귀가를 한다.
오랜만에 집에 간 영일이는 아버지와 함께 두던 매우 큰 오목에 대해서 생각해 보다가
"바둑판에 돌을 올린 것을 프로그래밍 할 수 있을까?"하고 생각하였다.
바둑판(19 * 19)에 n개의 흰 돌을 놓는다고 할 때,
n개의 흰 돌이 놓인 위치를 출력하는 프로그램을 작성해보자.
참고
가로번호, 세로번호를 사용할 수 있는 2차원 배열을 사용하면
이러한 형태를 쉽게 기록하고 사용할 수 있다. 물론 더 확장한 n차원 배열도 만들 수 있다.
예시

int n, i, j, x, y;
int a[20][20]={};
scanf("%d", &n);
for(i=1; i<=n; i++)
{
  scanf("%d %d", &x, &y);
  a[x][y]=1;
}
for(i=1; i<=19; i++) //한 줄(위에서 아래로) 씩
{
  for(j=1; j<=19; j++) //한 열(왼쪽에서 오른쪽으로) 씩
  {
    printf("%d ", a[i][j]); //값 출력
  }
  printf("\n"); //줄 바꾸기
}

문제풀이

  1. 입력횟수와 좌표를 잘 입력받는다
  2. 반복문으로 출력을 한다

1096 코드

#include <stdio.h>
int main(){
    int a[19][19] ={0},b,n1,n2;
    scanf("%d",&b);
    for(int i=0;i<b;i++){
        scanf("%d %d",&n1,&n2);
        a[n1-1][n2-1] = 1;
    }
    for(int i=0;i<19;i++){
        for(int j=0;j<19;j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }

}

1098

문제

부모님과 함께 유원지에 놀러간 영일이는
설탕과자(설탕을 녹여 물고기 등의 모양을 만든 것) 뽑기를 보게 되었다.
길이가 다른 몇 개의 막대를 바둑판과 같은 격자판에 놓는데,
막대에 있는 설탕과자 이름 아래에 있는 번호를 뽑으면 설탕과자를 가져가는 게임이었다.
(잉어, 붕어, 용 등 여러 가지가 적혀있다.)

격자판의 세로(h), 가로(w), 막대의 개수(n), 각 막대의 길이(l),
막대를 놓는 방향(d:가로는 0, 세로는 1)과
막대를 놓는 막대의 가장 왼쪽 또는 위쪽의 위치(x, y)가 주어질 때,
격자판을 채운 막대의 모양을 출력하는 프로그램을 만들어보자.

문제풀이

  1. 가로와 세로를 입력받는다
  2. 막대기 수를 입력받는다
  3. 막대기 수 만큼 반복하는 반복문에 길이 기울기 시작좌표를 매번 입력받고 기울기에 따라 다르게 2차원 배열 c를 채워주게 만든다
  4. 배열을 출력한다

1098 코드

#include <stdio.h>
int main(){
    int a,b,c[1001][101]={0};
    scanf("%d %d",&a,&b);
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int len=0,inc=0,x=0,y=0;
        scanf("%d %d %d %d",&len,&inc,&x,&y);
        if(inc == 1){
            for(int j = 0;j<len;j++){
                c[x-1+j][y-1]=1;
            }
        }else if(inc == 0){
            for(int j = 0;j<len;j++){
                c[y-1][x-1+j]=1;
            }

        }
    }
    for(int i = 0;i<a;i++){
        for(int j=0;j<b;j++){
            printf("%d ",c[i][j]);
        }
        printf("\n");
    }
}

1405

문제

n개의 숫자가 입력되면,
n개의 숫자를 왼쪽으로 하나씩 돌려서 출력하시오.
예) 1 2 3 4 5가 입력된 경우,
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4

문제풀이

  1. 배열을 입력받고 원래 배열의 끝부분에 한번더 배열을 넣는다
  2. 배열을 반복문 2개에 넣고 원래 반복문 2배의 길이까지 출력한다

1405 코드

#include <stdio.h>
int main(){
    int a, b[2002];
    scanf("%d",&a);
    for(int i=0;i<a;i++){
        scanf("%d",&b[i]);
        *(b+i+a)=*(b+i);
    }
    for(int i=0;i<a;i++){
        for(int j=0;j<a;j++){
            printf("%d ",*(b+i+j));
        }
        printf("\n");
    }
}

1097

문제

부모님을 기다리던 영일이는 검정/흰 색 바둑알을 바둑판에 꽉 채워 깔아 놓고 놀다가...
"십(+)자 뒤집기를 해볼까?"하고 생각했다.
바둑판(19 * 19)에 흰 돌(1) 또는 검정 돌(0)이 모두 꽉 채워져 놓여있을 때,
n개의 좌표를 입력받아 십(+)자 뒤집기한 결과를 출력하는 프로그램을 작성해보자.
참고
가로 번호, 세로 번호를 사용할 수 있는 2차원 배열을 사용하면
이러한 형태를 쉽게 기록하고 사용할 수 있다. 물론 더 확장한 n차원 배열도 만들 수 있다.
예시

int n, i, j, x, y;
int a[20][20]={};
for(i=1; i<=19; i++) //한 줄씩 바둑판 상황 입력 받기
  for(j=1; j<=19; j++)
    scanf("%d", &a[i][j]);
scanf("%d", &n); //좌표 개수 입력받기
for(i=1; i<=n; i++) //좌표의 개수만큼
{
  scanf("%d %d", &x, &y);
  for(j=1; j<=19; j++) //가로 줄 흑<->백 바꾸기
  {
    if(a[x][j]==0) a[x][j]=1;
    else a[x][j] = 0;
  }
  for(j=1; j<=19; j++) //세로 줄 흑<->백 바꾸기
  {
    if(a[j][y]==0) a[j][y]=1;
    else a[j][y] = 0;
  }
}
...

문제풀이

  1. 2차원 배열을 입력받는다
  2. 좌표의 갯수를 입력받고 그 좌표를 입력받아 가로와 세로를 바꿔주는 반복문을 작성한다
  3. 십자 뒤집기를 완료한 2차원 배열을 출력한다

1097 코드

#include <stdio.h>
int main(){
    int a[19][19]={0}, b, c,x,y,n;
    for(int i=0;i<19;i++){
        for(int j=0;j<19;j++){
            scanf("%d",&a[i][j]);
        }
    }
    scanf("%d", &n);
    for(int i=0; i<n; i++){
        scanf("%d %d", &x, &y);
        x-=1;
        y-=1;
        for(int j=0; j<19; j++){
            if(a[x][j]==0){
                a[x][j]=1;
            }else{
                a[x][j]= 0; 
            }
        }
        for(int j=0; j<19; j++){
            if(a[j][y]==0){
                a[j][y]=1;
            }else{
                a[j][y] =0;
        
            }
        }
        

    }
    for(int i=0;i<19;i++){
        for(int j=0;j<19;j++){
            printf("%d ",a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

1581

문제

함수명 : myswap
매개 변수(parameter) : 정수형 포인터 변수 변수
2개(매개변수를 반드시 int∗로 사용)
반환 형(return type) : 없음(void)
함수 내용 : 첫 번째 포인터가 가리키는 변수의 값이 두 번째 포인터가 가리키는 변수의 값보다 클 경우 두 값을 서로 바꾼다.

문제풀이

  1. int *a같은 형식으로 바꾸는 두 수를 함수에서 포인터 변수를 선언한다
  2. 역참조를 통해 주소에 있는 값들을 임시저장(temp)를 이용해 swap해준다.

1581 코드

#include <stdio.h>

void myswap(int *a,int *b){
    if(*a>*b){
        int temp;
        temp= *a;
        *a=*b;
        *b=temp;
    }
    return;

}
main()
{
    int a, b;
    scanf("%d%d", &a, &b);
    myswap(&a, &b);
    printf("%d %d", a, b);
}

1810

문제

어떤 문자열에서 부분문자열을 추출하여 출력하는 프로그램을 작성하시오.
단 배열 대신 동적메모리 할당방법을 사용하시오.
C언어인 경우 이 문제는 가급적 포인터(*)를 사용하시기 바랍니다.

문제풀이

  1. 동적메모리 할당을 위한 라이브러리 호출
  2. 문자열 배열 sen의 메모리 크기를 malloc을 써서 동적할당 해준다
  3. 입력받고 역참조를 이용해 주소값들을 출력해준다

1810 코드

#include <stdio.h>
#include <stdlib.h>
int main(){
    int a, b;
    char *sen = (char*) malloc(sizeof(char));
    scanf("%s",sen); 
    scanf("%d %d",&a,&b);
    for(int i=0;i<b-a+1;i++){
        printf("%c",*(sen+a+i-1));
    }
}

창작 문제(선택)

풀이를 설명

  1. 우선 포인터 생각하기 머리아프니까 그냥 뇌빼고 작성해 본다
#include <stdio.h>
#include <stdlib.h>
int main(){
    //입력
    int input,arr[100];
    printf("입력할 정수의 개수: ");
    scanf("%d",&input);
    printf("정수를 입력하세요: ");
    for(int i=0;i<input;i++){
        scanf("%d",&arr[i]);
    }
    printf("중복 제거 후 오름차순 정렬된 결과: ");
    // 오름차순
    for (int i = 0; i < input - 1; i++) {
        for (int j = 0; j < input - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    // 중복 제거 및 출력
    printf("%d ",arr[0]);
    for(int i=1;i<input; i++){
        if(arr[i]!=arr[i-1]){
            printf("%d ",arr[i]);
        }
    }
}
  1. 작성을 마친 후 소스의 길이를 감상하고 땅을 치며 후회한다
#include <stdio.h>
#include <stdlib.h>
int main(){
    //입력
    int input;
    int *arr = (int*) malloc(sizeof(int));
    printf("입력할 정수의 개수: ");
    scanf("%d",&input);
    printf("정수를 입력하세요: ");
    for(int i=0;i<input;i++){
        scanf("%d",&*(arr+i));
    }
    printf("중복 제거 후 오름차순 정렬된 결과: ");
    // 오름차순
    for (int i = 0; i < input - 1; i++) {
        for (int j = 0; j < input - 1 - i; j++) {
            if (*(arr+j) > *(arr+j+1)) {
                int temp = *(arr+j);
                *(arr+j) = *(arr+j+1);
                *(arr+j+1) = temp;
            }
        }
    }
    // 중복 제거 및 출력
    printf("%d ",*(arr));
    for(int i=1;i<input; i++){
        if(*(arr+i)!=*(arr+i-1)){
            printf("%d ",*(arr+i));
        }
    }
    free(arr);
}
  1. 풀이를 한다

풀이

  1. 입력횟수를 정수형으로 선언한다
  2. 정수형 배열은 문제 주문사항대로 malloc을 사용해 필요한 만큼만 크기를 쓰게 한다
  3. 입력을 받는다
  4. 반복문을 사용하여 오른쪽에 있는 수가 작으면 swap을 해주는 구조로 오름차순 정리를 해준다
  5. 정리된 배열의 첫번째 값은 그냥 출력한다
  6. 그 후의 값들을 반복문을 이용해 바로 전 값들과 크기를 비교해 전 값과 같지 않을 때만 출력하게 만든다

코드

#include <stdio.h>
#include <stdlib.h>
int main(){
    //입력
    int input;
    int *arr = (int*) malloc(sizeof(int));
    printf("입력할 정수의 개수: ");
    scanf("%d",&input);
    printf("정수를 입력하세요: ");
    for(int i=0;i<input;i++){
        scanf("%d",&*(arr+i));
    }
    printf("중복 제거 후 오름차순 정렬된 결과: ");
    // 오름차순
    for (int i = 0; i < input - 1; i++) {
        for (int j = 0; j < input - 1 - i; j++) {
            if (*(arr+j) > *(arr+j+1)) {
                int temp = *(arr+j);
                *(arr+j) = *(arr+j+1);
                *(arr+j+1) = temp;
            }
        }
    }
    // 중복 제거 및 출력
    printf("%d ",*(arr));
    for(int i=1;i<input; i++){
        if(*(arr+i)!=*(arr+i-1)){
            printf("%d ",*(arr+i));
        }
    }
    free(arr);
}

결과





0개의 댓글