C++:将 std::string 分配给缓冲区数组

问题描述 投票:0回答:1

在处理必须与 C 代码互操作的代码时,我经常遇到这个问题,其中有一个

std::string
,您需要将其内容复制到纯字符缓冲区,如下所示:

struct T
{
    int i;
    char cstr[size + 1];
};

// `std::` removed here for clarity only.
void f(vector<pair<int, string>> const& in)
{
   T* out = new/malloc whatever.

   for (size_t i = 0; i < in.size(); ++i) {
       out[i].i = in[i].first;
       strncpy(out[i].cstr, in[i].c_str(), sizeof(out[i].cstr));
   }

   // whatever
}

但是,这很不方便,也不太具有表现力。我更愿意做一些更类似于:

void f(vector<pair<int, string>> const& in)
{
   T* out = new/malloc whatever.

   for (size_t i = 0; i < in.size(); ++i)
       out[i] = T{ in[i].first, in[i].c_str() };

   // whatever
}

如何解决这个“字符串复制问题”?唯一的解决方案是通过一个能够包装 c 数组的对象,以便运算符=“做正确的事情”,以启用如下模式:

void f(vector<pair<int, string>> const& in)
{
   T* out = new/malloc whatever.

   for (size_t i = 0; i < in.size(); ++i)
       std::tie(out[i].id, WRAPPER(out[i].cstr)) = in[i];

   // whatever
}

语言或标准库中是否有任何内容已经解决了“那个问题”?或者我唯一的选择是用正确的语义构建我自己的类? (我自己知道怎么做;我问是否已经做了一些东西)。

c++ string c++17
1个回答
0
投票

我更喜欢继承 C

struct
并添加一个转换构造函数。

示例:

struct T {
    int i;
    char cstr[size + 1];
};

struct T2 : T {
    T2(const std::pair<int, std::string>& pair) : T{pair.first} {
        std::strncpy(cstr, pair.second.c_str(), sizeof cstr);
        cstr[sizeof cstr - 1] = '\0';        
    }
};

这样,您的 C++ 代码就可以获得更多表现力:

void f(std::vector<std::pair<int, std::string>> const& in) {
    std::vector<T2> out(in.begin(), in.end());

    //...
}

然后,您可以将

T2
切片为
T
,并根据需要提供指向每个元素的指针:

for (T& t : out) { // slice
    std::cout << t.i << ' ' << t.cstr << " ptr: " << &t << '\n';
}

或者使用

out.data(), out.size()
调用 C 函数,如下所示:

// a C function
void foo(T* ts, size_t size) {
    for(size_t i = 0; i < size; ++i) {
        printf("%d %s %p\n", ts[i].i, ts[i].cstr, (void*)&ts[i]);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.