繁体   English   中英

如何在 char* 上使用 strtok

[英]How to use strtok on char*

在 c++ 中,要使用strtok过滤掉分隔符,源必须是 char 数组,否则会出现段错误。 如何在指向char的指针上使用strtok

如何构造strtok的代码示例:

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

int main () {
  char str[] ="- This, a sample string."; // this is the string i want to split. notice how it's an array
  char * pch;
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

我想做的事的例子:

/* strtok example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char* str ="- This, a sample string."; // since this is a pointer to char, it gives a segmentation fault after compiling, and executing.
  char * pch;
  pch = strtok (str," ,.-");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, " ,.-");
  }
  return 0;
}

您正在尝试修改字符串文字( function strtok更改源字符串插入 null 个字符'\0'

char* str ="- This, a sample string.";

首先,在 C++ 中,与 C 相对,字符串文字的类型为常量字符 arrays。因此,您必须在 C++ 程序中使用限定符const编写指针的声明。

const char* str ="- This, a sample string.";

任何更改 C 和 C++ 中的字符串文字的尝试都会导致未定义的行为。

例如在 C 标准中有这样写的 (6.4.5 String literals)

7 未指定这些 arrays 是否不同,前提是它们的元素具有适当的值。 如果程序试图修改这样的数组,则行为是未定义的。

因此,在 C 中,使用限定符const声明指向字符串文字的指针总是更好。

您可以使用例如 C 标准字符串 function strspnstrcspn代替strtok

这是一个演示程序。

#include <iostream>
#include <iomanip>
#include <string_view>
#include <cstring>

int main()
{
    const char *s = "- This, a sample string.";
    const char *delim = " ., -";

    for (const char *p = s; *( p += strspn( p, delim ) ) != '\0'; )
    {
        auto n = strcspn( p, delim );

        std::string_view sv( p, n );

        std::cout << std::quoted( sv ) << ' ';

        p += n;
    }

    std::cout << '\n';
}

程序 output 是

"This" "a" "sample" "string"

例如,您可以声明一个字符串视图向量,如std::vector<std::string_view>并将每个 substring 存储在其中。

例如

#include <iostream>
#include <iomanip>
#include <string_view>
#include <vector>
#include <cstring>

int main()
{
    const char *s = "- This, a sample string.";
    const char *delim = " ., -";

    std::vector<std::string_view> v;

    for (const char *p = s; *( p += strspn( p, delim ) ) != '\0'; )
    {
        auto n = strcspn( p, delim );

        v.emplace_back( p, n );

        p += n;
    }

    for (auto sv : v)
    {
        std::cout << std::quoted( sv ) << ' ';
    }
    std::cout << '\n';
}

程序output与上图相同。

或者,如果编译器不支持 C++ 17,则可以使用std::vector<std::pair<const char *, size_t>>类型的向量代替std::vector<std::string_view>类型的向量std::vector<std::pair<const char *, size_t>>

例如

#include <iostream>
#include <iomanip>
#include <utility>
#include <vector>
#include <cstring>

int main()
{
    const char *s = "- This, a sample string.";
    const char *delim = " ., -";

    std::vector<std::pair<const char *, size_t>> v;

    for (const char *p = s; *( p += strspn( p, delim ) ) != '\0'; )
    {
        auto n = strcspn( p, delim );

        v.emplace_back( p, n );

        p += n;
    }

    for (auto p : v)
    {
        std::cout.write( p.first, p.second ) << ' ';
    }
    std::cout << '\n';
}

程序 output 是

This a sample string

或者您可以使用std::string类型的对象向量: std::vector<std::string>

在 C 中,您可以使用可变长度数组或动态分配的数组,其结构类型的元素类型包含两个类型为const char *size_t的数据成员,类似于 C++ class std::pair 但是要定义数组,您首先需要使用相同的 for 循环计算字符串文字中有多少个单词。

这里有一个C的演示程序。

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

int main( void )
{
    const char *s = "- This, a sample string.";
    const char *delim = " ., -";

    size_t nmemb = 0;

    for (const char *p = s; *( p += strspn( p, delim ) ) != '\0'; )
    {
        ++nmemb;
        size_t n = strcspn( p, delim );
        p += n;
    }    

    struct SubString
    {
        const char *pos;
        size_t size;
    } a[nmemb];

    size_t i = 0;

    for (const char *p = s; *( p += strspn( p, delim ) ) != '\0'; )
    {
        size_t n = strcspn( p, delim );

        a[i].pos = p;
        a[i].size =n;
        ++i;
        p += n;
    }

    for ( i = 0; i < nmemb; i++ )
    {
        printf( "%.*s ", ( int )a[i].size, a[i].pos );
    } 

    putchar( '\n' );   
}

程序 output 是

This a sample string

我想做的事的例子:

 char* str ="- This, a sample string."

你不能做你想做的,因为字符串文字不能隐式转换为指向 C++ 中非常量字符的指针。此外, strtok修改参数字符串,并且 srtring 文字不得在 C++ 中修改。

如何在 char* 上的 c++ 上使用 strtok

如果你真的想要,你可以这样做:

char str_arr[] ="- This, a sample string.";
char* str = str_arr;

但这毫无意义


为了标记字符串文字而不将其复制到可修改数组中,您不得使用strtok

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM