曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4385|回复: 1
打印 上一主题 下一主题

cin / cin.get / cin.ignore / getline()

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2011-6-21 13:40:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 beyes 于 2013-9-30 23:22 编辑

cin 对象可以用来接收键盘的输入,可以接收整数,浮点数,字符以及字符串等类型。

用 cin 对象来接收字符时只能用来读取单个字符,如果用来读取字符串,它一旦遇到空格、制表符、换行符以及回车时都将结束一个输入字符串,也就是说,这些符号之前的字符串作为有效输入,而其后的字符串则被忽略。

cin 对象中的 get() 函数可以用来读取任意一个字符 --- 包括各种空白字符,回车换行等符号,比如:
char choice;
std::cin.get(choice);

下面通过一个简单的测试代码来演示 cin 对象和 cin.get() 函数的应用,并由此引出 cin.ignore() 函数的说明:
[C++] 纯文本查看 复制代码
#include <iostream>

int main(void)
{
        char answer;
        char nextanswer;

        std::cout << "Enter your answer[Y/N]";
        std::cin >> answer;

        std::cout << "\n";

        switch (answer) {
                case 'y':
                case 'Y':
                        std::cout << "OK, format is begin" << "\n";
                        break;
                case 'n':
                case 'N':
                        std::cout << "Do nothing" << "\n";
                        break;
                default:
                        std::cout << "Wrong choice" << "\n";
                        break;
        }

        std::cout << "Press Enter or Return to continue.\n";
        std::cin.get();

        return 0;
}

运行输出:
$ ./cin
Would you like to erase your hard drive?[Y/N]y

OK, accepted
Press Enter or Return to continue.

$ ./cin
Would you like to erase your hard drive?[Y/N]n

Do nothing.
Press Enter or Return to continue.

在程序里,我们原本上希望在输入我们的答案后,再通过 cin.get() 函数等待用户输入一个回车后再退出,但是在运行时却是一下子就退出了。这里的原因是:当按下回车时,之前的键盘输入一次性的发送到程序中(并不是每敲一个字符就读入一个字符)。在程序收到输入数据之后,cin 将把输入数据复制给指定的变量(假设输入数据和变量类型匹配)。在上面程序中,当按下 y 或 n 然后回车时,y 或 n 被读入 answer 变量中,而 回车 还留在输入流中(输入缓冲区),这样当程序执行到 cin.get() 时,它就会将缓冲区中的 回车 读进来,这样程序自然就直接退出了。如果在程序中添加下面两句:
[C++] 纯文本查看 复制代码
char nextanswer;
std::cin >> nextanswer;   // 再声明一个 char 变量,然后从留中读取内容

然后再 switch() 后添加一行对 nextanswer 变量的输出:
[C++] 纯文本查看 复制代码
std::cout << "nextanswer = " << nextanswer << "\n";

接着再将改成 std::cin.get();:
[C++] 纯文本查看 复制代码
std::cout << (char)std::cin.get() << "\n";


在编译程序后,再次运行,然后输入 yes 看看会有什么效果:
./cin
Would you like to erase your hard drive?[Y/N]yes

OK, accepted
nextanswer = e
Press Enter or Return to continue.
s

从上面可以看到,answer 变量读入了 “yes" 中的字符 'y' ;nextanswer 变量读入了字符 'e' ;而 cin.get() 则读入了字符 's' 。

所以如果希望在 answer 读入 y 后,在 cin.get() 这里等待用户输入,一个办法就是将 'y' 字符后面输入缓冲区中的所有内容删除掉。这里,可以使用 cin.ignore() 函数。ignore() 函数可以如下使用:
[C++] 纯文本查看 复制代码
std::cin.ignore(100, '\n');

这里,ignore() 的第 2 个参数表示 ”停止字符“,它的作用是告诉 ignore() 函数在读到什么字符时停止执行。所以上面的语句表示:
丢掉缓冲区中的 100 个字符 或者 直到它遇到一个换行符(遇到后,也将丢弃它前面的输入内容) 时停止 --- 两个参数组合到一起时,就要看先遇到那件事先发生。

当然 ignore() 函数也可以只带 1 个整形参数,这时表示在丢弃掉参数所表示的字符个数后程序继续往下运行。比如当 cin.ignore(5) 时,它需要丢掉 5 个字符。比如,当运行下面的代码
[C++] 纯文本查看 复制代码
std::cout << "your school is " << school << "\n"; 
std::cin.ignore(5);

时,在输入 school 名之后,ignore(5) 强制丢掉 5 个字符,此时,你需要再连续按下 5 次回车(包括输入 school 名字后的那次回车),或者再次输入包括回车在内一个字符串共累计 5 个字符时,程序才能继续往下执行。

对于 cin 对象,get() 和 ignore() 函数有下面的测试代码:
[C++] 纯文本查看 复制代码
#include <iostream>
#include <string>

int main(void)
{
    std::string Name;
    std::string school;
    char choice = 'y';

    while (true) {
        std::cout << "Enter your name: ";
        std::cin >> Name;
        std::cout << "your name is " << Name << "\n";

        std::cout << "Enter your school name: ";
        std::cin >> school;
        std::cout << "your school is " << school << "\n";

        std::cin.ignore(100, '\n');
        std::cout << "Press 'Enter' for return or continue: ";
        std::cin.get(choice);
        if (choice == '\n') {
            std::cout << "goodbye" << "\n";
            break;
        }
    
        std::cin.ignore(100, '\n');
    } 
                    
    return 0;
}

上面程序的功能是,在输入姓名及学校名后,等待用户输入;如果用户直接输入回车,那么程序退出;否则程序循环继续要求输入。
上面代码中有 3 处地方使用了 ignore() 函数。第 1 处的目的是过滤掉输入缓冲区中的换行符,以免程序还没等待用户输入就直接退出;第 2 处的目的是,如果用户输入的不是回车,而是其它的字符串或者别的什么,也要将其丢弃,否则它们会被读到再一次循环的 Name 变量中,从而造成误读。当然,如果你输入超过 100 个字符的字符串,那么程序也会直接退出的。但是这里 100 这个参数足够处理这种情况。

cin.get() 还可用来获取输入的字符串,此时有 2 个参数,第 1 个参数是存储输入字符串的缓冲区,第 2 个参数表示限制最大可以读取多少个字符,如下测试代码:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;

int main()
{

char line[8];
cout << " Type a line terminated by carriage return\n>";
cin.get( line, 8 );
cout << line << endl;

}


如上所示,我们限定了最多获取输入的 8 个字符。如果输入的是 12345678,那么最后输出的字符串是 1234567,而不是 12345678,原因是第 8 个字符用来存放 '\0' ,表示字符串的结尾。

如果 cin.get() 不带任何参数,那么默认从输入流里读入单个字符,不管你输入多长的东西。


4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
沙发
 楼主| 发表于 2011-7-7 01:12:56 | 只看该作者

getline() -- 读入一整行输入

getline() 函数可以用来读入一整行文本,这行文本中可以有空格隔开,直到输入回车后输入结束。该函数有 2 个参数,第 1 个是 std::in ,第 2 个是用来保存输入值的变量。

测试代码
[C++] 纯文本查看 复制代码
#include <iostream>
#include <string>

int main(void)
{
    std::cout << "Enter something you want to say about: ";
    std::string saysomething;
    std::getline (std::cin, saysomething);
    std::cout << "you said:" << saysomething << '\\n';

    return 0;
}

运行输出
$ ./getline
Enter something you want to say about: welcome to groad.net ^_^
you said:welcome to groad.net ^_^
getline() 会丢弃作为文本行结束标记的换行符,所以换行符不会作为输入值的一部分。

实际上,getline() 还可有一个可选的第 3 个参数,它用来定义一个停止字符。默认情况下,停止字符是换行符,但也可以用别的字符来达到这一目的,比如使用 '#' 号什么别的什么的。

这里需要注意的是,getline() 因为遇到换行符时会停止读入,所以必须保证在调用它之前缓冲区内没有任何多余的输入。比如你先用 std::cin >> year; 读取 1 个整数到 year 变量,这在输入整数值并按下回车后,整数值会赋给 year 变量,而回车符号还留在缓冲区中,这样如果你接着用 getline() 函数就会被马上退出。简单的解决办法是,先用 getline() 函数处理它的输入,然后再处理整数值的输入。或者使用 cin.ignore() 函数如下处理:
[C++] 纯文本查看 复制代码
std::cin >> year;
std::cin.ignore(1, '\\n');
std::getline (std::cin, saysomething);

第 2 条语句用 cin.ignore() 将整数输入后边的换行符吃掉,这样就能保证 getline() 的正常使用了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-17 21:14 , Processed in 0.078451 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表