본문

[C] strtok을 대체할 문자열 분리함수 getSplit()을 구현

Java, C#등에 있는 split() 하다못해 비슷한 언어형태를 가진 php또한 split()[explode()]을 가진다. 이런 언어들에 익숙한 나머지 c의 strtok()의 사용이 매우 불편하다 느껴졌고, 지난 게시물("[C] 함수에서 2차원 배열 반환받기, 구분자로 문자열 나누기")에 이어 결국 getSplit()이라는 함수를 만들기에 이른다. 이번 버전은 메모리 해제도 고려하여 freeSplit()이라는 함수도 같이 제공한다. malloc된 항목에 대한 항목의 개수를 분리된 영역에서 동적으로 알아올 수는 없으므로 이를 위하여 getSplit()에서는 결과 배열의 갯수를 리턴한다. 아래 freeSplit()은 getSplit()에서 나온 result의 메모리를 해제해 주는 함수이며, 안에있는 주석을 제거하면 메모리의 이용현황, 그리고 진행과정을 쉽게 볼 수 있다.

아래 main()에서는 /etc/passwd파일의 일부를 :으로 나누고 이를 순서대로 보여주는 역할을 한다. 원한다면 passwd파일을 통으로 읽어와 (물론 gets()를 사용하면 라인단위로 쉽게 불러오지만) 이를 분석하고자 한다면 loop를 중첩해서 만들고 바깥쪽엔 "\n"으로 라인단위로 나누고, 나눈것은 내부loop에서는 이를 ";"단위로 나누는 상황도 생각할 수 있다. 자세한 주석도 달까 했는데 너무 길어질까봐 우선은 이대로 놓아둔다. 처음에 영어로 주석을 달아놓은 흔적이 있다.

main(){
    char **split;
    char msg[]="jsmith:x:1001:1000:Joe Smith,Room 1007,(234)555-8910,(234)555-0044,email:/home/jsmith:/bin/sh";
    int count=getSplit(msg, ":", &split);
    int i=0;

    for(;i<count;++i){
        printf("%d. %s\n", i, split[i]);
    }
    freeSplit(split, count);
}

/*
    설명 :  msg에서 split을 찾아 이를 기준으로 문자열을 분리한다. (frontjang.info:80 -> {"frontjang", "80"}
    인자 :  char* msg 분리할 문자열을 담은 원본(대상) 문자열
              char* split 분리할 기준  문자열.
              char*** result 문자열 배열이 저장될 포인터.
    반환 :  분리된 배열 수.
*/

int getSplit(char* msg, char* split, char*** result){
    int i=0;
    int charCount=0;
    int totalCount=0;
    char *prevPoint=msg;
    char *currPoint=NULL;
    char **array2d=NULL;
    do{
        currPoint=strstr(prevPoint, split);
        if(currPoint!=NULL){
            totalCount=currPoint-msg;/*total length of msg so far.*/
            if(prevPoint==msg) charCount=totalCount;/*total length of msg so far(1st)*/
            else charCount=currPoint-prevPoint;/*difference between currPoint - prevPoint*/
           
            array2d=(char**)realloc( array2d, sizeof(char*)*(i+1));
            array2d[i]=(char*)malloc(charCount);
            strncpy(array2d[i], prevPoint, charCount);
            array2d[i][charCount]='\0';
            prevPoint=currPoint+strlen(split);
        }
    } while(currPoint!=NULL && ++i);
    if(i>0) {
        array2d=(char**)realloc( array2d, sizeof(char*)*(i+1));
        charCount=strlen(msg)-totalCount;
        array2d[i]=(char*)malloc(charCount);
        strncpy(array2d[i], prevPoint, charCount);
        array2d[i][charCount]='\0';
        ++i;
        *result=array2d;
    }
    return i;
}

/*
    free the memory allocated from getSplit
*/

void freeSplit(char** result, int count){
    //printf("size:%d\n", count);
    while(--count>-1){
        /*printf("%d. %s[%x]\n", count, result[count], result[count]);*/
        free(result[count]);
    }
    /*printf("%x\n", result);*/
    free(result);
}

댓글

Holic Spirit :: Tistory Edition

design by tokiidesu. powerd by kakao.