我想用C ++编写一些标记字符串的东西。要解释我想要的内容,请使用以下字符串:
add string "this is a string with spaces!"
必须按如下方式拆分:
add
string
this is a string with spaces!
是否有基于标准库的快速方法?
答案 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;
}
}