将以null结尾的char数组复制到符合缓冲区长度的std::字符串中
Copy null terminated char array to std::string respecting buffer length
也许只是缺少咖啡,但我正试图从一个已知最大长度的空终止char
数组创建一个std::string
,我不知道该怎么做。
auto s = std::string(buffer, sizeof(buffer));
是我最喜欢的候选者,但由于C++字符串不是以null结尾的,因此无论包含什么"\0",该命令都将复制sizeof(buffer)
字节。
auto s = std::string(buffer);
从CCD_ 4拷贝直到找到CCD_。这几乎是我想要的,但我不能信任接收缓冲区,所以我想提供最大长度。
当然,我现在可以像这样集成strnlen()
:
auto s = std::string(buffer, strnlen(buffer, sizeof(buffer)));
但这似乎很糟糕——它遍历了缓冲区两次,我必须处理像string.h
和strnlen()
这样的C工件(而且很难看)。
在现代C++中我该如何做到这一点?
const char* end = std::find(buffer, buffer + sizeof(buffer), ' ');
std::string s(buffer, end);
类似的东西可以在一次通过中工作。
auto eos = false;
std::string s;
std::copy_if(buffer, buffer + sizeof(buffer), std::back_inserter(s),
[&eos](auto v) {
if (!eos) {
if (v) {
return true;
}
eos = true;
}
return false;
});
如果您想要单程解决方案,请从以下内容开始:
template<class CharT>
struct smart_c_string_iterator {
using self=smart_c_string_iterator;
std::size_t index = 0;
bool is_end = true;
CharT* ptr = nullptr;
smart_c_string_iterator(CharT* pin):is_end(!pin || !*pin), ptr(pin) {}
smart_c_string_iterator(std::size_t end):index(end) {}
};
现在,对它进行美化,使其成为一个完整的随机访问迭代器。大多数操作都非常简单(++
等应该同时推进ptr
和index
),除了==
和!=
。
friend bool operator==(self lhs, self rhs) {
if (lhs.is_end&&rhs.is_end) return true;
if (lhs.index==rhs.index) return true;
if (lhs.ptr==rhs.ptr) return true;
if (lhs.is_end && rhs.ptr && !*rhs.ptr) return true;
if (rhs.is_end && lhs.ptr && !*lhs.ptr) return true;
return false;
}
friend bool operator!=(self lhs, self rhs) {
return !(lhs==rhs);
}
我们还需要:
template<class CharT>
std::pair<smart_c_string_iterator,smart_c_string_iterator>
smart_range( CharT* ptr, std::size_t max_length ) {
return {ptr, max_length};
}
现在我们这样做:
auto r = smart_range(buffer, sizeof(buffer));
auto s = std::string(r.first, r.second);
在每一步中,我们都会在进行复制时检查缓冲区长度和空终止。
现在,Ranges v3引入了sentinal的概念,它允许您在降低运行时成本的情况下执行类似于上面的操作。或者你也可以手工制作同等的解决方案。
相关文章:
- std::带有自定义缓冲区的 iostream 不允许我写入
- istream std::cin如何修改自定义istream缓冲区
- 在共享缓冲区内存中创建 ::std::string 对象
- 是否可以将 std::basic_ifstream 和 std::basic_ofstream 与自定义缓冲区一起使用?
- std::vector::assign/std::vector::operator=(const&) 是否保证在"this"中重用缓冲区?
- 如何将文件的一部分读取到std::list缓冲区?
- 在 std::string::end() 和 std::string::capacity() 之间使用缓冲区
- std::ifstream.read() 不会向我的缓冲区返回任何内容
- 输出操纵器 std::ends 是否向输出缓冲区添加空字符?
- 调整我的std :: string时,角色缓冲区会发生什么
- std::字符串与字节缓冲区(C++的差异)
- STD ::向量如何调整其内部缓冲区大小
- 在C 中,是否有可能在不兼容类型的std ::向量对象之间传输不同类型的缓冲区
- 我可以做一个循环,直到“std::cin”在输入缓冲区中看到“”字符
- 缓冲区刷新究竟是如何工作的(std::endl 和 之间的区别)?
- C++如何检查std::cin缓冲区是否为空
- 如何使用 std::istringstream 获取正确的缓冲区大小以进行数据解析
- 初始化的std ::阵列从指针优雅地变成缓冲区
- 别名,用于使用 std::aligned_union 和 std::aligned_union 进行小型缓冲区优化
- 如何使用 std::make_shared 创建动态大小缓冲区