파스칼에서는 문자열 변수인 경우 무조건 256byte를 잡고 첫 번째 바이트에는 문자열 길이를 넣었습니다. 그래서 255자 까지는 모든 문자, 심지어는 NULL(0x00) 문자까지 입력할 수 있습니다. 32비트 윈도즈가 나온 이후로는 길이가 2G까지 매우 긴 문자열을 담는 변수까지 제공하고 있습니다만, 모두 선두에 문자열의 길이를 담는 것에는 변함이 없습니다.

 

C에서는 파스칼과는 달리 문자열의 길이 정보가 없습니다. 대신에 NULL(0x00)을 만나면 문자열 끝이라고 봅니다. 그래서 NULL String이라고 자주 말하지만, 정확히는 Null Terminated String이 맞습니다. NULL로 종료되는, 즉 끝을 알 수 있는 문자열이라는 얘기가 되겠지요. 그래서 printf( "%s\n", p_str); 이라고 실행했을 때, p_str이 100 byte 짜리여도 NULL 문자가 없으면 100byte를 넘어 NULL을 만날 때까지 주구장창(주야장천(晝夜長川)) 출력하게 됩니다.

 

파스칼의 Legnth String이 좋은지, 아니면 C의 Null Termianted String이 더 좋은지 비교할 수 있겠지만, 우열을 가리기는 힘들지요. 둘다 장단점이 있기 때문입니다. 이번 시간에는 C의 Null Termianted String의 장점을 얘기하려 합니다. 이번에 비슷한 코드를 짜게 되어 예전 기억이 났거든요.

 

후배가 매우 귀찮은 것을 억지로 한다는 듯한 표정으로 꾸역꾸역 타이핑 하는 모습을 보았습니다. 그래서 뭐하나 가만 보니 출력할 내용은 많고, 거기다가 화면에 좌표까지 맞추어서 출력하려고 하니 옆에서 보아도 즐거운 작업은 아니었습니다.

 

날짜 시간 장소 속도 높이 개수 원인 ...
2011-08-03 13:10 서쪽 타워 25.6 34.5 20 Over Flow  
2011-08-03 13:20 동쪽 타워 30.2 25.5 10 No Power  
2011-08-04 12:33 장앙로 30.2 25.5 10 No Power  
2011-08-05 13:34 동쪽 타워 30.2 25.5 10 No Power  
2011-08-05 18:45 동쪽 타워 30.2 25.5 10 No Power  
... ... ... ... ... ... ...  

 

파일 안에 행 단위로 데이터가 주욱 적혀 있습니다. 이것을 화면에 출력하는데 컬럼이 날짜, 시간, 장소, ... 로 해서 30개 가까이 되었습니다. 이것을 각가 컬럼 별로 나누어 화면에 여러 행으로 출력해 주어야 합니다. 짜증이 날만 하네요. 그 후배는 아래와 같이 처리했습니다.

 

char buff[2048];
char date[20];
char time[20];
char location[50];
char vilocity[20];
char height[20];
char count[20];
char reason[50];
        :
        :

while( fgets( buff, 2048, fd)){

    memset( date    , 0, 20);
    memset( time    , 0, 20);
    memset( location, 0, 50);
    memset( vilocity, 0, 20);
    memset( height  , 0, 20);
    memset( count   , 0, 20);
    memset( reason  , 0, 50);
                 :
                 :
                 
    memcpy( date    , buff   , 0, 10);
    memcpy( time    , buff+11, 0, 5 );
    memcpy( location, buff+17, 0, 14);
    memcpy( vilocity, buff+22, 0, 4 );
    memcpy( height  , buff+27, 0, 4 );
                 :
                 :
    
    g_textout( 20 , coor_y, date    );
    g_textout( 80 , coor_y, time    );
    g_textout( 110, coor_y, location);
    g_textout( 200, coor_y, vilocity);
    
    coor_y += 20;

    g_textout( 20 , coor_y, height  );
    g_textout( 80 , coor_y, count   );
    g_textout( 110, coor_y, reson   );
                 :
                 :
}

물론 이렇게 처리하는 것이 틀린 것은 아닙니다. 그러나 파일의 내용을 보니 각 컬럼이 모두 같은 폭을 가지고 있었습니다. 그렇다면 Null Termited String의 특성을 살려서 아래와 같이 코드를 줄일 수 있습니다.

 

char  buff[2048];
char *date;
char *time;
char *location;
char *vilocity;
char *height;
char *count;
char *reason;
        :
        :

while( fgets( buff, 2048, fd)){
    buff[10]    = '\0';             // 각 컬럼별로 NULL을 입력합니다.
    buff[16]    = '\0';
    buff[21]    = '\0';
    buff[26]    = '\0';
    buff[30]    = '\0';
                 :
                 :

    date        = buff   ;          // 각 컬럼별로 선두 주소를 구합니다.
    time        = buff+11;
    location    = buff+17;
    vilocity    = buff+22;
    height      = buff+27;
                 :
                 :
    
    g_textout( 20 , coor_y, date    );
    g_textout( 80 , coor_y, time    );
    g_textout( 110, coor_y, location);
    g_textout( 200, coor_y, vilocity);
    
    coor_y += 20;

    g_textout( 20 , coor_y, height  );
    g_textout( 80 , coor_y, count   );
    g_textout( 110, coor_y, reson   );
                 :
                 :
}

 

파일에서 읽어 들인 buff의 문자열에 NULL 값을 컬럼 별로 삽입하고 거기 까지만 출력하게 하는 것이죠. 새로울 것도 없는 내용이지만, 포인터를 이용하면서 Null Terminated String의 특성을 이용하면 조금 더 편하게 처리할 수 있다는 얘기를 드리고 싶었습니다. 그리고 조금 더 편하게 코딩한다면 이렇게 변경하면 조금 더 낳겠지요.

 

char *buff;
char *date;
char *time;
char *location;
char *vilocity;
char *height;
char *count;
char *reason;
        :
        :

while( fgets( buff, 2048, fd)){

    date        = buff   ;
    time        = buff+11;  *( time     -1) = '\0';
    location    = buff+17;  *( location -1) = '\0';
    vilocity    = buff+22;  *( vilocity -1) = '\0';   
    height      = buff+27;  *( height   -1) = '\0';
                 :
                 :
    
    g_textout( 20 , coor_y, date    );
    g_textout( 80 , coor_y, time    );
    g_textout( 110, coor_y, location);
    g_textout( 200, coor_y, vilocity);
    
    coor_y += 20;

    g_textout( 20 , coor_y, height  );
    g_textout( 80 , coor_y, count   );
    g_textout( 110, coor_y, reson   );
                 :
                 :
}

 

내일은 즐거운 토요일. 즐거운 주말을 보내세요. ^^