Programming/빡공(Nefus)

170324(금)

Jubil 2017. 3. 25. 00:17
반응형

C언어



-전위 연산과 후위 연산의 차이점


-이중 for문 


-배열의 선언과 초기화와 사용법


-2차원 배열


-codeup 문제 풀이 1409, 1093, 1503, 1504, 1505


-------------------------------------------------------------------------------------------


1. 전위 연산과 후위 연산의 차이점


++i와 i++


빠른건 ++i가 빠르다.


다음 예제를 통해서 알아보자.



예제는 굉장히 단순하다.

처음 x * y++ 에서는 x * y가 먼저 연산되고 y += 1이 되기 때문에

2 * 2 가 출력되고 y = 3이 된다.


두 번째 x * ++y 에서는 y += 1이 먼저 연산되고 x * y가 되기 때문에

y = 4가 되고 2 * 4 가 출력된다.




2. 이중 for문


for문은 거의 두 가지 이유로 쓴다.

첫 번째, 별 찍기

두 번째, 배열 제어


두 번째를 설명하겠다.


1차원 배열에서 있어서 단일 for문으로 출력이 가능했다.



(간단한 예제)


하지만 2차원, 3차원, ... , n차원을 표현하려면 단일 for문으로는 힘들다.

그래서 다중 for문이 사용되었다.


다음은 이중 for문에 대한 예제이다.



이렇게 이중 for문으로 구구단을 출력 할 수 있다.

(i와 j의 증가와 반복을 이용)




3. 배열의 선언과 초기화와 사용법


배열은 변수 많이 만들기 귀찮아서 쓴다.

배열은 for문에서 사용하기 쉽기 때문에 쓴다.


배열의 선언과 초기화는 변수의 선언과 초기화와 비슷하다.

자료형 배열명[배열의 크기]

이렇게 배열을 선언할 때는 [] 안에 그 개수를 명시하여 선언해야 한다.


1
int a[] = {1,2,3,4,5}
cs


물론 이렇게 하면 알아서 a[5] 가 만들어진다.



배열은 메모리에 연속해서 저장된다.

그리고 byte 만큼 주소값이 차이 난다.


초기화는



이렇게 int a[10]; 했을 때는 모두 쓰레기 값이 들어갔고


int b[10] = {1, 2, 3, 4}; 이렇게 중괄호로 열고 값을 받아줘서

index 0 ~ 3까지는 받은 값을 초기화 하고 4 ~ 9까지는 0으로 초기화 한다.


또, int c[10] = {0}; 했을 경우 모든 배열 값을 0으로 초기화 해준다.




사용법도 변수와 비슷하다.

배열명[index]로 쓰면 된다.

여기서 index는 0부터 배열의 크기 - 1 로 부여된다.


for문을 이용해서 출력하는 예제를 만들어 봤다.



이렇게 증가하는 i 값을 이용해서 배열을 제어 할 수 있다.




4. 2차원 배열


int a[1차 배열의 크기][2차 배열의 크기];


1
int a[3][3= { 1,2,3,4,5,6,7,8,9 };
cs


이렇게 했을 때 어떤 값이 어느 index에 들어가는지 볼 수 있는 예제를 만들었다.



1차부터 순서대로 들어간다.


1
int a[3][3= {{1,2,3}, {4,5,6}, {7,8,9}}
cs


원래는 이렇게 하는거란다.


1
int a[3][3= {{0},{0},{0}}
cs


이건 다 0으로 초기화.


그리고 이중 for문으로 2차원 배열을 출력 할 수 있다.

a[0][0~2]

a[1][0~2]

a[2][0~2]


이 순서대로 출력을 한다.




5. codeup 문제 풀이 1409, 1093, 1503, 1504, 1505


1) 1409


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
int main() {
    int num[10];
    int i, k;
 
    for (i = 0; i < 10++i) { //10개의 숫자 입력
        scanf("%d "&num[i]);
    }
 
    scanf("%d"&k); //k번째 숫자 입력
    printf("%d\n", num[k - 1]); //k번째 숫자 출력
 
    return 0;
}
cs



for문으로 10개의 값을 입력한다.

내가 중요하다고 생각하는 부분은 12번 라인이다.

k - 1을 써주는 이유는 배열의 index값이 0부터 시작되기 때문이다.



2) 1093


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int main() {
    int n[10000], students[23= { 0, }; //23명의 학생들의 값을 0으로 초기화
    int num, i;
 
    scanf("%d"&num); //출석을 부를 횟수를 입력
 
    for (i = 0; i < num; ++i) { //출석 부를 횟수만큼 for문을 돌림
        scanf("%d"&n[i]); //부를 출석 번호를 입력
        ++students[n[i] - 1]; //입력된 출석 번호의 값을 1증가
    }
 
    for (i = 0; i < 23++i) {
        printf("%d ", students[i]); //for문을 이용하여 학생들이 count된 횟수를 출력
    }
    printf("\n");
 
    return 0;
}
cs



23명의 학생들의 값을 23으로 초기화 해 주어야 한다.

그렇지 않으면 쓰레기 값이 들어가 원하는 출력 값이 나오지 않기 때문이다.


첫 for문 10번 라인에서 4가 입력됬다고 가정 해보자

n[0] = 4; 가 되고 ++students[n[0] - 1]이 실행 된다.

++students[4]가 count 된다면 5번 학생이 불린 것이 되고 논리 오류가 발생한다.

그래서 n[i] - 1 을 증가 해 주는 것이고

이게 복잡하다면


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int main() {
    int n[10000], students[24= { 0, }; //23명의 학생들의 값을 0으로 초기화
    int num, i;
 
    scanf("%d"&num); //출석을 부를 횟수를 입력
 
    for (i = 0; i < num; ++i) { //출석 부를 횟수만큼 for문을 돌림
        scanf("%d"&n[i]); //부를 출석 번호를 입력
        ++students[n[i]]; //입력된 출석 번호의 값을 1증가
    }
 
    for (i = 1; i < 24++i) {
        printf("%d ", students[i]); //for문을 이용하여 학생들이 count된 횟수를 출력
    }
    printf("\n");
 
    return 0;
}
cs


이렇게 짜서 students[0]을 입력, 출력 모두 하지 않는 존재로 만들고

students[24]를 만들어서 0의 빈자리를 대신 채워 준다.

(꼭 배열 index와 출석 번호가 같으란 법은 없으니까)


3) 1503


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
#include <stdio.h>
 
int main() {
    int n, i, j, count = 0;
    int num[50][50];
 
    scanf("%d"&n);
 
    for (i = 0; i < n; ++i) {
        if (0 == i % 2) {
            for (j = 0; j < n; ++j) {
                num[i][j] = ++count;
 
            }
        }
        else {
            for (j = n - 1; j >= 0; j--) {
                num[i][j] = ++count;
 
            }
        }
    }
 
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            printf("%d ", num[i][j]);
        }
        printf("\n");
    }
    return 0;
}
cs



