Lesson 1

해커스쿨 서버는 현재 열려있지 않아서 로컬에 ftz 서버를 구축하고, ssh를 이용하여 접속했다. 

비밀번호를 입력하여 로그인 성공시 프롬프트가 나타나며 프롬프트는 명령 입력 대기 상태에서 명령을 기다린다.

프롬프트에는 접속 id, 서버, 현재위치의 정보가 있다.

프롬프트에 ls 명령어를 입력하면 다음과 같이 현재 디렉터리의 파일 목록을 확인할 수 있다.

ls 명령어에 -l 옵션을 추가하여 ls -l 을 입력하면 어떤것이 디렉터리이고, 어떤것이 파일인지 등 더 자세한 정보를 확인할 수 있다.

각 파일마다 구분되어 있는 필드에는 파일이 생성된 날짜 정보가 있고, 14698 같은 숫자들은 파일의 용량이다. tranier1 trainer1 과 같은 내용을 퍼미션에 관련한 정보이며 맨 첫번째 필드가 파일의 모드와 성격 정보를 가지고 있는데 가장 왼쪽의 문자가 - 면 일반 파일이고, d이면 디렉터리를 의미한다.

이후로 퀴즈가 나오는데 퀴즈 내용과 답은 다음과 같다.

ls명령어로는 보이지 않는 숨김 파일은 -a 옵션을 추가한 ls -a 명령어로 확인할 수 있다.

숨김 파일은 파일명 가장 앞에 . 이 붙어있다는 특징있다. 

ls 명령어는 ls -al 처럼 둘 이상의 옵션도 함께 사용할 수 있다. 함께 사용하면 사용하는 모든 옵션의 효과를 한번에 사용할 수 있다.

 

Lesson 2

자신이 현재 속해있는 디렉터리를 확인하려면 pwd 명령어를 이용하면 된다.

프롬프트에서 현재 위치의 정보는 앞의 경로는 생략하고 가장 뒤쪽의 경로만 나타내고 있다.

현재 경로에서 한 단계 위로 가려면 cd .. 명령어를 이용한다. 지금 경로에서 한단계 위로 가면 /home 가 되고 또 한단계 위로 가면 / 가 되는데, / 은 최상위 디렉토리이며 루트 디렉토리 라고도 한다.

경로를 내려갈때는 cd trainer2 처럼 디렉토리 이름을 붙이면 된다. 

.. 을 사용하지 않고 한번에 루트 디렉터리로 올라가려면 cd / 을 입력하면 된다. 또한 한 번에 trainer2 로 내려가려면 cd /home/trainer2처럼 루트 디렉토리부터 모든 경로를 입력하면 된다.

새로운 디렉토리를 만드는 명령어는 mkdir 이다. mkdir에 만들 디렉토리의 이름을 지정해주면 된다.

mkdir linuxer로 linuexer로 디렉토리를 만들면 ls 명령어로 확인 시 만든 디렉토리가 생성됨을 확인할 수 있다.

 

디렉토리를 삭제할 때는 rmdir이라는 명령어를 이용한다. 

rmdir linuxer을 입력하고 ls -al을 입력하면 linuxer 디렉터리가 삭제됨을 확인할 수 있다.

 

cp 명령어는 파일을 복사하는 명령어다. cp 파일1 파일2 와 같은 형태로 사용하면 파일1이 파일2의 이름으로 복사된다.

 

파일을 삭제하는 명령어는 rm이다. rm 복사사본을 입력하고 ls 명령어로 확인하면 파일이 삭제됨을 확인할 수 있다.

 

파일을 옮기는 명령어는 mv이다. mv명령어는 파일을 옮기는 것을 파일을 복사하고 원본 파일을 자동으로 삭제하는 것으로 처리하기 때문에 파일 이름을 변경할 때도 자주 사용된다.

mv 파일1 파일 2의 형식으로 사용하면 파일1의 이름이 파일2로 변경된다.

 

Lesson3

터미널은 ssh나 텔넷등의 서버를 통해 접속한 것이고, 콘솔은 부팅한 컴퓨터에 직접 접속한 것이라는 의미이다. 

 

w명령어를 사용하면 현재 서버에 접속한 사용자 목록을 확인할 수 있다.

첫번째 필드는 접속한 아이디를 나타낸다. 두번째 필드는 콘솔로 접속했는지, 터미널로 접속했는지 보여준다. tty면 콘솔접속, pts면 터미널 접속을 의미한다. 3번째 필드는 접속한 사람의 ip를 의미한다. 콘솔 접속한 경우 ip는 보이지 않는다. 4번째 필드는 로그인 시간이고, 5번째 필드는 지연시간으로 사용자가 얼마나 아무것도 입력을 안했는지 확인할 수 있다. 6번째 필드는 cpu를 사용한 지연 시간이고, 7번째 필드는 what 필드에 있는 명령이 지연된 시간, 8번째 필드는 현재 사용하고 있는 명령을 보여준다.

 

finger -l 명령어를 확인하면 사용자에 대한 좀 더 많은 정보를 확인할 수 있다.

 

tty 명령어를 사용하면 자신의 터미널 정보를 확인할 수 있다.

 

ifconfig 명령어를 사용하면 ip 정보를 확인할 수 있다.

 

write 사용자id /dev/pts/pts번호 의 명령어로 서버에 접속한 다른 사용자에게 메시지를 전달할 수 있다.

 

wall "내용" 의 명령어로 현재 접속한 모든 사용자에게 메시지를 전달할 수 있다.

0부터 9까지 몇번 사용됬는지 저장할 공간을 int형 포인터에 int 자료형 크기로 10개 할당하였다.

자연수 세개를 입력받아, 입력받은 자연수 3개를 곱한다.

곱한 값이 0보다 클때까지 반복하고 반복문 안에는 곱한 값을 10으로 나눈 나머지를 배열의 인덱스로 하여 그 숫자가 나올때 마다 해당 인덱스에 1씩 누적하고 곱한 값을 10으로 나눈다.

