填充 std::vector的最佳方式缓冲

发布于 2024-12-06 17:26:48 字数 1237 浏览 0 评论 0原文

该缓冲区应包含长度相等的槽(本例中为 3 个)(本例中为 20)
缓冲区必须具有连续的内存,以便可以以非常量方式传递给 C 函数。

const int slot_size = 20;
std::vector<char> vbuffer;

该函数接受一个字符串,复制到所需大小的临时缓冲区,然后将其附加到vbuffer

void prepBuffer( const std::string& s)
{
  std::vector<char> temp(slot_size);
  std::copy(s.c_str(), s.c_str() + s.length() + 1, temp.begin());
  vbuffer.insert(vbuffer.end(), temp.begin(), temp.end());
}

测试函数

int main()
{
  vbuffer.reserve(60);
  prepBuffer( "Argentina");
  prepBuffer( "Herzegovina");
  prepBuffer( "Zambia");

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}

问题。有很多在我的 prepBuffer 函数中复制字符串。我正在寻找一种更好的方法来以最少的复制来填充 vbuffer
编辑
插槽的大小由程序中的其他部分确定。但在编译时并不知道。

编辑

根据下面我接受的答案,我已经选择了这个版本

void prepBuffer(const std::string& s)
{
  assert(s.size() < slot_size );
  vbuffer.insert(vbuffer.end(), s.begin(), s.end());
  vbuffer.insert(vbuffer.end(), slot_size - s.size(), '\0' ); 
}


仍然欢迎提出建议

This buffer should contain slots (three in this example) of equal length ( 20 in this example)
The buffer has to have contiguous memory so that it can be passed to a C function in non-const fashion.

const int slot_size = 20;
std::vector<char> vbuffer;

This function takes a string, copies to a temporary buffer of the required size then appeds it to vbuffer

void prepBuffer( const std::string& s)
{
  std::vector<char> temp(slot_size);
  std::copy(s.c_str(), s.c_str() + s.length() + 1, temp.begin());
  vbuffer.insert(vbuffer.end(), temp.begin(), temp.end());
}

Testing the function

int main()
{
  vbuffer.reserve(60);
  prepBuffer( "Argentina");
  prepBuffer( "Herzegovina");
  prepBuffer( "Zambia");

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}

Question. There is a lot of string copying in my prepBuffer function. I am looking for a better way to fill up vbuffer with minimal copying
EDIT
The size of slots is determined elsewhere in the program. But it is not known at compile time.

EDIT

In line with my accepted answer below, I have settled on this version

void prepBuffer(const std::string& s)
{
  assert(s.size() < slot_size );
  vbuffer.insert(vbuffer.end(), s.begin(), s.end());
  vbuffer.insert(vbuffer.end(), slot_size - s.size(), '\0' ); 
}

Suggestions are still welcome

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

爱*していゐ 2024-12-13 17:26:48

怎么样:

vbuffer.reserve(vbuffer.size() + 20);
vbuffer.insert(vbuffer.end(), s.begin(), s.end());
vbuffer.insert(vbuffer.end(), 20 - s.size(), '\0');

建议对字符串长度进行额外检查,并制定处理超长字符串的策略(例如 assert(s.size() < 20);)。

How about this:

vbuffer.reserve(vbuffer.size() + 20);
vbuffer.insert(vbuffer.end(), s.begin(), s.end());
vbuffer.insert(vbuffer.end(), 20 - s.size(), '\0');

An additional check on the string length is recommended, along with a policy for handling over-long strings (e.g. assert(s.size() < 20);).

我偏爱纯白色 2024-12-13 17:26:48

如果您根本不使用 std::string 并避免使用临时 std::vector,则无需任何额外的动态分配即可轻松完成此操作。

template <unsigned N>
void prepBuffer(char const (&s)[N])
{
    std::copy(s, s + N, std::back_inserter(vbuffer));
    vbuffer.resize(vbuffer.size() - N + 20);
}

或者,由于要写入的字符数提前已知,因此您可以轻松地使用非模板函数:

