C++ I/O流

一:流的概念

程序的輸入指的是從輸入文件將數據傳送給程序,程序的輸出指的是從程序將數據傳送給輸出文件。

C++輸入輸出包含以下三個方面的內容:

    對系統指定的標準設備的輸入和輸出。即從鍵盤輸入數據,輸出到顯示器屏幕。這種輸入輸出稱爲標準的輸入輸出,簡稱標準I/O

    以外存磁盤文件爲對象進行輸入和輸出,即從磁盤文件輸入數據,數據輸出到磁盤文件。以外存文件爲對象的輸入輸出稱爲文件的輸入輸出,簡稱文件I/O

    對內存中指定的空間進行輸入和輸出。通常指定一個字符數組作爲存儲空間(實際上可以利用該空間存儲任何信息)。這種輸入和輸出稱爲字符串輸入輸出,簡稱串I/O

 

C++I/OC的發展--類型安全和可擴展性

         C語言中,用printfscanf進行輸入輸出,往往不能保證所輸入輸出的數據是可靠的安全的。C++的輸入輸出中,編譯系統對數據類型進行嚴格的檢查,凡是類型不正確的數據都不可能通過編譯。因此C++I/O操作是類型安全(type safe)的。C++I/O操作是可擴展的,不僅可以用來輸入輸出標準類型的數據,也可以用於用戶自定義類型的數據。

         C++通過I/O類庫來實現豐富的I/O功能。這樣使C++的輸人輸出明顯地優於C 語言中的printfscanf,但是也爲之付出了代價,C++I/O系統變得比較複雜,要掌握許多細節。

         C++編譯系統提供了用於輸入輸出的iostream類庫。iostream這個單詞是由3個部分組成的,即i-o-stream,意爲輸入輸出流。在iostream類庫中包含許多用於輸入輸出的類。常用的見表

ios是抽象基類,由它派生出istream類和ostream類,兩個類名中第1個字母io分別代表輸入(input)和輸出(output) istream類支持輸入操作,ostream類支持輸出操作,iostream類支持輸入輸出操作。iostream類是從istream類和ostream類通過多重繼承而派生的類。其繼承層次見上圖表示。

C++對文件的輸入輸出需要用ifstrcamofstream類,兩個類名中第1個字母io分別代表輸入和輸出,第2個字母f代表文件 (file)ifstream支持對文件的輸入操作,ofstream支持對文件的輸出操作。類ifstream繼承了類istream,類ofstream繼承了類ostream,類fstream繼承了類iostream。見圖

I/O類庫中還有其他一些類,但是對於一般用戶來說,以上這些已能滿足需要了。

 

iostream類庫有關的頭文件

iostream類庫中不同的類的聲明被放在不同的頭文件中,用戶在自己的程序中用#include命令包含了有關的頭文件就相當於在本程序中聲明瞭所需 要用到的類。可以換—種說法:頭文件是程序與類庫的接口,iostream類庫的接口分別由不同的頭文件來實現。常用的有

  • iostream  包含了對輸入輸出流進行操作所需的基本信息。
  • fstream  用於用戶管理的文件的I/O操作。
  • strstream  用於字符串流I/O。
  • stdiostream  用於混合使用C和C + +的I/O機制時,例如想將C程序轉變爲C++程序。
  • iomanip  在使用格式化I/O時應包含此頭文件。

iostream頭文件中定義的流對象

iostream 頭文件中定義的類有 iosistreamostreamiostreamistream _withassign ostream_withassigniostream_withassign 等。

 

iostream頭文件中不僅定義了有關的類,還定義了4種流對象,

 

對象

含義

對應設備

對應的類

c語言中相應的標準文件

cin

標準輸入流

鍵盤

istream_withassign

stdin

cout

標準輸出流

屏幕

ostream_withassign

stdout

cerr

標準錯誤流

屏幕

ostream_withassign

stderr

clog

標準錯誤流

屏幕

ostream_withassign

stderr

 

iostream頭文件中定義以上4個流對象用以下的形式(以cout爲例):
    ostream cout ( stdout);
在定義coutostream流類對象時,把標準輸出設備stdout作爲參數,這樣它就與標準輸出設備(顯示器)聯繫起來,如果有
    cout <<3;
就會在顯示器的屏幕上輸出3

 

iostream頭文件中重載運算符

“<<”“>>”本來在C++中是被定義爲左位移運算符和右位移運算符的,由於在iostream頭文件中對它們進行了重載,使它們能用作標準類型數據的輸入和輸出運算符。所以,在用它們的程序中必須用#include命令把iostream包含到程序中。

    #include <iostream>

1)      >>a表示將數據放入a對象中。

2)      <<a表示將a對象中存儲的數據拿出。


二:標準I/O

標準I/O對象:cincoutcerrclog

cout流對象

contconsole output的縮寫,意爲在控制檯(終端顯示器)的輸出。強調幾點。

1) cout不是C++預定義的關鍵字,它是ostream流類的對象,在iostream中定義。顧名思義,流是流動的數據,cout流是流向顯示器的數據。cout流中的數據是用流插入運算符“<<”順序加入的。如果有
    cout<<"I "<<"study C++"<<"very hard. << “wang bao ming ";

按順序將字符串"I ", "study C++ ", "very hard."插人到cout流中,cout就將它們送到顯示器,在顯示器上輸出字符串"I study C++ very hard."cout流是容納數據的載體,它並不是一個運算符。人們關心的是cout流中的內容,也就是向顯示器輸出什麼。
2)“ccmt<<”輸出基本類型的數據時,可以不必考慮數據是什麼類型,系統會判斷數據的類型,並根據其類型選擇調用與之匹配的運算符重載函數。這個過程都是自動的,用戶不必干預。如果在C語言中用prinf函數輸出不同類型的數據,必須分別指定相應的輸出格式符,十分麻煩,而且容易出錯。C++I/O機制對用戶來說,顯然是方便而安全的。

3) cout流在內存中對應開闢了一個緩衝區,用來存放流中的數據,當向cout流插人一個endl時,不論緩衝區是否已滿,都立即輸出流中所有數據,然後插入一個換行符,並刷新流(清空緩衝區)。注意如果插人一個換行符”\n“(如cout<<a<<"\n"),則只輸出和換行,而不刷新cout (但並不是所有編譯系統都體現出這一區別)。
4) iostream中只對"<<"">>"運算符用於標準類型數據的輸入輸出進行了重載,但未對用戶聲明的類型數據的輸入輸出進行重載。如果用戶聲明瞭新的類型,並希望用"<<"">>"運算符對其進行輸入輸出,按照重運算符重載來做。

cerr流對象

cerr流對象是標準錯誤流,cerr流已被指定爲與顯示器關聯。cerr的作用是向標準錯誤設備(standard error device)輸出有關出錯信息。cerr與標準輸出流cout的作用和用法差不多。但有一點不同:cout流通常是傳送到顯示器輸出,但也可以被重定向輸出到磁盤文件,而cerr流中的信息只能在顯示器輸出。當調試程序時,往往不希望程序運行時的出錯信息被送到其他文件,而要求在顯示器上及時輸出,這時應該用cerrcerr流中的信息是用戶根據需要指定的。

clog流對象

clog流對象也是標準錯誤流,它是console log的縮寫。它的作用和cerr相同,都是在終端顯示器上顯示出錯信息。區別:cerr是不經過緩衝區,直接向顯示器上輸出有關信息,而clog中的信息存放在緩衝區中,緩衝區滿後或遇endl時向顯示器輸出。

 

三:標準輸入流

標準輸入流對象cin,重點掌握的函數

         cin.get()//一次只能讀取一個字符

         cin.get(一個參數) //讀一個字符

         cin.get(三個參數) //可以讀字符串

         cin.getline()

         cin.ignore()

         cin.peek()

         cin.putback()


//1 cin cout能根據類型 獲取數據 / 輸出數據
//2 輸入字符串 你 好  遇見空格,停止接受輸入
void main01()
{
	char YourName[50];
	int myInt;
	long myLong;
	double myDouble;
	float myFloat;
	unsigned int myUnsigned;

	cout << "請輸入一個Int: ";
	cin >> myInt;
	cout << "請輸入一個Long: ";
	cin >> myLong;
	cout << "請輸入一個Double: ";
	cin >> myDouble;

	cout << "請輸入你的姓名: ";
	cin >> YourName;

	cout << "\n\n你輸入的數是:" << endl;
	cout << "Int: \t" << myInt << endl;
	cout << "Long: \t" << myLong << endl;
	cout << "Double: \t" << myDouble << endl;
	cout << "姓名: \t" << YourName << endl;
	cout<< endl << endl;
	system("pause");
	return ;
}

//1 輸入英文 ok 
//2 ctr+z  會產生一個 EOF(-1)
int main02()
{
	char ch;
	while( (ch= cin.get())!= EOF)
	{
		std::cout << "字符: " << ch << std::endl;
	}
	std::cout << "\n結束.\n";
	system("pause");
	return 0;
}

//演示:讀一個字符 鏈式編程
void main03()
{
	char a, b, c;
	cin.get(a);
	cin.get(b);
	cin.get(c);
	cout << a << b << c<< endl;

	cout << "開始鏈式編程" << endl;
	cout.flush();

	cin.get(a).get(b).get(c);
	cout << a << b << c<< endl;
	system("pause");
	return ;
}


//演示cin.getline() 可以接受空格
void main04()
{
	char buf1[256];
	char buf2[256]; 
	cout << "\n請輸入你的字符串 不超過256" ;
	cin.getline(buf1, 256, '\n'); 
	cout << buf1 << endl;

	// 
	cout << "注意: cin.getline() 和 cin >> buf2 的區別, 能不能帶空格 " << endl;
	cin >> buf2 ; //流提取操作符 遇見空格 停止提取輸入流
	cout << buf2 << endl;
	system("pause");
}

//緩衝區實驗 
/*
1 輸入 "aa bb cc dd" 字符串入緩衝區 
2 通過 cin >> buf1; 提走了 aa 
3 不需要輸入 可以再通過cin.getline() 把剩餘的緩衝區數據提走
*/
void main05()
{
	char buf1[256];
	char buf2[256];

	cout << "請輸入帶有空格的字符串,測試緩衝區" << endl; 
	cin >> buf1;
	cout << "buf1:" << buf1 << endl; 

	cout << "請輸入數據..." << endl;

	//緩衝區沒有數據,就等待; 緩衝區如果有數據直接從緩衝區中拿走數據
	cin.getline(buf2, 256); 
	cout << "buf2:" << buf2 << endl;
	system("pause");
}

// ignore 和 peek
void main06()
{
	int  intchar;
	char buf1[256];
	char buf2[256];

	cout << "請輸入帶有空格的字符串,測試緩衝區 aa bb cc dd ee " << endl; 
	cin >> buf1;
	cout << "buf1:" << buf1 << endl; 

	cout << "請輸入數據..." << endl;
	cin.ignore(2);
	//intchar = cin.peek();
	//cout << "緩衝區若有數據,返回第一個數據的asc碼:" << intchar << endl;

	//緩衝區沒有數據,就等待; 緩衝區如果有數據直接從緩衝區中拿走數據
	cin.getline(buf2, 256); 
	cout << "buf2:" << buf2 << endl;

	intchar = cin.peek(); //沒有緩衝區 默認是阻塞模式 
	cout << "緩衝區若有數據,返回第一個數據的asc碼:" << intchar << endl;
	system("pause");
}

