2011. 9. 2. 19:02

▣ 설명 : 하나의 커맨드라인 인자를 가지고 makeargv() 호출하여 인자 배열을 만든다.

원형

int makeargv(const char *s, const char *delimiters, char ***argvp);

인수

const char *s : 문자열

const char *delimiters : 구분자

char ***argvp : 인자 배열을 가리키는 포인터.

반환

성공 : 토큰 수

실패 : -1리턴, errno 설정.

makeargv 함수는 delimiter를 구분자로 가지고, 문자열 s로부터 argvp가 가리키는 곳에 인자 배열을 만든다.

 

[ 예제코드 : argtest.c ]

#include <stdio.h>
#include <stdlib.h>

extern int makeargv(const char *s, const char *delimiters, char ***argvp);
extern void freemakeargv(char **argv);

int main(int argc, char *argv[]) {
    char delim[] = " \t";
    int i;
    char **myargv;
    int numtokens;

    if (argc != 2) {
	fprintf(stderr, "Usage: %s string\n", argv[0]);
	return 1;
    }

    if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) {
	fprintf(stderr, "Failed to construct an argument array for %s\n",
	    argv[1]);
	return 1;
    }
    fputs("The argument array contains:\n", stdout);
    for (i=0; i<numtokens; i++)
	printf("%d: %s\n", i, myargv[i]);

    freemakeargv(myargv);
    return 0;
}

 

[ 예제코드 : makeargv.c ]

#include <errno.h>
#include <stdlib.h>
#include <string.h>

int makeargv(const char *s, const char *delimiters, char ***argvp) {
    int error;
    int i;
    int numtokens;
    const char *snew;
    char *t;

    if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
	errno = EINVAL;
	return -1;
    }
    *argvp = NULL;

    /* snew is real start of string */
    snew = s + strspn(s, delimiters);	
    if ((t = malloc(strlen(snew) + 1)) == NULL)
	return -1;
    strcpy(t, snew);

    numtokens=0;
    /* count the number of tokens in s */
    if (strtok(t, delimiters) != NULL)
	for (numtokens=1; strtok(NULL, delimiters) != NULL; numtokens++) ;

    /* create argument array for ptrs to the tokens */
    if ((*argvp = malloc((numtokens + 1) * sizeof(char *))) == NULL) {
	error = errno;
	free(t);
	errno = error;
	return -1;
    }

    /* insert pointers to tokens into the argument array */
    if (numtokens == 0) {
	free(t);
    } else {
	strcpy(t, snew);
	**argvp = strtok(t, delimiters);
	for(i=1; i<numtokens; i++)
	    *((*argvp)+i) = strtok(NULL, delimiters);
    }
    /* put in final NULL pointer */
    *((*argvp)+numtokens) = NULL;    
    return numtokens;
}

void freemakeargv(char **argv) {
    if (argv == NULL)
	return;
    if (*argv != NULL)
	free(*argv);
    free(argv);
    argv=NULL;
}

 

▣ 사용 예: 하나의 커맨드라인 인자("큰따옴표"로 묶는다)를 받아 인자 배열로 만듬.

$ ./argtest

Usage: ./argtest string

 

$ ./argtest "mine -c 10 2.0"

The argument array contains:

0: mine

1: -c

2: 10

3: 2.0

 

전반적인 구현 순서 :

1. 문자열 분석을 위한 버퍼 tmalloc로 할당한다.

버퍼 t는 문자열 s와 종료문자 '\0'을 담을 수 있을 만큼 충분한 크기를 가져야 한다.

2. st에 복사 (문자열 : "mine -c 10 2.0")

3. 문자열 t를 매개변수로 strtok 함수를 호출하여 토큰의 수를 계산.

4. 토큰의 수(numtokens)를 이용하여 argv 배열의 크기를 할당.

5. st에 다시 복사.

6. strtok를 사용하여 각각의 토큰에 대한 포인터를 만들고, t를 분석하기 좋은 형태로 수정.

 

Posted by devanix