std :: string.c_str()与std :: string的值不同?

时间:2012-05-08 22:11:17

标签: c++ cstring stdstring

我一直在使用C ++字符串,并尝试使用char *等C函数将std::string字符串加载到strcpy()。由于strcpy()char *作为参数,我必须将其转换为类似这样的内容:

std::string destination;
unsigned char *source;
strcpy((char*)destination.c_str(), (char*)source);

代码工作正常,当我在调试器中运行程序时,*source的值存储在destination中,但由于某些奇怪的原因,它不会打印出语句

std::cout << destination;

我注意到,如果我使用

std::cout << destination.c_str();

该值打印正确,一切正常。为什么会这样?有没有更好的方法将unsigned char*char*复制到std::string(字符串流?)这似乎只有在复制操作中将字符串指定为foo.c_str()时才会发生

编辑:要回答“你为什么要这样做?”的问题,我使用strcpy()作为一个简单的例子。还有一些时候它比分配更复杂。例如,必须使用strncpy()将X量的字符串A复制到字符串B中,或者将std::string传递给C库中的函数,该函数将char *作为缓冲区的参数

7 个答案:

答案 0 :(得分:8)

这就是你想要的

 std::string destination = source;

你所做的事情在很多层面都是错的......你在写std::string的内心表现......我的意思是......不是很酷的人...它要复杂得多比这更重要的是,数组被调整大小,只读内存......工作。

答案 1 :(得分:4)

这完全不是一个好主意,原因有两个:

  1. destination.c_str()是一个const指针并且抛弃它的const并且写入它是未定义的行为。
  2. 你没有设置字符串的大小,这意味着它甚至不会有足够大的缓冲区来保存可能导致访问冲突的字符串。
  3. std::string有一个构造函数,允许它从char*构造,所以只需写:

    std::string destination = source

答案 2 :(得分:3)

你正在做的是未定义的行为。你的c_str()返回一个const char *,并不打算分配给它。为什么不使用定义的构造函数或赋值运算符。

答案 3 :(得分:3)

std::string defines an implicit conversionconst char*std::string ...所以请使用它。

您决定抛弃错误,因为c_str()返回const char*,即它不允许写入其底层缓冲区。你尽了一切努力来解决这个问题并且它不起作用(你不应该对此感到惊讶)。

c_str()有充分理由返回const char*。你不知道这个指针是否指向字符串的底层缓冲区。您不知道此指针是否指向足以容纳新字符串的内存块。该库正在使用它的界面来告诉你应该如何使用c_str()的返回值,而你完全忽略了它。

答案 4 :(得分:1)

不要做你正在做的事情!!!

我再说一遍!

不要做你做什么!!!

当你做一些奇怪的事情似乎有点工作是字符串类的实现方式的结果。你几乎可以肯定在记忆中写下你不应该和其他一些虚假的东西。

当您需要与写入缓冲区的C函数进行交互时,有两种基本方法:

std::string read_from_sock(int sock) {
    char buffer[1024] = "";

    int recv = read(sock, buffer, 1024);
    if (recv > 0) {
      return std::string(buffer, buffer + recv);
    }
    return std::string();
}

或者您可以尝试使用peek方法:

std::string read_from_sock(int sock) {

    int recv = read(sock, 0, 0, MSG_PEEK);
    if (recv > 0) {
      std::vector<char> buf(recv);
      recv = read(sock, &buf[0], recv, 0);
      return std::string(buf.begin(), buf.end());
    }
    return std::string();
}

当然,这些并不是非常强大的版本......但它们说明了这一点。

答案 5 :(得分:0)

首先,您应该注意c_str返回的值是const char*,不得修改。实际上它甚至不必指向string的内部缓冲区。

答案 6 :(得分:0)

回复您的修改:

  

必须使用strncpy()

将X量的字符串A复制到字符串B中

如果字符串A是char数组,字符串B是std :: string,而strlen(A)&gt; = X,那么你可以这样做:

B.assign(A, A + X);
  

将std :: string传递给带有char的C库中的函数   *作为缓冲区的参数

如果参数实际为const char *,则可以使用c_str()。但是,如果它只是普通的char *,并且您使用的是兼容C ++ 11的编译器,那么您可以执行以下操作:

c_function(&B[0]);

但是,您需要确保数据的字符串中有空间(就像使用普通的c-string一样),可以通过调用resize()函数来完成。如果函数将未指定数量的字符作为以null结尾的c字符串写入字符串,那么您可能希望之后截断字符串,如下所示:

B.resize(B.find('\0'));

你可以在C ++ 11编译器而不是C ++ 03编译器中安全地执行此操作的原因是在C ++ 03中,标准不保证字符串是连续的,但在C ++ 11中, 他们是。如果您想要C ++ 03中的保证,那么您可以使用std::vector<char>代替。