【问题标题】:std::string to char*std::string 到 char*
【发布时间】:2011-11-13 04:55:13
【问题描述】:

我想将 std::string 转换为 char*char[] 数据类型。

std::string str = "string";
char* chr = str;

导致:“错误:无法将‘std::string’转换为‘char’...”.

有哪些方法可以做到这一点?

【问题讨论】:

标签: c++ string char


【解决方案1】:

它不会自动转换(谢天谢地)。您必须使用方法c_str() 来获取C 字符串版本。

std::string str = "string";
const char *cstr = str.c_str();

注意它返回一个const char *;您不能更改 c_str() 返回的 C 风格字符串。如果你想处理它,你必须先复制它:

std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;

或者在现代 C++ 中:

std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);

【讨论】:

  • @Kerrek SB:这是一个示例,将在实际代码中使用智能指针,或者更可能完全避免这种 c_str 疯狂。
  • 答案是庞大、不优雅、非本地、使用原始数组,并且需要注意异常安全。 vector 正是作为动态数组的包装器而发明的,因此不使用它充其量似乎是错失良机,最坏的情况是违反了 C++ 的精神。
  • 首先,是的,答案很庞大。首先我解释了 OP 的错误(认为std::string 会自动转换),然后我用一个简短的代码示例解释他应该使用什么。向前思考我还解释了使用此函数的一些副作用,其中一个是您可能无法编辑c_str()返回的字符串。您错误地将我的简短示例视为真正解决问题的代码,但事实并非如此。
  • 我对答案投了反对票。这个答案确实没有用,而且它被接受的事实是最不幸的。这个答案完全无视良好的 C++ 编程实践和异常安全性,并且有很多更好的解决方案,其中一些在这个问题的其他答案中给出(例如,ildjarn 给出的答案使用std::vector&lt;char&gt;)。
  • @james-mcnellis,我选择了这个答案作为正确答案,因为它完全回答了我的要求......不多也不少。我没有要求你认为我应该做什么,我没有要求你认为我正在做的事情有不同的解决方案,我没有要求好的做法。你不知道我在做什么,我的代码将在哪里实现以及在什么条件下实现。有些人应该学习阅读、理解问题并回答实际提出的问题。没必要在这里炫耀。
【解决方案2】:

假设您只需要一个 C 风格的字符串作为输入传递:

std::string str = "string";
const char* chr = str.c_str();

