如何迭代 std::vector并找到以 null 结尾的 c 字符串

发布于 2024-12-05 03:25:46 字数 1036 浏览 0 评论 0原文

根据以下代码片段,我有三个问题
我有一个字符串列表。它恰好是一个向量,但可能是任何源

vector<string> v1_names = boost::assign::list_of("Antigua and Barbuda")( "Brasil")( "Papua New Guinea")( "Togo");

以下是存储每个名称的长度

vector<int> name_len;

以下是我要存储字符串的位置

std::vector<char> v2_names;

估计从 v1_names 复制名称所需的内存

v2_names.reserve( v1_names.size()*20 + 4 );

< strong>问题:这是估计存储空间的最佳方法吗?我将最大长度固定为 20 即可,然后为 null tr​​eminator 添加空间
现在复制名称

for( std::vector<std::string>::size_type i = 0; i < v1_names.size(); ++i)
{
    std::string val( v1_names[i] );
    name_len.push_back(val.length());
    for(std::string::iterator it = val.begin(); it != val.end(); ++it)
    {
        v2_names.push_back( *it );
    }
    v2_names.push_back('\0');
}

问题:这是将元素从 v1_name 复制到 v2_names 的最有效方法吗?
主要问题:如何迭代 v2_names 并打印 v2_names 中包含的国家/地区名称

I have three questions based on the following code fragments
I have a list of strings. It just happens to be a vector but could potentially be any source

vector<string> v1_names = boost::assign::list_of("Antigua and Barbuda")( "Brasil")( "Papua New Guinea")( "Togo");

The following is to store lengths of each name

vector<int> name_len;

the following is where I want to store the strings

std::vector<char> v2_names;

estimate memory required to copy names from v1_names

v2_names.reserve( v1_names.size()*20 + 4 );

Question: is this the best way to estimate storage? I fix the max len at 20 that is ok, then add space for null treminator
Now copy the names

for( std::vector<std::string>::size_type i = 0; i < v1_names.size(); ++i)
{
    std::string val( v1_names[i] );
    name_len.push_back(val.length());
    for(std::string::iterator it = val.begin(); it != val.end(); ++it)
    {
        v2_names.push_back( *it );
    }
    v2_names.push_back('\0');
}

Question: is this the most efficient way to copy the elements from v1_name to v2_names?
Main Question: How do I iterate over v2_names and print the country names contained in v2_names

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

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

发布评论

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