이건 말로 설명하기 힘들었습니다.



그림을 그렸죠.


예.


4) 1504


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
#include <stdio.h>
 
int main() {
    int n, i, j, count = 0;
    int num[100][100];
 
    scanf("%d"&n);
 
    for (i = 0; i < n; ++i) {
        if (0 == i % 2) {
            for (j = 0; j < n; ++j) {
                num[j][i] = ++count;
 
            }
        }
        else {
            for (j = n - 1; j >= 0; j--) {
                num[j][i] = ++count;
 
            }
        }
    }
 
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            printf("%d ", num[i][j]);
        }
        printf("\n");
    }
    return 0;
}
cs



아까와는 달리 행에는 계속 순환하는 j를 넣고

j가 다 돌때마다 한 번씩만 도는 i를 열에다가 넣어서

만약 5가 들어왔다고 할 때

1

2

3

4

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
29
30
31
32
33
#include <stdio.h>
 
int main() {
    int n, i, j, count = 0;
    int num[100][100];
 
    scanf("%d"&n);
 
    for (i = 0; i < n; ++i) {
        if (0 == i % 2) {
            for (j = 0; j < n; ++j) {
                num[i][j] = ++count;
 
            }
        }
        else {
            for (j = n - 1; j >= 0; j--) {
                num[i][j] = ++count;
 
            }
        }
    }
 
    for (i = 0; i < n; i++)
    {
        for (j = 0; j < n; j++)
        {
            printf("%d ", num[j][i]);
        }
        printf("\n");
    }
    return 0;
}
cs


저게 어려우면 이렇게 출력 순서만 바꿀수도 있다.



5) 1505


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
#include <stdio.h>
 
int main() {
    int input, n, i, j, k;
    int count = 0, right = 0, down = 1, left, up;
    int condition, helpCondition = 0, num = 0;
    int arr[50][50];
 
    scanf("%d"&input);
    n = input;
    left = n - 2;
    up = n - 2;
 
    for (i = 0; i < input; ++i) {
        if (i % 2 == 0) {
 
            condition = helpCondition++;
            for (j = right++; j < n; ++j)  //오른쪽으로 가면서 숫자 채움
                arr[condition][j] = ++count; 
 
            condition = --n; //index값을 위해서 --n 사용
            for (j = down++; j <= n; ++j) //아래쪽으로 가면서 숫자 채움
                arr[j][condition] = ++count;
 
            
        }
        else {
 
            for (k = left; k >= num; --k)  //왼쪽으로 가면서 숫자 채움
                arr[left + 1][k] = ++count;
 
            for (j = up--; j > num; j--//위쪽으로 가면서 숫자 채움
                arr[j][num] = ++count;
 
            ++num;
            --left;
        }
    }
 
    for (i = 0; i < input; i++)
    {
        for (j = 0; j < input; j++)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}
cs



이거 푸는데 처음으로 디버깅 모드를 썻다.

디버깅 모드로 오류 2개 잡았다.

분석하고 푸는데 3시간 걸렸다. (물론 오류 찾는데 1시간 30분)

어쨋든!


right++, down++, up--, --left

--n, num++

모두 2씩 줄여주는 역할을 한다.

이해가 안된다고?


6을 입력했을 때


6-5-5-4

4-3-3-2

2-1-1-0


2씩 줄어드는걸 볼 수 있다.


그리고 6-5-5-4 에서

5를 x로 두었을 때

x+1 - x - x - x-1

이렇게 나오는 것도 확인 할 수 있는데

그것은 코드보고 머리로 직접 돌려보도록 하자.


물론 나도 그랬다.

(--n하고 위에 조건에 n을 써놓고 i < input 해놓고 밑에 i = left 해놓고 다른거 봄..)


어쨋든 디버깅 모드도 굉장히 유용하다.

버그 찾는데 꿀.



반응형

'Programming > 빡공(Nefus)' 카테고리의 다른 글

2017.07.25(화) - 웹 과제  (0) 2017.07.25
2017.05.21(일) - 게임 프로젝트 보고서  (0) 2017.05.21
170329(수)  (0) 2017.03.29
170322(수)  (0) 2017.03.22
170320(월)  (0) 2017.03.20