用C ++分隔字符串

时间:2015-05-10 07:31:43

标签: c++ string strtok system-calls

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

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

尝试使用input并尝试使用|分隔时,输出将为:

falseecho "hello world"grep hello

相反,我希望输出为:

false || echo "hello world"grep hello

我怎样才能以不同的方式对待|||,而不是说它们是相同的?

5 个答案:

答案 0 :(得分:8)

#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;
    });

}
丑陋而漫长!但是有效!

答案 1 :(得分:1)

strtok()将逐个字符地扫描,而不考虑它所寻找的字符之前和之后的字符。如果您想要更智能的扫描,您需要自己实施额外的检查。

由于strtok只返回字符串中找到令牌的位置,因此您必须手动检查要返回的令牌的第一个字符,看它是否也是&#39; |&#39 ;,然后采取相应行动。

更好的解决方案是在这里研究正则表达式的使用。听起来你想要拆分的符号不仅仅是|,而是一个|被空格包围 - 也就是说,你实际上正在搜索和分裂三个字符(空格 - 管道 - 空间)

答案 2 :(得分:1)

我说你的问题的答案首先是不使用strtok(),它有很多问题,甚至在联机帮助页中都有记录(至少在Linux上)。

其次,确保你有测试。使用测试驱动开发是这些任务的必要条件,因为这里有几个简单的事情可能会相互影响很严重,并且在一个地方修复错误会导致另一个问题。

此外,还有一些工具(例如各种YACC变体和类似的生成器)允许您指定抽象语法,然后将此定义转换为C ++代码。我建议将这些用于任何非平凡的任务。

最后,如果您只是为了娱乐和学习而这样做,那么编写一个循环或一组函数来从字符串中提取各种标记是一种很好的方法。

答案 3 :(得分:1)

#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;
}

答案 4 :(得分:1)

一个相当简单直接的解决方案似乎可以解决您的问题。

  

std :: string :: find()搜索第一次出现的字符串   由其参数指定的序列(在本例中为字符串&#39;分隔符&#39;)。当指定pos时,   搜索仅包括位置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 ||回声&#34;你好世界&#34;

grep hello