C++的輸入、輸出與文件

1、

C++的輸入、輸出分爲基於控制檯的輸入/輸出、基於文件的輸入/輸出和基於字符串的輸入/輸出。


在輸入操作中,字節從設備(如鍵盤、磁盤)流向內存,稱爲輸入流。

在輸出操作中,字節從內存流向設備(如顯示器、打印機、磁盤等)稱爲輸出流。

C++還提供了無格式輸入/輸出和格式化輸入/輸出兩種操作,無格式的傳輸速度快,格式化的按不同類型、不同格式對數據進行處理,不適合大容量的數據傳輸。

在C++中:iostream 定義了基於控制檯的輸入/輸出類型,fstream定義了基於文件的輸入/輸出類型;sstream定義了基於字符串的輸入/輸出類型



2、輸出輸出的緩衝

當用戶在鍵盤上輸入數據時,在按了回車鍵後,輸入的數據及回車鍵被傳送到cin對象的緩衝區中,

當執行>>操作時,從cin對象緩衝區中取數據存入變量,如果緩衝區無數據,程序暫停,等待外圍設備傳送數據到cin緩衝區,<<操作時將數據放入輸出緩衝區,如

os<<"please enter the value";

下面幾種情況導致緩衝區的內容被刷新:

(1)、程序正常結束,main函數結束會清空所有的輸出緩衝區

(2)、當緩衝區已滿,在寫入下一個值之前,會刷新緩衝區

(3)、用標準的操作符,如行結束符endl,顯式地刷新緩衝區

(4)、可將輸出流與輸入流關聯起來,在這種情況下,讀輸入流時刷新其相關聯的輸出緩衝區,在標準庫中,將cout和cin關聯在一起,因此每個輸入操作都將刷新cout關聯的緩衝區

基於控制檯的輸入輸出

1、在C++中,如果輸出的指針變量是一個指向字符的指針時,C++並不輸出該指針中保存的地址,而是輸出該指針指向的字符串,如果確實像輸出這個指向字符的指針變量中保存的地址,可以用強制類型轉換,將它轉換成void *類型,事實上,如果程序員想輸出地址,最好都把指針轉換成void *類型。

#include<iostream>
using namespace std;
int main(void)
{
char *ptr="abcdef";
cout<<"ptr指向的內容爲:"<<ptr<<endl;
cout<<"ptr中保存的地址爲:"<<(void *)ptr<<endl;

return 0;
}


結果:

abcdef
0x440000

2、通過put成員函數進行字符輸出

字符型數據還可以通過成員函數put來輸出,put函數有一個字符類型的形式參數,它的返回值是調用put函數對象的引用。例如:

cout.put('A');

將字符A顯示在屏幕上,而

cout.put(65);

輸出ASCII碼值爲65的字符,輸出也是字符A。

由於put函數的返回值是當前對象的引用,因此可以連續調用put函數:

cout.put('A').put('\n');

3、通過write成員函數進行無格式的輸出

它有兩個參數:第一個參數是一個指向字符的指針,表示一個字符數組;第二個參數是一個整型值,表示輸出的字符的個數

例如:

char buffer[]="HAPPY BIRTHDAY";

cout.write(buffer,10);

輸出buffer中的10個字節,函數調用

cout.write("adsfjlkl;weio",10);

顯示了字母表中前10個字母

write函數在控制檯輸入/輸出中的應用非常有限,它主要被用於文件訪問。

4、通過get和getline成員函數進行字符和字符串的輸入

get函數有3中格式,即不帶參數、帶1個參數和帶3個參數

i;不帶參數的個體函數從當前的輸入流對象讀入一個字符,包括空白字符以及表示文件結束的EOF,並將讀入值作爲函數的返回值返回如:

while((ch=cin.get())!=EOF) cout<<ch;

ii、get函數帶一個參數它將輸入流中的下一個字符存儲在參數中,他的返回值是當前輸入流對象的引用如:

cin.get(ch[0]);

for(i=0;ch[i]!='\n';i++)

cin.get(ch[i+1]);

ch[i]='\0';

iii、get函數有3個參數,即字符數組、數組規模和表示輸入結束的結束符(結束符默認‘\n’)

get(ch,80,'\n'); 也可以用get(ch,80);

