source

C에서 strtok과 strsep의 차이점은 무엇입니까?

nicesource 2023. 9. 11. 21:52
반응형

C에서 strtok과 strsep의 차이점은 무엇입니까?

이 에 가 해 요 요 해 이 가 에 strtok()그리고.strsep()장점과 입니까? 그들의 장점과 단점은 무엇입니까?그리고 내가 왜 다른 것보다 하나를 고르겠어요.

와 와 의 한가지 주요한 차이점은strtok()는 C 표준으로 표준화되어 있지만(따라서 POSIX로도 표준화되어 있음), 표준화되어 있지는 않습니다(C 또는 POSIX에 의해; GNU C 라이브러리에서 이용할 수 있으며 BSD에서 기원함).따라서, 휴대용 코드는 사용할 가능성이 더 높습니다.strtok()strsep().

또 다른 차이점은 전화가strsep()수 ,른는수만될할을수은다의할수다otht은n른nesu의ste는,,strtok()이 할 수 ) 이수할만)만수(록할u이( )strtok_r())를 사용합니다.strsep()도서관에서는 다른 코드를 실수로 끊지 않습니다. 반면에strtok(). 다른 을리다야기다야r는nget른e는any을리dt .strtok()동시에 라이브러리 함수를 호출할 수 없습니다.

의 매뉴얼 strsep()kernel.org 에서 다음과 같이 말합니다.

strsep() 함수는 strtok(3)의 대체 함수로 도입되었는데, strtok(3)은 빈 필드를 처리할 수 없기 때문입니다.

따라서 다른 중요한 차이점은 조지 갈이 그의 답변에서 강조한 것입니다.strtok()토큰 에 여러 를 허용하는 ,는일에러를는면큰면는를strsep()은 토큰 간의 단일 구분 기호를 예상하고 인접 구분 기호를 빈 토큰으로 해석합니다.

둘다요.strsep()그리고.strtok()할 수 둘 다 력한분다수둘할를기에다을을을의고둘기에(lny다eahds다을uhdrts력mefrerydr( ).'\0'토큰 종료 후 분리막 위로 이동합니다).

언제 사용합니까?

  • 당신은 사용할 것입니다.strsep()토큰 간에 여러 구분자를 허용하는 대신 빈 토큰을 원할 때, 휴대성에 신경 쓰지 않을 때.
  • 당신은 사용할 것입니다.strtok_r()토큰 간에 여러 구분자를 허용하고 빈 토큰을 원하지 않을 때(그리고 POSIX는 사용자에게 충분히 휴대할 수 있습니다).
  • 만은 합니다만 합니다.strtok() 수 있을 한번생명을 위협하는 상황에서 벗어날 수 있을 정도로 오랫동안 사용해야 합니다. 그러면 다시 한번 사용을 포기하게 됩니다.그것은 독이 있습니다. 사용하지 마십시오.자신의 것을 쓰는 것이 더 나을 것입니다.strtok_r()아니면strsep()다를 사용하는 strtok().

.strtok()독이 있다고요?

strtok()함수는 라이브러리 함수에 사용되면 독이 됩니다.라이브러리 함수에서 다음을 사용하는 경우strtok() , 하게 되어야 되어야 하게 .

그 이유는:

  1. 이 이 인 인 를 사용하는 경우strtok()를는의를s도 사용하는 합니다.strtok()기능을 합니다. , 합니다 을 합니다 을 .
  2. 가 를strtok()은 당신 의 , 은 의 을 할 입니다 의 입니다 할 을 의 의 strtok().
  3. 스레드라면 에서 이 의 에서 할 인 할 에서 이 을 사용할 수 있습니다.strtok()-정에에의에faet에정–의nye의 순서에 걸쳐strtok() 호출

이 문제의 근본은 다음을 허용하는 호출 사이의 저장 상태입니다.strtok()중단된 곳에서 계속할 겁니다문제를 해결할 합리적인 방법은 "사용하지 않음" 이외에는 없습니다.strtok()".

  • 을 사용할 수 .strsep()가능한 경우에는
  • 가능하다면 POSIX를 사용할 수 있습니다.
  • 사용 가능하다면 마이크로소프트의 것을 사용할 수 있습니다.
  • Annex1 기능 ISO/IEC 9899:2011 Annex K.3.7.3.1 을 할 을 할 strtok_s()는 둘 다 , 는 의 는 의 .strtok_r()마이크로소프트 사의strtok_s().

