簡體   English   中英

不修改原始字符串指針的 strtok_r() 和 strsep() 的 C 字符串替代品?

[英]C-string alternatives to strtok_r() and strsep() that don't modify the original string pointer?

我正在查看 2 個 C 字符串函數 strtok_r() 和 strsep(),並注意到這兩個函數都修改了傳入的原始字符串的位置。

是否還有其他不修改傳入的原始字符串的 C 字符串函數?

在我的應用程序中,原始字符串是動態分配的,所以我希望在解析完成后釋放原始字符串。

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“教程和示例”。

strsep() 也會發生類似的 output 。

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);
}

謝謝你。

我認為您誤解strtok_r 它不會改變原始字符串的位置,而且它不能——function 不能改變傳遞給它的指針的值,並使這個改變對調用代碼可見。

它可以並且將會做的是通過用nul終止符替換標記來修改字符串本身的內容 所以回答你原來的問題:

在我的應用程序中,原始字符串是動態分配的,所以我希望在解析完成后釋放原始字符串。

你不必做任何特別的事情。 完成后,您可以並且應該釋放原始字符串。

您看到一個單詞Tutorial打印只是因為下一個字符被替換為nul -終止符並且printf停在那里。 如果您要逐個字符地檢查字符串,您會發現它在其他方面保持不變。

盡管提到的字符串函數改變了原始字符串,但指針str指向動態分配的 memory,您可以使用它來釋放分配的 memory。

如果您不想更改原始字符串,可以使用標准 C 字符串函數strspnstrcspn

例如

#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;
}

程序 output 是

Tutorial and example
Tutorial
and
example

使用這種方法,您可以為每個提取的 substring 動態分配 memory。

例如

#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;
}

程序 output 與上圖相同。

Tutorial and example
Tutorial
and
example

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM