我理解EOF和EOL,但当我正在阅读this question (答案的第二部分)时,我的概念被破坏了: 特别是段落:
在找到文件结尾( cin使用)之前,它不会停止输入 stdin,被视为非常像文件)
所以我想知道我们什么时候在windows下用c ++做一些事情:
std::cin>>int_var;
,我们按下输入,这结束输入,但根据参考链接,它只应在点击ctrl+z
后停止输入。
所以我很想知道std::*stream
如何处理EOF和EOL。
第二部分: 请看一下这个例子:
std::cin.getline(char_array_of_size_256 ,256); cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); cout << "artist is " << artist << endl;
如果我删除std::cin.ignore()
它只是停止输入(这是已知的情况)但是当我保留它时,它等待由'\n'
结束的新输入。但它应该简单地清理上游而不是等待任何以'\ n'结尾的新输入。
感谢您给我时间)
答案 0 :(得分:6)
行尾和文件结尾是非常不同的概念。
行结尾实际上只是另一个输入字符(或字符序列),可以出现在输入流的任何位置。如果您从文本流中一次读取一个字符输入,则行尾仅表示您将看到换行符('\n'
)。一些输入例程特别处理这个角色;例如,它告诉getline
停止阅读。 (其他例程特别对待' '
;没有根本区别。)
不同的操作系统使用不同的约定来标记行的结尾。在Linux和其他类Unix系统上,文件中一行的末尾标有单个ASCII换行符(LF
,'\ n')字符。从键盘读取时,LF和CR通常都映射到'\n'
(尝试键入Enter
,Control-J
或Control-M
)。在Windows上,文件中某一行的结尾标有CR
- LF
对(\r\n
)。 C和C ++ I / O系统(或它们在其上运行的低级软件)将所有这些标记映射到单个'\n'
字符,因此您的程序不必担心所有可能的变化。
文件结尾不是字符,它是条件,表示没有更多字符可供阅读。不同的事情可以触发这种情况。当您从磁盘文件中读取时,它只是文件的物理端。当您从Windows上的键盘读取时,control-Z
表示文件结束;在Unix / Linux上,它通常是control-D
(虽然它可以配置不同)。
(你通常通常在文件结束之前有一个行尾(字符序列),但并非总是如此;在某些系统上,输入有时会以未终止的行结束。)
不同的输入例程有不同的方式表明他们已经看到了文件结束条件。请阅读每篇文档以获取详细信息。
至于EOF
,这是<stdio.h>
或<cstdio>
中定义的宏。它扩展为负整数常量(通常为-1),由某些函数返回到表示它们已达到文件结束条件。
编辑:例如,假设您正在阅读包含两行的文本文件:
one
two
假设您使用C的getchar()
,getc()
或fgetc()
函数一次读取一个字符。连续调用返回的值为:
'o', 'n', 'e', '\n', 't', 'w', 'o', '\n', EOF
或者,以数字形式(在典型系统上):
111, 110, 101, 10, 116, 119, 111, 10, -1
每个'\n'
或10(0x0a)是从文件中读取的换行符。最终-1
是EOF的值;这不是一个字符,而是表示没有更多字符可供阅读。
更高级别的输入例程,如C fgets()
和C ++的std::cin >> s
或std::getline(std::cin, s)
,都建立在这种机制之上。
答案 1 :(得分:3)
所以我想知道我们什么时候在windows下用c ++做一些事情:std :: cin&gt;&gt; int_var; ,我们按回车键,输入结束但是根据参考链接它应该只在按下ctrl + z后停止输入。
不,您将格式化的输入操作与流迭代器混淆。以下将重复使用格式化的输入操作(operator>>
),直到到达文件末尾,因为“end iterator”表示流的结束。
std::vector<int> integers;
std::copy(
std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(integers));
如果您使用以下内容:
int i = 0;
std::cin >> i;
在交互式shell中(例如在控制台模式下),std::cin
将阻止逐行获取的用户输入。因此,如果没有可用的数据(或只有空格),此操作实际上会强制用户键入一行输入并按Enter键。
然而,
int i = 0;
int j = 0;
std::cin >> i >> j;
可能会阻止一行或两行输入,具体取决于用户输入的内容。特别是,如果用户键入
1<space>2<enter>
然后使用相同的输入行应用两个输入操作。
考虑代码段:
std::cin.getline(char_array_of_size_256 ,256);
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "artist is " << artist << endl;
如果该行包含255行或更少的字符数据行,std::cin.getline()
将消耗行尾字符。因此,第二行将消耗所有字符,直到下一行完成。如果你想只捕获当前行并忽略256以上的所有字符,我建议你使用类似的东西:
std::cin.getline(char_array_of_size_256 ,256);
if (std::cin.gcount() == 256) {
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
cout << "artist is " << artist << endl;
答案 2 :(得分:1)
在第二部分:
当链接的答案说“读入字符串”时,我猜他们的意思是
std::string s;
std::getline(std::cin, s);
始终将整行读入字符串s
(同时将s
设置为正确的大小)。
这样一来,输入行就没有任何遗留物来清理。