1、简单提示输入和输出
2、为格式化提供操作符和标志
3、输入和输出对象类型
4、解析输入例子(日期确认)
1、简单提示输入和输出
最常用的程序结合输入和输出来沟通,从他们信息(输入)中为用户呈现有用的信息(输出)。无论什么程序一旦离开输入或者输出功能就是没有用的!
命令行的输入和输出是一个程序与用户之间的互动。虽然命令行界面是如此的单调,但至少可以说,这是最基本和最快捷的执行。
一个C++程序可以执行输入和输出有好几种方式,最常见的是通过使用流。“流”这个词语的直觉是一个程序“看”只有输入或输出,而不是起源(源)或数据的目的地。一个常见的比喻,当水从你的脚边流过,你看见你脚下的水却不知道这水从哪里来又要流到哪里去。
一个输出例子。
#include <iostream>
namespace std;
using namespace std;
int main(){
cout << "Hello,world.\n"; // The simple "Hello World" example.
return 0;
}
用cout和插入操作符(“<<”)应该始终显示在屏幕终端。
输入就像输出一样使用cin和提取操作(“>>”)。cin是最好想法的语法用来获取从键盘输入。尽管使用cin靠近提取操作时所有空白被忽略和跳过。使用复合的提取操作来处理字符串,可能会产生不可预期的运行时效果-通常被称为缓冲区问题-适当的对于用户的不可预测性和他们古怪的输入。
提取操作是最保守的用来数字输入或者用来可预测性的格式输入-通常来自一个准备好的文件。
cout派生自ostream类和cin是派生自istrem类。继承是很有用处的,等下介绍。
获取用户最安全的方式是使用重载成员函数get()通常很多程序员都这么做。
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char unit;
bool boolExit = true;
do
{
cout << "Enter Compass Direction.";
cin.get(unit); // Get a single character.
while('\n' != cin.get()); // Clear Buffer.
switch(unit)
{
case 'n':
case 'N':
cout << "North.";
break;
case 's':
case 'S':
cout << "South.";
break;
case 'e':
case 'E':
cout <<"East.";
break;
case 'w':
case 'W':
cout <<"West.";
break;
default:
cout << "Check Your Compass.\n";
boolExit = false;
break;
}
} while ( !boolExit);
return 0;
}
前面这个例子的程序请求用户输入,程序预期一个单独的字符。然而用户不会注意到这个单独字符的条件,因此程序员的职责需要预料和处理所有可能的输入-包括“愚蠢”的输入。
例子中,只有用户在输入第一个字符来试着存储和验证。所有其他后面的字符串会被这一行“吃掉”:while( '\n' == cin.get() );这会避免缓冲区问题和停止do..while loop 重复的一遍又一遍的同时从一个长的字符串获取各个字符和阻止转储“Check Your Compass”。大家都清楚没有清除缓冲会遇到不良运行时效果。使用流时出现缓冲错误是很常见的。记住要要永远清除缓冲!
程序要能处理用户输入不同长度的字符和有效率的方式存储输入在内存中。通过使用指针可以达到这个目的。
记住指针是一个保存一段运行时在堆上分配预留内存的首地址。一个指针可以“指向”所有类型的变量。一个指针甚至可以指向另外一个指针。
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char buffer[101], * said;
cout << "Enter:";
cin.get(buffer, 101, '\n');
while('\n' != cin.get());
said = new char[strlen(buffer)+1];
strcpy(said, buffer);
cout << "Echo:" << said;
delete []said;
system("pause");
return 0;
}
前面这个例子第一申明了一个正常的cstring, 有充足的缓冲。第二,一个新的动态的cstring的大小是由通过strlen()函数取得缓冲的大小再增加1用来存放null终止符。显然这样可以节省内存,如果要存储有多个cstring,而不是分配相同的固定长度为每个cstring的。
由于输出可能要被“分流”到不同的目的地,比如,给的低劣的屏幕或文本文件,继承的使用。
#include <iostream>
#include <fstream>
using namespace std;
void stream2(ostream& os, char *);
int _tmain(int argc, _TCHAR* argv[])
{
stream2(cout, "Hello World.\n");
char *say = "And Hello again.\n";
stream2(cout, say);
ofstream outFile;
outFile.open("sample.txt");
stream2(outFile, say);
outFile.close();
return 0;
}
void stream2(ostream& os, char *say)
{
os << say;
return;
}
前面这个例子,ostream类是作为函数stream2()的一个参数。这是因为继承允许许多输入流通过函数体,包括ofstream类型的文件流和ostream类型的标准cout。
也有一些与char say[] = "Whatever"很相似;而不是char *say="Whatever";。大多数人会说这两个代码片段没什么不同。那么,这两者之间是否有所不同呢?当然有。使用数组在静态内存块标记了9个字节的存储,8个字符加上一个NULL字符。然而,指针同样标记了需要的9个字节,另外有两个字节来保存引用char2say的指针变量。
继承是C++一个强大的特征,用来派生类。简单地说,一个派生类使用一个现有的类,但是添加了独特的功能(额外的特征)类形成一个新的类。比如,cout和ofstream同样都派生自ostream类-ofstream类增加额外的成员函数像open()和close()。cin和ifstream同样派生自istream类。
需要注意的是一个流可以成为一个函数的参数,唯一的限制是这个函数的形参必须传引用而不是传值。
一些有用的流控制函数的概况:
istream::get() 从istrem获取和返回一个字符-包含空白字符。
istream::get(char&) 从istream获取一个字符并且存储到参数别名的引用。也包含空白字符。
istream::get(char*, int ,char) 从istream处不断获取字符直到整数限制-1到达,找到分界字符,或者到达流的末尾。获取的字符存储到给定的由null终结的cstring。如果分界符找到了,那么它不提取也不存放。这个也包含空白字符。
ostream::put(char) 放一个单独发字符到ostream中。
istream::putback(char) 将一个字符放回到istream。这个字符必须是刚刚提取的,否则其结果未定义。