1

我一直在使用 C++ 字符串,并尝试char *使用std::stringC 函数(例如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()一个简单的例子。有时它比分配更复杂。例如,必须将仅 X 数量的字符串 A 复制到字符串 B 中,使用strncpy()或将 a 传递std::string给 C 库中的函数,该函数将 achar *作为缓冲区的参数。

4

7 回答 7

9

这就是你想要的

 std::string destination = source;

你所做的在很多层面上都是错误的......你正在写一个std::string......我的意思是......不是很酷的人......它比这更复杂,数组正在调整大小,阅读- 只有记忆......作品。

于 2012-05-08T22:14:54.587 回答
4

这根本不是一个好主意,原因有两个:

  1. destination.c_str()是一个 const 指针,丢弃它的 const 并写入它是未定义的行为。
  2. 您还没有设置字符串的大小,这意味着它甚至不需要足够大的缓冲区来保存可能导致访问冲突的字符串。

std::string有一个构造函数,它允许它从一个char*如此简单的写法中构造出来:

std::string destination = source

于 2012-05-08T22:15:55.190 回答
3

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

于 2012-05-08T22:16:12.443 回答
3

std::string 定义从const char*to的隐式转换std::string...所以使用它。

您决定将错误丢弃为c_str()返回 a const char*,即它不允许写入其底层缓冲区。你尽你所能来解决这个问题,但它没有奏效(你不应该对此感到惊讶)。

c_str()const char*有充分的理由返回 a 。您不知道该指针是否指向字符串的底层缓冲区。你不知道这个指针是否指向一个足够大的内存块来保存你的新字符串。该库正在使用它的接口来准确地告诉您应该如何使用的返回值,c_str()而您完全忽略了这一点。

于 2012-05-08T22:16:29.553 回答
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();
}

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

于 2012-05-08T22:47:38.537 回答
0

首先你应该注意返回的值c_str是a const char*,不能修改。实际上它甚至不必指向string.

于 2012-05-08T22:15:45.207 回答
0

回应您的编辑:

必须使用 strncpy() 仅将 X 数量的字符串 A 复制到字符串 B

如果字符串 A 是一个 char 数组,而字符串 B 是 std::string,并且 strlen(A) >= X,那么你可以这样做:

B.assign(A, A + X);

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

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

c_function(&B[0]);

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

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

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

于 2012-05-08T22:51:54.430 回答