get(ch,80,'.');當遇到輸入結束符“.”或輸入字符數達到79時,函數執行結束,輸入結束符沒有放在字符數組中,而是保留在了輸入流中,下一個和輸入相關的語句會讀入這個輸入結束符get(ch,80,'.');

輸入

abcdef.回車

則ch中存放字符串“abcdef”,而“.“仍保留在輸入緩衝區中,如果繼續調用cin.get(ch1)或cin>>ch1;則字符變量ch1中保存的是”.“

getline()函數功能和第三種形式的get函數類似,它也有3個參數,參數類型和作用與第三種形式的get函數完全相同,這兩個函數的唯一區別是對輸入結束符的處理,get函數將輸入結束符留在輸入流中,而getline函數將輸入結束符從輸入流中刪除

5、通過read函數進行無格式的輸入

char buffer[80];

cin.read(buffer,10);

不管輸入緩衝區有多少個字節,都只讀入10個字節,放入buffer。

#include<iostream>
using namespace std;
int main(void)
{
char buffer[80];
cout<<"enter a sentence:\n";
cin.read(buffer,20);
cout<<"\nThe crsentence entered was :\n";
cout.write(buffer,cin.gcount());
cout<<endl;
cout<<"一共輸入了"<<cin.gcount()<<"個字符\n";
return 0;
}


結果:

enter a sentence:
erwwer
asdfsdf
sadf


The sentence entered was :
erwwer
asdfsdf
sadf


一共輸入了20個字符
請按任意鍵繼續. . .


格式化的輸入、輸出

輸入、輸出流中的整型默認爲十進制表示,爲了使流中的整形數不侷限與十進制,可以插入hex操縱符將基數設爲十六進制,插入oct操縱符將基數設爲八進制,也可以插入dec操縱符將基數重新設爲十進制。

改變輸入輸出流中整形數的基數也可以通過流操縱符setbase來實現,該操縱符有一個整形參數,它的值可以是16、10、8

#include<iostream>
#include<iomanip>
using namespace std;
int main(void)
{
int n;
cout<<"enter a octal number";
cin>>n;
cout<<"octal"<<oct<<n<<" in hexdecimal is :"<<hex<<n<<'\n';
cout<<"hexdecimal"<<n<<" in decimal is :"<<dec<<n<<'\n';
cout<<setbase(8)<<"octal"<<n<<"in octal is:"<<n<<endl;
return 0;
}


結果:

enter a octal number30
octal36 in hexdecimal is :1e
hexdecimal1e in decimal is :30
octal36in octal is:36
請按任意鍵繼續. . .


設置浮點數的精度可以用precision來實現

設置域寬:cin>>sew(n)>>n

打印一個區域的操作:  cout<<n1<<tab<<n2<<endl;

文件和流:

C++文件沒有記錄,它只是把文件看成是字節序列,每一個文件以文件結束符(EOF)結束,這種文件稱爲流式文件,可以把將C++的文件看成一個字符串,只不過這個字符串不是放在內存中而是存放在外村中,不是以'\0'結束,而是用EOF結束。

C++文件又被分爲ASCII文件和二進制文件,ASCII文件也被稱爲文本文件。二進制文件是指將每個字節僅看成是一個二進制位串,

ifstream是輸入文件流類,當要從文件讀取數據時,必須定義一個ifstream類的對象與之關聯,ofstream是輸出文件流類,當要向文件寫數據時,必須定義一個ofstream類的對象與之關聯。fstream類的對象即可以讀也可以寫,如:

ifstream in;

infile>>x; //可以將這個對象像cin一樣使用。

文件打開模式:

in                      打開文件,做讀操作

out                    打開文件,做寫操作

app                   在文件尾後面添加

ate                    打開文件後,立即將文件定位在文件尾

trunc                 打開文件,清空文件

binary               以二進制模式進行輸入、輸出操作,默認爲ASCII文件

========================================================

ifstream流對象默認以in模式打開,該模式只允許對文件執行讀操作;與ofstream流關聯的文件則以out模式打開,使文件可寫,以out模式開始文件時,如果文件不存在,會自動創建一個空文件,否則將被打開的文件清空,丟棄該文件原有數據;對於fstream流關聯的對象,默認打開方式是in|out,表示同時以in|out的方式打開,使文件即可讀又可寫,當同時以in 和out方式打開時,文件不會清空,如果ofstream的對象在打開時想要保存源文件中的數據,可以指定app模式打開,這樣寫入文件的數據將被添加到被添加到源文件數據後面。