BSDstrsep():

char *strsep(char **stringp, const char *delim);

포식스strtok_r():

char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state);

마이크로소프트strtok_s():

char *strtok_s(char *strToken, const char *strDelimit, char **context);

K strtok_s():

char *strtok_s(char * restrict s1, rsize_t * restrict s1max,
               const char * restrict s2, char ** restrict ptr);

에는 에서와 가 의 가 의 가 에는 strtok().

GNU C 라이브러리 매뉴얼 - 문자열에서 토큰 찾기:

의 의 한가지strsep그리고.strtok_r에 구분 에 둘 력에의가에둘상어는우분우는어s력상tfstrsep구분 기호의 각 문자 쌍에 대해 빈 문자열을 반환합니다.이는 프로그램이 일반적으로 다음에 대해 테스트해야 함을 의미합니다.strsep처리하기 전에 빈 문자열을 반환합니다.

1 의 첫 번째 strtok()그리고.strsep()는 입력 문자열의 연속 구분 문자를 처리하는 방식입니다.

가 을 합니다 합니다 을 가 strtok():

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

int main(void) {
    const char* teststr = "aaa-bbb --ccc-ddd"; //Contiguous delimiters between bbb and ccc sub-string
    const char* delims = " -";  // delimiters - space and hyphen character
    char* token;
    char* ptr = strdup(teststr);

    if (ptr == NULL) {
        fprintf(stderr, "strdup failed");
        exit(EXIT_FAILURE);
    }

    printf ("Original String: %s\n", ptr);

    token = strtok (ptr, delims);
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok (NULL, delims);
    }

    printf ("Original String: %s\n", ptr);
    free (ptr);
    return 0;
}

출력:

# ./example1_strtok
Original String: aaa-bbb --ccc-ddd
aaa
bbb
ccc
ddd
Original String: aaa

에서 을 에서 을 을 볼 수 있습니다."bbb"그리고."ccc"strtok() 는 연속된 구분 기호 문자의 발생을 나타냅니다.그리고 또.strtok() 입력 문자열을 수정합니다.

가 을 합니다 합니다 을 가 strsep():

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

int main(void) {
    const char* teststr = "aaa-bbb --ccc-ddd"; //Contiguous delimiters between bbb and ccc sub-string
    const char* delims = " -";  // delimiters - space and hyphen character
    char* token;
    char* ptr1;
    char* ptr = strdup(teststr);

    if (ptr == NULL) {
        fprintf(stderr, "strdup failed");
        exit(EXIT_FAILURE);
    }

    ptr1 = ptr;

    printf ("Original String: %s\n", ptr);
    while ((token = strsep(&ptr1, delims)) != NULL) {
        if (*token == '\0') {
            token = "<empty>";
        }
        printf("%s\n", token);
    }

    if (ptr1 == NULL) // This is just to show that the strsep() modifies the pointer passed to it
        printf ("ptr1 is NULL\n");
    printf ("Original String: %s\n", ptr);
    free (ptr);
    return 0;
}

출력:

# ./example1_strsep
Original String: aaa-bbb --ccc-ddd
aaa
bbb
<empty>             <==============
<empty>             <==============
ccc
ddd
ptr1 is NULL
Original String: aaa

두 의 빈 에서두 의 을 할 를 됨 를 됨 에서 )을 볼 수 .<empty>) bbb그리고.ccc 두 빈은 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ."--"에 사이에"bbb"그리고."ccc".strsep()를다a를m호dr분ra다 .' '"bbb"은 구분 를 , 은 를 했습니다 했습니다 로 했습니다.'\0'"bbb"이에. . 에.strsep()른분호를다를 찾았습니다.'-'를 . 를 과 과 를 '\0'문자를 입력하고 빈 문자열을 반환합니다.다음 구분 기호 문자도 마찬가지입니다.

연속된 구분 기호 문자는 Null 문자(즉, 값이 있는 문자)로 포인터를 반환할 때 표시됩니다.'\0').

strsep() 입력 문자열과 주소가 첫 번째 인수로 전달된 포인터를 수정합니다.strsep().

은,strtok()문자열 내의 현재 구문 분석 위치를 추적하기 위해 정적 변수에 의존합니다.이 구현에서는 두 번째 문자열을 시작하기 전에 하나의 문자열을 완전히 구문 분석해야 합니다.하지만 이것은 사실이 아닙니다.strsep().