void prepBuffer(char const* s)
{
    unsigned n = vbuffer.size();
    vbuffer.resize(n + 20);
    while (*s && n != vbuffer.size())
    {
        vbuffer[n] = *s;
        ++n;
        ++s;
    }

    assert(*s == 0 && n != vbuffer.size());
    // Alternatively, throw an exception or handle the error some other way
}

If you don't use std::string at all and avoid the temporary std::vector, you can easily do this without any extra dynamic allocation.

template <unsigned N>
void prepBuffer(char const (&s)[N])
{
    std::copy(s, s + N, std::back_inserter(vbuffer));
    vbuffer.resize(vbuffer.size() - N + 20);
}

Or, since the number of characters to be written is known ahead of time, you could just as easily use a nontemplate function:

void prepBuffer(char const* s)
{
    unsigned n = vbuffer.size();
    vbuffer.resize(n + 20);
    while (*s && n != vbuffer.size())
    {
        vbuffer[n] = *s;
        ++n;
        ++s;
    }

    assert(*s == 0 && n != vbuffer.size());
    // Alternatively, throw an exception or handle the error some other way
}
万水千山粽是情ミ 2024-12-13 17:26:48

另一个想法:

std::vector<std::array<char, 20> > prepped(3);

strncpy(prepped[0].begin(), "Argentina",   20);
strncpy(prepped[1].begin(), "Herzegovina", 20);
strncpy(prepped[2].begin(), "Zambia",      20);

您可以这样写

typedef std::vector<std::array<char, 20> > prepped_t;
strncpy(..., ..., sizeof(prepped_t::value_type));

如果您想在更改嵌套数组的大小时更加灵活,

Another idea:

std::vector<std::array<char, 20> > prepped(3);

strncpy(prepped[0].begin(), "Argentina",   20);
strncpy(prepped[1].begin(), "Herzegovina", 20);
strncpy(prepped[2].begin(), "Zambia",      20);

You could write

typedef std::vector<std::array<char, 20> > prepped_t;
strncpy(..., ..., sizeof(prepped_t::value_type));

in case you wanted to be a bit more flexible when changing the size of the nested array

北风几吹夏 2024-12-13 17:26:48
void prepBuffer( const char *s, std::size_t offset)
{
  strncpy(&vbuffer[offset], s, 20);
}

功能

int main()
{
  vbuffer.resize(60);
  prepBuffer( "Argentina", 0);
  prepBuffer( "Herzegovina", 20);
  prepBuffer( "Zambia", 40);

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}

测试以可维护性为代价最大限度地减少复制的


Here is nearly-optimal code that is still readable and maintainable.

std::string vbuffer;
void prepBuffer( const std::string& s)
{
  vbuffer += s;
  vbuffer.resize( ( (vbuffer.size() +19) / 20) * 20));
}

Testing the function

int main()
{
  vbuffer.reserve(60);
  prepBuffer( "Argentina");
  prepBuffer( "Herzegovina");
  prepBuffer( "Zambia");

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}
void prepBuffer( const char *s, std::size_t offset)
{
  strncpy(&vbuffer[offset], s, 20);
}

Testing the function

int main()
{
  vbuffer.resize(60);
  prepBuffer( "Argentina", 0);
  prepBuffer( "Herzegovina", 20);
  prepBuffer( "Zambia", 40);

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}

That minimizes copying, at the cost of maintainability.


Here is nearly-optimal code that is still readable and maintainable.

std::string vbuffer;
void prepBuffer( const std::string& s)
{
  vbuffer += s;
  vbuffer.resize( ( (vbuffer.size() +19) / 20) * 20));
}

Testing the function

int main()
{
  vbuffer.reserve(60);
  prepBuffer( "Argentina");
  prepBuffer( "Herzegovina");
  prepBuffer( "Zambia");

  cout << &vbuffer[0] << endl;
  cout << &vbuffer[20] << endl;
  cout << &vbuffer[40] << endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文