2011년6월24일_2차원 동적배열을 달팽이 배열에 적용하여 사용자가 입력한 크기의 배열출력

 

 

 

예전에 한 과제 중 달팽이배열처럼 순차적인 배열에 비순차적으로 값을 대입하는 과제가 있었다.
URL : http://sumanaki.tistory.com/78

이 과제에 사용된 배열을 2차원 메모리 동적할당 하여 어떤 크기의 배열이라도 실행시 생성하여,
정적배열 사용시 보다 메모리를 효율적으로 사용하자.

정적배열의 경우 그 크기가 고정적일 수 밖에 없는게 배치되는 영역이 Stack영역이라,
ebp에서 상대적인 주소(위치)로 엑세스해 프로그램이 돌아가는 동안 배열의 크기가 변하게 되면 다른 변수의 영역을 침범한다.
그러나 동적배열은 배치 되는 영역이 heap영역이고 ebp와 esp의 지배를 받지 않는다(?).
엑세스법은 포인터를 사용하여 그 포인터가 기억하고 있는 시작주소로 부터 (+)방향(stack이 있는 쪽)으로 상대적인 주소를 참조한다.

이번에 동적할당할 배열은 2차원 배열이므로 1차원과는 많이 다르다는 것을 웹서핑을 통해 알게 되었고,
간단한 테스트를 통한 후 달팽이 배열에 적용하였다.
기본 코드는 다음과 같이,

   1:  int **p;
   2:  int i, iSize;
   3:   
   4:  //scanf()로 iSize의 값을 받아옴.
   5:   
   6:  //동적배열의 시작주소 할당받음. 이중포인터의 시작점이라 보면 된다.
   7:  p = (int **)malloc(sizeof(int *) * iSize);
   8:  //각 행의 원소들을 할당받음. 2차원배열은 1차원배열 * 열의 개수
   9:  for(i = 0 ; i < iSize ; i++)
  10:  {
  11:      p[i] = (int *)malloc(sizeof(int) * iSize);    //각 행의 시작을 가리키는 포인터변수
  12:  }
  13:   
  14:  //동적배열의 각각의 행이 순서대로 소멸.
  15:  for(i = 0 ; i < iSize ; i++)
  16:  {
  17:       free(p[i]);
  18:  }
  19:  //동적배열의 각 행을 가리키는 포인터를 가리키는 포인터변수 소멸.
  20:  free(p);    

이중포인터에 대한 이해가 잘 가지 않지만 내 나름대로 분석을 해서 주석에 적어 놓았으나 잘 읽어 볼 것.
혹, 틀린 점이 있다면 알려주세요.

 

 

 

 

2차원 동적배열을 적용한 달팽이 배열 소스코드



<실행결과>


