C언어에서 2차원 배열인 "포인터의 배열"에 대해서


char *ptr;

⇒ 이렇게 선언되면 임의의 문자열을 저장할수 있는 char형 포인터 변수가 만들어 진 것이다.

임의의 문자열 자체가 가로축으로 가변인 1차원 배열인 것이다.


ex) 

ptr = "aldjsldjflsj asldjf  eof 임의의 길이의 문자열들 어쩌고 저쩌고 owqieul sdlj sdlfj  fowieowei";


ex)

int char_size = 123; //임의로 문자열 길이(가로 축이 가변인)를 지정할 수 있다.

ptr = (char*)malloc(sizeof(char) * char_size);


그런데 char *ptr[7]은 가로 축으로 문자열을 저장하는 1차원 배열(char형 포인터)이 7개 있다는 뜻이므로 가로축이 가변이면서 세로축이 고정(여기서는 7)인 2차원 배열이 되는 것이다.


char *ptr[3]의 형태 자체가 char *ptr이 배열로 3개 존재한다는 뜻이 되므로 char *ptr 자체가 가로 축으로 가변인 1차원 배열인데 1차원 배열 자체가 여러 개(여기서는 3개) 존재하는 형태이므로 char *ptr[] 자체가 곧 2차원 배열이 되는 것이다.


한 마디로 요약하자면 char *ptr[]의 형태는 갯수가 정해져 있고 길이는 서로 다른 여러 개의 문자열을 다룰 때 주로 사용이 되는 형태이다.


아래 코드는 명령행에서 임의의 길이의 문자열 인자를 줄수 있는 코드이다.

여기서 char *argv[]가 "포인터의 배열"이다.


#include <stdio.h>


void main(int argc, char *argv[])

{

int i = 0;

printf("%d개의 매개인자 입력\n", argc);


for (i = 0; i < argc; i++)

{

printf("%d : %s\n", i, argv[i]);

}

}


위 코드의 실행 파일이 test.exe라고 할때 다음과 같이 실행한다면

C:\>test source1.txt dest1.txt


출력 결과는 다음과 같다.


3개의 매개인자 입력

0 : test

1 : source1.txt

2 : dest1.txt





구조체 변수와 구조체 포인터 변수의 멤버변수 접근법

다음과 같은 구조체가 있다고 할때


typedef struct

{

int price;

int count;

} Item;


Item item; //구조체 변수

Item *ptrItem; //구조체 포인터 변수

ptrItem = &item;


일반적인 구조체 변수가 있고, 구조체 포인터 변수가 있다.

일반적인 구조체 변수가 구조체 멤버 변수에 접근코자 할 때는 . 연산자로 접근하고

예) item.price = 100;


반면에 구조체 포인터 변수가 구조체 멤버 변수에 접근코자 할 때는 -> 연산자로 접근한다.

예) ptrItem->price = 100;


아래는 샘플 코드이다.


#include <stdio.h>


typedef struct

{

char name[20];

int price;

int count;

} Item;


void main()

{

Item item = {"수박", 100, 30}; //item은 구조체 변수

Item *ptrItem; //ptrItem은 구조체 포인터 변수


ptrItem = &item;


printf("%s\n", item.name);

printf("%d\n", item.price);

printf("%d\n\n", item.count);


printf("%s\n", ptrItem->name);

printf("%d\n", ptrItem->price);

printf("%d\n", ptrItem->count);

}





C 언어에서 enum을 사용하는 예제이다. 

코드가 복잡하지도 않으니 설명은 굳이...


주목할 부분은 

enum을 선언하는 방식과 

선언 위치,

그리고 enum을 사용할 때 어떤 식으로 사용하는지만 주목하면 될 것이다.

아래는 코드.


#include <stdio.h>


enum Member {JAVA, CPP, ANDROID, PHP, JSP, C, DELPHI, JAVASCRIPT};


void main()

{

enum Member mem = ANDROID; //초기 값 지정

int num;


printf("1: Java, 2:CPP, 3:ANDROID, 4:PHP, 5:JSP, 6:C, 7:DELPHI, 8:JAVASCRIPT");

printf("\n\n사용할 언어를 선택하세요 : ");

scanf("%d", &num);

--num; //enum은 index가 0부터 시작되기 때문에

mem = num;


switch (mem)

{

case JAVA:

printf("Java로 코딩하세요\n");

break;

case CPP:

printf("C++로 코딩하세요\n");

break;

case ANDROID:

printf("Android로 코딩하세요\n");

break;

case PHP:

printf("PHP로 코딩하세요\n");

break;

case JSP:

printf("JSP로 코딩하세요\n");

break;

case C :

printf("C로 코딩하세요\n");

break;

case DELPHI :

printf("Delphi로 코딩하세요\n");

break;

case JAVASCRIPT :

printf("JavaScript로 코딩하세요\n");

break;

}

}



#include <stdio.h>

#include <malloc.h>


struct MySMS