호출 strtok()nstrtok()완료되지 않았습니다.

#include <stdio.h>
#include <string.h>

void another_function_callng_strtok(void)
{
    char str[] ="ttt -vvvv";
    char* delims = " -";
    char* token;

    printf ("Original String: %s\n", str);
    token = strtok (str, delims);
    while (token != NULL) {
        printf ("%s\n", token);
        token = strtok (NULL, delims);
    }
    printf ("another_function_callng_strtok: I am done.\n");
}

void function_callng_strtok ()
{
    char str[] ="aaa --bbb-ccc";
    char* delims = " -";
    char* token;

    printf ("Original String: %s\n", str);
    token = strtok (str, delims);
    while (token != NULL)
    {
        printf ("%s\n",token);
        another_function_callng_strtok();
        token = strtok (NULL, delims);
    }
}

int main(void) {
    function_callng_strtok();
    return 0;
}

출력:

# ./example2_strtok
Original String: aaa --bbb-ccc
aaa
Original String: ttt -vvvv
ttt
vvvv
another_function_callng_strtok: I am done.

function_callng_strtok()만 토큰쇄만"aaa"그리고 입력 문자열의 나머지 토큰을 인쇄하지 않습니다. 왜냐하면 그것이 호출하기 때문입니다.another_function_callng_strtok()h를strtok()그리고 그것은 정적 포인터를 설정했습니다.strtok()NULL모든 토큰을 추출하는 것이 끝나면.통제권은 다시 다음으로 넘어갑니다.function_callng_strtok() while리,strtok()NULL를 가리키는 정적 포인터 때문에NULL 조건을을는것프것e는d을고eh프로 만듭니다.false루프 출구도 있고요.

호출 strsep()nstrsep()완료되지 않았습니다.

#include <stdio.h>
#include <string.h>

void another_function_callng_strsep(void)
{
    char str[] ="ttt -vvvv";
    const char* delims = " -";
    char* token;
    char* ptr = str;

    printf ("Original String: %s\n", str);
    while ((token = strsep(&ptr, delims)) != NULL) {
        if (*token == '\0') {
            token = "<empty>";
        }
        printf("%s\n", token);
    }
    printf ("another_function_callng_strsep: I am done.\n");
}

void function_callng_strsep ()
{
    char str[] ="aaa --bbb-ccc";
    const char* delims = " -";
    char* token;
    char* ptr = str;

    printf ("Original String: %s\n", str);
    while ((token = strsep(&ptr, delims)) != NULL) {
        if (*token == '\0') {
            token = "<empty>";
        }
        printf("%s\n", token);
        another_function_callng_strsep();
    }
}

int main(void) {
    function_callng_strsep();
    return 0;
}

출력:

# ./example2_strsep
Original String: aaa --bbb-ccc
aaa
Original String: ttt -vvvv
ttt
<empty>
vvvv
another_function_callng_strsep: I am done.
<empty>
Original String: ttt -vvvv
ttt
<empty>
vvvv
another_function_callng_strsep: I am done.
<empty>
Original String: ttt -vvvv
ttt
<empty>
vvvv
another_function_callng_strsep: I am done.
bbb
Original String: ttt -vvvv
ttt
<empty>
vvvv
another_function_callng_strsep: I am done.
ccc
Original String: ttt -vvvv
ttt
<empty>
vvvv
another_function_callng_strsep: I am done.

여기 보시는 것처럼, 전화를 합니다.strsep()하나의 문자열을 완전히 파싱하기 전에는 아무런 차이가 없습니다.

의 .strtok()그리고.strsep()다둘력을는다다다는ths을 .strsep()는 Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ strtok()위에 예시한 바와 같이

스트렙에서:

strsep() 함수는 strtok() 함수를 대체하기 위한 것입니다.strtok() 함수는 휴대성의 이유로 선호되어야 하지만(ISO/IEC 9899:1990('ISO C90'') 빈 필드, 즉 두 개의 인접한 구분 문자로 구분되는 필드를 탐지하거나 한 번에 하나 이상의 문자열에 사용할 수 없습니다.strsep() 함수는 4.4에서 처음 나타났습니다.BSD.


참고용:

언급URL : https://stackoverflow.com/questions/7218625/what-are-the-differences-between-strtok-and-strsep-in-c

반응형