C ++使用空格和引号标记字符串

时间:2013-09-07 16:20:24

标签: c++ string token

我想用C ++编写一些标记字符串的东西。要解释我想要的内容,请使用以下字符串:

add string "this is a string with spaces!"

必须按如下方式拆分:

add
string
this is a string with spaces!

是否有基于标准库的快速方法?

6 个答案:

答案 0 :(得分:7)

不需要图书馆。迭代可以完成任务(如果它像您描述的那样简单)。

string str = "add string \"this is a string with space!\"";

for( size_t i=0; i<str.length(); i++){

    char c = str[i];
    if( c == ' ' ){
        cout << endl;
    }else if(c == '\"' ){
        i++;
        while( str[i] != '\"' ){ cout << str[i]; i++; }
    }else{
        cout << c;
    }
}

输出

add
string
this is a string with space!

答案 1 :(得分:3)

这是一个完整的功能。根据需要修改它,它将部分字符串添加到矢量字符串(qargs)。

void split_in_args(std::vector<std::string>& qargs, std::string command){
        int len = command.length();
        bool qot = false, sqot = false;
        int arglen;
        for(int i = 0; i < len; i++) {
                int start = i;
                if(command[i] == '\"') {
                        qot = true;
                }
                else if(command[i] == '\'') sqot = true;

                if(qot) {
                        i++;
                        start++;
                        while(i<len && command[i] != '\"')
                                i++;
                        if(i<len)
                                qot = false;
                        arglen = i-start;
                        i++;
                }
                else if(sqot) {
                        i++;
                        while(i<len && command[i] != '\'')
                                i++;
                        if(i<len)
                                sqot = false;
                        arglen = i-start;
                        i++;
                }
                else{
                        while(i<len && command[i]!=' ')
                                i++;
                        arglen = i-start;
                }
                qargs.push_back(command.substr(start, arglen));
        }
        for(int i=0;i<qargs.size();i++){
                std::cout<<qargs[i]<<std::endl;
        }
        std::cout<<qargs.size();
        if(qot || sqot) std::cout<<"One of the quotes is open\n";
}

答案 2 :(得分:2)

Boost库具有一个tokenizer类,可以接受一个escaped_list_separator。这些看起来像它们的组合可能会提供您想要的东西。

这里是boost文档的链接,这些是本文发布时的最新文档,几乎可以肯定是您阅读本文时的旧版本。

https://www.boost.org/doc/libs/1_73_0/libs/tokenizer/doc/tokenizer.htm

https://www.boost.org/doc/libs/1_73_0/libs/tokenizer/doc/escaped_list_separator.htm

该示例是从boost文档中窃取的。原谅我没有创建自己的示例。

// simple_example_2.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>

int main(){
   using namespace std;
   using namespace boost;
   string s = "Field 1,\"putting quotes around fields, allows commas\",Field 3";
   tokenizer<escaped_list_separator<char> > tok(s);
   for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end();++beg){
       cout << *beg << "\n";
   }
}

答案 3 :(得分:1)

我想标准库没有直接的方法。间接跟随算法将起作用:

a)使用string::find('\"')搜索“\”,如果找到任何内容,请使用string::find('\'',prevIndex)搜索下一个“\”,如果找到则使用string::substr()。从原始字符串中丢弃该部分。

b)现在以同样的方式搜索' '字符。

注意:您必须遍历整个字符串。

答案 4 :(得分:1)

我将定义一个类Token来从流中读取单个令牌。

然后使用您的代码变得非常简单。

#include <iostream>
#include <string>

int main()
{
    // Simply read the tokens from the stream.
    Token   t;
    while(std::cin >> t)
    {
        std::cout << "Got: " << t << "\n";
    }
}

这样的流对象很容易编写:

class Token
{
    // Just something to store the value in.
    std::string     value;

    // Then define the input and output operators.
    friend std::ostream& operator<<(std::ostream& str, Token const& output)
    {
        return str << output.value;
    }

    // Input is slightly harder than output.
    // but not that difficult to get correct.
    friend std::istream& operator>>(std::istream& str, Token& input)
    {
        std::string tmp;
        if (str >> tmp)
        {
            if (tmp[0] != '"')
            {
                // We read a word that did not start with
                // a quote mark. So we are done. Simply put
                // it in the destination.
                input.value = std::move(tmp);
            }
            else if (tmp.front() == '"' && tmp.back() == '"')
            {
                // we read a word with both open and close
                // braces so just nock these off.
                input.value = tmp.substr(1, tmp.size() - 2);
            }
            else
            {
                // We read a word that has but has a quote at the
                // start. So need to get all the characters upt
                // closing quote then add this to value.
                std::string tail;
                if (std::getline(str, tail, '"'))
                {
                    // Everything worked
                    // update the input
                    input.value = tmp.substr(1) + tail;
                }
            }
        }
        return str;
    }
};

答案 5 :(得分:0)

我想知道为什么这里没有介绍这种简单的C ++样式的解决方案。 基于这样的事实,如果我们首先用\"分割字符串,那么每个偶数块都在“内部”引号中,并且每个奇数块都应另外用空格分割。

超出范围或其他任何可能性的可能性。

unsigned counter = 0;
std::string segment;
std::stringstream stream_input(input);
while(std::getline(stream_input, segment, '\"'))
{
    ++counter;
    if (counter % 2 == 0)
    {
        if (!segment.empty())
            std::cout << segment << std::endl;
    }
    else
    {
        std::stringstream stream_segment(segment);
        while(std::getline(stream_segment, segment, ' '))
            if (!segment.empty())
                std::cout << segment << std::endl;
    }
}