不修改原始字符串指针的 strtok_r() 和 strsep() 的 C 字符串替代方案?

如何解决不修改原始字符串指针的 strtok_r() 和 strsep() 的 C 字符串替代方案?

我查看了 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);
}

输出

Tutorial and example                                                                                                                                                        
Tutorial                                                                                                                                                                    
and                                                                                                                                                                         
example                                                                                                                                                                     
                                                                                                                                                                            
                                                                                                                                                                            
                                                                                                                                                                            
Tutorial                                                                                                                                                                          

在最后一行,我希望 str 指向未修改的 cstring“教程和示例”。

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

谢谢。

解决方法

我认为您误解了strtok_r。它不会改变原始字符串的位置,而且,它也不能——函数不能改变传递给它的指针的值并使这个改变对调用代码可见。

它可以并且将会做的是修改字符串本身的内容,用nul-终止符替换标记。所以要回答你原来的问题:

在我的应用中,原始字符串是动态分配的,所以我 希望在解析完成后释放原始字符串。

您不必做任何特别的事情。完成后,您可以并且应该释放原始字符串。

您看到一个单词 Tutorial 被打印出来,只是因为下一个字符被替换为 nul-终止符并且 printf 停在那里。如果您要逐个字符地检查字符串,您将看到它在其他方面保持不变。

,

虽然上面提到的字符串函数改变了原来的字符串,但是指针str指向动态分配的内存,你可以用它来释放分配的内存。

如果您不想更改原始字符串,您可以使用标准 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;
}

程序输出为

Tutorial and example
Tutorial
and
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 );
        
        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;
}

程序输出与上图相同。

Tutorial and example
Tutorial
and
example

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?