원래 문자열 포인터를 수정하지 않는 strtok_r() 및 strsep()에 대한 C-문자열 대안? (C-string alternatives to strtok_r() and strsep() that don't modify the original string pointer?)


문제 설명

원래 문자열 포인터를 수정하지 않는 strtok_r() 및 strsep()에 대한 C‑문자열 대안? (C‑string alternatives to strtok_r() and strsep() that don't modify the original string pointer?)

2개의 C‑string 함수인 strtok_r() 및 strsep()을 살펴보고 두 함수 모두 전달된 원래 문자열의 위치를 수정하는 것을 발견했습니다.

다른 C 문자열이 있습니까? ‑string 전달된 원본 문자열을 수정하지 않는 함수는?

내 응용 프로그램에서 원본 문자열이 동적으로 할당되므로 구문 분석이 완료된 후 원본 문자열을 해제하고 싶습니다.

strtok_r()을 사용한 예

int main(){
    char * str = strdup("Tutorial and example");
    char* token;
    char* rest = str;

    printf("%s\n", rest);
    while ((token = strtok_r(rest, " ", &rest)))
        printf("%s\n", token);
    printf("\n%s\n",str);
    return(0);
}

Output

Tutorial and example                                                                                                                                                        
Tutorial                                                                                                                                                                    
and                                                                                                                                                                         
example                                                                                                                                                                     



Tutorial                                                                                                                                                                          

마지막 줄에서 str이 수정되지 않은 cstring "Tutorial and example"을 가리키도록 하고 싶습니다.

strsep()에서도 유사한 출력이 발생했을 것입니다.

int main(){
    char * str = strdup("Tutorial and example");
    char* token;
    char* rest = str;

    printf("%s\n", rest); 
    while ((token = strsep(&rest, " ")))
        printf("%s\n", token);
    if (rest != NULL)
        printf("%s\n", rest);

    printf("%s\n", str); 
    return(0);
}

감사합니다.


참조 솔루션

방법 1:

I think you are misunderstanding strtok_r. It does not change the location of the original string, moreover, it can not ‑ the function can not change the value of the pointer passed into it and make this change visible to the calling code.

What it can and will do is modifying the contents of the string itself, by replacing tokens with nul‑terminators. So to answer your original question:

In my application, the original string is dynamically allocated, so I wish to free the original string after the parsing is done.

You do not have to do anything special. You can and should free original string after you are done with it.

You are seeing a single word Tutorial printed simply because the next character was replaced with nul‑terminator and printf stop there. If you are to inspect the string character by character, you will see that it otherwise have remained intact.

방법 2:

Though the mentioned string functions change the original string nevertheless the pointer str points to the dynamically allocated memory and you may use it to free the allocated memory.

if you do not want to change the original string you can use standard C string functions strspn and strcspn.

For example

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

int main(void) 
{
    const char *s = "Tutorial and example";
    const char *separator = " \t";

    puts( s );

    for ( const char *p = s; *p; )
    {
        p += strspn( p, separator );

        const char *prev = p;

        p += strcspn( p, separator );

        int width = p ‑ prev;

        if ( width ) printf( "%.*s\n", width, prev );
    }

    return 0;
}

The program output is

Tutorial and example
Tutorial
and
example

Using this approach you can dynamically allocate memory for each extracted substring.

For example

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

int main(void) 
{
    const char *s = "Tutorial and example";
    const char *separator = " \t";

    puts( s );

    size_t n = 0;
    char **a = NULL;
    int success = 1;

    for ( const char *p = s; success && *p; )
    {
        p += strspn( p, separator );

        const char *prev = p;

        p += strcspn( p, separator );

        if ( p ‑ prev != 0 )
        {
            char *t = malloc( p ‑ prev + 1 );

            if ( ( success = t != NULL ) )
            {
                t[p ‑ prev] = '\0';
                memcpy( t, prev, p ‑ prev );

                char **tmp = realloc( a, ( n + 1 ) * sizeof( char * ) );

                if ( ( success = tmp != NULL ) )
                {
                    a = tmp;
                    a[n++] = t;
                }
                else
                {
                    free( t );
                }
            }
        }
    }

    for ( size_t i = 0; i < n; i++)
    {
        puts( a[i] );
    }

    for ( size_t i = 0; i < n; i++)
    {
        free( a[i] );
    }

    free( a );

    return 0;
}

The program output is the same as shown above.

Tutorial and example
Tutorial
and
example

(by Stephen WongSergeyAVlad from Moscow)

참조 문서

  1. C‑string alternatives to strtok_r() and strsep() that don't modify the original string pointer? (CC BY‑SA 2.5/3.0/4.0)

#split #strsep #c-strings #strtok #C






관련 질문

오류: 이 범위에서 '분할'이 선언되지 않았습니다. (error: ‘split’ was not declared in this scope)

화살표 문자가 포함된 문자열 분할 (Split a string containing arrow characters)

문자 수로 문자열의 특정 부분 가져오기 (Take specific part of a string by character count)

VBScript: 새로운 분할 항목이 있는 리조트 문자열 및 그룹 (VBScript: Resort String and group with new Split Item)

python 태그에서 단어와 숫자 나누기 (Split words and numbers from tags python)

구두점을 문자열 끝에서 시작 부분으로 이동하려면 어떻게 해야 합니까? (How can I move the punctuation from the end of a string to the beginning?)

쉼표로 문자열을 분할하지만 대괄호 또는 따옴표로 묶인 쉼표는 무시하십시오. (Split string by comma but ignore commas in brackets or in quotes)

숫자를 나누고 점 뒤에 하나의 숫자를 유지하십시오. (Split the number and keep one number after the dot)

Oracle에서 쉼표로 구분된 문자열의 최대 개수를 얻는 방법은 무엇입니까? (How to get maximum COUNT of comma separated string in Oracle?)

분할 방법을 사용하여 텍스트 파일에서 범주를 열로 분리 (Using the split method to separate categories into columns from a text file)

Powershell에서 문자열 분할 및 추가 (Splitting and Adding String in Powershell)

원래 문자열 포인터를 수정하지 않는 strtok_r() 및 strsep()에 대한 C-문자열 대안? (C-string alternatives to strtok_r() and strsep() that don't modify the original string pointer?)







코멘트