字符串末尾的额外零字符出现在 C++ 中用于范围循环

Posted

技术标签:

【中文标题】字符串末尾的额外零字符出现在 C++ 中用于范围循环【英文标题】:Extra zero char at end of string appears in C++ for range loop 【发布时间】: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 来自哪里?

【问题讨论】:

这是常量字符串中的空终止符。 【参考方案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 << " ";

【讨论】:

以上是关于字符串末尾的额外零字符出现在 C++ 中用于范围循环的主要内容,如果未能解决你的问题,请参考以下文章

将字符串转换为 byte[] 创建零字符

java 16进制字符串怎么转换成10进制字符串

mysql匹配模式

华为机试真题 C++ 实现数字字符串组合倒序

替换文本末尾的额外字符

循环链表并在C中的末尾函数插入