基本输入/输出(Basic Input/Output)

重要的事情说三遍:

强烈建议按照目录结构中的顺序学习!!!点我查看教程目录结构

强烈建议按照目录结构中的顺序学习!!!点我查看教程目录结构

强烈建议按照目录结构中的顺序学习!!!点我查看教程目录结构

前几节的示例程序几乎没有与用户的交互,只是在屏幕上打印简单的值。然而,标准库提供了许多其他方式,通过其输入/输出功能与用户交互。本节将简要介绍一些最有用的方法。

C++使用一种称为 的便捷抽象来在屏幕、键盘或文件等顺序介质上执行输入和输出操作。流是一个实体,程序可以向其插入或从中提取字符。我们不需要知道与流相关的介质或其任何内部规范的详细信息。我们只需要知道流是字符的来源/目的地,这些字符是顺序提供/接受的(即,一个接一个)。

标准库定义了一些流对象,可用于访问程序运行环境中被认为是标准字符来源和目的地的对象:

描述
cin标准输入流
cout标准输出流
cerr标准错误(输出)流
clog标准日志记录(输出)流

我们将更详细地介绍coutcin(标准输出和输入流);cerrclog也是输出流,因此它们的工作方式与cout基本相同,唯一的区别是它们用于特定目的:错误消息和日志记录;在许多情况下,在大多数环境设置中,它们实际上做同样的事情:在屏幕上打印,尽管它们也可以单独重定向。

标准输出(cout)

在大多数程序环境中,标准输出默认是屏幕,而C++流对象定义为访问它的是cout
对于格式化输出操作,cout插入运算符 一起使用,插入运算符写作<<(即两个“小于”符号)。

cout << "Output sentence"; // 在屏幕上打印Output sentence
cout << 120;               // 在屏幕上打印数字120
cout << x;                 // 在屏幕上打印变量x的值

<<运算符将其后的数据插入到其前的流中。在上面的示例中,它将字面字符串Output sentence、数字120和变量x的值插入到标准输出流cout中。注意,第一个语句中的句子用双引号(")括起来,因为它是一个字符串字面量,而最后一个语句中的x则没有。双引号使区别不同;当文本用它们括起来时,文本按字面打印;当没有括起来时,文本被解释为变量的标识符,并打印其值。例如,这两句话有非常不同的结果:

cout << "Hello";  // 打印Hello
cout << Hello;    // 打印变量Hello的内容

多个插入操作(<<)可以在一个语句中链接:

cout << "This " << " is a " << "single C++ statement";

最后一个语句将打印文本This is a single C++ statement。链接插入在单个语句中混合字面量和变量特别有用:

cout << "I am " << age << " years old and my zipcode is " << zipcode;

假设变量age的值是24,变量zipcode的值是90064,则前一个语句的输出将是:

I am 24 years old and my zipcode is 90064

cout不会自动在末尾添加换行符,除非有指示。例如,以下两个插入到cout的语句:

cout << "This is a sentence.";
cout << "This is another sentence.";

输出将在一行中,没有任何换行符。类似这样:

This is a sentence.This is another sentence.

要插入换行符,应在应分行的位置插入换行字符。在C++中,换行字符可以指定为\n(即反斜杠字符后跟小写字母n)。例如:

cout << "First sentence.\n";
cout << "Second sentence.\nThird sentence.";

这将产生以下输出:

First sentence.  
Second sentence.  
Third sentence.

或者,也可以使用endl操纵符来换行。例如:

cout << "First sentence." << endl;
cout << "Second sentence." << endl;

这将打印:

First sentence.
Second sentence.

endl操纵符生成换行符,与插入'\n'的效果完全相同;但它还有一个附加行为:流的缓冲区(如果有)将被刷新,这意味着请求物理写入设备(如果尚未完成)。这主要影响 完全缓冲 的流,cout通常不是 完全缓冲 的流。尽管如此,通常只有在刷新流是一项功能时才使用endl,而在不需要时使用'\n'。请记住,刷新操作会带来一定的开销,在某些设备上可能会产生延迟。

标准输入(cin)

在大多数程序环境中,标准输入默认是键盘,而C++流对象定义为访问它的是cin

对于格式化输入操作,cin提取运算符 一起使用,提取运算符写作>>(即两个“大于”符号)。然后,该运算符后跟存储提取数据的变量。例如:

int age;
cin >> age;

第一个语句声明一个名为ageint类型变量,第二个语句从cin中提取一个值并存储在其中。此操作使程序等待从cin输入;通常,这意味着程序将等待用户通过键盘输入一些序列。在这种情况下,注意到使用键盘输入的字符只有在按下ENTER(或RETURN)键时才会传输到程序。一旦执行到包含cin提取操作的语句,程序将等待,直到引入某些输入为止。
cin上的提取操作使用>>运算符后的变量类型来确定如何解释从输入中读取的字符;如果是整数,则期望格式是数字序列,如果是字符串,则是字符序列,等等。

// 输入/输出示例

#include <iostream>
using namespace std;

int main ()
{
  int i;
  cout << "Please enter an integer value: ";
  cin >> i;
  cout << "The value you entered is " << i;
  cout << " and its double is " << i*2 << ".\n";
  return 0;
}

如你所见,从cin提取似乎使从标准输入获取输入变得相当简单和直接。但是这种方法也有一个很大的缺点。如果用户输入了无法解释为整数的内容,该怎么办?在这种情况下,提取操作将失败。默认情况下,这会使程序继续执行而不为变量i设置值,如果稍后使用i的值,将产生不确定的结果。

这是非常糟糕的程序行为。大多数程序应无论用户输入什么都能按预期行为运行,适当地处理无效值。只有非常简单的程序才应该依赖从cin直接提取的值而不进一步检查。稍后我们将看到如何使用 stringstreams 来更好地控制用户输入。

cin上的提取操作也可以在一个语句中链式请求多个数据:

cin >> a >> b;

这等同于:

cin >> a;
cin >> b;

在这两种情况下,期望用户输入两个值,一个给变量a,另一个给变量b。任何类型的空格用于分隔两个连续的输入操作;这可以是空格、制表符或换行符。

cin和字符串

提取运算符可以在cin上用于获取字符串,就像对基本数据类型一样:

string mystring;
cin >> mystring;

然而,cin提取总是将空格(空格、制表符、换行符……)视为终止提取值,因此提取字符串总是提取单个单词,而不是短语或整个句子。

为了从cin获取整行,存在一个名为getline的函数,它将流(cin)作为第一个参数,字符串变量作为第二个参数。例如:

// 使用cin处理字符串
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string mystr;
  cout << "What's your name? ";
  getline (cin, mystr);
  cout << "Hello " << mystr << ".\n";
  cout << "What is your favorite team? ";
  getline (cin, mystr);
  cout << "I like " << mystr << " too!\n";
  return 0;
}

