这是一个简单的问题。我写了这个 C++ 代码:
char chaine[12];
cin.width(12);
cin >> chaine;
但是,如果我在运行时输入一些长度超过 12 个字符的文本,Visual Studio 会通知我堆栈现在已损坏。
据我所知,问题是缓冲区溢出。但我认为“宽度”方法可以防止这种情况。
如果宽度方法不能防止缓冲区溢出,有人可以向我解释一下它的作用是什么吗?我在网上搜索过,但没有找到任何东西。
谢谢!
最佳答案
这段代码确实显然应该将输入限制为 11 个字符(第 12 个字符用于终止空字符)。该标准在 27.7.2.2.3 [istream::extractors] 第 7 和 8 段中明确指出:
... If width() is greater than zero, n is width(). ... Characters are extracted and stored until any of the following occurs: - n-1 characters are stored; ...
我也用 gcc 尝试过,它显然只能读取 11 个字符。我不知道解决这个问题的最佳方法是什么。通常,我不会遇到这样的问题,因为我只是简单地读取 std::string
对象,这些对象可以根据需要增长。嗯,也有一些巨大的限制,我从来没有尝试过当超过这个限制时会发生什么。如果您绝对需要读入char
数组,您可以做两件事:
- 您可以为
char
数组创建适配器并自行定义合适的输入运算符 - 您可以创建一个临时安装的过滤流缓冲区,它限制字符数或假装读取空格字符。
下面是有关如何执行后者的示例。创建适配器的技术实际上可以用于根据数组的大小自动设置宽度。
#include <iostream>
#include <cctype>
struct adaptor
{
template <int Size>
adaptor(char (&array)[Size]): it(array), end(array + Size - 1) {}
mutable char* it, * end;
};
std::istream& operator>> (std::istream& in, adaptor const& value)
{
std::istreambuf_iterator<char> it(in), end;
if (it == end)
{
in.setstate(std::ios_base::failbit);
}
for (; it != end && value.it != value.end && !std::isspace(static_cast<unsigned char>(*it));
++it, ++value.it)
{
*value.it = *it;
}
*value.it = 0;
return in;
}
int main()
{
char buffer[12];
if (std::cin >> adaptor(buffer))
std::cout << "read='" << buffer << "'\n";
else
std::cout << "input failed\n";
}
关于c++ - 在 C++ 中使用 cin 和 Width() 来避免缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8766641/