{

//이거 자체가 1차원 배열을 구성

//char형 포인터로 선언한 것은 실행 타임에서 메시지의 길이를

//동적으로 지정하겠다는 뜻임.

char *message;


//여기서 아래와 같이 배열로 입력 받을 문자열 갯수를 지정할수도 있으나

//이렇게 되면 메시지의 길이에 따라 메모리가 낭비되거나

//메시지 내용이 잘릴수 있다.

//char message[50];

};


void main()

{

int row;

int col;


//아래와 같이 선언하는 건 2차원 배열이라는 뜻

//2차원 배열 중에서 행도 가변, 열도 가변의 2차원 포인터가 되시겠다.

//혹은 이런 식도 가능 하겠다.

//struct MySMS arr[10]; //이렇게 하면 열의 갯수는 가변이나

//행의 갯수가 고정이 되는 형태인데 이를 '포인터의 배열'이라고 한다.

//arr[0].message = (char*)malloc(sizeof(char) * 10); //문자열 9개를 받겠다는 뜻

struct MySMS *obj = NULL;


printf("메시지 갯수(행의 갯수) 입력 : ");

scanf("%d", &row);


//2차원 배열 중 행(row)의 갯수

//배열과 달리 실행 타임에 동적으로 크기를 결정 가능.

obj = (struct MySMS *)malloc(sizeof(MySMS) * row);


printf("문자열 갯수(열의 갯수) 입력 : ");

scanf("%d", &col);


//입력한 수치 만큼 실제로 문자열(메시지) 입력 받기 위해

//맨 끝에는 문자열의 끝을 나타내는 널 문자(\0)가 들어가기 때문이다.

col++; 

obj[0].message = (char*)malloc(sizeof(char) * col);


//printf("사이즈 : %d\n", sizeof(char) * 6); //이건 6 byte

//printf("사이즈 : %d\n", sizeof(char*) * 6); //이건 24 byte


scanf("%s", obj[0].message);

printf("%s\n", obj[0].message);


//아래와 같은 순으로 반드시 메모리 해제를 해줘야 된다.

free(obj[0].message);

free(obj);

}


만일 위의 scanf("%d", &col);에서 입력한 col의 수치 보다 더 많은 문자열을 입력하게 하면 다음과 같은 에러 발생






C언어에서 2차원 배열의 형태가 몇 가지 있는데


(1) 행(row)이 고정 갯수, 열(column)이 고정 갯수 일때

  • '2차원 배열'을 이용하면 되고
  • 예) int [3][5]


(2) 행(row)이 고정 갯수, 열(column)이 가변 갯수 일때

  • '포인터의 배열'을 이용하면 되고
  • 예) char *pArr[5]

(3) 행(row)이 가변 갯수, 열(column)이 고정 갯수 일때
  • '배열의 포인터'를 이용하면 되고
  • 예) char (*pArr)[10]


(4) 행(row)이 가변 갯수, 열(column)이 가변 갯수 일때

  • 2차원 포인터를 이용하면 된다
  • 예) char **ptr


아래는 배열의 포인터를 이용해서 2차원 배열에 값을 저장하고 출력하는 간단한 개념을 구현한 것이다.

이때 scanf라는 좀 독특한 성격의 함수에 어떻게 값을 입력해 주어 2차원 배열에 값을 저장하는지를 예제로 보여주는 코드이다.


#include <stdio.h>

#include <malloc.h>

#define LESSONS 3


int main(void)

{

int l, s;

int sum;

int students;


char *lssn[] = {"Korean", "English", "Math"};


//2차원 배열. '배열의 포인터'

//'배열의 포인터'는 2차원 배열 중에서 열(column)은 고정 갯수이고

//행(row)는 가변 갯수일 때 사용할수 있는 2차원 배열의 형태이다.

int(*score)[LESSONS] = NULL;


printf("학생 수를 입력하세요 : ");

scanf("%d", &students);


score = (int(*)[LESSONS])malloc(students * sizeof(int[LESSONS]));

//score = (int(*)[3])malloc(sizeof(int[LESSONS]) * students);


for (s = 0; s < students; s++)

{

printf("%d번째 학생의 점수 : ", s + 1);

for (l = 0; l < LESSONS; l++)

{

//scanf함수는 공백이 있는 곳까지 읽거나 엔터 키까지 읽거나

//혹은 탭문자까지 읽는 성질머리를 가진 함수이다.

scanf("%d", &score[s][l]);

printf("%d, %d ==> %d\n", s, l, score[s][l]);

}

}


printf("%d\t", score[0][0]);

printf("%d\t", score[0][1]);

printf("%d\n", score[0][2]);


free(score);

return 0;

}


위를 실행하면 다음과 같은 결과를 출력한다.

이때 for문 안에서 scanf 값을 11 22 33과 같이 값을 입력한 후 엔터키를 치면 안쪽 for문이 한 바퀴 돌면서 2차원 배열에 값을 저장한다.

만일 다음과 같이 해도 결과는 동일하다.

11

22

33

혹은 11(탭키)22(탭키)33(엔터)






+ Recent posts