[英]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 strspn
和strcspn
代替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.