개강한지 한달, 전역한지는 약 네달이 지났으니 21개월+4개월 시간이 흘러서인지 포인터를 배웠었는지 조차 기억이 나지 않았다.


후배 학번들이 포인터 배열, 배열 포인터에 대한 개념을 막힘없이 이해하고,


포인터 개념조차 까먹은 본인을 포함한 동기 복학생들이 멘붕에 빠진 상황을 겪게 되며 슬럼프가 찾아오게 되었다.


그래서 불쌍한 복학생들을 구원해주실 바이블인 열혈강의c를 꺼내어 포인터에 대해 정독한 후 복습차원에서 글을 써본다.


포인터를 공부할때 멘탈이 붕괴되는 이유는 '포인터를 왜 써야하는지'와 '포인터가 대체 무엇인가?' 같은


현재 수준에선 절때 답이 나오지 않을 질문들을 스스로에게 던져 자학하게 되어 포기하는 것 같다.


그래서 이번에 포인터를 공부할 때는 그런 질문들은 잊어버리고 한칸씩, 한칸씩 책에서 알려주는 계단을 오르듯이 공부를 했다. 




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



포인터는 메모리의 주소 값을 저장하기 위한 변수이다.



1
2
3
4
5
int main() {
    char c = 'a';
    int n = 7;
    double d = 3.14;
}
cs


책에 나오는 예제를 하나 참조했다. 


위에 코드를 실행하게 되면 메모리 상에는


1바이트를 가진 c, 4바이트를 가진 n, 8바이트를 가진 d 변수가 할당되고 각각의 변수들은 주소를 가지게 된다.


예를들어 c는 1000, n은 1001-4, d는 1005-c 와 같은 주소를 가지게 된다.


포인터는 다른 변수들에 주소 값들을 참조(사용)하기 위한 변수이다.


char c는 a란 값을 int n은 7을, double d는 3.14란 값을 가지듯이 포인터 p 는 1000, 1001, 1005 와 같은 자신이 참조할 변수의 주소값들을 변수로 가진다는 말이다.


예를들어 p라는 포인터가 변수 char c를 가르키게 되면 p 는 1000라는 c의 주소값을 변수로 가지게 될것이다. 


또한 p도 변수이기 때문에 자신의 주소값을 가지게 된다. 




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



포인터 선언 방법


1
2
3
4
int main() {
    int a = 2005;
    int *= &a;
}
cs


포인터를 선언할 때에는 * 연산자를 사용한다.


또 포인터에도 char, int, double 과 같은 타입이 존재한다. 


포인터가 참조할 변수의 자료형에 따라서 적절한 타입의 포인터를 선언해야 한다.




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



포인터 참조 연산자



& 연산자포인터가 가르키는 변수의 주소값을 반환할 때 사용한다.


int *p = &a; 는 포인트p가 a의 주소값을 변수로 가지게 된다.


* 연산자변수를 참조하는 연산자이다.


1
2
3
4
5
6
7
8
9
#include <iostream>
 
int main() {
    int a = 2005;
    int *= &a;
 
    std::cout << p << "\n";
    std::cout << *<< "\n";
}
cs


5번째 줄에서 포인터 p에 &연산자를 붙여 변수 a의 주소값을 초기화 하고 있다.


7번째 줄에서 &a를 변수로 가진 p를 출력하니 a의 주소값이 출력될것이다.


8번째 줄은 변수를 참조하는 연산자인 *가 붙어 있으니 p가 가르키는 주소에 변수를 참조 한다는 말이니 a의 변수인 2005가 출력되는것이다.



다음 예제는 지금까지 배운 선언, 참조와 더불어 포인터를 이용한 연산이 이뤄지는 예제이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
 
using namespace std;
 
int main() {
    int a = 2005;
    int* p = &a;
 
    cout << p << "\n";
    cout << &a << "\n";
 
    (*p)++;
    cout << a << "\n";
    cout << *<< "\n";
}
cs

 

6번째 줄에서 정수형 a를 선언해 2005를 초기화 했고, 포인터 p를 선언해 a의 주소값을 참조하였다.


9번째 줄에서 출력하는 p는 a의 주소값이 출력될것이고 10번째 줄에 주소반환 연산자가 붙은 &a도 a의 주소값을 출력하게 된다. 


이 예제에서 주목해야 할 곳이 12번째 줄이다. 가르키는 주소의 변수를 참조하는 *가 붙은 p의 값을 1 증가 시키고 있다.


