Windows下行尾与文件结尾之间的实际差异?

时间:2011-08-17 15:39:44

标签: c++

我理解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'结尾的新输入。

感谢您给我时间)

3 个答案:

答案 0 :(得分:6)

行尾和文件结尾是非常不同的概念。

行结尾实际上只是另一个输入字符(或字符序列),可以出现在输入流的任何位置。如果您从文本流中一次读取一个字符输入,则行尾仅表示您将看到换行符('\n')。一些输入例程特别处理这个角色;例如,它告诉getline停止阅读。 (其他例程特别对待' ';没有根本区别。)

不同的操作系统使用不同的约定来标记行的结尾。在Linux和其他类Unix系统上,文件中一行的末尾标有单个ASCII换行符(LF,'\ n')字符。从键盘读取时,LF和CR通常都映射到'\n'(尝试键入EnterControl-JControl-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 >> sstd::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设置为正确的大小)。

这样一来,输入行就没有任何遗留物来清理。