【问题标题】:how to copy char * into a string and vice-versa如何将 char * 复制到字符串中,反之亦然
【发布时间】:2011-02-03 13:51:13
【问题描述】:

如果我将 char * 传递给函数。然后我想将该 char * 转换为 std::string ,一旦我得到结果,将其从 std::string 转换回 char * 以显示结果。

  1. 我不知道如何进行转换(我说的不是 const char *,只是 char *)
  2. 我不知道如何操作我发送的指针的值。

所以我需要做的步骤

  1. 接受一个字符 *
  2. 将其转换为字符串。
  3. 获取该字符串的结果并将其以 char * 的形式放回
  4. 返回结果,以便该值在函数外部可用且不会被破坏。

如果可能的话,我可以看看它是如何通过引用和指针来完成的(我通过值传递其地址,但是我仍然可以修改指针指向的值。所以即使指针地址的副本在函数被破坏了,我仍然在外面看到改变的值。

谢谢!

【问题讨论】:

  • "将其从 std::string 转换回 char * 以显示结果。" - 为什么当它是一个字符串时你不能显示结果?应该能够做到 std::cout
  • 这是我必须使用的界面。因此,尽管我尽可能使用字符串,但如果接口需要 char *,那么这就是我必须使用的。函数输出参数是一个 char *...这就是我必须使用的
  • 在这种情况下,界面应该说一些关于内存管理的内容。我说“应该”是因为它可能不是 - 一些接口指定不明确,这是不争的事实。每当您从函数返回指针时,您需要说明谁负责分配指向的数据、它保持有效的时间以及谁负责释放它(如果适用)。如果你能解决这个问题,你就能弄清楚如何返回一个适当的指针值。
  • 好吧,我只是在编写一个测试应用程序,它将为指针分配内存(因此使用该接口的人将是管理指针的人)。我的实际函数将只接受 2 个参数,其中一个需要返回一个 char * 值。所以我这样做是为了测试我将要发送的库的精神。

标签: c++


【解决方案1】:

char* 转换为std::string

char* c = "Hello, world";
std::string s(c);

std::string 转换为char*

std::string s = "Hello, world";
char* c = new char[s.length() + 1];
strcpy(c, s.c_str());

// and then later on, when you are done with the `char*`:
delete[] c;

我更喜欢使用std::vector<char> 而不是实际的char*;那么你就不必管理自己的记忆了:

std::string s = "Hello, world";
std::vector<char> v(s.begin(), s.end());
v.push_back('\0'); // Make sure we are null-terminated
char* c = &v[0];

【讨论】:

  • 是的,但在后一种情况下,当您使用 c_str() 时,它会返回 const char * 而不是 char *
  • @user295030: c_str() 确实返回了 const char*; strcpy(源字符串)的第二个参数是const char* 类型。如果你只需要一个const char*,则不需要这样做,你可以使用c_str()的结果。
  • s.c_str() 返回一个 const char*,这就是他将其复制到名为 c 的 char* 中的原因。在您的函数中,您将返回 c。
  • 如果您在堆栈上声明了 C 数组,您也不必管理内存。
  • @wilhelmtell:是的,但这会违反 OP 的要求之一(“返回结果,使得值应该在函数之外可用并且不会被破坏”)。它还有一个缺点,就是你必须在编译时猜测它需要多大。通常这很好。其他时候不是。
【解决方案2】:

你需要注意你如何处理你返回的指针的内存,例如下面的代码将不会工作,因为在 std::string 中分配的内存将在 fn() 退出时被释放。

const char* fn(const char*psz) {
    std::string s(psz);
    // do something with s
    return s.c_str();   //BAD
}

一种解决方案是在函数中分配内存并确保函数的调用者释放它:

const char* fn(const char*psz) {
    std::string s(psz);
    // do something with s
    char *ret = new char[s.size()]; //memory allocated
    strcpy(ret, s.c_str());
    return ret;
}
....
const char* p = fn("some text");
//do something with p
delete[] p;// release the array of chars

或者,如果您知道字符串大小的上限,您可以自己在堆栈上创建它并传入一个指针,例如

void fn(const char*in size_t bufsize, char* out) { 
    std::string s(psz);
    // do something with s
    strcpy_s(out, bufsize, s.c_str()); //strcpy_s is a microsoft specific safe str copy
}
....
const int BUFSIZE = 100;
char  str[BUFSIZE];

fn("some text", BUFSIZE, str);
//ok to use str (memory gets deleted when it goes out of scope)

【讨论】:

    【解决方案3】:

    您可以为您的库维护一个垃圾收集器,实现为 std::vector&lt;char*&gt; g_gc; 可在您的库“lib”中访问。稍后,您可以在方便时调用lib::release_garbage();释放g_gc中的所有指针

    char* lib::func(char*pStr)
    {
      std::string str(pStr);
      char *outStr = new char[str.size()+1];
      strcpy(outStr, str.c_str());
      g_gc.push_back(outStr); // collect garbage
      return outStr;
    }
    

    release_garbage 函数如下所示:

    void lib::release_garbage()
    {
       for(int i=0;i<g_gc.size();i++)
       {
           delete g_gc[i];
       }
       g_gc.clear();
    }
    

    在单线程模型中,您可以将此 g_gc 保持为静态。多线程模型将涉及锁定/解锁它。

    【讨论】:

    • 这是非常危险的;在容器中存储裸指针几乎总是一个坏主意,因为很难确保异常安全。 (有关替代方案,请参见此处:stackoverflow.com/questions/2558134/2558152#2558152)。此外,您答案中的代码有一个严重错误:它使用了不匹配的new[]delete
    • 这是一个很棒的话题。感谢您指出 delete[]。
    • 这样,您甚至不能按需“收集垃圾”,因为某些指针可能正在使用中。您只能在应用程序退出时安全地执行此操作,这使其毫无用处,因为分配的内存在您的应用程序退出时会被释放。
    猜你喜欢
    • 2011-05-18
    • 1970-01-01
    • 2016-05-08
    • 2012-03-06
    • 2017-02-05
    • 2015-12-09
    • 2014-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多