//案例:輸入的整數和字符串分開處理
int main07() 
{
	cout << "Please, enter a number or a word: ";
	char c = std::cin.get();

	if ( (c >= '0') && (c <= '9') ) //輸入的整數和字符串 分開處理
	{
		int n; //整數不可能 中間有空格 使用cin >>n
		cin.putback (c);
		cin >> n;
		cout << "You entered a number: " << n << '\n';
	}
	else
	{
		string str;
		cin.putback (c);
		getline (cin,str); // //字符串 中間可能有空格 使用 cin.getline();
		cout << "You entered a word: " << str << '\n';
	}	system("pause");
	return 0;
}
四:標準輸出流

/*

標準輸出流對象cout

         cout.flush()

         cout.put()

         cout.write()

         cout.width()

         cout.fill()

         cout.setf(標記)

*/

/*

manipulator(操作符、控制符)

flush

endl

oct

dec

hex

setbase

setw

setfill

setprecision

*/




#include "iostream"
using namespace std;
#include <iomanip> 

void main81()
{
	cout << "hello world" << endl;
	cout.put('h').put('e').put('l').put('\n');
	cout.write("hello world", 4); //輸出的長度

	char buf[] = "hello world";
	printf("\n");
	cout.write(buf, strlen(buf));

	printf("\n");
	cout.write(buf, strlen(buf) - 6);

	printf("\n");
	cout.write(buf, strlen(buf) + 6); //給的大於buf長度 不會幫我們檢查 提高速度

	printf("\n");
	
	system("pause");
	return ;
}

//使用cout.setf()控制符
void main82()
{
	//使用類成員函數
	cout << "<start>";
	cout.width(30);
	cout.fill('*');
	cout.setf(ios::showbase); //#include <iomanip>
	cout.setf(ios::internal); //設置
	cout << hex << 123 << "<End>\n";

	cout << endl;
	cout << endl;
	//manipulator(操作符、控制符)

	//使用控制閥
	cout << "<Start>" 
		<< setw(30) 
		<< setfill('*') 
		<< setiosflags(ios::showbase) //基數
		<< setiosflags(ios::internal)
		<< hex
		<< 123
		<< "<End>\n"
		<< endl;

	system("pause");
}

最後補一些關於格式化輸出的知識:

C++格式化輸出,C++輸出格式控制

在輸出數據時,爲簡便起見,往往不指定輸出的格式,由系統根據數據的類型採取默認的格式,但有時希望數據按指定的格式輸出,如要求以十六進制或八進制形式輸出一個 整數,對輸出的小數只保留兩位小數等。有兩種方法可以達到此目的。

1)使用控制符的方法;

2)使用流對象的有關成員函數。分別敘述如下。

 


int main()
{
	int a;
	cout<<"input a:";
	cin>>a;
	cout<<"dec:"<<dec<<a<<endl; //以十進制形式輸出整數
	cout<<"hex:"<<hex<<a<<endl; //以十六進制形式輸出整數a
	cout<<"oct:"<<setbase(8)<<a<<endl; //以八進制形式輸出整數a
	char *pt="China"; //pt指向字符串"China"
	cout<<setw(10)<<pt<<endl; //指定域寬爲,輸出字符串
	cout<<setfill('*')<<setw(10)<<pt<<endl; //指定域寬,輸出字符串,空白處以'*'填充
	double pi=22.0/7.0; //計算pi值
	//按指數形式輸出,8位小數
	cout<<setiosflags(ios::scientific)<<setprecision(8);
	cout<<"pi="<<pi<<endl; //輸出pi值
	cout<<"pi="<<setprecision(4)<<pi<<endl; //改爲位小數
	cout<<"pi="<<setiosflags(ios::fixed)<<pi<<endl; //改爲小數形式輸出
	system("pause");
	return 0;
}


發佈了35 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章