C++ 从流提取到字符数组或std::string的最安全方法

C++ 从流提取到字符数组或std::string的最安全方法,c++,stream,buffer-overflow,C++,Stream,Buffer Overflow,我担心缓冲区溢出,需要从std::istream派生的类中获取一些字符。据我所知,没有我自己的>>操作符,无法直接从istream流式传输到std::string。所以我考虑将内容流式传输到一个char数组,然后将其放入std::string。下面是一个简单的例子: char CharArray[1000] = {0}; SomeIStream >> CharArray; std::string StuffFromStream(CharArray); 然而,似乎没有办法知道Char

我担心缓冲区溢出,需要从std::istream派生的类中获取一些字符。据我所知,没有我自己的>>操作符,无法直接从istream流式传输到std::string。所以我考虑将内容流式传输到一个char数组,然后将其放入std::string。下面是一个简单的例子:

char CharArray[1000] = {0};
SomeIStream >> CharArray;
std::string StuffFromStream(CharArray);
然而,似乎没有办法知道CharArray不会溢出。流提取运算符是否有写入chararray的最大值?有什么方法可以检查有多少会被抢先提取?这一切都错了吗?有没有比这更好的方法

Edit1:,我修复了我的问题,但不是内存泄漏。不需要调用delete。我不敢相信我做了那件事

Edit2:建议直接使用>>来创建字符串。我在代码库中尝试了前一个问题,但失败了。表示找不到适合操作员的匹配项。然后我尝试使用std::fstream,但再次失败。在简单的简约项目中尝试std::fstream代码成功。这告诉我,我的大项目还有其他问题。这个问题的原意已不再有效

我解决了这个问题。我试图流式生成一个typedef字符串,我认为它实际上是和std::String,但它实际上是一个const std::String。当然,没有用于写入不可写入对象的流提取操作符,因此它只提供了istream头中列出的所有操作符(我需要的是字符串头中的操作符)


感谢那些指出我的错误研究并为我指明正确方向的人。

将老式C风格的字符数组与流混合在一起?看起来像是一些非常混乱的代码

撇开注释不谈,直接提取到字符串。您可以(通过
c_str()
方法)将其传递给需要
const char*
参数的c风格API。如果出于某种奇怪的原因,你真的需要一个字符数组,那么在检查边界后,你可以将
字符串
安全地复制到字符数组中

顺便说一下,你已经非常清楚地说明了主要的方法。在您的例子中,所讨论的神奇数字是
1000
。你不知道
1000
是合适的——不太大,也不太小——不需要完全猜测。在编程中,猜测常常是失败的。更糟糕的是,没有撞车

顺便说一下,您正在删除上面的自动变量。你不能这样做。使用
delete
当且仅当您使用
new
时。您没有
新建
,因此不要
删除

顺便说一下,如果您只想将整个流提取到字符串中,您可以这样做:

string s = SomeIStream.str();
所有流都提供.str()方法,该方法将以std::string(或wstring或其他typedef的任何形式)的形式提供其缓冲区的副本

另外,您在堆栈上声明了一个数组,然后试图删除它,它是UB。

如果您(正确地)继承了std::istream,那么您不需要做任何特殊的操作,只需使用
操作符>(std::istream&,std::string&)

当我说“正确”时,我的意思是重写了istream中适当的虚函数


“我知道,如果在删除之前出现异常,这将泄漏内存。”不,不会。您没有将
CharArray
分配给
new
;对其调用
delete
将无法实现您想要的功能。

如果您想将整个流读入一个字符串,这不是非常有效,但很安全:

std::string str((std::istream_iterator<char>(some_istream)), std::istream_iterator<char>());

请注意,这不会使数组终止为null。如果你想让数组的最后一个字符保持不变,请传递sizeof(char\u array)-1。

这就是我通常的方法(来自Bruce Eckel的“用C++思考”:

ifstream-in(“somefile.txt”,ios::in); istreambuf_迭代器istr(in),结束; 字符串str; 插入迭代器ins(str,str.begin()); while(istr!=结束){ *ins++=*istr++; }


在上面的代码中,整个文件被当作一个字符流,然后放入一个字符串中。这只是一个示例。

只有stringstreams和stringbufs有str()成员。我确实尝试过,但我的编译器明确表示没有定义此类运算符重载。我将检查是否只是这个流实现问题,或者它是否都是IStream。我使用和std::fstream测试了这个问题,但失败了。然而,使用std::fstream::read读取字符数组,然后将其传递到字符串中是可行的。我看了这个,它不在那里,但在这里:。我想知道为什么我用fstream测试或者用从istream派生的原始类测试时都找不到它。
std::string str((std::istream_iterator<char>(some_istream)), std::istream_iterator<char>());
some_istream.read(some_char_array, sizeof(some_char_array));
ifstream in("somefile.txt",ios::in); istreambuf_iterator istr(in),end; string str; insert_iterator ins(str,str.begin()); while(istr != end){ *ins++ = *istr++; }