注意在两次调用getline时,我们使用了相同的字符串标识符(mystr)。程序在第二次调用时所做的只是用新输入的内容替换之前的内容。

大多数用户对控制台程序的标准行为是,每次程序查询用户输入时,用户输入字段,然后按ENTER(或RETURN)键。也就是说,输入通常以控制台程序中的行的形式进行,这可以通过使用getline从用户那里获取输入来实现。因此,除非有强烈的理由不这样做,否则在控制台程序中获取输入时应始终使用getline,而不是从cin提取。

stringstream

标准头文件<sstream>定义了一种类型,称为stringstream,允许将字符串视为流,因此允许从/向字符串进行提取或插入操作,就像对cincout进行操作一样。这个功能对于将字符串转换为数值或将数值转换为字符串非常有用。例如,为了从字符串中提取整数,我们可以写:

string mystr ("1204");
int myint;
stringstream(mystr) >> myint;

这声明了一个初始化为值"1204"的字符串和一个int类型的变量。然后,第三行使用这个变量从由字符串构造的stringstream中提取。这段代码将数值1204存储在名为myint的变量中。

// stringstreams 示例
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main ()
{
  string mystr;
  float price=0;
  int quantity=0;

  cout << "Enter price: ";
  getline (cin,mystr);
  stringstream(mystr) >> price;
  cout << "Enter quantity: ";
  getline (cin,mystr);
  stringstream(mystr) >> quantity;
  cout << "Total price: " << price*quantity << endl;
  return 0;
}

在此示例中,我们间接从 标准输入 获取数值:不是直接从cin提取数值,而是从中获取行并放入字符串对象(mystr),然后从这个字符串中提取值到变量pricequantity。一旦这些值是数值,就可以对它们执行算术操作,例如将它们相乘以获得总价。

通过这种获取整行并提取其内容的方法,我们将获取用户输入的过程与其作为数据的解释分离开来,使输入过程符合用户的期望,同时通过程序更好地控制其内容转换为有用的数据。

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值