将字节序列转换为字符串表示形式的 C++ 函数会导致垃圾输出

问题描述 投票:0回答:1

我编写了多个简单的 C++ 函数来将字节序列转换为字符串表示形式。

这非常简单,我确信我的逻辑是正确的,我认为这非常简单,直到我开始打印字符串,我发现输出是垃圾:

#include <iostream>
#include <string>
#include <vector>

using std::vector;
typedef vector<uint8_t> bytes;
using std::string;
using std::cout;
using namespace std::literals;

string DIGITS = "0123456789abcdef"s;

static inline string hexlify(bytes arr) {
    string repr = ""s;
    for (auto& chr : arr) {
        repr += " " + DIGITS[(chr & 240) >> 4] + DIGITS[chr & 15];
    }
    repr.erase(0, 1);
    return repr;
}

bytes text = {
    84, 111, 32, 98, 101, 32,
    111, 114, 32, 110, 111, 116,
    32, 116, 111, 32, 98, 101
}; // To be or not to be

int main() {
    cout << hexlify(text);
}
2♠
÷82♠
÷82♠
÷82♠
÷

为什么会出现这种情况?

我知道我的逻辑是对的,以下是Python的直接翻译:

digits = "0123456789abcdef"
def bytes_string(data):
    s = ""
    for i in data:
        s += " " + digits[(i & 240) >> 4] + digits[i & 15]
    return s[1:]

它有效:

>>> bytes_string(b"To be or not to be")
'54 6f 20 62 65 20 6f 72 20 6e 6f 74 20 74 6f 20 62 65'

但是为什么它在 C++ 中不起作用?

我使用的是 Visual Studio 2022 V17.9.7,编译器标志:

/permissive- /ifcOutput "hexlify_test\x64\Release\" /GS /GL /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"hexlify_test\x64\Release\vc143.pdb" /Zc:inline /fp:precise /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /std:c17 /Gd /Oi /MD /std:c++20 /FC /Fa"hexlify_test\x64\Release\" /EHsc /nologo /Fo"hexlify_test\x64\Release\" /Ot /Fp"hexlify_test\x64\Release\hexlify_test.pch" /diagnostics:column 
c++ string type-conversion c++20
1个回答
0
投票

正如评论中所指出的(也这里),这里的问题在于字符串连接或周围。以下代码不进行串联:

" " + DIGITS[(chr & 240) >> 4]

当您从字符串

DIGTS
中提取字符时,它具有类型
char
— 单个字符的专用类型。由于历史原因(与 C 兼容),
+
运算符将字符串文字
" "
解释为指针,将数字字符解释为整数,并执行一些无用的指针运算。

要进行串联,请使用

std::string
类型的字符串文字,就像您在代码中其他地方所做的那样:

" "s + DIGITS[(chr & 240) >> 4]

在这里,

operator+
遇到了正确的类型
std::string
char
,所以它可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.