【问题标题】:Actual difference between end of line and end of file under windows?windows下行尾和文件尾的实际区别?
【发布时间】:2011-08-17 15:39:43
【问题描述】:

我了解 EOF 和 EOL,但是当我阅读 this question (答案的第二部分)时,我的概念被打破了: 特别是段落:

在找到文件结尾之前它不会停止输入(cin 使用 stdin,它被视为非常像一个文件

所以我想知道我们什么时候在 windows 下用 c++ 做一些事情: std::cin>>int_var; ,然后我们按 enter ,这会结束输入,但根据参考链接,它应该只有在点击 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' 结尾的新输入。

感谢您抽出宝贵时间)

【问题讨论】:

  • 你知道EOF通常是指文件到达末尾的情况,但实际上并不是文件数据的一部分(可以是任意字节组合),而EOL是通常指的是表示行尾的实现特定字符(序列)?
  • @PlasmaHH:是的,我知道 EOF 信号是由操作系统向程序发出的。但是你能解释一下问题的第一部分吗?
  • 请针对单独的问题提出单独的问题。不要在这里将它们作为单独的“部分”询问
  • @jalf 对此我深表歉意,下次我会记住这一点吗?

标签: c++


【解决方案1】:

行尾和文件尾是完全不同的概念。

行尾实际上只是另一个输入字符(或字符序列),它可以出现在输入流中的任何位置。如果您从文本流中一次读取一个字符,则行尾只是意味着您将看到一个换行符 ('\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,那是在&lt;stdio.h&gt;&lt;cstdio&gt; 中定义的宏。它扩展为由某些函数返回的负整数常量(通常为 -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 &gt;&gt; sstd::getline(std::cin, s),都建立在此机制之上。

【讨论】:

  • 你能解释一下你在这行中的意思吗? : "如果您从文本流中一次读取一个输入字符,行尾只是意味着您将看到一个换行符 ('\n') "
  • @Hades:我会将此添加到我的答案中,因为我需要进行一些格式化。
【解决方案2】:

第一个“部分”

所以我想知道我们什么时候在 windows 下用 c++ 做一些事情:std::cin>>int_var; ,然后我们按 enter ,这会结束输入,但根据参考链接,它应该只在按下 ctrl+z 后才停止输入。

不,您将格式化输入操作与流迭代器混淆了。以下将重复使用格式化输入操作(operator&gt;&gt;)直到到达文件末尾,因为“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;

在交互式外壳中(例如在控制台模式下),std::cin 将阻止逐行获取的用户输入。因此,如果没有数据(或只有空白)可用,此操作实际上会强制用户键入一行输入并按下回车键。

然而,

int i = 0;
int j = 0;
std::cin >> i >> j;

可能会阻止一两行输入,具体取决于用户键入的内容。特别是,如果用户键入

1<space>2<enter>

那么这两个输入操作将使用同一行输入来应用。

第二“部分”

考虑代码sn-p:

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;

【讨论】:

    【解决方案3】:

    关于第二部分:

    当链接的答案说“读入字符串”时,我猜他们的意思是

    std::string   s;
    std::getline(std::cin, s);
    

    它总是将整行读入字符串s(同时将s设置为适当的大小)。

    这样输入行就没有任何东西需要清理了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-09
      • 2015-12-17
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 2016-02-10
      相关资源
      最近更新 更多