輸入輸出流
1. 用控制符輸出格式,例:
1 #include <iostream> 2 #include <iomanip>//利用控制符輸出必須包含iomanip頭文件 3 using namespace std; 4 int main() 5 {int a; 6 cout<<"input a:"; 7 cin>>a; 8 cout<<"dec:"<<dec<<a<<endl; //以十進制輸出 9 cout<<"hex:"<<hex<<a<<endl; //十六進制 10 cout<<"oct:"<<setbase(8)<<a<<endl; //八進制 11 char *pt="China"; 12 cout<<setw(10)<<pt<<endl; //寬度為10,China前補上5個空格 13 cout<<setfill('*')<<setw(10)<<pt<<endl; //China前補上5個* 14 double pi=22.0/7.0; 15 cout<<setiosflags(ios::scientific)<<setprecision(8);//科學記數法,8位小數 16 cout<<"pi="<<pi<<endl; //輸出pi 17 cout<<"pi="<<setprecision(4)<<pi<<endl; //改為4位小數 18 cout<<"pi="<<setiosflags(ios::fixed)<<pi<<endl;//去掉科學記數法 19 return 0; 20 }
控制符用法列表如下:
2. 用流對象cout中用於控制輸出格式的成員函數來控制輸出格式
例如:
cout.setf(iso::showbase)
cout.setf(iOS::oct)
cout.width(10)
cout.setf(ios::internal | ios::showpos)
等等,其中參數iso::showbase屬於格式標志,是在類ios中定義的枚舉值。因為用流控制成員函數沒有控制符使用方便,所以一般不常用。
3. put函數(cout對象的成員函數)
作用:輸出單個字符,例如:
cout.put(‘a’); //等價於cout.put(97),97為a的ASCII碼
cout.put(71).put(79).put(79).put(68).put(‘\n’);//連續輸出字符GOOD
將字符串“BASIC”反序輸出:
1 #include <iostream> 2 using namespace std; 3 int main( ) 4 { 5 char *a="BASIC"; 6 for(int i=4;i>=0;i--) 7 cout.put(*(a+i)); 8 cout.put('\n'); 9 return 0; 10 }
也可以用C語言的格式:將上面的cout.put()改成putchar()
4. cin.get()提取一個字符,類似於C語言中的getchar(),但是它可以有3個參數:
cin.get(字符數組,字符個數n,終止字符)
例如:cin.get(ch, 10, ‘\n’); cout<<ch<<endl;
get函數中第三個參數可以省略,此時默認為’\n’。下面兩行等價:
cin.get(ch, 10, ‘\n’);
cin.get(ch, 10);
終止字符也可以用其他字符,例如:
cin.get(ch,10,’x’);
5. cin.getline用於輸入一個字符串
用法:cin.getline(char*,int,char),ENTER來結束輸入,例如:
1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 const int ArSize = 20; 6 char name[ArSize]; 7 char dessert[ArSize]; 8 9 cout<<"Enter your name:\n"; 10 cin.getline(name,ArSize); 11 cout<<"Enter your favorite dessert:\n"; 12 cin.getline(dessert,ArSize); 13 cout<<"I have some delicious "<<dessert; 14 cout<<" for you, "<<name<<".\n"; 15 return 0; 16 }
cin<<與cin.getline()的區別:用“cin<<”讀數據時以空白字符(空格、tab、回車)作為終止標志,而用cin.getline()可以讀入一系列字符,包括空格。例如:
char c[30];//輸入I’m a good boy !
cin>>c;// c只能得到第一個空格前的I’m
cin.getline(c);//c可以得到整句I’m a good boy !
6. eof函數
eof是end of file的縮寫,表示“文件結束”,eof函數值為非零表示真,否則為0表示假。例如:
1 #include <iostream> 2 using namespace std; 3 int main( ) 4 { 5 char c; 6 7 while (!cin.eof()) 8 { 9 if( (c=cin.get()) != ' ') 10 cout.put(c); 11 } 12 return 0; 13 }
當輸入Ctrl+Z時,cin.eof()就為真,!cin.eof()則為假,所以結束while循環。
7. cin.peek()函數和cin.putback()函數
用法見下面程序的注釋:
1 #include <iostream> 2 using namespace std; 3 int main( ) 4 { 5 char c[30]; 6 char w; 7 cin.getline(c, 30, '^');//輸入I am a cool boy !^'m bad girl.^ 8 w=cin.peek();//獲取當前指針(指向^)的下一個字符(即’) 9 cout.put(w).put('\n'); 10 cin.putback(c[0]);//獲取前面get或者getline中的一個字符,插入到當前字符前(即w前) 11 cin.getline(c, 30, '^'); 12 cout<<c<<endl; 13 return 0; 14 }
即,我們可以用cin.peek()函數來獲取當前輸入流指針的當前指向;可以用cin.putback()來獲取前面get或getline函數輸入的內容中的一個字符,並插入到當前流指針的前面。
8. cin.ignore()函數
用法cin.ignore(5, ‘A’); //從當前指針位置(不包括當前指針)開始,忽略後面cin輸入的5個字符,或者遇到字符’A’就不再往後跳了(‘A’會被跳過)。
默認寫作:cin.ignore(),相當於cin.ignore(1, EOF),EOF代表文件結束符
例如:
1 #include <iostream> 2 using namespace std; 3 int main( ) 4 { 5 char c[30]; 6 cin.getline(c, 30, '^');//輸入I am a cool boy !^123I'm bad girl.^I’m smart. 7 cout<<"The first part is: "<<c<<endl; 8 cin.ignore(3);//忽略掉^後面的1233個字符 9 cin.getline(c, 30, '^'); 10 cout<<"The second part is: "<<c<<endl; 11 return 0; 12 }
9.文件
(1)ASCII文件(類名ifstream、ofstream和fstream,存入是out,讀取是in)
a. 存入文件
ofstream outfile;
outfile.open("f1.dat",ios::out); // ios::out(格式標志)是默認的,故也可以省略
上面兩行等價於:
ofstream outfile("f1.dat",ios::out);
現在可以用outfile對象來存入數據了:
cin>>a[i];
outfile<<a[i]<<" ";//每讀入一個整數就輸出到磁盤文件
用完記得,關閉文件:
outfile.close();
文件輸入輸出格式標志如下:
完整實例:
1 /*將鍵盤輸入的數據存入文件中*/ 2 #include <fstream> 3 #include <iostream> 4 using namespace std; 5 int main( ) 6 { 7 int a[10]; 8 ofstream outfile("f1.dat",ios::out); 9 if(!outfile) 10 { 11 cerr<<"open error!"<<endl; 12 exit(1); 13 } 14 cout<<"enter 10 integer numbers:"<<endl; 15 for(int i=0;i<10;i++) 16 { 17 cin>>a[i]; 18 outfile<<a[i]<<" ";//每讀入一個整數就輸出到磁盤文件 19 } 20 outfile.close();//記住關閉文件 21 return 0; 22 }
生產的f1.dat文件可以用記事本打開,也可以在DOS下用TYPE命令打開:
C:\Documents and Settings>D: //直接輸入盤符,切換到D盤
D:\>cd 001\mycpp //用cd命令切換到文件目錄
D:\ 001\mycpp>type f1.dat //用TYPE命令查看dat文件
2 5 6 8 7 9 5 6 4 10
b. 讀取文件,例:
和存入文件差不多:infile("f1.dat",ios::in),infile>>a[i],infile.close()
實例如下:
1 /*將文件中的數據在屏幕中顯示*/ 2 #include <fstream> 3 #include <iostream> 4 using namespace std; 5 int main( ) 6 { 7 int a[10],max,i,order; 8 ifstream infile("f1.dat",ios::in);//打開磁盤文件 9 if(!infile) 10 { 11 cerr<<"open error!"<<endl; 12 exit(1); 13 } 14 for(i=0;i<10;i++) 15 { 16 infile>>a[i];//從文件中讀入整數,存到a[i]中 17 cout<<a[i]<<" "; 18 } 19 cout<<endl; 20 max=a[0]; 21 order=0; 22 for(i=1; i<10; i++)//找出最大的數及下標 23 { 24 if(a[i]>max) 25 { 26 max=a[i]; 27 order=i; 28 } 29 } 30 cout<<"max="<<max<<endl<<"order="<<order<<endl; 31 infile.close();//記住關閉文件 32 return 0; 33 }
編一個專門讀取dat文件內容的程序:
1 #include <fstream> 2 #include <iostream> 3 using namespace std; 4 void display_dat(char *filename) 5 { 6 ifstream infile(filename, ios::in); 7 if(!infile) 8 { 9 cerr<<"open error!"<<endl; 10 exit(1); 11 } 12 char ch; 13 while (infile.get(ch)) 14 { 15 cout.put(ch); 16 } 17 cout<<endl; 18 infile.close(); 19 } 20 21 int main( ) 22 { 23 display_dat("f1.dat");//相對目錄 24 return 0; 25 }
(2)二進制文件(類名為ifstream、ofstream和fstream,與ASCII用到的類相同)
成員函數read和write,原型如下:
istream & read(char * buffer, int len);//讀取
ostream & write(const char * buffer, int len);//存入
兩個參數:char指針指向要讀寫的對象,len代表讀寫的字節數。用法如下:
outfile.write((char *)&stud[i], sizeof(stud[0]));
iofile.read((char *)&stud[i], sizeof(stud[0]));
注意原型聲明中類型為字符指針型,傳遞時必須用字符指針(p)或者字符類型數據的地址(&s),只能將相同類型的指針或者地址賦值給指針。
其他成員函數,例如:
infile.seekg(100);//g是get的意思,代表輸入。文件指針向前移動50個字節
infile.seekg(-50,ios::cur);//輸入文件指針從當前位置後移50字節
outfile.seekp(-70,ios::end);//輸出文件指針從文件尾倒退70字節
完整實例:
1 /*將數據存入文件*/ 2 #include <fstream> 3 #include <iostream> 4 using namespace std; 5 struct student 6 { 7 char name[20]; 8 int num; 9 int age; 10 char sex; 11 }; 12 int main( ) 13 { 14 student stud[3]={"Li",1001,18,'f',"Fun",1002,19,'m',"Wang",1004,17,'f'}; 15 ofstream outfile("stud.dat",ios::binary);//以二進制形式輸入數據到文件 16 if(!outfile) 17 { 18 cerr<<"open error!"<<endl; 19 abort( ); 20 } 21 for(int i=0;i<3;i++) 22 { 23 outfile.write((char*)&stud[i], sizeof(stud[i]));//強制數據類型轉換 24 } 25 outfile.close( ); 26 return 0; 27 }
例子:訪問文件中的任何一個位置,並頻繁讀寫
要求:有5個學生的數據,把它們存到磁盤文件中,將磁盤文件中的第1,3,5個學生數據讀入程序,並顯示出來;將第3個學生的數據修改後存回磁盤文件中的原有位置;從磁盤文件讀入修改後的5個學生的數據並顯示出來。程序如下:
1 #include <fstream> 2 #include <iostream> 3 using namespace std; 4 struct student 5 { 6 int num; 7 char name[20]; 8 float score; 9 }; 10 11 int main( ) 12 { 13 student stud[5]={1001,"Li",85,1002,"Fun",97.5,1004,"Wang",54, 14 1006,"Tan",76.5,1010,"ling",96}; 15 fstream iofile("stud.dat",ios::in|ios::out|ios::binary); 16 //用fstream類定義輸入輸出二進制文件流對象iofile,注意名字iofile是自定義的 17 if(!iofile) 18 { 19 cerr<<"open error!"<<endl; 20 abort( ); 21 } 22 for(int i=0;i<5;i++)//向磁盤文件輸出5個學生的數據 23 { 24 iofile.write((char *)&stud[i], sizeof(stud[i])); 25 } 26 student stud1[5]; //用來存放從磁盤文件讀入的數據 27 for(i=0; i<5; i=i+2) 28 { 29 iofile.seekg(i*sizeof(stud[i]),ios::beg); //定位於第0,2,4學生數據開頭 30 iofile.read((char *)&stud1[i/2], sizeof(stud1[0])); 31 //先後讀入3個學生的數據,存放在stud1[0],stud[1]和stud[2]中 32 cout<<stud1[i/2].num<<" "<<stud1[i/2].name<<" "<<stud1[i/2].score<<endl; 33 //輸出stud1[0],stud[1]和stud[2]各成員的值 34 } 35 cout<<endl; 36 stud[2].num=1012; //修改第3個學生(序號為2)的數據 37 strcpy(stud[2].name,"Wu"); 38 stud[2].score=60; 39 iofile.seekp(2*sizeof(stud[0]),ios::beg); //定位於第3個學生數據的開頭 40 iofile.write((char *)&stud[2],sizeof(stud[2])); //更新第3個學生數據 41 iofile.seekg(0,ios::beg); //重新定位於文件開頭 42 for(i=0;i<5;i++) 43 { 44 iofile.read((char *)&stud[i],sizeof(stud[i])); //讀入5個學生的數據 45 cout<<stud[i].num<<" "<<stud[i].name<<" "<<stud[i].score<<endl; 46 } 47 iofile.close( ); 48 return 0; 49 }