【问题标题】:const unsigned char * to std::stringconst unsigned char * 到 std::string
【发布时间】:2010-10-22 16:37:15
【问题描述】:

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

【问题讨论】:

    标签: c++ std


    【解决方案1】:

    一个古老但重要的问题,如果您必须保留 unsigned char 序列中的完整信息。在我看来,reinterpret_cast 并非如此。我在converting string to vector 下找到了一个有趣的解决方案 我修改为

    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() );
    

    【讨论】:

      【解决方案2】:

      我不是专家,但这里的示例似乎要简单得多:

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

      【讨论】:

      • 不要在 C++ 中使用 C cast,这是一种不好的做法。 reinterpret_cast 会更清楚地表明您的意图。
      【解决方案3】:

      人们通常使用 (unsigned char *) 类型的原因是表明数据是二进制而不是纯 ASCII 文本。我知道 libxml 是这样做的,从外观上看,sqlite 也在做同样的事情。

      您从 sqlite 调用返回的数据可能是 UTF-8 编码的 Unicode 文本。虽然 reinterpret_cast 可能看起来有效,但如果有人在非纯 ASCII 字段中存储文本,您的程序可能不会表现良好。

      std::string 类在设计时并未考虑到 Unicode,因此如果您询问字符串的 length(),您将获得字节数,在 UTF-8 中,不一定与字符数相同。

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

      【讨论】:

      • 有没有办法用 std:: 库做到这一点?
      • 我不知道。标准方法是使用 3rd 方库,例如:site.icu-project.org
      【解决方案4】:

      如果你真的想要一串无符号字符,你可以创建自己的类型:

      typedef std::basic_string <unsigned char> ustring;
      

      然后你应该可以说:

      ustring s = sqlite3_column_text(this->stmts.read_documents, 0);
      

      【讨论】:

        【解决方案5】:

        您不能从 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。
        【解决方案6】:

        尝试:

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

        【讨论】:

        • 我看到有人已经发布了答案,我在另一个发布之前开始写这个答案(正在检查答案在VS中是否正确)
        • 我只是这么说,所以我不会认为我复制答案
        • 我只是这么说,所以你不会认为我复制答案
        • const char* 和 const unsigned char* 不是同一类型。字符串构造函数期望 const char* ,因此需要强制转换
        【解决方案7】:

        你可以试试:

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

        虽然std::string 可以有一个接受const unsigned char* 的构造函数,但显然它没有。

        那为什么不呢?你可以看看这个有点相关的问题:Why do C++ streams use char instead of unsigned char?

        【讨论】:

        • +1。不过,我认为您应该在尖括号内添加“const char *”。你不想试图抛弃 const-ness(它甚至可能不允许)。
        • 我收到此错误:1>.\storage_manager.cpp(109):错误 C2440:“static_cast”:无法从“const unsigned char *”转换为“const char *”1> 指向的类型不相关;转换需要 reinterpret_cast、C-style cast 或 function-style cast
        • 呃-哦。那么,也许你需要 reinterpret_cast 而不是 static_cast?
        • 既然我很确定它会起作用,我也会编辑答案。
        • 您的意思是 reinterpret_cast 而不是 static_cast?见:*.com/questions/573294/when-to-use-reinterpretcast
        【解决方案8】:

        如果 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' : cannot convert from 'const unsigned char * ' to 'const char *' 1> 指向的类型是不相关的;转换需要 reinterpret_cast、C-style cast 或 function-style cast
        【解决方案9】:

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

        然而,奇怪的是这个 sqlite 函数返回一个无符号字符*,它返回一个 Pascal 字符串(第一个字符是字符串的长度)吗?如果是这样,那么您必须使用字节和长度创建 std::string。

        【讨论】:

        • 不,它们是空终止的。