在 C++ 中寻找 strtok() 的替代方案
Searching for an alternative for strtok() in C++
我正在使用 strtok 将字符串分成几个部分。
在此示例中,将从字符串中读取所有部分,这些部分由冒号或分号包围
char string[] = "Alice1:IscoolAlice2; Alert555678;Bob1:knowsBeepBob2;sees";
char delimiter[] = ":;";
char *p;
p = strtok(string, delimiter);
while(p != NULL) {
cout << "Result: " << p << endl;
p = strtok(NULL, delimiter);
}
结果我得到:
Result: Alice1
Result: IscoolAlice2
Result: Alert555678
Result: Bob1
Result: knowsBeepBob2
Result: sees
但我想得到这个结果:
Result: Alice1:
Result: Alice2;
Result: Bob1:
Result: Bob2;
限制是我在使用strtok时只能选择单个字符。
有谁知道我也可以搜索字符串的 strtok 替代方法?
或者有谁能解决我的问题?
您声明的数据集不可能按照您想要的方式正确拆分。您可以想出一个 "just so" 规则来仅拆分您显示的数据,但考虑到数据的混乱性质,它很可能会在其他示例中失败。让我们从这个令牌开始。
IscoolAlice2
计算机程序如何知道其中哪一部分是名字,哪一部分不是?你想从中得到 "Alice2"。如果您决定用大写字母指定名称,那么它只会吐出 "name" IscoolAlice2。与以下相同:
knowsBeepBob2
如果您搜索第一个大写字母,那么程序将确定他的名字是 BeepBob2,因此在每种情况下搜索令牌中最后一次出现的大写字母都会找到该名称。但是如果一个名字包含两个大写字母呢?该程序将删除他们的名字,您对此无能为力。
如果您乐于接受这些限制,您可以通过 strtok 仅使用 ; 进行初始拆分。字符,给出:
Alice1:IscoolAlice2
Alert555678
Bob1:knowsBeepBob2
sees
这不太理想。然后,您可以指定一个规则,使得名称存在于任何包含 : 的行中,将 : 左边的任何内容作为名称,然后找到最后一个大写字母,并且从该点开始的任何内容也是一个名称。那会给你你想要的输出。
但是我概述的规则对于刚刚输入的数据非常具体。如果其他数据样本的任何内容与此完全不同(例如,其中包含两个大写字母的名称),那么它将失败,因为那里在地球上,程序无法确定 "name" 从哪里开始。
解决此问题的唯一方法是返回数据的来源并采用不同的格式,以便名称前有某种标点符号。
或者您需要一个包含所有可能出现的名称的完整数据库,然后搜索它们,找到下一个 : 或 ; 之前的任何字符。并附加它们并打印名称。但这似乎非常不切实际。
这只是一些简单的临时逻辑,大致如下:
char *ptr = string;
while(*ptr)
{
printf("Result:");
while(*ptr)
{
printf("%c", *ptr);
if(ispunc(*ptr))
{
ptr++;
printf("\n");
break;
}
else
{
ptr++;
}
}
}
You can not do that task with strtok
since you need more complex search
虽然我不确定你的 string
是什么作为分隔符,但可以使用以下命令完成相同的输出:
char string[] = "Alice1:IscoolAlice2; Alert555678;Bob1:knowsBeepBob2;sees";
char delimiter[] = "(?:Alice|Bob)\d.";
std::regex regex( delimiter );
std::regex_iterator< const char* > first( std::begin( string ), std::end( string ), regex ), last;
while( first != last ){
std::cout << "Result: " << first->str() << '\n';
++first;
}
输出:
Result: Alice1;
Result: Alice2;
Result: Bob1;
Result: Bob2;
我正在使用 strtok 将字符串分成几个部分。 在此示例中,将从字符串中读取所有部分,这些部分由冒号或分号包围
char string[] = "Alice1:IscoolAlice2; Alert555678;Bob1:knowsBeepBob2;sees";
char delimiter[] = ":;";
char *p;
p = strtok(string, delimiter);
while(p != NULL) {
cout << "Result: " << p << endl;
p = strtok(NULL, delimiter);
}
结果我得到:
Result: Alice1
Result: IscoolAlice2
Result: Alert555678
Result: Bob1
Result: knowsBeepBob2
Result: sees
但我想得到这个结果:
Result: Alice1:
Result: Alice2;
Result: Bob1:
Result: Bob2;
限制是我在使用strtok时只能选择单个字符。 有谁知道我也可以搜索字符串的 strtok 替代方法? 或者有谁能解决我的问题?
您声明的数据集不可能按照您想要的方式正确拆分。您可以想出一个 "just so" 规则来仅拆分您显示的数据,但考虑到数据的混乱性质,它很可能会在其他示例中失败。让我们从这个令牌开始。
IscoolAlice2
计算机程序如何知道其中哪一部分是名字,哪一部分不是?你想从中得到 "Alice2"。如果您决定用大写字母指定名称,那么它只会吐出 "name" IscoolAlice2。与以下相同:
knowsBeepBob2
如果您搜索第一个大写字母,那么程序将确定他的名字是 BeepBob2,因此在每种情况下搜索令牌中最后一次出现的大写字母都会找到该名称。但是如果一个名字包含两个大写字母呢?该程序将删除他们的名字,您对此无能为力。
如果您乐于接受这些限制,您可以通过 strtok 仅使用 ; 进行初始拆分。字符,给出:
Alice1:IscoolAlice2
Alert555678
Bob1:knowsBeepBob2
sees
这不太理想。然后,您可以指定一个规则,使得名称存在于任何包含 : 的行中,将 : 左边的任何内容作为名称,然后找到最后一个大写字母,并且从该点开始的任何内容也是一个名称。那会给你你想要的输出。
但是我概述的规则对于刚刚输入的数据非常具体。如果其他数据样本的任何内容与此完全不同(例如,其中包含两个大写字母的名称),那么它将失败,因为那里在地球上,程序无法确定 "name" 从哪里开始。
解决此问题的唯一方法是返回数据的来源并采用不同的格式,以便名称前有某种标点符号。
或者您需要一个包含所有可能出现的名称的完整数据库,然后搜索它们,找到下一个 : 或 ; 之前的任何字符。并附加它们并打印名称。但这似乎非常不切实际。
这只是一些简单的临时逻辑,大致如下:
char *ptr = string;
while(*ptr)
{
printf("Result:");
while(*ptr)
{
printf("%c", *ptr);
if(ispunc(*ptr))
{
ptr++;
printf("\n");
break;
}
else
{
ptr++;
}
}
}
You can not do that task with
strtok
since you need more complex search
虽然我不确定你的 string
是什么作为分隔符,但可以使用以下命令完成相同的输出:
char string[] = "Alice1:IscoolAlice2; Alert555678;Bob1:knowsBeepBob2;sees";
char delimiter[] = "(?:Alice|Bob)\d.";
std::regex regex( delimiter );
std::regex_iterator< const char* > first( std::begin( string ), std::end( string ), regex ), last;
while( first != last ){
std::cout << "Result: " << first->str() << '\n';
++first;
}
输出:
Result: Alice1;
Result: Alice2;
Result: Bob1;
Result: Bob2;