如何遍历 std::vector<char> 并查找以 null 结尾的 c 字符串
How to iterate over std::vector<char> and find null-terminated c-strings
基于以下代码片段,我有三个问题
我有一个字符串列表。它只是碰巧是一个向量但也可以是任何来源
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 );
问题:这是估计存储的最佳方法吗?我将最大长度固定为20,然后为零终止符
添加空间现在复制名称
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(' ');
}
问题:这是将元素从v1_name复制到v2_names的最有效方法吗?
主要问题:如何遍历v2_names并打印v2_names中包含的国家名称
使用简单连接,获利!
#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, " ");
}
要估计存储空间,您可能应该测量字符串,而不是依赖于硬编码的常量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);
这并不一定是最有效的,因为在vector中有一定数量的可用空间的冗余检查,但它不应该太糟糕,而且它很简单。另一种方法是在开始时设置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
,那么大的字符串仍然是非常罕见的。
计算所需存储空间的最佳方法是将v1_names
中每个字符串的长度相加。
对于您的第二个问题,而不是使用For循环For,您可以在字符串上使用begin
和end
的向量的iterator, iterator
追加方法。
对于你的第三个问题:不要那样做。迭代v1_names
的字符串。创建v2_names
的唯一原因是将其传递到遗留的C API中,然后您不必担心迭代它。
如果您想要连接所有字符串,您可以只使用一次传递并依赖于平摊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
,如果您认为这有帮助的话。这取决于你对弦的了解程度。但也许没有必要担心,因为从长远来看,插入次数是0(1)。
- 正在查找文档以获得PS4平台的C++中的设备信息
- 在C++中查找文件
- 模板元程序查找相似的连续类型名称
- 在UNIX系统中使用DIR查找文件的字节大小
- 查找最接近的大于当前数字的数字的索引
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 查找后更改类变量
- 使用正则表达式regex_search在字符串中查找字符串
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 使用gcc从静态链接的文件中查找可选符号
- 如何在 c++ 中'NULL'字符串
- 在C++中查找范围的长度
- c++使用foreach使数组为null
- 当使用通配符和null指针调用函数时,对输出的说明
- 算法问题:查找从堆栈中弹出的所有序列
- 在Windows中查找扬声器输出的当前音量级别
- 无法使用指针查找正确的元素 - 从函数返回时,对象上的 poiting 为 null
- C++:无法通过传递给查找器函数来重新分配 null 初始化的对象指针
- 在std向量中查找NULL指针
- 如何遍历 std::vector<char> 并查找以 null 结尾的 c 字符串