【C++】学习笔记十八——循环和文本输入

循环和文本输入

逐字符的读取来自文件或键盘的文本。

1. 使用原始的cin进行输入

如果程序要使用循环来读取来自键盘的文本输入,则必须有办法知道何时停止读取。

一种方法是选择某个特殊字符——有时被称为哨兵字符(sentinel character),将其作为停止标记。

程序5.16

#include<iostream>
int main()
{
    using namespace std;
    char ch;
    int count = 0;
    cout << "Enter characters; enter # to quit:\n";
    cin >> ch;
    while (ch != '#')
    {
        cout << ch;
        ++count;
        cin >> ch;
    }
    cout << endl << count << " characters read\n";
    system("pause");
    return 0;
}

这里写图片描述

程序5.16在遇到#时停止读取输入。该程序计算读取的字符数,并回显这些字符,即在屏幕上显示读取的字符。按下键盘上的键不能自动将字符显示到屏幕上,程序必须通过回显输入字符来完成这项工作。

程序在循环之前读取第一个第一个输入字符,这样循环可以测试第一个字符,因为第一个字符可能是#,这样程序能够正确地跳过整个循环。

如果读取到的第一个字符不是#,则程序进入该循环,显示字符,增加计数,然后读取下一个字符。

最后一步是极为重要的,没有这一步,循环将反复处理第一个输入字符,一直进行下去。有了这一步后,程序就可以处理到下一个字符。

结束循环的条件是最后读取的一个字符是#。该条件是通过在循环之前读取一个字符进行初始化的,而通过循环体结尾读取下一个字符进行更新。

程序在输出时省略了空格。cin在读取char值时,与读取其他基本类型一样,将忽略空格和换行符,因此输入中的空格没有被回显,也没有被包括在计数内。

发送给cin的输入被缓冲,只有在按下回车键后,输入的内容才会被发送给程序。这就是在运行该程序时,可以在#后面输入字符的原因。按下回车键后,整个字符序列将被发送给程序,但程序在遇到#字符后将结束对输入的处理。

2.使用cin.get(char)进行补救

通常,逐个字符读取输入的程序需要检查每个字符,包括空格、制表符和换行符。cin所述的istream类中包含一个能够满足这种要求的成员函数cin.get()。cin.get(ch)读取输入的下一个字符(即使它是空格),并将其赋给变量ch。

程序5.17

#include<iostream>
int main()
{
    using namespace std;
    char ch;
    int count = 0;
    cout << "Enter characters; enter # to quit:\n";
    cin.get(ch);
    while (ch != '#')
    {
        cout << ch;
        ++count;
        cin.get(ch);
    }
    cout << endl << count << " characters read\n";
    system("pause");
    return 0;
}

这里写图片描述

程序5.17回显了每个字符,并将全部字符计算在内,包括空格。

3.文件尾条件

如果输入来自文件,可以使用一种功能更强大的技术——检测文件尾(EOF)——来表示输入结束。

很多操作系统都支持重定向(<),允许用文件替换键盘输入,还允许通过键盘来模拟文件尾条件。

如果编程环境能够检测到EOF,则可以在程序中使用重定向的文件。检测到EOF后,cin将两位(eofbit和failbit)都设置为1。可以通过成员函数eof()来查看eofbit是否被设置;如果检测到EOF,则cin.eof()将返回bool值true,否则返回false。同样,如果eofbit或failbit被设置为1,则fail()成员函数返回true,否则返回false。

程序5.18

#include<iostream>
int main()
{
    using namespace std;
    char ch;
    int count = 0;
    cin.get(ch);
    while (cin.fail() == false)
    {
        cout << ch;
        ++count;
        cin.get(ch);
    }
    cout << endl << count << " characters read\n";
    system("pause");
    return 0;
}

这里写图片描述

在windows系统上运行该程序,因此用【Ctrl+Z】和回车键来模拟EOF条件。

通过使用重定向,可以用该程序来显示文本文件,并报告它包含的字符数。

1. EOF结束输入

cin检测到EOF时,将设置cin对象中一个指示EOF条件的标记。设置这个标记后,cin将不读取输入,再次调用cin也不管用。

2.常见的字符输入做法

每次读取一个字符,直到遇到EOF的输入循环的基本设计如下:

cin.get(ch);
while (cin.fail() == false)
{
    ...
    cin.get(ch);
}

可以将while改写为:

while (!cin.fail())

方法cin.get(char)的返回值是一个cin对象。然而,istream类提供了一个可以将istream对象(如cin)转换为bool值的函数:当cin出现在需要bool制的地方(如在while循环的测试条件中)时,该转换函数被调用。另外,如果最后一次读取成功了,则转换得到的bool值为true,否则为false。

因此上述while可改写为:

while (cin)

这比!cin.fail()或!cin.eof()更通用,因为它可以检测到其他失败原因,如磁盘故障。

由于cin.get(char)的返回值为cin,因此可以将循环精简为:

while (cin.get(ch))
{
    ...
}

这样,cin.get(char)只被调用一次,而不是两次(循环前一次、循环结束后一次)。

4. 另一个cin.get()版本

不接受任何参数的cin.get()成员函数返回输入中的下一个字符,因此,可以这样使用它:

ch = cin.get();

该函数的工作方式与C语言中的getchar()相似,将字符编码作为int值返回;而cin.get(ch)返回一个对象,而不是读取的字符。

同样,可以使用cout.put()参数来显示字符:

cout.put(ch);

该函数的工作方式类似于C语言中的putchar(),只不过其参数类型为char,而不是int。

程序5.19

#include<iostream>
int main(void)
{
    using namespace std;
    int ch;
    int count = 0;

    while ((ch = cin.get()) != EOF)
    {
        cout.put(char(ch));
        ++count;
    }
    cout << endl << count << " characters read\n";
    system("pause");
    return 0;
}

这里写图片描述

下表总结了cin.get(ch)和cin.get()的差别:

属性cin.get(ch)ch=cin.get()
传递输入字符的方式赋值给参数ch将函数返回值赋给ch
用于字符输入时函数的返回值istream对象(执行bool转换后为true)int类型的字符编码
到达EOF时函数的返回值istream对象(执行bool转换后为false)EOF
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值