字符数组转换为无符号8位整数数组

4
这是C/C++中我不擅长的一个领域。
我的问题在于,我有一个字符串最终需要包含一些空字符。把所有东西都视为char数组(或字符串)是行不通的,因为当查找到第一个空值时,事情往往会出错。所以我想,好吧,我会切换到uint8_t,这样所有东西就只是一个数字。我可以根据需要移动它们,然后在准备好之后将其强制转换回char。
我当前的主要问题是:如何将字符串的一部分复制到uint8_t缓冲区中?
实际上,我想做的事情类似于:
std::string s = "abcdefghi";
uint8_t *val = (uint8_t*)malloc(s.length() + 1);
memset(val, 0, s.length() + 1);

// Assume offset is just some number
memcpy(val + offset, s.substr(1, 5).c_str(), 5);

显然,当我尝试这样做时会出现错误。在memcpy的第一个参数中可能有一些诡计(我看到一些像(*(uint8_t*))这样的东西在线上,但不知道那是什么意思)。
请问该怎么办呢?
另外,我想知道如何轻松地将其转换回char数组?只需将uint8_t指针静态转换为char指针吗?
非常感谢。

5
std::string 完全可以包含 '\0' 字符,除非你在使用 C 串操作函数或其他只接受没有长度的 char* 的 API。但是,那些 API 对于包含嵌入 null 字符的字符串也无法正常工作。 - Nicol Bolas
阅读了你的留言后,我开始四处寻找。std::string 可能会起作用。我将进行一些测试。只要远离 c_str,看起来我就没问题了。我仍然想知道上面的问题的答案,只是出于好奇。 - jasonmclose
类似 (*(uint8_t*)) 这样的东西通常是将数据类型转换为更抽象的类型,然后进行一次合法的强制转换,但在此之前它并不合法,最后再将其转换回去。例如,在转换函数指针时经常使用它,比如 (DWORD)(*(void**))(void(*)(int))(大概是这样,我有一段时间没用过了)。仅供参考 :) - ssube
1
“当我尝试这样做时,显然会出现错误。” 不要让我们猜测,你收到了什么错误信息? - Robᵩ
你有多个错误的基本假设。因此很难回答你的问题。char 数组与 std::string 对象一样完全能够容纳空字符。而且,uint8_t 所做的并没有 char 做得不好。请向我们展示您尝试过什么,我们将告诉您哪里出了问题。您能否创建一个10行的程序,演示您遇到的问题?请查看http://sscce.org/。 - Robᵩ
这就是为什么我喜欢StackOverflow。所以在阅读了您的评论、其他一些内容并尝试了一些东西之后,我可以说我的理解完全错误了。不幸的是,我打印字符串的方式是其中的一部分,因为我的空值没有被打印出来,这让我认为有些东西出了问题。其实没有问题;只是空值没有被打印出来。我能够使用std::string做到我想做的一切。感谢您的启发。 - jasonmclose
2个回答

1
我想,好吧,我会切换到uint8_t,这样一切都只是一个数字。
这并不意味着查找'\0'的算法会突然停止查找,也不意味着使用char的算法必须注意'\0'。用空字符表示结尾是C字符串的约定,而不是char数组。uint8_t可能只是char的typedef。
正如Nicol Bolas所指出的那样,std::string已经能够存储包含空字符的字符串,而不需要特殊处理空字符。
至于你的问题,我不确定你指的是什么错误,因为以下代码可以正常工作:
#include <iostream>
#include <string>
#include <cstdint>
#include <cstring>

int main() {
    std::string s = "abcdefghi";
    std::uint8_t *val = (std::uint8_t*)std::malloc(s.length() + 1);
    std::memset(val, 0, s.length() + 1);

    int offset = 2;
    std::memcpy(val + offset, s.substr(1, 5).c_str(), 5);
    std::cout << (val+offset) << '\n';
}

memcpy函数从字符串s中取第二个到第六个字符,并将它们复制到val中。cout语句输出"bcdef"。

当然,这是C++语言,如果你想手动分配一些内存并将其清零,可以这样做:

std::unique_ptr<uint8_t[]> val(new uint8_t[s.length()+1]());

或者使用向量:

std::vector<uint8_t> val(s.length()+1,0);

要从uint8_t数组中转换,您可以(但通常不应该)执行以下操作:
char *c = reinterpret_cast<uint8_t*>(val);

0

嗯,代码可以正常工作,它会复制val中的子字符串。但是,在偏移位置之前,所有位置上都将有0。

例如,对于偏移量为2,val将为{0,0,b,c,d,e,f,0,0,0}。

如果打印此内容,将什么也不会显示,因为字符串在第一个位置上以null结尾(我想这就是你谈论的错误...)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接