할당한 메모리를 해제하고 종료한다.

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int a, b, c, mul, i;
    int *numPtr = (int*)malloc(sizeof(int* 10);
    scanf("%d %d %d"&a, &b, &c);
    mul = a * b * c;
    
    while(mul > 0)
    {
        i = mul % 10;
        numPtr[i] = numPtr[i] + 1;
        mul /= 10;
    }
    
    for(int i=0; i<10; i++
    {
        printf("%d\n", numPtr[i]);
    }
    free(numPtr);
    return 0;
}
cs

과목의 개수를 저장할 변수, 평균을 저장할 변수, 점수 중 최댓값을 저장할 변수를 선언하고 점수들을 저장할 공간의 포인터를 선언하고, 과목의 개수를 입력받는다.

점수를 고치는 연산을 하며 소수가 될 수 있으므로 double 자료형 크기의 과목 개수만큼 저장할 수 있도록 메모리를 할당한다.

과목의 개수 만큼 반복하면서 최댓값을 찾고, 또 과목의 개수만큼 반복하면서 각 점수를 최댓값을 사용하여 문제에서 주어진 식으로 연산하여 저장한다.

연산한 점수들을 평균을 저장할 avg변수에 누적하여 저장하고, avg를 과목의 개수로 나누어 평균을 구한다.

메모리를 해제하고, 구한 평균을 출력한다.

정답 코드는 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <stdlib.h>
 
int main(void)
{
    int subNum = 0;
    double avg = 0, big = 0;
    double *subArr;
    
    scanf("%d"&subNum);
    
    subArr = (double*)malloc(sizeof(double* subNum);
    
    for(int i = 0; i < subNum; i++)
    {
        int tmp;
        scanf("%d"&tmp);
        subArr[i] = double(tmp);
        
    }
 
    for(int i = 0; i < subNum; i++)
    {
        if(subArr[i] > big)
            big = subArr[i];
    }
 
    for(int i = 0; i < subNum; i++)
    {
        subArr[i] = subArr[i]/big*100;
    }
 
    for(int i = 0; i < subNum; i++)
    {
        avg += subArr[i];
    }
    avg = avg / subNum;
    
    free(subArr);
    printf("%lf", avg);
    return 0;
}
cs

크기가 9인 int형 배열을 선언하고, 그 배열을 포인터에 저장한다.

최댓값과 최댓값의 위치를 저장할 변수를 선언하고 0으로 초기화한다.

반복문으로 9번 반복하면서 포인터에 저장된 주솟값으로 배열에 값을 저장한다.

반복문으로 0부터 9까지 반복하면서 각 인덱스가 max보다 큰지 비교하고, 크면 max에 그 값을 저장하고, loc에 그 인덱스를 저장한다.

반복문이 끝나면 max값과 인덱스는 0부터 시작하기 때문에 loc + 1을 출력한다.

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
int main()
{
    int arr[9];
    int *numList = arr;
    int max = 0, loc = 0;
    
    for(int i = 0; i < 9; i++)
    {
        scanf("%d"&numList[i]);
    }
    for(int i = 0; i < 9; i++)
    {
        if(numList[i] > max)
        {
            max = numList[i];
            loc = i;
        }
    }
    
    printf("%d\n%d", max, loc+1);
    return 0;
}
cs

테스트 케이스의 개수를 입력받고, 개수 만큼 반복한다.

반복문 안에는 char 자료형 크기 80개를 저장할 수 있는 메모리 공간을 할당하고, 그 공간에 문자열을 입력받는다.

점수를 누적할 변수 sum과 점수를 다음 추가할 점수를 저장할 변수 score를 만들고 sum은 0으로, score는 1로 초기화 한다.

입력받은 문자열의 길이 만큼 반복하여 'O'이면 score의 값을 sum에 누적시키고 score의 값을 1 증가시킨다. 'X'면 score의 값을 1로 초기화 한다.

입력 받은 문자열의 개수는 string.h헤더파일의 strlen()함수를 이용하면 구할 수 있다.

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
 
int main()
{
    int cnt;
    scanf("%d",&cnt);
    
    for(int i=0; i<cnt; i++)
    {
        char *result = malloc(sizeof(char* 80);
        int score = 1,sum = 0;
        scanf("%s",result);
        
        for(int j=0; j < strlen(result); j++)
        {
            if(result[j]=='O')
            {
                sum += score;
                score++;
            }
            else
            {
                score = 1;
            }
        }
        printf("%d\n",sum);
        free(result); 
    }
    
    return 0;
}
 
cs

금지 키워드로 [ 가 설정되어 있으므로 인덱스 기능을 이용해서는 풀지 못하고, 역참조 연산자를 사용해야 한다.

(char 자료형 크기 * 100) 크기의 메모리를 할당한 포인터를 생성하고 할당한 메모리 공간에 문자열을 입력받는다.

부분 문자 시작 위치와 끝 위치로 사용할 변수 a,b를 선언하고 입력받는다.

반복문으로 a-1부터 b보다 작을때 까지 반복하여 역참조 연산자를 사용하여 문자를 출력한다.

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
 
int main() 
{
    char *sPtr = malloc(sizeof(char* 100);
    scanf("%s", sPtr);
    
    int a, b;
    scanf("%d %d"&a, &b);
    
    for(int i = a-1; i < b; i++)
    {
        printf("%c"*(sPtr + i));    // 역참조 연산자 
    }
    return 0;
}
cs

Unit 37. 2차원 배열 사용하기

2차원 배열은 다음과 같이 가로 x 세로 의 형태로 되어 있는 평면 구조이며 행과 열 모두 0부터 시작한다.

37.1 2차원 배열을 선언하고 요소에 접근하기

2차원 배열은 [](대괄호)를 두번 사용하여 선언하며 첫 번째 대괄호는 세로크기, 두 번째 대괄호는 가로 크기를 지정한다.

2차원 배열을 선언하면서 초기화 하려면 { }(중괄호)를 사용하는데, 다음과 같이 가로 요소들을 먼저 묶고, 가로 줄을 세로 크기만큼 다시 묶는다.

int numArr[3][4] = {
    { 가로 요소 4개 },
    { 가로 요소 4개 },
    { 가로 요소 4개 }
};

{ }를 사용라여 배열에 값을 할당하는 방법은 배열을 선언할 때만 사용할 수 있으며 이미 선언한 배열에는 사용할 수 없다.

2차원 배열의 요소에 접근하려면 배열 뒤에 [ ](대괄호)를 두 번 사용하여 안에 세로와 가로 인덱스를 지정하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
 
int main()
{
    int numArr[3][4= {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };
 
    printf("%d\n", numArr[0][0]);
    printf("%d\n", numArr[1][2]);
    printf("%d\n", numArr[2][0]);
    printf("%d\n", numArr[2][3]);
    return 0;
}
cs

세로크기가 3, 가로크기가 4인 int형 2차원 배열을 선언하고, 값을 초기화 했다.

2차원 배열도 가로, 세로 인덱스 모두 0부터 시작한다.

배열을 초기화 할때 가로 요소를 중괄호로 묶지 않아도 되지만 알아보기가 힘들어 잘 사용하진 않는다.

37.2 2차원 배열을 초기화하기

2차원 배열은 다음 코드로 모든 요소를 0으로 초기화 할 수 있다.

int numArr[3][4] = { 0, };

37.3 2차원 배열의 요소에 값 할당하기

다음 코드와 같이 값을 초기화 하지 않은 배열의 요소에 값을 할당할 수 있다.

int numArr[3][4];

numArr[0][1] = 5;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
int main()
{
    int numArr[3][4];
 
    numArr[0][0= 11;
    numArr[0][1= 22;  
    numArr[0][2= 33;    
    numArr[0][3= 44;  
 
    numArr[1][0= 55;   
    numArr[1][1= 66;  
    numArr[1][2= 77;   
    numArr[1][3= 88;   
 
    numArr[2][0= 99;   
    numArr[2][1= 110;  
    numArr[2][2= 121;   
    numArr[2][3= 132;  
 
    printf("%d\n", numArr[-1][-1]);   
    printf("%d\n", numArr[0][4]);     
    printf("%d\n", numArr[4][0]);  
    printf("%d\n", numArr[5][5]);     
 
    return 0;
}
cs

2차원 배열도 범위를 벗어난 인덱스에 접근하여 출력하면 쓰레기값이 출력된다. 배열의 범위를 벗어난 인덱스에 접근하면 배열이 아닌 다른 메모리 공간에 접근하게 된다. 또한 [0][4]처럼 가로 인덱스만 범위를 벗어나도록 지정하면 그 다음 세로 인덱스 요소인 [1][0]에 접근된다.

37.4 2차원 배열의 크기 구하기

2차원 배열의 전체공간, 가로, 세로 요소의 개수는 다음과 같이 sizeof 연산자를 이용하여 구할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
 
int main()
{
    int numArr[3][4= {    
        { 11223344 },
        { 55667788 },
        { 99110121132 }
    };
 
    printf("%d\n"sizeof(numArr));  
 
    int col = sizeof(numArr[0]) / sizeof(int);                                    
    int row = sizeof(numArr) / sizeof(numArr[0]); 
 
    printf("%d\n", col);   
    printf("%d\n", row);   
    return 0;
}
cs

sizeof로 2차원 배열의 크기를 구하면 전체 공간을 구할 수 있다. 위에서는 4바이트 요소가 8개 있으므로 48이 나온다.

가로의 요소 개수는 가로 한 줄의 크기를 요소 자료형의 크기로 나누면 된다.

세로의 요소 개수는 배열의 전체 공간을 가로 한 줄의 크기로 나누면 된다.

37.5 반복문으로 2차원 배열의 요소를 모두 출력하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
int main()
{
    int numArr[3][4= {    
        { 11223344 },
        { 55667788 },
        { 99110121132 }
    };
 
    int col = sizeof(numArr[0]) / sizeof(int);  
    int row = sizeof(numArr) / sizeof(numArr[0]);
 
    for (int i = 0; i < row; i++)    
    {
        for (int j = 0; j < col; j++)    
        {
            printf("%d ", numArr[i][j]); 
        }
        printf("\n");                
    }
 
    return 0;
}
cs

배열의 세로와 가로 요소의 개수를 구하고, 2중 for문으로 세로부터 반복하고, 가로를 반복한다. 2차원 배열의 인덱스로는 세로에는 바깥쪽 반복문의 i를, 가로에는 안쪽 반복문의 j를 넣어 배열의 요소를 순서대로 접근하여 출력할 수 있다. 안쪽 반복문이 끝나면 개행문자를 출력함으로 세로줄이 바뀔때 줄을 바꿔 출력한다.

다음 코드와 같이 역순으로도 출력할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
 
int main()
{
    int numArr[3][4= {    
        { 11223344 },
        { 55667788 },
        { 99110121132 }
    };
 
    int col = sizeof(numArr[0]) / sizeof(int);  
    int row = sizeof(numArr) / sizeof(numArr[0]);
 
    for (int i = row - 1; i >= 0; i--)    
    {
        for (int j = col-1; j >= 0; j--)    
        {
            printf("%d ", numArr[i][j]); 
        }
        printf("\n");                
    }
 
    return 0;
}
cs

세로와 가로의 마지막 인덱스부터 0까지 인덱스를 1씩 감소시키면서 출력하면 된다.

37.6 2차원 배열을 포인터에넣기

2차원 배열을 포인터에 담으려면 가로의 크기를 알아야 한다. 다음과 같이 포인터를 선언할 때 *과 포인터 이름을 괄호로 묶은 뒤 []에 가로 크기를 지정하면 된다.

int (*numPtr)[4];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int main()
{
    int numArr[3][4= {    
        { 11223344 },
        { 55667788 },
        { 99110121132 }
    };
    int (*numPtr)[4= numArr;
 
    printf("%p\n"*numPtr);
    printf("%p\n"*numArr);
    printf("%d\n", numPtr[1][2]);
    printf("%p\n"sizeof(numArr));
    printf("%p\n"sizeof(numPtr));
    return 0;
}
cs

위 코드와 같이 2차원 배열을 포인터에 할당할 수 있다.

2차원 배열을 포인터에 할당한 뒤 포인터를 역참조 해보면 세로 첫번째 요소의 주솟값이 나온다. 배열을 역참조해도 같은 값이나온다.

2차원 배열 포인터도 대괄호를 두 번 사용하여 배열의 요소에 접근할 수 있다.

sizeof로 크기를 계산하면 배열은 메모리가 차지하는 전체 공간이 출력되지만, 포인터는 포인터의 크기만 출력된다.

37.7 퀴즈

정답은 c이다.

정답은 d이다.

정답은 c이다.

정답은 b,d,e이다.

37.8 연습문제 : 행렬의 주대각선 성분 구하기

정답은 다음 코드와 같다.

for (int i = 0; i < sizeof(matrix) / sizeof(matrix[0]); i++)
{
    printf("%d ", matrix[i][i]);
}

인덱스 값이 (0,0), (1,1) ... 처럼 가로 세로 모두 1씩 증가하기 때문에 0~7까지 반복한 값을 가로, 세로 인덱스에 넣으면 된다.

37.9 심사문제 : 전치 행렬 구하기

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
int col = sizeof(matrix[0]) / sizeof(int);  
int row = sizeof(matrix) / sizeof(matrix[0]);
 
for (int i = 0; i < row; i++)    
{
    for (int j = 0; j < col; j++)    
    {
        printf("%d ", matrix[j][i]); 
    }
        printf("\n");                
}
cs

행과 열이 서로 바뀌어있기 때문에 2차원 배열을 출력할 때 세로에 i를 넣고, 가로에 j를 넣으면 된다.

Unit 38. 포인터와 배열 응용하기

다음과 같이 프로그램 실행 중 원하는 크기 만큼 배열을 생성하는 기능은 gcc에서는 지원하지만 Viual Studio에서는 지원하지 않아 컴파일 에러가 발생한다.

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int main()
{
    int size;
    scanf("%d"&size);  
 
    int numArr[size];    // 입력값을 배열의 크기로 사용
    return 0;
}
cs

컴파일 에러 없이 배열의 크기를 동적으로 지정하려면 포인터를 선언하고 메모리를 할당한 뒤 메모리를 배열처럼 사용해야 한다.

38.1 포인터에 할당된 메모리를 배열처럼 사용하기

포인터에 malloc 함수로 메모리를 할당하여 포인터를 배열처럼 사용할 수 있다.

자료형 *포인터이름 = malloc(sizeof(자료형) * 크기);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int *numPtr = malloc(sizeof(int* 10);
    numPtr[0= 10;
    numPtr[9= 20;
 
    printf("%d\n", numPtr[0]);
    printf("%d\n", numPtr[9]);
    free(numPtr);
    return 0;
}
cs

위 코드와 같이 int 크기에 10을 곱하여 동적으로 메모리를 할당하여 배열처럼 사용할 수 있다. 배열 처럼 대괄호 안데 인덱스를 지정하여 값을 저장하거나 가져올 수 있다.

배열은 한번 선언하면 끝이지만 위와 같은 포인터는 malloc함수로 메모리를 할당했기 때문에 free함수로 해제해야 한다.

*numPtr처럼 역참조 한것과 numPtr[0]으로 0번 인덱스를 가져오는 것은 같은 값을 가져오고, *(numPtr + 1)은 numPtr[1]과 같은 값을 가져오게 된다. 포인터에 값을 더하는 방식을 포인터 연산 이라고 한다.

38.2 입력한 크기만큼 메모리를 할당하여 배열처럼 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int size;
    scanf("%d"&size);
 
    int *numPtr = malloc(sizeof(int* size);
 
    for(int i = 0; i < size; i++)
    {
        numPtr[i] = i;
    }
    for(int i = 0; i < size; i++)
    {
        printf("%d\n", numPtr[i]);
    }
    free(numPtr);
    return 0;
}
cs

scanf로 크기를 입력받고, int 크기에 입력받은 크기를 곱하여 메모리를 할당했다.

입력받은 크기 만큼 반복하며 값을 할당 하고, 입력받은 크기만큼 반복하며 값을 출력하였다.

사용이 끝나면 free함수로 할당한 메모리를 해제해야 한다.

38.3 포인터에 할당된 메모리를 2차원 배열처럼 사용하기

2차원 배열처럼 사용하기 위해 포인터에 할당하는 방법은 다음과 같다.

1. 자료형 **포인터이름 = malloc(sizeof(자료형 *) * 세로크기); 와 같이 세로 공간 메모리 할당

2. 반복문으로 반복하며 포인터[i] = malloc(sizeof(자료형) * 가로크기); 와 같이 가로 공간 메모리 할당

3. 반복문으로 반복하면서 free(포인터[i]); 와 같이 가로 공간 메모리 해제

4. 반복문으로 반복하면서 free(포인터); 와 같이 세로 공간 메모리 해제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int **= malloc(sizeof(int ** 3);
 
    for(int i = 0; i < 3; i++)
    {
        m[i] = malloc(sizeof(int* 4);
    }
 
    m[0][0= 1;
    m[2][0= 5;
    m[2][3= 2;
 
    printf("%d\n", m[0][0]);
    printf("%d\n", m[2][0]);
    printf("%d\n", m[2][3]);
 
    for(int i = 0; i < 3; i++)
    {
        free(m[i]);
    }
    free(m);
    return 0;
}
cs

2중 포인터에 2차원 배열의 세로 공간에 해당하는 메모리를 할당한다. 이때 세로 공간에는 값이 들어가지 않고 가로 공간의 메모리 주소가 들어간다. 그래서 sizeof(int *)처럼 포인터의 크기를 구한 후 세로 크기 3을 곱하는 것이다.

이후 세로 크기 만큼 반복하며 2차원 배열의 가로 공간에 해당하는 메모리를 할당한다.

가로 공간은 int 자료형의 크기에 가로크기 4를 곱해주었다.

이중 포인터를 2차원 배열처럼 사용하도록 메모리를 할당하는 모습을 그림으로 표현하면 다음과 같다.

m은 pointer to pointer to int이므로 int **m 처럼 선언한다.

2차원 배열을 사용하는 것처럼 [ ] [ ]에 세로인덱스, 가로인덱스를 지정하여 값을 할당하거나 가져올 수 있다.

포인터를 다 사용하면 가로 공간에 해당하는 메모리부터 해제한다. 이후 세로 공간에 해당하는 메모리를 해제한다.

메모리를 할당할 때는 세로 - > 가로의 순서로 할당했으므로 해제할 때는 가로 -> 세로의 순서로 해제하는 것이다.

38.4 입력한 크기만큼 메모리를 할당하여 포인터를 2차원 배열처럼 사용하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int row, col;
    scanf("%d %d"&row, &col);
 
    int **= malloc(sizeof(int ** row);
    for(int i = 0; i < row; i++)
    {
        m[i] = malloc(sizeof(int* col);
    }
 
    for(int i = 0; i < row; i++)
    {
        for(int j = 0; j < col; j++)
        {
            m[i][j] = i + j;
        }
    }
 
    for(int i = 0; i < row; i++)
    {
        for(int j = 0; j < col; j++)
        {
            printf("%d ", m[i][j]);
        }
        printf("\n");
    }
 
    for(int i = 0; i < row; i++)
    {
        free(m[i]);
    }
    free(m);
    return 0;
}
cs

세로 크기와 가로 크기를 입력 받고, 입력받은 값을 활용하여 세로공간과 가로공간 메모리를 할당하였다.

세로, 가로 크기가 고정되어 있지 않으므로 입력값 row, col을 활용하여 반복하면서 값을 할당하고, 값 할당이 끝나면 다시 반복하면서 2차원 배열의 값을 출력한다.

사용이 모두 끝나면 입력받은 세로 크기만큼 반복하며 가로 공간 메모리를 해제하고, 이후 세로 공간 메모리를 해제한다.

38.5 퀴즈

정답은 d이다.

정답은 b이다.

38.6 연습문제 : 포인터에 할당된 메모리를 3차원 배열처럼 사용하기

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 1.
for(int depth = 0; depth < 2; depth++)
{
    m[depth] = malloc(sizeof(long long ** 3);
    
    for(int row = 0; row < 3; row++)
    {
        m[depth][row] = malloc(sizeof(long long* 5);
    }
}
 
// 2.
for(int depth = 0; depth < 2; depth++)
{
    for(int row = 0; row < 3; row++)
    {
        free(m[depth][row]);
    }
    free(m[depth]);
}
cs

3차원의 면에 해당하는 공간은 할당되어 있기 때문에 2중 for문으로 면의 개수만큼 반복하면서 세로공간에 해당하는 메모리를 할당하고, 안쪽 반복문에서 세로 크기만큼 반복하며 가로 공간에 해당하는 메모리를 할당하였다.

메모리를 해제할 때도 2차원 배열과 마찬가지로 할당의 역순으로 가로 -> 세로 -> 면 순서로 해제하면 된다.

38.7 심사문제 : 단위 행렬 만들기

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int size;
    scanf("%d"&size);
 
    int **= malloc(sizeof(int ** size);
    for(int i = 0; i < size; i++)
    {
        m[i] = malloc(sizeof(int* size);
    }
 
    for(int i = 0; i < size; i++)
    {
        for(int j = 0; j < size; j++)
        {
            if(i == j)
            {
                m[i][j] = 1;
            }
            else
            {
                m[i][j] = 0;
            }
        }
    }
 
    for(int i = 0; i < size; i++)
    {
        for(int j = 0; j < size; j++)
        {
            printf("%d ", m[i][j]);
        }
        printf("\n");
    }
 
    for(int i = 0; i < size; i++)
    {
        free(m[i]);
    }
    free(m);
    return 0;
}
cs

가로 인덱스와 세로 인덱스가 같은 위치는 1이고, 다른 위치는 모두 0이므로 2차원 배열에 값을 할당하는 부분에서 if 조건문으로 해당 조건에 맞게 값을 저장하였다.

38.8 심사문제 : 지뢰찾기

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int m, n;
    int cnt = 0;
    scanf("%d %d"&m, &n);
 
    // 메모리 할당
    char **matrix = malloc(sizeof(char ** m);
    for(int i = 0; i < m; i++)
    {
        matrix[i] = malloc(sizeof(char ** (n+1));
    }
 
    // 입력
    for(int i = 0; i < m; i++)
    {
        scanf("%s", matrix[i]);
    }
    
    for (int i = 0; i < m; i++
    {
        for (int j = 0; j < n; j++
        {
            if (matrix[i][j] == '.'
            {
                matrix[i][j] = '0';
            }
        }
    }
    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
        {
            // 지뢰일 경우
            if(matrix[i][j] == '*')
            {
                for(int y = i - 1; y < i + 2; y++)
                {
                    for(int x = j - 1; x < j + 2; x++)
                    {
                        if(y < 0 || x < 0 || y >= m || x >= n || matrix[i][j] == matrix[y][x] || matrix[y][x] == '*')
                        {
                            continue;
                        }
                        matrix[y][x] += 1;
                    }
                }
            }
        }
        
    }
    
    // 결과 출력
    for (int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++)
        {
            printf("%c", matrix[i][j]);
        }
        printf("\n");
    }
    // 메모리 해제
    for (int i = 0; i < m; i++
    {
        free(matrix[i]);
    }
    free(matrix);
    return 0;
}
cs

행렬 크기와 행렬을 입력받고, 각 요소별로 반복하면서 '.' 인 경우 '0' 으로 바꿔 주었다.

각 요소별로 반복하면서 요소가 지뢰일 경우 그 요소를 둘러싸고 있는 요소들에 1씩 추가해 줬는데, 조건문을 사용하여 행렬을 벗어나지 않고, 둘러싸고 있는 요소가 지뢰가 아닐 경우에만 1씩 누적하였다.

반복문의 실행이 끝나면 다시 반복문으로 수정된 행렬의 결과를 출력하고 메모리를 해제하였다.

Unit 35. 메모리 사용하기

포인터에 원하는 만큼 메모리 공간을 할당받아 사용할 수 있다.

메모리는 malloc -> 사용 -> free의 패턴으로 사용한다.

35.1 메모리 할당하기

메모리를 사용하려면 malloc 함수로 사용할 메모리 공간을 확보해야 한다. 할당할 메모리 크기는 바이트 단위로 지정한다. malloc함수는 stdlib.h 헤더파일에 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int num1 = 20;
    int *numPtr1;
 
    numPtr1 = &num1;
 
    int *numPtr2;
    numPtr2 = malloc(sizeof(int));
 
    printf("%p\n", numPtr1);
    printf("%p\n", numPtr2);
    
    free(numPtr2);
    return 0;
}
cs

메모리를 할당할 때는 malloc 함수를 사용하여 할당할 메모리 공간의 크기를 넣어주는데, 위 코드에서는 sizeof 연산자를 이용하여 int크기 만큼의 즉 4바이트 크기의 메모리를 할당했다.

이처럼 원하는 시점에 원하는 메모리를 할당할 수 있어 동적 메모리 할당이라 부른다.

출력값은 같은 메모리 주소를 출력하는것 같지만 메모리 주소에는 내부적인 차이가 있다. 변수는 스택에 생성되며 malloc함수는 힙부분의 메모리를 사용한다.

스택에 생성된 변수는 사용한뒤 따로 처리를 하지 않아도 되지만 malloc함수를 사용하여 힙에 할당한 메모리는 반드시 해제를 해야 한다. free 함수를 이용하여 메모리를 해제할 수 있다.

메모리를 해제하지 않으면 시스템의 메모리가 부족해져 운영체제가 프로그램을 강제로 종료시키거나 메모리 할당에 실패할 수 있다. 메모리를 해제하지 않아 메모리 사용량이 계속 증가하는 현상을 메모리 누수(memory leak)라 한다.

35.2 메모리에 값 저장하기

다음은 할당한 메모리에 값을 저장하는 코드이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
 
int main()
{
    int *numPtr;
    numPtr = malloc(sizeof(int));
    *numPtr = 10;
 
    printf("%d\n"*numPtr);
    free(numPtr);
    return 0;
}
cs

malloc 함수로 할당한 메모리에 값을 저장할 때는 포인터를 역참조한 뒤 값을 저장하면 된다. 값을 출력할 때도 역참조를 사용하면 된다. 메모리를 할당하고 사용한 뒤에는 반드시 free함수로 해제를 해 줘야 한다.

35.3 메모리 내용을 한꺼번에 설정하기

memset 함수를 사용하면 메모리의 내용을 원하는 크기 만큼 특정 값으로 설정할 수 있다. 설정하는 크기는 바이트 단위이며 이 함수는 string.h 헤더파일에 선언되어 있다. memset 함수는 다음과 같이 사용한다.

memset(포인터, 설정할값, 크기);

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
    long long *numPtr = malloc(sizeof(long long));
    memset(numPtr, 0x278);
 
    printf("0x%llx"*numPtr);
    free(numPtr);
    return 0;
}
cs

long long 자료형의 크기인 8바이트 만큼 동적 메모리를 할당하고, memset 함수로 numPtr이 가리키는 메모리에 16진수 27이 8개 들어가도록 한다.

memset함수는 다음과 같이 설정할 값을 모두 0으로 지정하여 메모리의 내용을 모두 0으로 만들 때 주로 사용한다.

memset(numPtr, 0, 8); 

35.4 널 포인터 사용하기

1
2
3
4
5
6
7
8
9
#include <stdio.h>
 
int main()
{
    int *numPtr1 = NULL;  
 
    printf("%p\n", numPtr1); 
    return 0;
}
cs

위 코드와 같이 NULL이 들어있는 포인터를 널 포인터라고 하며 아무것도 가리키지 않는 상태이다. 역참조도 할 수 없다.

실무에서는 다음과 같이 포인터가 NULL인지 확인하고, NULL이면 메모리를 할당하는 방식을 주로 사용한다.

if (ptr == NULL)      
{
    ptr = malloc(1024);  
}

35.5 퀴즈

정답은 d이다.

정답은 c이다.

정답은 b이다.

정답은 a이다.

정답은 d이다.

정답은 널 포인터 이다.

35.6 연습문제 : 메모리 할당하기

정답은 다음과 같다.

1. malloc(sizeof(int));

2. malloc(sizeof(long long));

각각 4바이트와 8바이트 만큼의 메모리를 할당해 줘야 하기 때문이다.

35.7 심사문제 : 두 정수의 합 구하기

정답은 다음 코드와 같다.

1
2
int *numPtr1 = malloc(sizeof(int));
int *numPtr2 = malloc(sizeof(int));
cs

Unit 36. 배열 사용하기

배열은 같은 자료형의 변수를 일렬로 늘어놓은 형태이다.

반복문과 결합하면 연속적이고 반복되는 값을 손쉽게 처리할 수 있다.

36.1 배열을 선언하고 요소에 접근하기

배열은 변수 이름 뒤에 [](대괄호)를 붙인 뒤 크기를 설정한다. 배열을 선언하며 값을 초기화 할 때는 {}(중괄호)를 사용한다.

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };    
 
    printf("%d\n", numArr[0]);    
    printf("%d\n", numArr[5]);    
    printf("%d\n", numArr[9]);    
    return 0;
}
cs

크기가 10인 int형 배열을 선언하며 값을 할당하였다. 값을 할당할 때 {} 안의 값 개수는 배열의 크기보다 작아도 되만 크면 안된다. 또한 {}를 사용하여 값을 할당하는 것은 배열을 선언할 때만 사용할 수 있으며 이미 선언된 배열에서는 사용할 수 없다.

배열 값이 저장된 각각의 공간을 요소라고 하며 요소에 접근할 때는 배열 뒤에 [](대괄호)를 사용하고, 대괄호 안에 각 요소의 인덱스를 지정한다. 배열의 인덱스는 항상 0부터 시작한다.

배열을 선언하며 값을 초기화하면 다음과 같이 배열의 크기를 생략할 수 있다. 초기화를 하지 않고 생략하면 컴파일 에러가 발생한다.

int numArr1[] = { 11, 22, 33, 44, 55, 66, 77, 88, 99, 110 }; 

36.2 배열을 0으로 초기화하기

다음과 같이 한번에 배열의 모든 요소를 0으로 초기화 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
 
int main()
{
    int numArr[10= {0, };    
 
    printf("%d\n", numArr[0]);    
    printf("%d\n", numArr[5]);    
    printf("%d\n", numArr[9]);    
    return 0;
}
cs

배열의 모든 요소를 한 번에 0으로 초기화하여 0을 일일이 나열하지 않아도 된다.

36.3 배열의 요소에 값 할당하기

배열은 []로 요소에 접근한 뒤 값을 할당할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int numArr[3];
 
    numArr[0= 1;
    numArr[1= 22;
    numArr[2= 8;
 
    printf("%d\n", numArr[0]); 
    printf("%d\n", numArr[1]); 
    printf("%d\n", numArr[2]);  
    return 0;
}
cs

인덱스는 0부터 시작하며 []에 인덱스를 지정한 뒤 값을 할당하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main()
{
    int numArr[3];
 
    numArr[0= 1;
    numArr[1= 22;
    numArr[2= 8;
 
    printf("%d\n", numArr[-1]); 
    printf("%d\n", numArr[5]); 
    printf("%d\n", numArr[10]);  
    return 0;
}
cs

위 코드와 같이 배열의 요소에 접근할 때 인덱스로 음수를 지정하거나, 배열의 크기를 벗어난 인덱스를 지정해도 컴파일에러는 발생하지 않지만, 쓰레기값을 출력한다. 배열의 범위를 벗어난 인덱스에 접근하면 배열이 아닌 다른 메모리 공간에 접근하여 엉뚱한 값을 출력하게 된다.

36.4 배열의 크기 구하기

반복문을 이용해서 배열의 요소를 모두 출력할 때 선언된 크기로 사용하면 나중에 배열의 크기를 늘려야 해서 코드를 수정해야 할 경우 반복문의 조건식도 수정해야 모든 배열이 출력될 수 있다. 이러한 불편함을 해결하려면 sizeof연산자를 사용하여 배열의 전체 요소의 개수를 구해 배열의 크기가 수정되면 반복문의 조건식에서도 알아서 계산되도록 할 수 있다.

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };    
 
    printf("%d\n"sizeof(numArr));                  
    printf("%d\n"sizeof(numArr) / sizeof(int));                                                     
    return 0;
}
cs

sizeof연산자로 numArr의 크기를 구하면 4바이트인 int형 요소가 10개 있으므로 40이 나온다. 요소의 개수를 구하려면 배열의 크기에서 요소의 크기(sizeof(int))로 나눠주면 된다.

36.5 반복문으로 배열의 요소를 모두 출력하기

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };    
 
    for (int i = 0; i < sizeof(numArr) / sizeof(int); i++)   
    {
        printf("%d\n", numArr[i]);   
    }
    return 0;
}
cs

반복문의 조건식에서 sizeof 연산자를 사용하여 배열의 요소 개수만큼 반복하였다.

변수 i는 변화식을 통해 1씩 증가하므로 인덱스에 i를 넣어서 모든 배열의 요소를 순서대로 출력할 수 있다.

다음과 같이 배열의 요소를 역순으로 출력할 수 도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };    
 
    for (int i = sizeof(numArr) / sizeof(int- 1; i >= 0; i--)  
    {
        printf("%d\n", numArr[i]);   
    }
    return 0;
}
cs

배열을 역순으로 출력할 때는 요소의 개수를 조건식에 바로 넣으면 인덱스는 0부터 시작하기 때문에 배열의 마지막 인덱스는 배열의 개수보다 1 작아서 반복문의 조건식에서도 요소의 개수에서 1 뺀 값에서 시작해야 한다. 조건식에서 0보다 크거나 같을 때 까지 반복하여 역순으로 출력할 수 있다.

36.6 배열의 요소 합계 구하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };
    int sum = 0;    
 
    for (int i = 0; i >= sizeof(numArr) / sizeof(int); i++)  
    {
        sum += numArr[i];
    }
    printf("%d\n", sum);
    return 0;
}
cs

위 코드와 같이 합을 저장할 변수를 만들고 배열의 요소만큼 반복하면서 배열의 각 요소의 값을 만든 변수에 누적시킨다. 저장할 변수를 만들때는 0으로 초기화 하지 않으면 쓰레기값이 들어간다.

36.7 배열의 요소에 저장된 값을 두 배로 만들기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 }; 
 
    for (int i = 0; i < sizeof(numArr) / sizeof(int); i++
    {
        numArr[i] *= 2;
    }
 
    for (int i = 0; i < sizeof(numArr) / sizeof(int); i++
    {
        printf("%d\n", numArr[i]);
    }
    
    return 0;
}
cs

배열의 요소에 저장된 값을 두 배로 만드려면 배열의 요소에 접근하여 2로 곱한 뒤 다시 요소에 저장하면 된다. *= 연산자를 사용하고, 반복문으로 모든 요소에 접근하여 값을 두배로 변경하고 출력했다.

36.8 배열을 초인터에 넣기

배열은 첫 번째 요소의 주솟값만 담고 있다. 배열은 주솟값이기 때문에 포인터에 넣을 수 있다. 다음과 같이 포인터에 배열을 넣고 포인터에서 인덱스로 요소에 접근할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
int main()
{
    int numArr[10= { 112233445566778899110 };
    int *numPtr = numArr;
 
    printf("%d\n"*numPtr);
    printf("%d\n"*numArr);
    printf("%d\n", numPtr[5]);
    printf("%d\n"sizeof(numArr));
    printf("%d\n"sizeof(numPtr));
    return 0;
}
cs

위 코드처럼 배열을 포인터에 바로 할당할 수 있다. 자료형이 같아야 하며 1차원 배열이면 *이 한개인 단일 포인터여야 한다. 배열을 포인터에 할당한뒤 포인터를 역참조하면 배열의 첫 번째 요소가 나온다. 배열도 주솟값을 가진 포인터이기 때문에 역참조 할 수 있다.

배열의 주소가 들어있는 포인터는 인덱스를 통해 요소에 접근할 수 있다.

sizeof 연산자를 사용하면 배열은 전체 공간의 크기가 출력되고, 포인터는 배열의 주소가 들어있는 포인터의 크기만 나온다. 운영체제가 32비트면 4, 64비트면 8이 나온다.

36.9 배열을 활용하여 10진수를 2진수로 변환하기

10진수를 2진수로 변환하는 방법은 다음과 같이 10진수를 0이 될 때 까지 2로 계속 나눈 뒤 나머지를 역순으로 읽으면 2진수가 된다.

이 식을 코드로 변환하면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
 
int main()
{
    int dec = 13;         
    int bin[20= {0, };
    int pos = 0;
 
    while(1)
    {
        bin[pos] = dec % 2;
        dec = dec / 2;
        pos++;
 
        if(dec == 0)
            break;
    }
 
    for(int i = pos-1; i >= 0; i--)
    {
        printf("%d", bin[i]);    
    }
 
    return 0;
}
cs

변환할 10진수 13을 변수 dec에 저장하고, 2진수를 저장할 배열 bin을 선언한다.

배열에 나머지를 구해서 저장하고 10진수를 2로 나눈 것을 dec가 0이 될 때까지 무한 반복한다.

가장 아래의 나머지부터 읽어야 하므로 배열을 출력할 때는 요소를 역순으로 출력해야 한다.

36.10 퀴즈

정답은 c이다.

정답은 d이다.

정답은 e 이다.

정답은 a, e이다. 배열의 범위는 0~99인데 범위를 벗어난 인덱스를 접근했다.

36.11 연습문제 : 점수 평균 구하기

정답은 다음 코드와 같다.

1. sum += scores[i];

2. average = sum / ( sizeof(scores) / sizeof(float) );

점수 합계를 구할 때는 배열의 모든 요소를 더해주면 되고 평균을 구할 때는 합계에서 요소의 개수로 나누면 된다.

36.12 연습문제 : 2진수를 10진수로 변환하기

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
int pos = 0;
 
for(int i = sizeof(binary) / sizeof(int) - 1; i >= 0; i--)
 
{
 
    if(binary[i] == 1)
 
        decimal += 1 << pos;
 
    pos++;
 
}
cs

2진수를 10진수로 변환하는 방법은 2진수의 각 자리수 1이면 비트 연산자로 해당 자리에 1을 위치시키면 된다.

36.13 심사문제 : 2진수를 10진수로 변환하기

정답은 다음 코드와 같다.

1
2
3
4
5
6
smallestNumber = numArr[0];
for(int i = 0; i <= 4; i++)
{
    if(smallestNumber > numArr[i])
        smallestNumber = numArr[i];
}
cs

미로 크기의 2차원 배열을 만들고, 2중 for 문으로 각 요소의 값들을 입력받는다.

이후 무한 루프를 만들어 조건을 만족시키면 반복문을 탈출하는 구조로 코드를 구성하였다.

현재 좌표의 값이 2(먹이)면 현재 좌표를 9로 만들고 반복문을 종료한다.

이동할 위치가 0(이동가능)이면 9로 만들어 현재 위치를 이동하며, 이동할 위치가 1(벽)이면 오른쪽 또는 아래로 방향을 바꾼다. 방향을 바꿔도 이동할 위치가 1이면 반복문을 종료한다. 

위 작업을 수행하는 반복문에 주석을 달아 더 자세히 설명할 것이다. 

정답은 다음 코드와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include  <stdio.h>
 
int main()
{
    int x = 2, y = 2;   // 초기 좌표값
    int miro[11][11= {};  // 미로 상자
    
    for(int i = 1; i <= 10; i++)    // 2차원 배열의 각 요소에 입력값을 받음
    {
        for(int j = 1; j <= 10; j++)
            scanf("%d"&miro[i][j]);
    }
    
    while(1)    // 무한루프
    {
        if(miro[x][y] == 2// 현재 좌표가 2면 
        {
            miro[x][y] = 9// 현재 좌표를 9로 만들고
            break;          // 반복문 종료
        }
        miro[x][y] = 9;     // 현재 좌표를 9로 만듬
        if(miro[x][y+1== 0)   // 아래쪽으로 이동 가능하면
            y += 1;             // y좌표값을 1 증가시킴
        else if(miro[x][y+1== 1)  // 아래 좌표가 벽이면
        {
            if(miro[x+1][y] == 1)   // 오른쪽도 벽이면
                break;              // 갈 곳이 없으므로 반복 종료
            else if(miro[x+1][y] == 2)  //오른쪽으로 이동한 좌표가 2(먹이)면
            {
                miro[x+1][y] = 9;   // 그 좌표를 9로 만들고
                break;              // 반복 종료
            }
            else    // 벽도 아니고 먹이도 아니면, 1칸 오른쪽으로 이동
                x += 1;
        }
        else if(miro[x][y+1== 2)   // 한 칸 아래 좌표가 2(먹이)면
        {
            miro[x][y+1= 9;       // 그 좌표애 9를 지정하고
            break;                  // 반복문 종료
        }
    }
    
    for(int  i = 1; i <= 10; i++)       // 위 반복문을 마친 후 미로 상자의 상태를 출력   
    {   
        for(int j = 1; j <= 10; j++)
            printf("%d ", miro[i][j]);
        printf("\n");
    }        
    return 0;
}
cs

 

바둑판을 표현하는 2차원 배열을 만들고, 흰 돌의 개수를 입력받는다. 

흰 돌의 개수만큼 반복하면서 흰 돌을 올릴 좌표를 입력 받고, 2차원 배열의 그 좌표를 1로 만든다.

2중 for문을 사용하여 흰 돌이 표현된 바둑판을 출력한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
 
int main()
{
    int n, x, y;    // 입력 받을 변수, x좌표, y좌표
    int pan[20][20]={};    // 바둑판
    scanf("%d"&n);    // 흰돌 개수 입력
    
    for(int i = 1; i <= n; i++)    // 1부터 흰돌 개수 만큼 반복
        {
            scanf("%d %d"&x, &y);    // x좌표, y좌표 입력
            pan[x][y]=1;            // 입력 받은 좌표에 해당하는 요소를 1로 바꿈
        }
        
    for(int i = 1; i <= 19; i++)    // 2중 for문으로 2차원 배열 출력(세로줄 만큼 반복)
        {
            for(int j = 1; j <= 19; j++)    // 가로줄 만큼 반복
            {
                printf("%d ", pan[i][j]);     // 가로줄 출력
            }
            printf("\n");    // 줄바꿈
        }
    
    return 0;
}
cs

 

+ Recent posts