我一直在使用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 *
作为缓冲区的参数
答案 0 :(得分:8)
这就是你想要的
std::string destination = source;
你所做的事情在很多层面都是错的......你在写std::string
的内心表现......我的意思是......不是很酷的人...它要复杂得多比这更重要的是,数组被调整大小,只读内存......工作。
答案 1 :(得分:4)
这完全不是一个好主意,原因有两个:
destination.c_str()
是一个const指针并且抛弃它的const并且写入它是未定义的行为。 std::string
有一个构造函数,允许它从char*
构造,所以只需写:
std::string destination = source
答案 2 :(得分:3)
你正在做的是未定义的行为。你的c_str()返回一个const char *,并不打算分配给它。为什么不使用定义的构造函数或赋值运算符。
答案 3 :(得分:3)
std::string
defines an implicit conversion从const 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>
代替。