*讀入數據:

ifstream infile;

infile.open("file1");

也可以利用構造函數直接打開:

ifstream infile("file1");

ifstream infile("file1",ifstream::in);

*寫入數據:

ofstream outfile;

outfile.open("file2");

也可以利用構造函數直接打開:

ofstream outfile("file1");

ofstream outfile("file1",ofstream::out);

*即可以讀也可以寫:

fstream iofile("file3");

顯示打開:fstream iofile ("file3",fstream::in | fstream::out);  //這樣不會清空數據

如果打開文件時定義了trunc模式,則無論是否指定in模式都會清空文件


如果文件打開成功,流對象會得到一個非0值,如果打開不成功,流對象將會得到值0,在打開文件後檢查文件打開是否成功是一個良好的程序設計習慣;

當文件訪問結束時,應該斷開文件與文件流對象的關聯,用  file.close();

文件的順序訪問

在讀文件操作中,經常要判斷文件是否結束,如果是使用>>或get函數讀文件,可以通過檢查>>的返回值是否爲false或get函數讀入的字符是否爲EOF來判斷,如果是使用read函數讀文件,可以通過基類ios的成員函數eof來實現,eof不需要參數,返回一個整型值,當讀操作遇到文件結束時,該函數返回true,否則返回false;

 #include<iostream>
#include<fstream>
using namespace std;
int main(void)
{
ofstream out("d:\\11.txt");//定義輸出流,並與file關聯
ifstream in;  //定義一個輸入流
int i;
if(!out)
{
cerr<<"create file error\n";
return 1;
}
for(i=1;i<=10;i++)
{
out<<i<<' ';    //將1到10寫到輸出流對象
}
out.close();
in.open("d:\\11.txt");  //重新以in的方式打開文件file
if(!in)
{ 
cerr<<"open file error\n";
return 1;
}
while(in>>i)              //讀文件,直到遇到文件結束
{
cout<<i<<' ';
}
in.close();
return 0;
}


1 2 3 4 5 6 7 8 9 10 請按任意鍵繼續. . .

讀取一個包含各種類型數據的文件操作的實例程序

#include<iostream>
#include<fstream>
using namespace std;
int main(void)
{
ifstream  fin("d:\\11.txt");
char s[80];
int i;
float x;

if(!fin)
{
cout<<"cannot open input file\n";
return 1;
}
fin>>i>>x>>s;
cout<<i<<" "<<x<<s<<endl;
fin.close();
return 0;
}


11.txt中內容:10 12.56"this is a file"

輸出爲:10 12.56"this

結果之所以這樣,是因爲在用流提取運算符讀字符時是以空白字符作爲結束符的,所以讀到了“this”

如果要讀入這個完整的字符串,可以其他的成員函數,如getline()----->fin>>i>>x>>getline(s,80,'\n')


文件隨機處理

文件定位指針是一個long類型的數據,表示當前讀寫的是文件的第幾個字節,ifstream和ofstream分別提供了成員函數tellg和tellp返回文件定位指針的當前位置,其中g表示get,p表示put,tellg返回讀文件定位指針,tellp返回寫文件定位指針。

當文件以in方式打開時,文件定位指針指向文件頭,所以讀文件是從頭開始讀的,當以out方式打開時,寫文件定位指針也是定位在文件頭,所以新寫入的內容覆蓋了文件原有信息。

ifstream和ofstream都提供了成員函數來重新設置文件定位指針,在ifstream,這個函數爲seekg,在ofstream,這個函數爲seekp,seekp和seekg函數有兩個參數,第一個參數爲long類型的整數,表示偏移;第二參數指定指針移動的參考的,ios::beg(默認)相對於流的開頭,ios::cur相對於文件定位指針的當前位置,ios::end 相對於流結尾;如in.seekg(0)表示將讀文件指針定位到輸入流in的開始處,in.seekg(10,ios::cur)表示定位到輸入流in當前位置後面的第10個字節。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章