2012-05-08 10 views
1

我一直在使用C++字符串,并尝试使用C函数(如strcpy())将char *字符串加载到std::string中。由于strcpy()需要char *作为参数,我一定要投它该是这样的:std :: string.c_str()与std :: string有不同的值吗?

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 *作为缓冲区的参数。

+11

所以,你忽略了你的编译器给你的错误,并决定关闭它,把它转换为'(char *)'?你想知道为什么你有问题? –

+2

为什么你不使用: destination = source; – Morwenn

+0

所有的答案都会问隐含的问题为什么?为什么? – rerun

回答

4

这是不是在所有的原因有两个一个好主意:

  1. destination.c_str()是一个const指针,虚掷它的常量和写入这是不确定的行为。
  2. 您没有设置该字符串的大小,这意味着它甚至不会necessealy具有足够大的缓冲区来存放这很可能会导致访问冲突的字符串。

std::string有一个构造函数,允许其从char*来构造简单的写:

std::string destination = source

8

这里有你想要的

std::string destination = source; 

你在做什么是错的这么多层次......你写在std::string内表现......我的意思是......不冷静人......它比这更复杂,数组被调整大小,只读存储器......作品。

+0

找到一个给你。虽然有点不同,它确实涉及:http://stackoverflow.com/questions/6456359/what-is-stdstringc-str-lifetime – chris

0

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

3

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

3

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

您决定放弃一个错误,因为c_str()返回const char*,即它不允许写入其基础缓冲区。你尽一切可能来解决这个问题,但它不起作用(你不应该对此感到惊讶)。

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

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(); 
} 

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

0

在回答您的编辑:

具有用strncpy()到串A的仅X量复制到串B

如果串A是一个字符数组,并串B是的std :: string,和strlen的(A)> = X,则可以做到这一点:

B.assign(A, A + X); 

传递的std :: string到功能从一个C库第在需要一个char * 作为一个参数为缓冲区

如果参数实际上是const char *,您可以使用c_str()了点。但是,如果只是普通的char *,和你使用的是C++ 11兼容的编译器,那么你就可以做到以下几点:

c_function(&B[0]); 

但是,您需要确保有足够空间字符串的数据(与使用纯C字符串相同),您可以通过调用resize()函数来完成此操作。如果函数写字符的数目不详的字符串作为空终止的C字符串,那么你可能会想以后截断字符串,像这样:

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

您可以安全地做到这一点的原因一个C++ 11编译器而不是一个C++ 03编译器就是在C++ 03中,字符串不被标准保证是连续的,但在C++ 11中是这样的。如果你想在C++ 03中保证,那么你可以使用std::vector<char>

+0

关于你的建议,传递'c_str()'的返回值到一个函数一个char *'...这是一个坏主意。你不知道const char *指向的是什么。我没有看到它指出它指向字符串使用的内部缓冲区的地方,所以它甚至可能不起作用,并且API向你大吼那个内存不应该被修改。除非你知道该函数不会修改指针指向的事实,否则不要这样做。 –

+0

@EdS。 - 我没有这样说过的好事。 –

+0

对不起,误读:D –

相关问题