今天看C++的输入和输出
今天的部分内容我参考了http://www.runoob.com/cplusplus/cpp-basic-input-output.html
C++ 的 I/O 发生在流中,流是字节序列。如果字节流是从设备(如键盘、磁盘驱动器、网络连接等)流向内存,这叫做输入操作。如果字节流是从内存流向设备(如显示屏、打印机、磁盘驱动器、网络连接等),这叫做输出操作。
C ++使用一种称为流的抽象操作来在顺序媒体(如屏幕,键盘或文件)中执行输入和输出操作。一个流是一个程序可以插入或提取字符的实体。无需了解与流相关的媒体或其任何内部规范的详细信息。我们需要知道的是,流是字符的源/目的地,并且这些字符是顺序提供/接受的(即一个接着一个)。
I/O 库头文件
下列的头文件在 C++ 编程中很重要。
头文件 | 函数和描述 |
iostream | 该文件定义了 cin、cout、cerr 和 clog 对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。 |
iomanip | 该文件通过所谓的参数化的流操纵器(比如 setw 和 setprecision),来声明对执行标准化 I/O 有用的服务。 |
fstream | 该文件为用户控制的文件处理声明服务。我们将在文件和流的相关章节讨论它的细节,在文件中输入或输出用。 |
流 | 描述 |
cin | 标准输入流 |
cout | 标准输出流 |
cerr | 标准错误(输出)流 |
clog | 标准日志记录(输出)流 |
- 标准输出(cout)
在大多数程序环境中,默认情况下标准输出是屏幕,并且定义cout为访问它的C ++流对象
对于格式化输出操作,cout与插入操作符一起使用,编写为<<(即两个“小于”符号)。
cout << "Output sentence"; // prints Output sentence on screen
cout << 120; // prints number 120 on screen
cout << x; // prints the value of x on screen
所述<<操作符将它后面的数据插入到它前面的流中。在上面的示例中,它将文字字符串Output sentence,数字120和变量值x的值插入到标准输出流中cout。请注意,第一个语句中的句子用双引号(")括起来,因为它是一个字符串文字,而在最后一个中x则不是。双引号是产生差异的原因; 当文本被包含在双引号之间时,文本按字面打印; 如果不是,则将文本解释为变量的标识符,打印其值。例如,这两个句子的结果差异很大:
cout << "Hello"; // prints Hello 打印Hello
cout << Hello; // prints the content of variable 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 <<“这是一个句子。”;
cout <<“这是另一句话。”;
上面两句话会显示在一行。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操作符产生一个换行符,确实是完全一样的插入; 但它还有一个额外的行为:流的缓冲区(如果有的话)被刷新,这意味着即使还没准备好,output流中的信息也会被物理的输出到终端。这主要影响完全缓冲的流,和(通常)不是完全缓冲的流。尽管如此,通常只有当刷新流是应该的的时候和\n不起作用的时候使用才是一个好主意。请记住,刷新操作会产生一定的开销,并且在某些设备上可能会产生延迟。
-
标准输入(cin)
在大多数程序环境中,默认情况下标准输入是键盘,并且定义为访问它的C ++流对象是cin。
对于格式化的输入操作,cin与提取操作符一起使用,该操作符被写为>>(即,两个“大于”符号)。然后,该运算符后跟cin提取数据存储的变量(总感觉很怪)。例如:int age;
cin >> age;
第一个语句声明一个被调用int类型的变量,第二个语句cin将一个值提取存储在age中。此操作使程序等待从cin的输入; 通常,这意味着程序将等待用户使用键盘输入一些序列。在这种情况下,请注意使用键盘引入的字符仅在按下ENTER(或RETURN)键时传输到程序。一旦运行到要提取操作的cin语句,程序将等待所需的时间,直到得到一些输入。
提取操作cin使用后的变量类型>>运算符,用于确定它用什么格式来读取从输入中读取的字符; 如果它是一个整数,则期望的格式是一系列数字,如果字符串则期望是一系列字符,等等。// i/o example #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; }
结果:
Please enter an integer value: 702
The value you entered is 702 and its double is 1404.
正如你看到的,用cin似乎使得从标准输入提取获得输入的任务变得非常简单和直接。但这种方法也有很大的缺点。如果用户输入了无法解释为整数的其他内容,上面的示例会发生什么?那么,在这种情况下,提取操作失败。默认情况下,这使得程序可以在不设置变量i值的情况下继续运行,如果稍后使用该i值,则会生成未确定的结果。
这是非常糟糕的程序行为。无论用户类型如何,大多数程序都应以预期的方式运行,并适当地处理无效值。只有非常简单的程序才能依赖直接提取的cin值而无需进一步检查。稍后我们会看到如何stringstreams可用于更好地控制用户输入。
提取cin也可以连接在一个语句中请求多个数据:
cin >> a >> b;
这相当于:
cin >> a;
cin >> b;
在这两种情况下,用户都需要引入两个值,一个用于变量a,另一个用于变量b。任何类型的空间用于分隔两个连续的输入操作; 这可以是空格,tab或换行符。
-
cin and strings
提取运算符cin可用于像基本数据类型那样获取字符串:
但是,cin提取始终将空格(空格,制表符,换行符…)视为终止要提取的值,因此提取字符串意味着始终提取单个单词,而不是短语或整个句子。
cin为了获得整行,存在一个函数,称为getline,将stream(cin)作为第一个参数,将字符串变量作为第二个参数。例如:// cin with strings
#include “iostream.h”
#include “string.h”
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;
}
结果是:
What’s your name? Homer Simpson
Hello Homer Simpson.
What is your favorite team? The Isotopes
I like The Isotopes too!
请注意,在两次调用中getline,我们使用相同的字符串标识符(mystr)。程序在第二次调用中所做的只是将之前的内容替换为引入的新内容。
大多数用户期望从控制台程序获得的标准行为是,每次程序向用户查询输入时,用户都会引入该字段,然后按ENTER(或RETURN)。也就是说,通常期望输入根据控制台程序上的行发生,并且这可以通过使用getline来获得来自用户的输入来实现。因此,除非你有充分的理由不这样做,否则你应该总是使用getline在控制台程序中获取输入而不是用cin从中提取。(事实上我之前一直都是用的cin,提取行用的是自己写的函数,想想真是很麻烦,一般国内教材好像很少说getline这个函数或者我自己看的太少了)。
-
字符串流
标准头sstream.h定义了一种称为stringstream的函数允许将字符串视为流的类型,从而允许从/向字符串提取或插入操作的方式与执行cin和执行cout相同。此功能对于将字符串转换为数字值非常有用,反之亦然。例如,为了从字符串中提取整数,我们可以编写:string mystr (“1204”);
int myint;
stringstream(mystr) >> myint;
这段代码第一行声明string类型的变量mystr并赋初值"1204",第二行声明一个int类型的变量myint,第三行用stringstream提取mystr中的int赋值给myint,myint的值为1204。// stringstreams
#include “iostream.h”
#include “string.h”
#include “sstream.h”
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;
}
结果是:
Enter price: 22.25
Enter quantity: 7
Total price: 155.75
在这个例子中,我们间接从标准输入中获取数值:不是直接从中提取数值cin,而是从它获取行到字符串对象(mystr),然后我们从这个字符串中提取值到变量price和quantity。一旦这些是数值,就可以对它们执行算术运算,例如将它们相乘以获得总价格。
通过这种获取整行和提取内容的方法,我们将获取用户输入的过程与其作为数据的解释分开,允许输入过程成为用户期望的过程,同时获得对其转换的更多控制。通过程序将内容转换为有用的数据。