将const unsigned char*转换为std::string

58

sqlite3_column_text返回一个const unsigned char*类型的值,我该如何将其转换为std::string类型?我尝试使用std::string()函数,但出现了错误。

代码:

temp_doc.uuid = std::string(sqlite3_column_text(this->stmts.read_documents, 0));
错误:
1>.\storage_manager.cpp(109) : error C2440: '<function-style-cast>' : cannot convert from 'const unsigned char *' to 'std::string'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
9个回答

75
你可以尝试:

你可以尝试:

temp_doc.uuid = std::string(reinterpret_cast<const char*>(
      sqlite3_column_text(this->stmts.read_documents, 0)
  ));

std::string没有一个可以接受const unsigned char*参数的构造函数。

为什么没有呢?你可以查看这个有点相关的问题:为什么C++流使用char而不是unsigned char?


2
虽然我认为你应该在尖括号内使用 "const char *"。你不想试图去除 const 属性(它甚至可能不允许)。 - rmeador
我遇到了这个错误: 1>.\storage_manager.cpp(109) : error C2440: 'static_cast' : 无法将 'const unsigned char *' 转换为 'const char *' 1> 所指向的类型不相关;转换需要reinterpret_cast、C风格转换或函数风格转换。 - LM.
哎呀,也许你需要使用reinterpret_cast而不是static_cast? - Reunanen
既然我相当确定它会起作用,我也会编辑答案。 - Reunanen
你是指使用reinterpret_cast而不是static_cast吗?请参考:https://dev59.com/N3RB5IYBdhLWcg3wn4UL - Reunanen

21

如果您确实需要一个无符号字符的字符串,您可以创建自己的类型:

typedef std::basic_string <unsigned char> ustring;

你应该能够像这样说:
ustring s = sqlite3_column_text(this->stmts.read_documents, 0);

20

人们通常使用(unsigned char*)类型来表示数据是二进制而不是普通的ASCII文本。我知道libxml这样做,看起来sqlite也是这么做的。

从sqlite调用返回的数据可能是UTF-8编码的Unicode文本。虽然reinterpret_cast可能看起来可以工作,但如果有人在字段中存储了非普通ASCII文本,则您的程序可能无法正常运行。

std::string类并没有考虑Unicode,因此如果您要求字符串的长度(length()),您将得到字节数,而在UTF-8中,这不一定意味着字符数。

简短回答:如果您确定数据只是ASCII,那么简单的强制转换可能会起作用。 如果它可以是任何UTF-8数据,则需要以更智能的方式处理编码/解码。


1
有没有使用std::库完成这个的方法? - LM.
我不知道。标准方法是使用第三方库,例如:http://site.icu-project.org/ - Mike Mueller

4

我不熟悉sqlite3_column_text,但你可能想做的一件事是在调用std:string构造函数时,需要将其转换为(const char*)。我相信它应该有一个适用于该类型的构造函数。

然而,这个sqlite函数返回unsigned char*比较奇怪,它是否返回Pascal字符串(第一个字符是字符串的长度)?如果是这样,那么你将不得不使用字节和长度创建std::string。


不,它们是以空字符结尾的。 - Navin

3
如果temp_doc.uuid是std::string类型,请尝试以下操作:
temp_doc.uuid = static_cast<const char*>(sqlite3_column_text(this->stmts.read_documents, 0));

这是一个std::string,尝试使用您的方法后我得到了以下错误:1>.\storage_manager.cpp(109) : error C2440: 'static_cast' : 无法将类型为 'const unsigned char *' 的值转换为类型为 'const char *' 的值 1> 所指向的类型不相关;转换需要reinterpret_cast、C风格转换或函数风格转换。 - LM.

3

尝试:

temp_doc.uuid = std::string(reinterpret_cast<const char*>(sqlite3_column_text(this->stmts.read_documents, 0)));

我看到有人已经发布了答案,但在此之前我已经开始写这个答案了(正在VS中检查答案是否正确)。 - user88637
我只是说一下这个,这样我才不会认为自己抄答案。 - user88637
我只是这样说,这样你就不会认为我在抄答案。 - user88637
const char* 和 const unsigned char* 不是同一种类型。字符串构造函数需要 const char*,因此需要进行强制转换。 - user88637

2
我并不是专家,但这个示例看起来简单得多:

string name = (const char*) (sqlite3_column_text(res, 0));

不要在C++中使用C cast,这是一种不好的做法。reinterpret_cast会更清晰地显示您的意图。 - Jean

2

你不能直接使用const unsigned char*来构造一个std::string -- 你需要先将其强制转换为const char*:

temp_doc.uuid = std::string( reinterpret_cast< const char* >(
  sqlite3_column_text(this->stmts.read_documents, 0) ) );

抱歉,必须使用reinterpret_cast而不是static_cast。 - Kasprzol

1

一个古老但重要的问题,如果你需要在unsigned char序列中保留完整信息。在我看来,使用reinterpret_cast并不是最佳选择。我在将字符串转换为��量下找到了一个有趣的解决方案,我进行了修改。

basic_string<unsigned char> temp = sqlite3_column_text(stmt, 0);
string firstItem( temp.begin(), temp.end() );

由于我正在使用gtkmm进行编程,因此您可以通过以下方式将其转换为Glib::ustring

basic_string<unsigned char> temp = sqlite3_column_text(stmt, 0);
Glib::ustring firstItem = string( temp.begin(), temp.end() );

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