当前位置: 首页 > 知识库问答 >
问题:

将以null结尾的字符数组复制到std::string中,并考虑缓冲区长度

曹臻
2023-03-14

也许这只是因为缺少咖啡,但我正试图从一个以空结尾的char数组中创建一个std::string,该数组的最大长度已知,我不知道该怎么做。

auto s = std::string(buffer, sizeof(buffer));

..是我最喜欢的候选者,但由于C字符串不是以null结尾的,所以无论包含什么“\0”,该命令都将复制sizeof(buffer)字节。

auto s = std::string(buffer);

..从缓冲区复制,直到找到\0。这几乎是我想要的,但我不能信任接收缓冲区,所以我想提供一个最大长度。

当然,我现在可以像这样集成strnlen()

auto s = std::string(buffer, strnlen(buffer, sizeof(buffer)));

但是这看起来很脏——它遍历缓冲区两次,我必须处理像string. hstrnlen()这样的C-工件(这很难看)。

我如何在现代C中做到这一点?


共有3个答案

白腾
2023-03-14
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) {}
};

现在,让它成为一个完全随机访问迭代器。除了=之外,大多数操作都非常简单(etc应该同时推进ptr索引)=

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的概念,它可以让您在降低运行时成本的情况下执行上述操作。或者你也可以手工制作出同等的解决方案。

终睿
2023-03-14

像这样的东西一次就能奏效。。

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;
  });
马国源
2023-03-14
const char* end = std::find(buffer, buffer + sizeof(buffer), '\0');
std::string s(buffer, end);
 类似资料:
  • 问题内容: 这个: 这样做(是空字节): 问题答案: Go的syscall程序包中隐藏了该函数,该函数查找第一个空字节([] byte {0})并返回长度。我假设它被称为C-Length。 抱歉,我迟到了一年,但是我认为它比其他两个 要 简单得多(没有不必要的输入等)。 所以, ^的意思是设置为从头到索引处的字节片。 结果将为3。

  • 我的要求是将字节流转换为具有预定义数据长度的结构类型。在下面的示例中,我可以将字节转换为“Test”对象并读取数据(func-buffertoStruct演示了这一点), 但问题是 我需要根据字符串或整数长度转换为数据类型。现在没有发生。 我有很多不同的结构,比如“类型测试”,每个结构都有大量的数据变量。因此,根据大小逐个将字节复制到结构测试变量中是行不通的。 我在考虑解决方案: 我正在考虑保留所

  • 我最近看到我的一位同事使用std::string作为缓冲区: 我猜这家伙想利用返回字符串的自动销毁,所以他不必担心释放分配的缓冲区。 这在我看来有点奇怪,因为根据cplusplus。com方法返回一个指向由字符串内部管理的缓冲区的常量字符*: Memcpy ing to a const char pointer?好吧,只要我们知道自己在做什么,这没有害处,但我错过了什么吗?这危险吗?

  • 我有这行代码 其中缓冲区是字节缓冲区。 有没有一种方法可以在不分配新字符串和/或复制字符数组的情况下将字节缓冲符转换为字符串?(也就是说,有没有办法将字符串的char[]值安全地指向字节缓冲区的byte[]hb?) 谢谢

  • 我有这样一个字符串: 和一个数组: 我想制作这个: 我试着用sscanf(),但我做不到。

  • 问题内容: Python字符串的末尾是否有特殊字符?就像在C或C ++中是\ 0。我想在不使用内置函数的情况下计算python中字符串的长度。 问题答案: Python中没有字符串结尾字符,至少没有一个公开的字符,它将取决于实现。字符串对象保持其自身的长度,您无需担心。有几种不使用来获取字符串长度的方法。 我怀疑这只是冰山一角。