使用 << 读取固定数量的字符在 istream 上
我正在尝试一些 C++ 中的文件读取策略,并且遇到了这个。
ifstream ifsw1("c:\\trys\\str3.txt");
char ifsw1w[3];
do {
ifsw1 >> ifsw1w;
if (ifsw1.eof())
break;
cout << ifsw1w << flush << endl;
} while (1);
ifsw1.close();
文件的内容是
firstfirst firstsecond secondfirst secondsecond
当我看到输出时,它被打印,因为
firstfirst firstsecond secondfirst
我期望输出如下:
fir stf irs tfi .....
此外,我看到“secondsecond”尚未打印。我猜想最后一次读取已经遇到了eof,cout可能还没有被执行。但第一个行为是不可理解的。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
提取运算符没有 ifsw1w 变量大小的概念,并且(默认情况下)将提取字符,直到遇到空格、null 或 eof。这些可能存储在 ifsw1w 变量之后的内存位置中,如果定义了其他变量,这将导致严重的错误。
为了获得所需的行为,您应该能够
限制要提取的字符数。
The extraction operator has no concept of the size of the ifsw1w variable, and (by default) is going to extract characters until it hits whitespace, null, or eof. These are likely being stored in the memory locations after your ifsw1w variable, which would cause bad bugs if you had additional variables defined.
To get the desired behavior, you should be able to use
to limit the number of characters to extract.
使用 std::istream& 实际上是不可能的。安全地使用operator>>(std::istream&, char *)——在这方面就像
gets
——你无法指定缓冲区大小。流只是写入缓冲区,从末尾开始。 (上面的示例调用了未定义的行为)。要么使用接受std::string
的重载,要么使用std::getline(std::istream&, std::string)
。检查
eof()
不正确。您需要fail()
来代替。您实际上并不关心流是否位于文件末尾,您只关心提取信息是否失败。对于这样的事情,您可能最好将整个文件读入字符串并从该点开始使用字符串操作。您可以使用字符串流来做到这一点:
It's virtually impossible to use
std::istream& operator>>(std::istream&, char *)
safely -- it's likegets
in this regard -- there's no way for you to specify the buffer size. The stream just writes to your buffer, going off the end. (Your example above invokes undefined behavior). Either use the overloads accepting astd::string
, or usestd::getline(std::istream&, std::string)
.Checking
eof()
is incorrect. You wantfail()
instead. You really don't care if the stream is at the end of the file, you care only if you have failed to extract information.For something like this you're probably better off just reading the whole file into a string and using string operations from that point. You can do that using a stringstream:
你正在浪费内存......它的读取超过了你定义的3个字符(它的读取直到遇到空格或新行......)。
逐个字符地读取以实现您提到的输出。
编辑:激怒是对的,这也有效(经过一些修复,但没有得到确切的结果,但这就是精神):
You're trashing the memory... its reading past the 3 chars you defined (its reading until a space or a new line is met...).
Read char by char to achieve the output you had mentioned.
Edit : Irritate is right, this works too (with some fixes and not getting the exact result, but that's the spirit):
该代码具有未定义的行为。当您执行以下操作时:
operator>>
收到指向缓冲区的指针,但不知道缓冲区的实际大小。因此,它无法知道它应该在两个字符后停止读取(请注意,它应该是 2,而不是 3 - 它需要'\0'
的空间来终止字符串)。底线:在探索读取数据的方法时,最好忽略此代码。您可以从这样的代码中学到的所有内容是您应该避免的一些事情。然而,通常只遵循一些经验法则比尝试研究所有可能出现的问题更容易。
std::string
读取字符串。当你想读取一个文件中的所有数据时,
std::copy
可以避免很多错误:The code has undefined behavior. When you do something like this:
The
operator>>
receives a pointer to the buffer, but has no idea of the buffer's actual size. As such, it has no way to know that it should stop reading after two characters (and note that it should be 2, not 3 -- it needs space for a'\0'
to terminate the string).Bottom line: in your exploration of ways to read data, this code is probably best ignored. About all you can learn from code like this is a few things you should avoid. It's generally easier, however, to just follow a few rules of thumb than try to study all the problems that can arise.
std::string
to read strings.When you want to read all the data in a file,
std::copy
can avoid a lot of errors:要读取空格,您可以使用“noskipws”,它不会跳过空格。
但如果你只想获取3个字符,我建议你使用get方法:
To read the whitespace, you could used "noskipws", it will not skip whitespace.
But if you want to get only 3 characters, I suggest you to use the get method: