Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将字符串解析为c样式字符数组的结构 我有一个VisualStudio 2008 C++项目,需要把字符串解析成C样式字符数组的结构。最优雅/有效的方法是什么_C++_String_Parsing - Fatal编程技术网

将字符串解析为c样式字符数组的结构 我有一个VisualStudio 2008 C++项目,需要把字符串解析成C样式字符数组的结构。最优雅/有效的方法是什么

将字符串解析为c样式字符数组的结构 我有一个VisualStudio 2008 C++项目,需要把字符串解析成C样式字符数组的结构。最优雅/有效的方法是什么,c++,string,parsing,C++,String,Parsing,以下是我当前的(功能)解决方案: struct Foo { char a[ MAX_A ]; char b[ MAX_B ]; char c[ MAX_C ]; char d[ MAX_D ]; }; Func( const Foo& foo ); std::string input = "abcd@efgh@ijkl@mnop"; std::vector< std::string > parsed; boost::split( parse

以下是我当前的(功能)解决方案:

struct Foo {
    char a[ MAX_A ];
    char b[ MAX_B ];
    char c[ MAX_C ];
    char d[ MAX_D ];
};

Func( const Foo& foo );

std::string input = "abcd@efgh@ijkl@mnop";
std::vector< std::string > parsed;
boost::split( parsed, input, boost::is_any_of( "@" ) );

Foo foo = { 0 };
parsed[ 1 ].copy( foo.a, MAX_A );
parsed[ 2 ].copy( foo.b, MAX_B );
parsed[ 3 ].copy( foo.c, MAX_C );
parsed[ 4 ].copy( foo.d, MAX_D );

Func( foo );
structfoo{
字符a[MAX_a];
字符b[MAX_b];
字符c[MAX_c];
字符d[MAX_d];
};
Func(const Foo&Foo);
std::字符串输入=”abcd@efgh@ijkl@mnop";
解析的std::vector;
boost::split(解析、输入、boost::是(“@”)中的任意一个);
Foo-Foo={0};
已分析[1]。复制(foo.a,MAX_a);
已解析[2]。复制(foo.b,MAX_b);
已解析[3]。复制(foo.c,MAX_c);
已解析[4]。复制(foo.d,MAX\u d);
Func(foo);
以下是我(现在已经过测试)的想法:


上现场观看,重新设计Foo怎么样

struct Foo {
  std::array<std::string, 4> abcd;
  std::string a() const { return abcd[0]; }
  std::string b() const { return abcd[1]; }
  std::string c() const { return abcd[2]; }
  std::string d() const { return abcd[3]; }
};


boost::algorithm::split_iterator<std::string::iterator> end,
    it = boost::make_split_iterator(input, boost::algorithm::first_finder("@"));
std::transform(it, end, foo.abcd.begin(),
               boost::copy_range<std::string, decltype(*it)>);
structfoo{
std::数组abcd;
std::string a()常量{return abcd[0];}
std::string b()常量{return abcd[1];}
std::string c()常量{return abcd[2];}
std::string d()常量{return abcd[3];}
};
boost::algorithm::split_迭代器结束,
it=boost::make_split_迭代器(输入,boost::algorithm::first_finder(“@”);
std::transform(it,end,foo.abcd.begin(),
boost::复制范围);

使用正则表达式如下所示(在C++11中,您可以将其转换为boost或VS2008的tr1):

您可能应该使用格式字符串和实际的
MAX.*
变量创建模式,而不是像我在这里做的那样在正则表达式中硬编码值,并且您可能还希望编译正则表达式一次并保存它,而不是每次都重新创建它


但除此之外,此方法避免了对字符串数据进行任何额外的复制。
res
中每个子匹配中保存的
char*
s是直接指向输入字符串缓冲区的指针,因此,唯一的副本是直接从输入字符串复制到最终的foo对象。

我看不出这个解决方案有任何错误,除非您经常添加到结构中,那么这可能是一个维护难题,因为对foo.a、foo.b等的赋值不遵循干式原则。你认为你会经常增加这个结构吗?我不认为我会经常增加。我最关心的是复制这些字符串的次数。有没有办法把它最小化?我不这么认为。如果要从中复制一个字符串,则只需将其复制到结构的起始地址即可。在您的情况下,它会起作用,因为您的结构中只有字符,并且它们是单字节对齐的。虽然我不建议这样做,因为我觉得这很难看。但你们无论如何也不能这样做,因为你们是从vector复制的,所以你们必须一个接一个地引用每个字符串。我认为你所拥有的还可以。你是否考虑过将整个问题放到一个单独的函数中,例如
Foo makefooformstring(std::string&input)
发明一个完整的其他问题,然后回答这个问题……?添加了一个测试。看现场直播
template <std::ptrdiff_t N>
std::string display(const char (&buf)[N])
{
    std::string result;
    for(size_t i=0; i<N && buf[i]; ++i)
       result += buf[i];
    return result; 
}

int main(int argc, const char *argv[])
{
    std::string input = "abcd@efgh@ijkl@mnop";

    Foo foo = { 0 };

    const char* cursor = input.c_str();
    cursor = extractToken(cursor, foo.a);
    cursor = extractToken(cursor, foo.b);
    cursor = extractToken(cursor, foo.c);
    cursor = extractToken(cursor, foo.d);

    std::cout << "foo.a: '" << display(foo.a) << "'\n";
    std::cout << "foo.b: '" << display(foo.b) << "'\n";
    std::cout << "foo.c: '" << display(foo.c) << "'\n";
    std::cout << "foo.d: '" << display(foo.d) << "'\n";
}
foo.a: 'abcd'
foo.b: 'efg'
foo.c: 'ijkl'
foo.d: 'mnop'
struct Foo {
  std::array<std::string, 4> abcd;
  std::string a() const { return abcd[0]; }
  std::string b() const { return abcd[1]; }
  std::string c() const { return abcd[2]; }
  std::string d() const { return abcd[3]; }
};


boost::algorithm::split_iterator<std::string::iterator> end,
    it = boost::make_split_iterator(input, boost::algorithm::first_finder("@"));
std::transform(it, end, foo.abcd.begin(),
               boost::copy_range<std::string, decltype(*it)>);
// Assuming MAX_A...MAX_D are all 10 in our regex

std::cmatch res;
if(std::regex_match(input.data(),input.data()+input.size(),
                    res,
                    std::regex("([^@]{0,10})([^@]{0,10})([^@]{0,10})([^@]{0,10})")))
{
    Foo foo = {};
    std::copy(res[1].first,res[1].second,foo.a);
    std::copy(res[2].first,res[2].second,foo.b);
    std::copy(res[3].first,res[3].second,foo.c);
    std::copy(res[4].first,res[4].second,foo.d);
}