p가 가르키는 주소가 a이고 a의 값이 2005이기 때문에 2005의 값이 하나 증가하여 2006이 되는것이다.


그래서 13번째 줄에 출력하는 a의 값은 2006이 될것이고 *p의 값도 2006이 출력된다.




1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
 
int main(){
    int count=0;
    char *a= "text @ ";
    for(int i=0*(a+i) !=NULL; i++) {
        if (*(a+i) != NULL && *(a+i) != ' ') count++;
        if (32 <= *(a+i) => 64) count++;
    }
    std::cout<<count<<"\n";
}
cs


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


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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <time.h>
 
void intro(); // 스플래시 
void com_mkrand(); // 컴퓨터 난수 생성,저장
int human_input(); // 플레이어 숫자 입력, 난수와 비교
int Avoid_duplication(); // 중복 숫자 입력 체크
int Avoid_range(); // 인풋 범위 체크
void count_reset(); // 카운트 리셋
 
int output[4], input[4], strike = 0, ball = 0, out = 0, count = 0// 리턴을 주는것보다 전역함수로 제어하는게 효율적이라고 판단
 
int main() {
    int exit;
    srand((unsigned)time(NULL)); // 매번 다른 난수 발생 위해 시드값 부여
    intro(); // 스플래시
 
    com_mkrand(); // 난수 발생
 
    exit = human_input(); // 플레이어 숫자 입력
    if (exit == 0// -1 입력시 종료
        return 0;
 
    std::cout << "\n                  " << count << "\a회 만에 당신이 이겼습니다! \n" << "                  정답 - ";
 
    for (int i = 0; i < 4; i++)
        std::cout << output[i] << " ";
    std::cout << "\n\n";
}
 
void com_mkrand() {
    output[0= rand() % 10// 첫번째 자리0부터 9까지 난수 생성
    while (1) {
        output[1= rand() % 10// 첫번째 자리와 중복되지 않는 난수 발생할때 까지 반복
        if (output[1!= output[0])
            break;
    }
    while (1) { // 왼쪽에 위치한 숫자들과 중복되지 않는 난수 발생할때 까지 반복
        output[2= rand() % 10;
        if (output[2!= output[0] && output[2!= output[1])
            break;
    }
    while (1) { // 왼쪽에 위치한 숫자들과 중복되지 않는 난수 발생할때 까지 반복
        output[3= rand() % 10;
        if (output[3!= output[0] && output[3!= output[1] && output[3!= output[2])
            break;
    }
    std::cout.width(20);
    for (int i = 0; i < 4; i++)
        std::cout << output[i] << " ";
    std::cout << "\n";
}
 
int human_input() {
    int num; // 중복숫자입력 체크용
    while (strike < 4) {
        count++// 게임 횟수 체크
        count_reset();
        std::cout << count << "회 플레이어 숫자 입력 (스페이스 바로 자릿수 입력 -1 입력시 종료):";
        std::cin >> input[0];
        if (input[0== -1// 종료 플래그
            return 0;
        std::cin >> input[1>> input[2>> input[3];
 
        num = Avoid_duplication(); // 중복, 범위 검사
 
        if (num == 1) {
        case1:
            std::cout << count << "회 플레이어 10보다 작은 중복 되지 않는 숫자 입력 (스페이스 바로 자릿수 입력 -1 입력시 종료):";
            std::cin >> input[0];
            if (input[0== -1// 종료 플래그
                return 0;
            std::cin >> input[1>> input[2>> input[3];
            num = Avoid_duplication(); // 중복, 범위 재검사
            if (num == 1// 검사 통과시 num 0반환, 못할 시 1반환. num 1반환 시 다시 입력
                goto case1;
        }
 
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (input[i] == output[i]) {
                    strike++// 스트라이크 카운트
                    break;
                }
                if (input[i] == output[j]) {
                    ball++// 볼 카운트
                    break;
                }
            }
        }
        out = 4 - strike - ball; // 아웃 카운트
        std::cout << "-----------------------------------------------------------------\n";
        std::cout.width(19);
        std::cout << strike << " 스트라이크! " << ball << " 볼! " << out << " 아웃!\n";
        std::cout << "-----------------------------------------------------------------\n";
    }
}
 
int Avoid_duplication() { // 중복 숫자 검사 함수
    int num;
    count_reset();
    for (int i = 0, j = 1; i < 3; i++) { // 중복 숫자 검사
        j = i + 1;
        for (; j < 4; j++) {
            if (input[i] == input[j]) {
                ball++;
            }
        }
    }
 
    if (ball > 0) { // 중복 시 1 반환
        count_reset();
        return 1;
    }
    else { // 중복이 아닐시
        count_reset();
        ball = Avoid_range(); // 10보다 큰 수가 있는지 확인 후
        if (ball > 0)
            return 1// 있을 시 1 반환
        else
            return 0// 없을 시 0 반환
    }
}
 
void count_reset() {
    strike = 0; ball = 0; out = 0// 카운트 리셋 함수
}
 
int Avoid_range() { // 범위 검사 함수
    count_reset();
    for (int i = 0; i < 4; i++) { // 사용자 input이 10보다 큰 수가 있는지 검사
        if (input[i] >= 10)
            ball++// 있을 시 ball 카운트
    }
    if (ball > 0) { // 10보다 큰 수 있을 시 1 반환
        count_reset();
        return 1;
    }
    else { // 없으면  0반환
        count_reset();
        return 0;
    }
}
 
void intro() { // 스플래시
    std::cout << "┌──────────────────────────────────┐\n";
    std::cout << "│                           숫자야구                                 │\n";
    std::cout << "│        윈도우 프로그래밍           김종완 교수님                   │\n";
    std::cout << "│                                                                    │\n";
    std::cout << "│                             developed by - 고상욱(20130889)        │\n";
    std::cout << "└──────────────────────────────────┘\n";
    std::cout.width(24);
    std::cout << "Wait";
    std::cout << ".";
    std::cout << ".";
    std::cout << ".\n";
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
 
int main() {
    char input[100], temp=0;
    while(1) {
        cout << "입력:";
        cin >> input;
 
        for (int i = 0; input[i] != NULL; i++) {
            temp = (temp < input[i]) ? input[i] : temp;
        }
 
        cout << temp<<"\n";
    }
}
cs


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 <iostream>
using namespace std;
 
int main() {
    int a=0;
    char num[100], temp[4];
 
    cout << "문자열 입력:";
    cin >> num;
 
    for (int i = 0; num[i]!=0; i++) {
        a++;
    }
    a -= 1;
    cout << num[a]<<"\n";
 
    for (int i = 0; a > 0; a--,i++) {
        if (a - i == 1 || a==i)
            break;
        * temp = num[a];
        num[a] = num[i];
        num[i] = * temp;
    }
    cout << num;
}
cs


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 <iostream>
#include <time.h>
#include <Windows.h>
 
void main(){
    int a[50]={0},input,i=0,j=49, count=0;
    srand(time(NULL));
    while(1) {
        input=rand() % 9 + 1;
        if (input%2 == 1) {
            a[i]=input;//홀수
            for(int i=0; i<=49; i++)
                std::cout<<a[i];
            i++;
            std::cout<<"\n";
        }
        else {
            a[j]=input;//짝수
            for(int i=0; i<=49; i++)
                std::cout<<a[i];
            j--;
            std::cout<<"\n";
        }
        count++;
        if (count==49) {
            for(int i=0; i<=49; i++
                a[i]=0;
            i=0,j=49;
            count=0;
        }
        Sleep(50);
    }    
}
cs


윈도우 프로그래밍 실습


난수를 발생시켜 홀수면 왼쪽, 짝수면 오른쪽에 저장한다


난수 50개가 전부 차면 0으로 초기화 한다

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
#include <iostream>
void main(){
    int a[10]={0},input,i=0,j=9, count=1;
 
    while(1) {
        std::cout<<count<<"입력: ";
        std::cin>>input;
        if (input == 0)
            break;
        if (input%2 == 1) {
            a[i]=input;//홀수
            for(int i=0; i<=9; i++)
                std::cout<<a[i];
            i++;
            std::cout<<"\n";
        }
        else {
            a[j]=input;//짝수
            for(int i=0; i<=9; i++)
                std::cout<<a[i];
            j--;
            std::cout<<"\n";
        }
        count++;
        if (a[5!= 0)
            break;
    }
    for(int i=0; i<=9; i++)
        std::cout<<"a["<<i<<"]="<<a[i]<<"\n";
}
cs

윈도우 프로그래밍 실습


사용자에게 입력받아 홀수면 왼쪽, 짝수면 오른쪽에 저장한다


난수 50개가 전부 차면 0으로 초기화 한다


+ Recent posts