【讨论】:

    【解决方案3】:
    • 如果你只想要一个代表相同内容的 C 风格字符串:

      char const* ca = str.c_str();
      
    • 如果你想要一个带有 new 内容的 C 风格字符串,一种方法(假设你在编译时不知道字符串大小)是动态分配:

      char* ca = new char[str.size()+1];
      std::copy(str.begin(), str.end(), ca);
      ca[str.size()] = '\0';
      

      以后别忘了delete[]

    • 如果您想要一个静态分配的、长度有限的数组:

      size_t const MAX = 80; // maximum number of chars
      char ca[MAX] = {};
      std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);
      

    std::string 不会隐式转换为这些类型,原因很简单,需要这样做通常是一种设计味道。确保您真的需要它。

    如果你肯定需要char*最好的方法可能是:

    vector<char> v(str.begin(), str.end());
    char* ca = &v[0]; // pointer to start of vector
    

    【讨论】:

    • 为什么是&amp;str.front(), &amp;str.back()(C++03 中不存在)而不是更常见的str.begin()str.end()
    • str.begin(),甚至std::begin(str),类似迭代器呢?我不相信string 有任何义务像vector 那样在连续的记忆中,或者有吗?
    • @xtofl:我已经在其中编辑了这些内容。是的,从 C++11 开始就有义务;这在 C++03 中是隐含的。
    • @xtofl:不在 C++03 中。在 C++11 中,我们有这样的保证,以及 front() 和 back() 函数,它们在原始答案中被滥用
    • @Tomalak:它们被滥用了,因为你需要&amp;back() + 1,而不是&amp;back()
    【解决方案4】:

    (此答案仅适用于 C++98。)

    请不要使用原始的char*

    std::string str = "string";
    std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
    // use &chars[0] as a char*
    

    【讨论】:

    • 我今天早些时候实际上只是需要这样的东西。我想知道,可以说vector&lt;char&gt;(str.c_str(), str.c_str() + str.size() + 1),而不将 char 指针分配给临时对象吗?
    • @Kerrek :是的,std::basic_string&lt;&gt;::c_str() 的返回值一直有效,直到 string 被更改或销毁。这也意味着只要 string 未被修改,它就会在后续调用中返回相同的值。
    • @friendzis :以这种方式使用vector 没有速度或空间开销。如果要在没有 RAII 机制(即使用原始指针)的情况下编写异常安全代码,则代码复杂度将远高于这种简单的单行代码。
    • vector 具有大量开销和复杂性是一个神话。如果您的要求是您有一个 mutable 字符数组,那么实际上字符向量几乎是理想的 C++ 包装器。如果您的要求实际上只需要一个 const-char 指针,那么只需使用 c_str() 就可以了。
    • @ildjarn:实际上,it basically was.
    【解决方案5】:

    严格来说,您不能“将 std::string 转换为 char* 或 char[] 数据类型”。

    正如其他答案所示,您可以将 std::string 的内容复制到 char 数组,或将 const char* 制作为 std::string 的内容,以便您可以在 " C 风格”。

    如果您尝试更改 std::string 的内容,std::string 类型具有执行您可能需要对其执行的任何操作的所有方法。

    如果你试图将它传递给某个接受 char* 的函数,则有 std::string::c_str()。

    【讨论】:

      【解决方案6】:

      如果我需要一个 c++ 字符串内容的可变原始副本,那么我会这样做:

      std::string str = "string";
      char* chr = strdup(str.c_str());
      

      及以后:

      free(chr); 
      

      那么我为什么不像其他人一样摆弄 std::vector 或 new[] 呢?因为 当我需要一个可变的 C 风格的原始 char* 字符串时,然后因为我想调用 C 代码来更改字符串,而 C 代码使用 free() 释放东西并使用 malloc() 分配(strdup 使用 malloc)。因此,如果我将原始字符串传递给某个函数 X 用 C 编写,它 可能 对其参数有一个约束,它必须在堆上分配(例如,如果函数可能想在参数上调用 realloc)。但它极不可能期望分配有(某些用户重新定义的)new[] 的参数!

      【讨论】:

      • 你应该解释strdup来自哪里。
      【解决方案7】:

      More details herehere 但你可以使用

      string str = "some string" ;
      char *cstr = &str[0];
      

      从 C++11 开始,您还可以使用 str.data() 成员函数,它返回 char *

      string str = "some string" ;
      char *cstr = str.data();
      

      【讨论】:

      • FWIW,在我的书中,这是对实际提出的问题的唯一正确答案。 std::string 本质上是可变的:那些听起来像是修改字符串内容的人似乎是魔鬼的工作似乎错过了这个事实。
      • 是的,这是正确的答案。愚蠢的是,考虑到使用频率,没有标准的方法可以做到这一点,比如 msoft 的 lockbuffer。
      • 我把 0 改成了 0u。因为一些编译器/库会(信不信由你)抱怨在 &str[0] 构造一直打开警告时会出现一些歧义
      • 请注意,这只是 C++11。以前的版本可能没有连续存储或缺少终止的 null
      • 这是唯一对我有用的,出于某种原因c_str() 一直停在我的空字节处,即使我的读数似乎表明它不应该。也许我在其他地方做错了什么,但是用这个(甚至 &str.first())交换 c_str() 效果很好
      【解决方案8】:

      为了完整起见,不要忘记std::string::copy()

      std::string str = "string";
      const size_t MAX = 80;
      char chrs[MAX];
      
      str.copy(chrs, MAX);
      

      std::string::copy() 不会 NUL 终止。如果您需要确保在 C 字符串函数中使用 NUL 终止符:

      std::string str = "string";
      const size_t MAX = 80;
      char chrs[MAX];
      
      memset(chrs, '\0', MAX);
      str.copy(chrs, MAX-1);
      

      【讨论】:

        【解决方案9】:

        这也可以

        std::string s;
        std::cout<<"Enter the String";
        std::getline(std::cin, s);
        char *a=new char[s.size()+1];
        a[s.size()]=0;
        memcpy(a,s.c_str(),s.size());
        std::cout<<a;  
        

        【讨论】:

          【解决方案10】:
          char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
          

          【讨论】:

            【解决方案11】:

            或者,您可以使用向量来获得可写的 char*,如下所示;

            //this handles memory manipulations and is more convenient
            string str;
            vector <char> writable (str.begin (), str.end) ;
            writable .push_back ('\0'); 
            char* cstring = &writable[0] //or &*writable.begin () 
            
            //Goodluck  
            

            【讨论】:

            • 这将为向量分配新内存,然后复制每个字符。 std::string 已经是一个容器,您不妨 push_back(0) 到您的字符串并执行 &str[0]
            【解决方案12】:

            这是来自Protocol Buffer 的更强大的版本

            char* string_as_array(string* str)
            {
                return str->empty() ? NULL : &*str->begin();
            }
            
            // test codes
            std::string mystr("you are here");
            char* pstr = string_as_array(&mystr);
            cout << pstr << endl; // you are here
            

            【讨论】:

            • +1 用于检查字符串是否为空。我还将添加一个检查以确保字符串以零结尾:if (str[str.length()-1] != 0) str.push_back(0)
            【解决方案13】:

            你可以使用迭代器来实现它。

            std::string str = "string";
            std::string::iterator p=str.begin();
            char* chr = &(*p);
            

            祝你好运。

            【讨论】:

              【解决方案14】:

              使用 unique_ptr 的 orlp 的 char* 答案的安全版本:

              std::string str = "string";
              auto cstr = std::make_unique<char[]>(str.length() + 1);
              strcpy(cstr.get(), str.c_str());
              

              【讨论】:

                【解决方案15】:

                作为对 bobobobo 答案的评论会更好,但我没有代表。它完成了同样的事情,但有更好的做法。

                虽然其他答案很有用,但如果您需要在没有 const 的情况下将 std::string 显式转换为 char*const_cast 是您的朋友。

                std::string str = "string";
                char* chr = const_cast<char*>(str.c_str());
                

                请注意,这不会为您提供数据的副本;它会给你一个指向字符串的指针。因此,如果您修改chr 的元素,您将修改str

                【讨论】:

                  【解决方案16】:

                  OOP 风格的转换

                  converter.hpp

                  class StringConverter {
                      public: static char * strToChar(std::string str);
                  };
                  

                  converter.cpp

                  char * StringConverter::strToChar(std::string str)
                  {
                      return (char*)str.c_str();
                  }
                  

                  用法

                  StringConverter::strToChar("converted string")
                  

                  【讨论】:

                  • 我喜欢强制转换为 char* 消除 c_str 输出中的 const,我认为 c_str 返回 const char* 的原因是通过提供只读版本的事物。 OP想要一个char *,但我认为c_str的const char *输出可能会更好地为他服务,因为这样更安全,并且采用char *的函数通常也采用const char *(假设函数不做任何事情,比如改变他们的输入,一般来说,他们不应该这样做)。
                  【解决方案17】:

                  要从std::string 获取const char *,请使用c_str() 成员函数:

                  std::string str = "string";
                  const char* chr = str.c_str();
                  

                  要从std::string 中获取非常量char *,您可以使用data() 成员函数,它从C++17 开始返回非常量指针:

                  std::string str = "string";
                  char* chr = str.data();
                  

                  对于旧版本的语言,您可以使用范围构造将字符串复制到可以从中获取非常量指针的向量中:

                  std::string str = "string";
                  std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
                  char* chr = str_copy.data();
                  

                  但请注意,这不会让您修改包含在str 中的字符串,只能通过这种方式更改副本的数据。请注意,在旧版本的语言中,在此处使用 c_str() 特别重要,因为当时 std::string 在调用 c_str() 之前不能保证为空终止。

                  【讨论】:

                    【解决方案18】:

                    没有人提到过 sprintf?

                    std::string s;
                    char * c;
                    sprintf(c, "%s", s.c_str());
                    

                    【讨论】:

                    • 按原样,这将导致分段错误。在调用 sprintf 之前,您需要在堆栈或堆上为 char 数组分配内存。最简单的做法是使用字符串的长度来决定 char 数组的大小。
                    猜你喜欢
                    • 2011-10-26
                    • 2017-08-22
                    • 2010-10-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-06-09
                    相关资源
                    最近更新 更多