在C 中分开字符串

Separating a string in C++

本文关键字:字符串      更新时间:2023-10-16

我试图将字符串分为多个字符串,以制作自定义的终端。到目前为止,我一直在使用Strtok分离控制信号,但是我不明白如何分离角色的特定实例。例如:

string input = "false || echo "hello world" | grep hello";

试图使用此input并尝试使用|进行分离时,输出将为:

falseecho "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