评论(4

最佳男配角 2024-12-12 03:25:46

使用简单加盟,盈利!

#include <boost/algorithm/string/join.hpp>
#include <vector>
#include <iostream>

int main(int, char **)
{
    vector<string> v1_names = boost::assign::list_of("Antigua and Barbuda")( "Brasil")( "Papua New Guinea")( "Togo");

    std::string joined = boost::algorithm::join(v1_names, "\0");
}

Use simple join, profit!

#include <boost/algorithm/string/join.hpp>
#include <vector>
#include <iostream>

int main(int, char **)
{
    vector<string> v1_names = boost::assign::list_of("Antigua and Barbuda")( "Brasil")( "Papua New Guinea")( "Togo");

    std::string joined = boost::algorithm::join(v1_names, "\0");
}
橘和柠 2024-12-12 03:25:46

为了估计存储空间,您可能应该测量字符串,而不是依赖于硬编码常量 20。例如:

size_t total = 0;
for (std::vector<std::string>::iterator it = v1_names.begin(); it != v1_names.end(); ++it) {
    total += it->size() + 1;
}

循环中的主要低效率可能是您依次获取每个字符串的额外副本:std: :string val( v1_names[i] ); 可以改为 const std::string &val = v1_names[i];。

要附加每个字符串,您可以使用 insert 函数:

v2_names.insert(v2_names.end(), val.begin(), val.end());
v2_names.push_back(0);

这不一定是最有效的,因为对向量中的可用空间进行了一定量的冗余检查,但不应太高不好而且很简单。另一种方法是在开始时调整 v2_names 的大小而不是保留空间,然后复制数据(使用 std::copy)而不是附加数据。但它们中的任何一个都可能更快,而且应该不会产生太大的差异。

对于主要问题,如果您只有 v2_names 并且您想打印字符串,您可以执行以下操作:

const char *p = &v2_names.front();
while (p <= &v2_names.back()) {
    std::cout << p << "\n";
    p += strlen(p) + 1;
}

如果您还有 name_len

size_t offset = 0;
for (std::vector<int>::iterator it = name_len.begin(); it != name_len.end(); ++it) {
    std::cout << &v2_names[offset] << "\n";
    offset += *it + 1;
}

请注意类型name_len 在技术上是错误的 - 它不能保证您可以将字符串长度存储在 int 中。也就是说,即使在特定实现中 int 小于 size_t,这么大的字符串仍然很少见。

To estimate storage, you should probably measure the strings, rather than rely on a hard-coded constant 20. For example:

size_t total = 0;
for (std::vector<std::string>::iterator it = v1_names.begin(); it != v1_names.end(); ++it) {
    total += it->size() + 1;
}

The main inefficiency in your loop is probably that you take an extra copy of each string in turn: std::string val( v1_names[i] ); could instead be const std::string &val = v1_names[i];.

To append each string, you can use the insert function:

v2_names.insert(v2_names.end(), val.begin(), val.end());
v2_names.push_back(0);

This isn't necessarily the most efficient, since there's a certain amount of redundant checking of available space in the vector, but it shouldn't be too bad and it's simple. An alternative would be to size v2_names at the start rather than reserving space, and then copy data (with std::copy) rather than appending it. But either one of them might be faster, and it shouldn't make a lot of difference.

For the main question, if all you have is v2_names and you want to print the strings, you could do something like this:

const char *p = &v2_names.front();
while (p <= &v2_names.back()) {
    std::cout << p << "\n";
    p += strlen(p) + 1;
}

If you also have name_len:

size_t offset = 0;
for (std::vector<int>::iterator it = name_len.begin(); it != name_len.end(); ++it) {
    std::cout << &v2_names[offset] << "\n";
    offset += *it + 1;
}

Beware that the type of name_len is technically wrong - it's not guaranteed that you can store a string length in an int. That said, even if int is smaller than size_t in a particular implementation, strings that big will still be pretty rare.

╰沐子 2024-12-12 03:25:46

计算所需存储空间的最佳方法是对 v1_names 中每个字符串的长度求和。

对于第二个问题,您可以不使用 for 循环,而是使用向量的 iterator, iterator 附加方法,并在细绳。

对于你的第三个问题:只是不要这样做。而是迭代 v1_names 的字符串。创建诸如 v2_names 这样的东西的唯一原因是将其传递到旧版 C API 中,这样您就不必担心对其进行迭代。

The best way to compute the required storage is to sum up the length of each string in v1_names.

For your second question instead of using the for loop for you could just use the iterator, iterator append method of vector with begin and end on the string.

For your third question: Just don't do that. Iterate over v1_names's strings instead. The only reason to ever create such a thing as v2_names is to pass it into a legacy C API and then you don't have to worry about iterating over it.

纸短情长 2024-12-12 03:25:46

如果您想连接所有字符串,您可以只使用一次传递并依赖于分摊 O(1) 插入:

name_len.reserve(v1_names.size());

// v2_names.reserve( ??? ); // only if you have a good heuristic or
                            // if you can determine this efficiently

for (auto it = v1_names.cbegin(); it != v1_names.cend(); ++it)
{
  name_len.push_back(it->size());
  v2_names.insert(v2_names.end(), it->c_str(), it->c_str() + it->size() + 1);
}

可以在此之前通过另一个循环预先计算总长度并调用 reserve 如果您认为这会有所帮助。这取决于你对琴弦的了解程度。但也许没有必要担心,因为从长远来看,插入的复杂度是 O(1)。

If you want to concatenate all the strings, you could just use a single pass and rely on amortized O(1) insertions:

name_len.reserve(v1_names.size());

// v2_names.reserve( ??? ); // only if you have a good heuristic or
                            // if you can determine this efficiently

for (auto it = v1_names.cbegin(); it != v1_names.cend(); ++it)
{
  name_len.push_back(it->size());
  v2_names.insert(v2_names.end(), it->c_str(), it->c_str() + it->size() + 1);
}

You could precompute the total length by another loop before this and call reserve if you think this will help. It depends on how well you know the strings. But perhaps there's no point worrying, since in the long run the insertions are O(1).

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