【问题标题】:convert a char* to std::string将 char* 转换为 std::string
【发布时间】:2010-11-14 19:19:10
【问题描述】:

我需要使用std::string 来存储fgets() 检索到的数据。为此,我需要将 char* 返回值从 fgets() 转换为 std::string 以存储在数组中。如何做到这一点?

【问题讨论】:

    标签: c++ stdstring


    【解决方案1】:

    从 C 风格字符串转换为 C++ 标准字符串更容易

    我们可以通过三种方式将 C 风格字符串转换为 C++ 标准字符串

    第一个是使用构造函数,

    char chText[20] = "I am a Programmer";
    // using constructor
    string text(chText);
    

    第二种是使用string::assign方法

    // char string
    char chText[20] = "I am a Programmer";
    
    // c++ string
    string text;
    
    // convertion from char string to c++ string
    // using assign function
    text.assign(chText);
    

    第三个是赋值运算符(=),其中字符串类使用运算符重载

    // char string
    char chText[20] = "I am a Programmer";
    
    // c++ string
    // convertion from char string to c++ string using assignment operator overloading
    string text = chText;
    

    第三个也可以写成下面这样-

    // char string
    char chText[20] = "I am a Programmer";
    
    // c++ string
    string text;
    
    
    // convertion from char string to c++ string
    text = chText;
    

    第三个比较简单,两种情况都可以使用

    1. 在我们声明和初始化时
    2. 当我们在对象创建或初始化后多次分配时

    【讨论】:

      【解决方案2】:

      std::string 有一个构造函数:

      const char *s = "Hello, World!";
      std::string str(s);
      

      请注意,此构造深度复制ss 处的字符列表不应为nullptr,否则行为未定义。

      【讨论】:

      • 如果是会发生什么?
      • 标准规定构造函数参数“不应是空指针”——它没有指定抛出任何异常。
      • 是浅拷贝还是深拷贝?
      • @pushkin No str 只是一个变量名。可以是任何东西:SabclIstrHelloWorld。显然,有些选择比其他选择更好。但是对于这个例子str 是完全可以接受的。
      • @Madhatter 这是一个深拷贝。指针分配将保留,字符串将自己进行新分配。
      【解决方案3】:

      我想提一个使用用户定义文字s 的新方法。这不是新的,但它会更常见,因为它是在 C++14 标准库中添加的。

      一般情况下是多余的:

      string mystring = "your string here"s;
      

      但它允许您使用自动,也可以使用宽字符串:

      auto mystring = U"your UTF-32 string here"s;
      

      这就是它真正闪耀的地方:

      string suffix;
      cin >> suffix;
      string mystring = "mystring"s + suffix;
      

      【讨论】:

        【解决方案4】:

        通过构造函数传入:

        const char* dat = "my string!";
        std::string my_string( dat );
        

        你可以使用函数 string.c_str() 去另一种方式:

        std::string my_string("testing!");
        const char* dat = my_string.c_str();
        

        【讨论】:

        • c_str() 返回const char*
        • 对,您不能(不应该)通过 c_str() 修改 std::string 中的数据。如果您打算更改数据,则 c_str() 中的 c 字符串应该是 memcpy'd
        【解决方案5】:

        大多数答案都是关于构造std::string

        如果已经构造,只需使用赋值运算符

        std::string oString;
        char* pStr;
        
        ... // Here allocate and get character string (e.g. using fgets as you mentioned)
        
        oString = pStr; // This is it! It copies contents from pStr to oString
        

        【讨论】:

          【解决方案6】:

          我一直在努力使用 MSVC2005 来使用 std::string(char*) 构造函数,就像最受好评的答案一样。当我看到这个变体在始终受信任的 http://en.cppreference.com/w/cpp/string/basic_string/basic_string 上列为 #4 时,我认为即使是旧的编译器也能提供这个。

          我花了很长时间才意识到这个构造函数绝对拒绝与(unsigned char*) 作为参数匹配!我收到了这些关于无法与std::string 参数类型匹配的令人费解的错误消息,这绝对不是我的目标。只需使用std::string((char*)ucharPtr) 进行论证就解决了我的问题...呵呵!

          【讨论】:

            【解决方案7】:
            char* data;
            stringstream myStreamString;
            myStreamString << data;
            string myString = myStreamString.str();
            cout << myString << endl;
            

            【讨论】:

              【解决方案8】:

              不知道为什么除了 Erik 之外没有人提到这一点,但根据 this page,赋值运算符工作得很好。无需使用构造函数、.assign() 或 .append()。

              std::string mystring;
              mystring = "This is a test!";   // Assign C string to std:string directly
              std::cout << mystring << '\n';
              

              【讨论】:

              • 它似乎在功能上工作,但是当我这样做时,我开始遇到 Valgrind 在程序结束时报告可达块的问题,源自=(和@ 987654325@)。像这样的文字似乎不会发生这种情况,而只是 char* 的事情。此类报告是否实际上泄漏的问题是discussed here。但是,如果我将分配更改为destString = std::string(srcCharPtr);,valgrind 泄漏报告就消失了。 YMMV。
              • HostileFork 的评论可能会让您相信从 char* 构造字符串(如从 fgets)将使 std::string 管理此内存的生命周期。然而,这种情况并非如此。请参阅标准 21.4.2.7 和 .9 Constructs an object of class basic_string and determines its initial string value from the array。它说的是价值,而没有关于缓冲区或指针所有权。
              【解决方案9】:
              const char* charPointer = "Hello, World!\n";
              std::string strFromChar;
              strFromChar.append(charPointer);
              std::cout<<strFromChar<<std::endl;
              

              【讨论】:

                【解决方案10】:

                如果您已经知道 char* 的大小,请改用它

                char* data = ...;
                int size = ...;
                std::string myString(data, size);
                

                这不使用 strlen。

                编辑:如果字符串变量已经存在,使用assign():

                std::string myString;
                char* data = ...;
                int size = ...;
                myString.assign(data, size);
                

                【讨论】:

                • 有点问题,尤金。如果 data 直到在例程的后期才被填充,那么你如何初始化 myString 呢?您是否只是在填充 myString 变量时声明它?
                • int size = strlen(data);
                • @vlad:这个想法是您知道来自其他来源的大小和/或数据不是 C 字符串(嵌入了空值或不以空值结尾)。如果你有一个 C 字符串,你可以简单地做 myString = data;它将为您运行 strlen 或等效项。
                • @huseyintugrulbuyukisik 你仍然需要正确处理原始内存——std::string 将复制字节,它不占用所有权。
                • @ZackLee 它将为字节分配新内存并将它们全部复制到那里,尽可能深。如果你想要浅拷贝的潜力,你需要将一个 std::string 复制到另一个。然后我认为一些实现可以做一个浅拷贝。
                【解决方案11】:

                我需要使用 std::string 来存储 fgets() 检索到的数据。

                为什么在编写 C++ 时使用fgets()?为什么不std::getline()

                【讨论】:

                  【解决方案12】:
                  char* data;
                  std::string myString(data);
                  

                  【讨论】:

                  • 这将导致未定义的行为。
                  • 只有这两行,data 保持未初始化(空)。
                  • 如果没有提供真正的“长度”指针,此代码可能会导致数据丢失,您的 std::string 将比原始字符“更短” *
                  • data保持未初始化可能会导致std::string读取垃圾数据
                  猜你喜欢
                  • 2013-07-18
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-06-10
                  • 2011-08-02
                  • 2014-07-23
                  • 2013-09-10
                  • 2012-10-31
                  • 2012-09-03
                  相关资源
                  最近更新 更多