【问题标题】:Extra zero char at end of string appears in C++ for range loop字符串末尾的额外零字符出现在 C++ 中用于范围循环
【发布时间】:2020-10-12 14:03:20
【问题描述】:

以下代码

#include <iostream>
#include <string>
int main()
{
    std::string s = "abc";
    for (char c : s)
        std::cout << (int) c << " ";
}

打印“97 98 99”。

以下代码

#include <iostream>
int main()
{
    for (char c : "abc")
        std::cout << (int) c << " ";
}

打印“97 98 99 0”。

第二个代码中多余的 0 来自哪里?

【问题讨论】:

  • 这是常量字符串中的空终止符。

标签: c++ string for-loop char


【解决方案1】:

文字"abc"const char[4] 类型:最后一个元素是NUL 终止符(值为0)。

在第二个 sn-p 中,NUL 终止符的值被打印出来,因为代码描述了对整个 const char[4] 数组的迭代。

在第一个 sn-p 中,std::string 类的底层迭代器技术将结束迭代器(在短形式 for 循环中无法到达)设置为 NUL 终止符。此行为与s.size() 一致。

【讨论】:

    【解决方案2】:

    在第一个 sn-p 中,您使用 range based loop 迭代字符串。 std::string 类型有 .begin().end() 迭代器。基于范围的循环使用这些标记范围的开始和结束。

    在第二个 sn-p 中,您使用基于范围的循环来迭代 string literal。字符串文字基本上是一个字符数组,末尾有一个额外的隐藏 \0 字符。该字符可转换为整数值0。因此输出中的额外 0。

    【讨论】:

      【解决方案3】:

      C++ 有两种不同属性的字符串:

      C 字符串和字符串文字

      它们是固定大小的空终止字符数组(最大大小在编译时确定)。 "abc" 称为string literal,您可以将其视为包含{ 'a', 'b', 'c', '\0' } 的字符数组。您的 range-based for loop 正在遍历数组中的 所有 个字符,包括空终止符。在没有空终止的情况下打印数据的 C 方式是:

      char ca[] = "abc";
      
      char *c = ca;
      while (*c)
          std::cout << (int) *(c++) << " ";
      

      请注意,不建议使用这种老式的原始指针摆弄方式 - 这太容易自取其辱。

      C++ 字符串和 C++ 字符串文字

      std::string 提供了一个字符串实现,可以处理任意长度的字符串(内存在运行时动态分配)。 C++ 字符串是具有自己的处理长度方式的对象,不需要空终止。 std::string 类提供了迭代器,使我们能够编写类似的循环

      std::string s = "abc";
      
      // Traditional loop with iterators:
      for (auto i = s.begin(); i != s.end(); i++)
          std::cout << (int) *i << " ";
      
      // Range-based for loop:
      for (char c : s)
          std::cout << (int) c << " ";
      

      C 字符串"abc" 被传递给std::string 的构造函数,该构造函数以其内部格式存储它。

      请注意,C++14 也支持C++ string literals"abc"s(注意末尾的运算符s)。在您的示例中,您可以像这样使用它们:

      using namespace std::string_literals;
      
      for (char c : "abc"s)
          std::cout << (int) c << " ";
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2018-06-25
        • 2017-12-28
        • 1970-01-01
        • 2018-07-07
        • 2010-12-06
        相关资源
        最近更新 更多