【问题标题】:C++ concatenate two unsigned char* [closed]C ++连接两个无符号字符* [关闭]
【发布时间】:2020-11-03 04:35:12
【问题描述】:

我有两个 unsigned char* 并尝试两个连接。这是代码示例。

unsigned char* finaleResult = (unsigned char*)malloc(size);
memcpy(finaleResult, part1, sizeof(part1));
memcpy(finaleResult+sizeof(part1), part2, sizeof(part2));
finaleResult[sizeof(part1) + sizeof(part2)+1] = '\0';
std::cout << "finaleResult: " << finaleResult << std::endl;

我假设在 finaleResult 中看到两个 part1 + part2,但只有 part1。 我的代码有什么问题?

【问题讨论】:

  • 我们看不到 partpart1part2 是如何定义的。请出示minimal reproducible example
  • 请发布更多代码,包括您定义和填充part1, part2 的位置。我怀疑你可能想要strlen 而不是sizeof
  • 请注意,如果part1unsigned char *sizeof(part1) 会给你指针的大小,而不是字符串的大小。如果你想要字符串的长度,使用strlen
  • @NateEldredge strlen 想要一个 char* 参数,而不是 unsigned char*。 C 风格的字符串是纯 char 的数组。如果您想使用以 nul 结尾的 unsigned char 数组,您可以这样做,但标准库不一定有太大帮助。

标签: c++ char memcpy unsigned


【解决方案1】:

如果您使用的是 C++,则无需对类似字符串的数据进行任何手动内存管理以及进行连接等操作。

std::basic_string 模板提供了为您进行连接的函数。您所要做的就是将类型作为模板参数提供给std::basic_string

由于类型为unsigned char,因此使用std::basic_string&lt;unsigned char&gt; 可以直接进行连接:

#include <string>
#include <iostream>

int main()
{
    std::basic_string<unsigned char> part1 = {'a','b','c'};
    std::basic_string<unsigned char> part2 = {'1','2','3'};
    std::basic_string<unsigned char> finaleResult = part1 + part2; // magic
    std::cout << finaleResult.c_str();
}

输出:

abc123

【讨论】:

  • 一旦您尝试使用 0x00-0x7f 范围之外的值,这会变得很有趣... ;-)
  • 是的,我知道。它对打印/输出不友好。但数据就在那里。
  • 实际上,该范围内的字符常量(例如'ß')将完全拒绝编译......因为OP澄清说这意味着数据和打印输出仅用于调试目的,它可能应该是一个vector&lt; unsigned char &gt;,而是以十六进制打印......但这需要更多的澄清。
  • 感谢您的回答。请问一个问题如何正确地将 finaleResult 转换为 unsigned char*?
  • 尝试...to..type..that...character...这些愚蠢的英文键盘。
【解决方案2】:

这段代码有很多问题。

unsigned char * 并不意味着指向 C 字符串。如果您在 C 中使用字符串,则应使用纯 char *unsigned char * 一般被认为是指向原始数据。


字符串

C 中,您将分别使用 strcpystrcat 来复制/连接字符串。确保您的目的地有足够的内存 malloc'ed 以包含连接的字符串以及空终止符。

C++ 中,您不执行上述任何操作。没有malloc,没有memcpystrcpystrcat,也没有指针。你 #include &lt;string&gt; 并使用 std::string 类。

std::string finaleResult{ part1 };
finaleResult += part2;
std::cout << "finaleResult: " << finaleResult << std::endl;

数据

后来您在 cmets 中确认您确实在这里处理原始数据。我们并没有真正看到part1part2size 是什么,所以有一些猜测,但我假设在part1 的某个地方,至少在finalResult[ sizeof( part1 ) ],你得到一个零字节,这使得std::cout 停止输出。

与字符串类似(见上文),在 C++ 中,处理原始数据时不应使用 C 原语(数组、malloc、拥有指针)。

如果您必须使用动态内存分配,请使用std::unique_ptr 获取在销毁时释放内存的智能指针(例如,在抛出异常的情况下)。

但一般来说,使用&lt;vector&gt; 会更好,这可以减轻您手动管理任何资源的负担:

vector< unsigned char > finaleResult { part1, part1 + sizeof part1 };
finaleResult.insert( result.end(), part2, part2 + sizeof part2 );

为了避免嵌入零字节、ASCII-7 范围之外的字符以及通常不应被解释为字符串的数据的有趣业务,请使用十六进制输出:

int elements { 0 };
int const elements_per_line { 4 };

for ( auto && c : finaleResult )
{
    std::cout << std::hex << std::setfill( '0' ) << std::setw( 2 ) << static_cast< int >( c ) << " ";

    if ( ( ++elements % elements_per_line ) == 0 )
    {
        std::cout << std::endl;
        elements = 0;
    }
}

【讨论】:

  • 答案的任何一部分虽然是正确的,但却无法回答观察到的行为的根本原因。
  • @SergeyA:观察到的行为的根本原因是 OP 在 C++ 程序中使用了 C 字符串,并且错误地使用了 C 字符串。解决方案 &lt;string&gt;.
  • 从表面上看,您似乎做出的假设似乎与问题文本无关。例如,问题中没有任何内容告诉我们 OP 真的想要使用标准 C 字符串。也许数据最好用unsigned char 表示?
  • @SergeyA:如果数据“最好用unsigned char 表示”,则它不是字符串。
  • 是的,我没有看到 OP 声称它是问题文本中任何地方的字符串。
猜你喜欢
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
相关资源
最近更新 更多