在C 中分开字符串
Separating a string in C++
我试图将字符串分为多个字符串,以制作自定义的终端。到目前为止,我一直在使用Strtok分离控制信号,但是我不明白如何分离角色的特定实例。例如:
string input = "false || echo "hello world" | grep hello";
试图使用此input
并尝试使用|
进行分离时,输出将为:
false
,echo "hello world"
,grep hello
相反,我希望输出为:
false || echo "hello world"
, grep hello
我如何使strtok对待 |
和 ||
,而不是说它们是相同的?
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
vector<string> split(string sentence,char delim)
{
string tempSentence = "";
tempSentence += delim;
tempSentence += sentence;
tempSentence += delim;
string token;
vector<string> tokens;
for (int i=1;i<tempSentence.length()-1;++i)
{
if (tempSentence[i] == delim && tempSentence[i-1] != delim && tempSentence[i+1] != delim)
{
if (token.length()) tokens.push_back(token);
token.clear();
}
else
{
token += tempSentence[i];
}
}
if (token.length()) tokens.push_back(token);
return tokens;
}
int main() {
string sentence = "false || echo "hello world" | grep hello";
char delim='|';
vector<string> tokens = split(sentence,delim);
for_each(tokens.begin(), tokens.end(), [&](string t) {
cout << t << endl;
});
}
丑陋而漫长!但是有效!
strtok()将按字符扫描角色,而无需考虑其在寻找内容之前和之后的字符。如果您想要更智能的扫描,则需要自己实施额外的检查。
由于Strtok只是返回找到令牌的字符串中的位置,因此您必须手动检查返回令牌的第一个字符,以查看它是否也是'|',然后采取相应的行动。<<<<<<<<<<<<
更好的解决方案是在此处研究使用正则表达式。听起来您要划分的符号不仅是|,而是|被空间包围着 - 即,您实际上是在搜索和分裂三个字符符号(空间 - 管道 - 空间)
我会说您的问题的答案首先不使用strtok()
,它有多种问题,甚至在Manpage中进行了记录(至少在Linux上)。<<<<<<<<<<<<<</p>
其次,请确保您有测试。使用测试驱动的开发是这些任务必须的,因为这里几个简单的事情可能会彼此差异很差,并且在一个地方修复错误可能会在另一个地方引起问题。
此外,有一些工具(例如,各种YACC变量和类似的生成器)使您可以指定抽象语法,然后将此定义转换为C 代码。我建议这些不平凡的任务。
最后,如果您只是为了娱乐和学习而这样做,写循环或从字符串中提取各种令牌的功能是一种很好的方法。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string input = "false || echo "hello world" | grep hello";
string::iterator itr;
itr = input.begin();
do {
itr = search_n(itr, input.end(), 1, '|');
if (itr < input.end() - 1)
{
if (*(itr + 1) == '|')
{
itr = itr + 2;
continue;
}
}
if (itr < input.end())
{
*itr = ',';
itr ++;
}
} while (itr < input.end());
cout << input << endl;
return 0;
}
一个相当简单明了的解决方案,似乎可以解决您的问题。
std :: string :: find()搜索第一次出现的字符串 由其参数指定的序列(在这种情况下为字符串"定界符")。指定POS时 搜索仅包括位置或之后的字符
编辑
#include <iostream>
#include <string>
int main(int argc, char const *argv[])
{
std::string s = "false || echo "hello world" | grep hello";
std::string delimiter = "|";
size_t pos = 0, pos1 = 0, flag = 0;
std::string token, token1;
while ((pos = s.find(delimiter)) != std::string::npos) {
pos1 = s.find(delimiter, pos + delimiter.length());
while (pos1 == pos+1){
pos = pos1;
pos1 = s.find(delimiter, pos + delimiter.length());
flag = 1;
}
if (flag) {
token = s.substr(0, pos1);
std::cout << token << std::endl;
if (pos1 > s.length())
exit(0);
s.erase(0, pos1 + delimiter.length());
}
else{
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
}
std::cout << s << std::endl;
return 0;
}
输出:
false ||回声" Hello World"
grep hello