<소스코드>

   1:  /********************************************************************
   2:  
   3:      사용자로 부터 달팽이 배열의 크기를 입력받아 출력하는 프로그램
   4:      가변적인 배열크기로 인해 동적배열을 사용함.
   5:      
   6:      작성자: 김수만
   7:      작성일자: 2011년 6월 24일
   8:      
   9:  ********************************************************************/
  10:  #include <stdio.h>
  11:  #include <stdlib.h>
  12:   
  13:  void Set_Snail_Array(int **, int);
  14:  void View_2Div_Array(int **, int);
  15:   
  16:   
  17:  int main()
  18:  {
  19:      int **pMatrix;
  20:      int iSize;
  21:      int iLoop;
  22:      int iStatus;
  23:      
  24:      while(1)
  25:      {
  26:          printf("달팽이 배열의 크기를 입력하세요. (0이하는 종료됨.) : ");
  27:          iStatus = scanf(" %d", &iSize);
  28:          
  29:          if(1 != iStatus)
  30:          {
  31:              printf("숫자만 입력하셔야 합니다.\n\n");
  32:              fflush(stdin);
  33:              continue;
  34:          }
  35:          
  36:          if(0 >= iSize)
  37:          {
  38:              printf("프로그램 종료!!\n");        
  39:              break;
  40:          }
  41:          
  42:          //동적배열 시작 부분 생성.
  43:          pMatrix = (int **)malloc(sizeof(int *) * iSize);
  44:          
  45:          if(NULL == pMatrix)
  46:          {
  47:              printf("메모리 동적할당에 실패하였습니다.\n");
  48:              return -10;
  49:          }        
  50:          //동적배열 행 부분 생성 * 행 횟수만큼. 
  51:          for(iLoop = 0 ; iSize > iLoop ; ++iLoop)
  52:          {
  53:              pMatrix[iLoop] = (int *)malloc(sizeof(int) * iSize);
  54:              
  55:              if(NULL == pMatrix)
  56:              {
  57:                  printf("메모리 동적할당에 실패하였습니다.\n");
  58:                  return -10;
  59:              }
  60:          }
  61:          
  62:          //본문
  63:          Set_Snail_Array(pMatrix, iSize);            //달팽이 배열 생성.
  64:          View_2Div_Array(pMatrix, iSize);            //2차원 배열에 들은 값을 보기 좋게 출력
  65:   
  66:          //동적배열 소멸.
  67:          for(iLoop = 0 ; iSize > iLoop ; ++iLoop)
  68:          {
  69:              free(pMatrix[iLoop]);
  70:          }
  71:          
  72:          free(pMatrix);
  73:      }
  74:      
  75:      return 0;
  76:  }
  77:      
  78:  //2차원 배열에 달팽이 배열 모양으로 값을 입력
  79:  void Set_Snail_Array(int **pMatrix, int iSize)
  80:  {
  81:      int iRow = 0;                //제어변수
  82:      int iCol = 0;                //제어변수
  83:      int iSeq = 1;                //행과 열 증감제어
  84:      int iRow_Max = iSize + 1;    //행의 최대값
  85:      int iCol_Max = iSize;        //열의 최대값
  86:      int iRow_Min = 0;            //행의 최소값
  87:      int iCol_Min = -1;            //열의 최소값
  88:      int iNum = 1;                //배열에 대입할 초기값
  89:   
  90:      //달팽이~
  91:      while((iSize * iSize) >= iNum)        //배열의 크기만큼 반복
  92:      {
  93:          if(0 != iSeq)                //평상시
  94:          {
  95:              pMatrix[iRow][iCol] = iNum;
  96:              ++iNum;
  97:          }
  98:          else                        //방향을 3번 바꾼 뒤
  99:          {
 100:              ++iSeq;                    //iSeq = 0에서 1이 된다.
 101:          }
 102:   
 103:          //디버그용 코드
 104:          //printf("(%d,%d) = %3d,\t%d", iRow, iCol, *(*(pArr + iRow) + iCol), iSeq);
 105:          //getchar();
 106:   
 107:          
 108:          //방향제어
 109:          if(1 == iSeq)                //열++ 시퀀스
 110:          {
 111:              ++iCol;
 112:              
 113:              if(iCol_Max <= iCol)    //열의 상한
 114:              {
 115:                  ++iSeq;
 116:                  --iCol;
 117:                  --iRow_Max;            //행의 최대값을 줄임 (배열 안으로 향함)
 118:              }
 119:          }
 120:   
 121:          if(2 == iSeq)                //행++ 시퀀스
 122:          {
 123:              ++iRow;
 124:              
 125:              if(iRow_Max <= iRow)    //행의 상한
 126:              {
 127:                  ++iSeq;
 128:                  --iRow;
 129:                  ++iCol_Min;            //열의 최소값을 늘림 (배열 안으로 향함)
 130:              }
 131:          }
 132:   
 133:          if(3 == iSeq)                //열-- 시퀀스
 134:          {
 135:              --iCol;
 136:              
 137:              if(iCol_Min > iCol)        //열의 하한
 138:              {
 139:                  ++iSeq;
 140:                  ++iCol;
 141:                  ++iRow_Min;            //행의 최소값을 늘림 (배열 안으로 향함)
 142:              }
 143:          }
 144:          
 145:          if(4 == iSeq)                //행-- 시퀀스
 146:          {
 147:              --iRow;
 148:              
 149:              if(iRow_Min > iRow)        //행의 하한
 150:              {
 151:                  ++iSeq;
 152:                  ++iRow;
 153:                  --iCol_Max;            //열의 최대값을 줄임 (배열 안으로 향함)
 154:              }
 155:          }
 156:          
 157:          if(4 < iSeq)                //4번째 시퀀스가 끝이니 0으로 초기화해
 158:          {                            //다시 0부터 돌게 함.
 159:              iSeq = 0;
 160:          }
 161:          
 162:      }
 163:      
 164:      return ;
 165:  }
 166:   
 167:  //2차원 배열의 값을 출력.
 168:  void View_2Div_Array(int **pMatrix, int iSize)
 169:  {
 170:      int iRow;
 171:      int iCol;
 172:      
 173:      //배열에 있는 값을 순차적으로 출력
 174:      for(iRow = 0 ; iSize > iRow ; ++iRow)
 175:      {
 176:          for(iCol = 0 ; iSize > iCol ; ++iCol)
 177:          {
 178:              printf("%3d", pMatrix[iRow][iCol]);
 179:          }
 180:          
 181:          putchar('\n');
 182:      }
 183:   
 184:      return ;
 185:  }