C/C++標準輸入輸出與文件輸入輸出

C語言輸入輸出函數有很多,標準I/O函數中包含了如下幾個常用的函數:

標準輸入輸出:

1. scanf, printf

int scanf(const char *format, arg_list)
scanf主要從標準輸入流中獲取參數值,format爲指定的參數格式及參數類型,如scanf("%s,%d",str,icount);

它要求在標準輸入流中輸入類似"son of bitch,1000"這樣的字符串,同時程序會將"son of bitch"給str,1000給icount。

scanf函數的返回值爲int值,即成功賦值的個數,在上例中如果函數調用成功,則會返回2,所以我們在寫程序時,可以通過語句
if( scanf("%s,%d",str,icount) != 2)
{
...
}
來判斷用戶輸入是否正確.

例子:
#include <stdio.h>
#include <stdlib.h>
int main()
{
    printf("Input Data:\n");
    char str[64];
    int num;
    scanf("%s,%d", str, &num);


    printf("%s,%d", str, num);
    return 0;
}

Input Data:
nihao,1
nihao,1,2009091631

此處將","當做了與前面的nhao以及1一起的字符串。注意scanf時,是以空格,製表符以及回車作爲變量之間的分割的。
因此在使用scanf時儘量採用這幾個作爲分割標記。而不要像scanf("%s,%d", str, &num);,它無法正確輸入數據。

int printf(const char *format, arg_list)
printf主要是將格式化字符串輸出到標準輸出流中,在stdio.h頭文件中定義了標準的輸入和輸出,分別是stdin,stdout。

arg_list可以是變量名,也可以是表達式,但最終都會以值的形式填充進format中

格式化輸入輸出:
1. 格式控制
格式控制是用雙引號括起來的字符串,也稱"轉換控制字符串",它包含以下兩部分信息。

格式說明:由"%"和格式字符組成,如%d,%f,%c,它的作用是把輸出數據轉換爲指定格式輸出,格式的說明總是由"%"字符開始的.
普通字符:需要原樣輸出的字符,或者是一些有特殊含義的字符,如\n,\t。
\n 換行
\f 清屏並換頁
\r 回車
\t Tab符
\xhh 表示一個ASCII碼用16進表示,其中hh是1到2個16進制數

2. 輸出列表
就是需要輸出的一些數據,也可以是表達式,如果在函數中需要輸出多個變量或表達式,則要用逗號隔開。

    一些特殊字符的輸出:
單引號,雙引號,和反斜槓的輸出在前面加轉義字符”\”,如:"\’", "\"",  "\\"。
% 的輸出用兩個連在一起的%%,即 printf(“%%”);

常用的格式說明如下:
格式字符
d  以十進制形式輸出帶符號整數(正數不輸出符號)
o  以八進制形式輸出無符號整數(不輸出前綴0)
x  以十六進制形式輸出無符號整數(不輸出前綴0x)
u  以十進制形式輸出無符號整數
f  以小數形式輸出單精度實數
lf 以小數形式輸出雙精度實數
e  以指數形式輸出單、雙精度實數
g  以%f,%e中較短的輸出寬度輸出單、雙精度實數
c  輸出單個字符
s  輸出字符串

特殊:
對64位整數的輸入輸出,在POJ上的C++環境下(即VC),64位整數是:
__int64    (注意int前面是兩個下劃線),輸入輸出格式爲”%I64d”.

在G++環境下(即Dev C++) 64位整數是
long long  輸入輸出格式爲”%lld”.

輸出寬度
  用十進制整數來表示輸出的最少位數。注意若實際位數多於定義的寬度,則按實際位數輸出,若實際位數少於定義的寬度則補以空格或0。

可以在"%"和字母之間插進數字表示最大寬度。

%9.2f 表示輸出場寬爲9的浮點數,其中小數位爲2,整數位爲6,小數點佔一位,不夠9位右對齊。
%8s 表示輸出8個字符的字符串, 不夠8個字符右對齊。

如果字符串的長度,或整型數位數超過說明的場寬,將按其實際長度輸出。
但對浮點數, 若整數部分位數超過了說明的整數位寬度, 將按實際整數位輸出;
若小數部分位數超過了說明的小數位寬度,則按說明的寬度以四捨五入輸出。
另外,若想在輸出值前加一些0, 就應在場寬項前加個0。
例如: d 表示在輸出一個小於4位的數值時, 將在前面補0使其總寬度爲4位。

如果用浮點數表示字符或整型量的輸出格式,小數點後的數字代表最大寬度,小數點前的數字代表最小寬度。
例如: %6.9s 表示顯示一個長度不小於6且不大於9的字符串。若大於9,則第9個字符以後的內容將被刪除。

精度
精度格式符以"."開頭,後跟十進制整數。意義是:如果輸出數字,則表示小數的位數;如果輸出的是字符,則表示輸出字符的個數;
若實際位數大於所定義的精度數,則截去超過的部分。

標誌格式字符
-  結果左對齊,右邊填空格
+  輸出符號(正號或負號)空格輸出值爲正時冠以空格,爲負時冠以負號

例如:
double c = 24212345.24232;
printf(“%020.4”);  表示輸出精確到小數點後4位,輸出佔20位,若有空餘的位補0。

2. getc,putc

int getc(FILE *fp)
getc主要是從文件中讀出一個字符.常用的判斷文件是否讀取結束的語句爲:(ch = getc(fp)) != EOF。EOF爲文件結束標誌,
定義在stdio.h中,就像EXIT_SUCCESS,EXIT_FAILURE定義在stdlib.h中一樣,文件也可以被理解爲一種流,所以當fp爲stdin時,
getc(stdin)就等同於getchar()了.

int putc(int ch,FILE *fp)
putc主要是把字符ch寫到文件fp中去。如果fp爲stdout,則putc就等同於putchar()了。

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE * fp = fopen("tmp.txt", "w+");
putc('a', fp);
fflush(fp);
fclose(fp);

fp = fopen("tmp.txt", "r+");
int c = getc(fp);
printf("%c\n", c);
fclose(fp);

int ch = getc(stdin);
putc( ch, stdout);
putc( '\n', stdout);
putc('a', stdout);

return 0;
}

3. getchar,putchar

int getchar(void)
getchar()主要是從標準輸入流讀取一個字符。默認的標準輸入流即stdio.h中定義的stdin。但是從輸入流中讀取字符時又
涉及到緩衝的問題,所以並不是在屏幕中敲上一個字符程序就會運行,一般是通過在屏幕上敲上回車鍵,然後將回車前的字符
串放在緩衝區中,getchar() 就是在緩衝區中一個一個的讀字符。當然也可以在while循環中指定終止字符,如下面的語句:
while ((c = getchar()) != '#')

這是以'#'來結束的。

int putchar(int ch)
putchar(ch)主要是把字符ch寫到標準流stdout中去.

#include <stdio.h>
#include <stdlib.h>

int main()
{
int n;
while((n = getchar()) != '#')
{
putchar((char)n);
}

return 0;
}

4. gets,puts

char * gets(char *str)
gets() 主要是從標準輸入流讀取字符串並回顯,讀到換行符時退出,並會將換行符省去。

返回值爲獲得的字符串的首地址,實現鏈接操作。

int puts(char *str)
puts() 主要是把字符串str寫到標準流stdout中去,並會在輸出到最後時添加一個換行符。

返回值爲0表示正常,非零表示錯誤
#include <stdio.h>
#include <stdlib.h>

int main()
{
char str[256];
printf("%s\n", gets(str));

int ret = puts(str);
printf("len: %d\n", ret);

return 0;
}

文件輸入輸出:

1. fgets,fputs

char *fgets(char *str, int num, FILE *fp)
str 是存放讀入的字符數組指針,num是最大允許的讀入字符數,fp是文件指針。
fgets的功能是讀一行字符,該行的字符數不大於num-1。因爲fgets函數會在末尾加上一個空字符以構成一個字符串。
另外fgets在讀取到換行符後不會將其省略。

出現換行字符、讀到文件尾或是已讀了size-1個字符則停止讀取,最後會加上NULL作爲字符串結束。 

返回值 gets()若成功則返回s指針,返回NULL則表示有錯誤發生。

int fputs(char *str, file *fp)
fputs() 將str寫入fp。fputs與puts的不同之處是fputs在打印時並不添加換行符。
返回值 若成功則返回寫出的字符個數,返回EOF則表示有錯誤發生。

#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * fp = fopen("temp.txt", "w+");

int ret = fputs("Hello world!", fp);
printf("%d\n", ret);
fputs("\n", fp);
fputs("Hello China!", fp);

rewind(fp);
char str[256];
fgets(str, 255, fp);
fputs(str, stdout);
fgets(str, 255, fp);
fputs(str, stdout);

fclose(fp);
return 0;
}

2. fgetc,fputc

int fgetc(FILE *fp)
fgetc從fp的當前位置讀取一個字符。若讀到文件尾而無數據時便返回EOF

int fputc(int ch, file *fp)
fputc是將ch寫入fp當前指定位置。

#include <stdio.h>
#include <stdlib.h>

int main()
{
FILE * fp = fopen("temp.txt", "r+");
FILE * fp1 = fopen("tmp.txt", "w+");


int c = 0;
while( (c = fgetc(fp)) != EOF)
{
fputc(c, fp1);
}
fclose(fp);
fclose(fp1);
return 0;
}

3. fscanf,fprintf

int fscanf(FILE *fp, char *format,...)
fscanf() 按照指定格式從文件中出讀出數據,並賦值到參數列表中。

int fprintf(FILE *fp, char *format,...)
fprintf() 將格式化數據寫入流式文件中。

#include<stdio.h>
int main()
{
char c;
FILE *fin,*fout;
fin=fopen("data.txt","r");
fout=fopen("data1.txt","w");
while(fscanf(fin,"%c",&c)==1)
fprintf(fout,"%c",c);
fclose(fin);
fclose(fout);
return 0;
}

#include <stdio.h>
#include <stdlib.h>
int main()
{
int year, month, day;
FILE *fp = fopen("tmp.txt","w+");


fprintf( fp, "%d-%d-%d",2013,9,29);
rewind(fp);
while( fscanf( fp, "%d-%d-%d", &year, &month, &day) > 1)
{
printf("Y: %d M: %d D: %d\n", year, month, day);
}


fclose(fp);
return 0;
}

4. fread, fwrite


size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream); 
fread()用來從文件流中讀取數據。
參數stream爲已打開的文件指針,參數ptr指向欲存放讀取進來的數據的空間,讀取的字符數以參數size*nmemb來決定。
fread()會返回實際讀取到的nmemb數目,如果此值比參數nmemb來得小,則代表可能讀到了文件尾或有錯誤發生,這時必須
用feof()或ferror()來決定發生什麼情況。


返回值 返回實際讀取到的nmemb數目。


size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream); 
fwrite()用來將數據寫入文件流中。
參數stream爲已打開的文件指針,參數ptr指向欲寫入的數據地址,總共寫入的字符數以參數size*nmemb來決定。
fwrite()會返回實際寫入的nmemb數目。

返回值 返回實際寫入的nmemb數目。



5. freopen


FILE * freopen(const char * path,const char * mode,FILE * stream); 


文件輸入輸出重定向。
參數path字符串包含欲打開的文件路徑及文件名,參數mode請參考fopen()說明。參數stream爲已打開的文件指針。
freopen()會將原stream所打開的文件流關閉,然後打開參數path的文件。

#include<stdio.h>


int main()
{
char c;
freopen( "temp.txt", "r", stdin);
freopen( "tmp.txt", "w", stdout);
while(scanf("%c",&c) == 1)
printf("%c",c);
return 0;
}

這種文件操作方式仍然使用scanf();和printf();



附註:


1. 文件操作類型
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
字符                  含義
────────────────────────────────────────────────────────
"r"            打開文字文件只讀
"w"           創建文字文件只寫
"a"           增補, 如果文件不存在則創建一個
"r+"          打開一個文字文件讀/寫
"w+"        創建一個文字文件讀/寫
"a+"         打開或創建一個文件增補
"b"           二進制文件(可以和上面每一項合用)
"t"             文這文件(默認項)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━


2. 文件讀寫指針移動:

int fseek (FILE *stream, long offset, int fromwhere);
fseek()函數的作用是將文件的位置指針設置到從fromwhere開始的第offset字節的位置上, 

其中fromwhere是下列幾個宏定義之一:
      
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 符號常數            數值             含義
────────────────────────────────────────
 SEEK_SET          0                從文件開頭
 SEEK_CUR         1                從文件指針的現行位置
 SEEK_END          2               從文件末尾
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


offset是指文件位置指針從指定開始位置(fromwhere指出的位置)跳過的字節數。它是一個長整型量,以支持大於64K字節的文件。
fseek()函數一般用於對二進制文件進行操作。
當fseek()函數返回0時表明操作成功, 返回非0表示失敗。


C++的輸入輸出常用函數:

1、getch()和getche(),非緩衝式輸入,從鍵盤讀入一個字符。getch()讀入字符不顯示,由conio.h支持。
2、cin.get(),getchar(),緩衝式輸入,從鍵盤讀入一個字符,並顯示。getchar()由stdio.h支持,cin.get()由iostream.h支持
3、putch()和putchar(),非緩衝式輸出,輸出一個字符到顯示器。putch()由conio.h支持,putchar()由stdio.h支持。
4、cout.put(),緩衝式輸出,輸出一個字符到顯示器,由iostream.h支持。
5、gets()和cin.geline(),緩衝式輸入,讀入一字符串(包括空格,不包括最後的回車),gets()由stdio.h支持,cin.getline()由iostream.h支持。
6、puts(),非緩衝輸出,輸出一個字符串,由stdio.h支持。
7、cin.putback(),把一個字符送回輸入緩衝區。
8、fflush(stdin),清除輸入緩衝區操作,無法清除cin.get()等帶來的操作。
9、cout.flush(),清除輸出緩衝區。

cin,cin.get(),cin.getline(),getline(),gets(),getchar

C++程序把輸入,輸出看作字節流,輸入時從輸入流中抽取字節,輸出時將字節流插入到輸出流中,輸出/輸入的字節可能是來自鍵盤輸入,
也可能來自外部存儲設備或其他程序,或者是來自網絡。

C++的iostream庫中有幾個比較常用的流對象。
cin:是標準輸入流對象,默認關聯到標準輸入設備鍵盤
cout:是標準輸出流對象,默認關聯到標準輸出設備顯示器
cerr,clog:是標準錯誤流對象,默認關聯到標準輸出設備顯示器。

1、cin
2、cin.get()
3、cin.getline()
4、getline()
5、gets()
6、getchar() 

1、cin>>           

最基本,也是最常用的用法,輸入一個數字:
#include <iostream>
using namespace std;
main ()
{
int a,b;
cin>>a>>b;
cout<<a+b<<endl;
}
輸入:2[回車]3[回車]
輸出:5

接受一個字符串,遇 空格、TAB、回車都會結束
#include <iostream>
using namespace std;
main ()
{
char a[20];
cin>>a;
cout<<a<<endl;
}

輸入:jkljkljkl
輸出:jkljkljkl
輸入:jkljkl jkljkl       //遇空格結束
輸出:jkljkl

2、cin.get()
cin.get(字符變量名)可以用來接收字符
#include <iostream>
using namespace std;
main ()
{
char ch;
ch = cin.get();      // 或者 cin.get(ch);
cout<<ch<<endl;
}
輸入:jljkljkl
輸出:j

cin.get( 字符數組名, 接收字符數目)用來接收一行字符串,可以接收空格
#include <iostream>
using namespace std;
main ()
{
char a[20];
cin.get(a,20);
cout<<a<<endl;
}

輸入:jkl jkl jkl
輸出:jkl jkl jkl
輸入:abcdeabcdeabcdeabcdeabcde (輸入25個字符)
輸出:abcdeabcdeabcdeabcd       (接收19個字符+1個'\0')

cin.get(無參數) 沒有參數主要是用於捨棄輸入流中的不需要的字符或者捨棄回車,彌補cin.get(字符數組名,接收字符數目)的不足。

3、cin.getline()   // 接受一個字符串,可以接收空格並輸出
#include <iostream>
using namespace std;
main ()
{
char m[20];
cin.getline( m, 5);
cout << m << endl;
}
輸入:jkljkljkl
輸出:jklj
接受5個字符到m中,其中最後一個爲'\0',所以只看到4個字符輸出。如果把5改成20:
輸入:jkljkljkl
輸出:jkljkljkl
輸入:jklf fjlsjf fjsdklf
輸出:jklf fjlsjf fjsdklf

延伸:
cin.getline()實際上有三個參數,cin.getline(接受字符串的空間m,接受個數5,結束字符)
當第三個參數省略時,系統默認爲'\0'。如果將例子中cin.getline()改爲cin.getline(m,5,'a');,指定結束字符爲'a'
當輸入jlkjkljkl時輸出jklj,輸入jkaljkljkl時,輸出jk。

當用在多維數組中的時候,也可以用cin.getline(m[i],20)之類的用法:
#include<iostream>
#include<string>
using namespace std;
main ()
{
char m[3][20];
for(int i=0;i<3;i++)
{
cout<<"\n請輸入第"<<i+1<<"個字符串:"<<endl;
cin.getline(m[i],20);
}
cout<<endl;
for(int j=0;j<3;j++)
cout<<"輸出m["<<j<<"]的值:"<<m[j]<<endl;
}

請輸入第1個字符串:
kskr1
請輸入第2個字符串:
kskr2
請輸入第3個字符串:
kskr3
輸出m[0]的值:kskr1
輸出m[1]的值:kskr2
輸出m[2]的值:kskr3

4、getline()     

接受一個字符串,可以接收空格並輸出,需包含“#include<string>”

#include<iostream>
#include<string>
using namespace std;
main ()
{
string str;
getline(cin,str);
cout<<str<<endl;
}

輸入:jkljkljkl
輸出:jkljkljkl
輸入:jkl jfksldfj jklsjfl
輸出:jkl jfksldfj jklsjfl

和cin.getline()類似,但是cin.getline()屬於istream流,而getline()屬於string流,是不一樣的兩個函數

5、gets()        

接受一個字符串,可以接收空格並輸出,需包含“#include<string>”

#include<iostream>
#include<string>
using namespace std;
main ()
{
char m[20];
gets(m);    //不能寫成m=gets();
cout<<m<<endl;
}

輸入:jkljkljkl
輸出:jkljkljkl
輸入:jkl jkl jkl
輸出:jkl jkl jkl

類似cin.getline()裏面的一個例子,gets()同樣可以用在多維數組裏面:
#include<iostream>
#include<string>
using namespace std;
main ()
{
char m[3][20];
for(int i=0;i<3;i++)
{
cout<<"\n請輸入第"<<i+1<<"個字符串:"<<endl;
gets(m[i]);
}
cout<<endl;

for(int j=0;j<3;j++)
cout<<"輸出m["<<j<<"]的值:"<<m[j]<<endl;
}

請輸入第1個字符串:
kskr1
請輸入第2個字符串:
kskr2
請輸入第3個字符串:
kskr3

輸出m[0]的值:kskr1
輸出m[1]的值:kskr2
輸出m[2]的值:kskr3

自我感覺gets()和cin.getline()的用法很類似,只不過cin.getline()多一個參數罷了;
這裏順帶說明一下,對於本文中的這個kskr1,kskr2,kskr3的例子,對於cin>>也可以適用,原因是這裏輸入的沒有空格。
如果輸入了空格,比如“ks kr jkl[回車]”那麼cin就會已經接收到3個字符串,“ks,kr,jkl”;再如“kskr 1[回車]kskr 2[回車]”,
那麼則接收“kskr,1,kskr”;這不是我們所要的結果!而cin.getline()和gets()因爲可以接收空格,所以不會產生這個錯誤。

6、getchar()   

接受一個字符,需包含“#include<string>”
#include<iostream>
#include<string>
using namespace std;
main ()
{
char ch;
ch = getchar();           // 不能寫成getchar(ch);
cout<<ch<<endl;
}

輸入:jkljkljkl
輸出:j

//getchar()是C語言的函數,C++也可以兼容,但是儘量不用或少用;
 
C++ 通過以下幾個類支持文件的輸入輸出:

ofstream: 寫操作(輸出)的文件類 (由ostream引申而來)
ifstream: 讀操作(輸入)的文件類(由istream引申而來)
fstream: 可同時讀寫操作的文件類 (由iostream引申而來)

打開文件(Open a file)

對這些類的一個對象所做的第一個操作通常就是將它和一個真正的文件聯繫起來,也就是說打開一個文件。
被打開的文件在程序中由一個流對象(stream object)來表示(這些類的一個實例) ,而對這個流對象所做的任何
輸入輸出操作實際就是對該文件所做的操作。

要通過一個流對象打開一個文件,使用它的成員函數open():

void open(const char * filename, openmode mode);

這裏filename 是一個字符串,代表要打開的文件名;mode 是以下標誌符的一個組合: 

ios::in 爲輸入(讀)而打開文件
ios::out 爲輸出(寫)而打開文件
ios::ate 初始位置:文件尾
ios::app 所有輸出附加在文件末尾
ios::trunc 如果文件已存在則先刪除該文件
ios::binary 二進制方式

這些標識符可以被組合使用,中間以”或”操作符(|)間隔。
file.open ("example.bin", ios::out | ios::app | ios::binary);

ofstream, ifstream 和 fstream所有這些類的成員函數open 都包含了一個默認打開文件的方式,這三個類的默認方式各不相同: 類 參數的默認方式

ofstream ios::out | ios::trunc
ifstream ios::in
fstream ios::in | ios::out

只有當函數被調用時沒有聲明方式參數的情況下,默認值纔會被採用。如果函數被調用時聲明瞭任何參數,默認值將被完全改寫,而不會與調用參數組合。
由於對類ofstream, ifstream 和 fstream 的對象所進行的第一個操作通常都是打開文件,這些類都有一個構造函數可以直接調用open函數,並擁有同樣的參數。
這樣,我們就可以通過以下方式進行與上面同樣的定義對象和打開文件的操作:ofstream file("example.bin", ios::out|ios::app|ios::binary);

兩種打開文件的方式都是正確的。可以通過調用成員函數is_open()來檢查一個文件是否已經被順利的打開了:bool is_open();
它返回一個布爾(bool)值,爲真(true)代表文件已經被順利打開,假( false )則相反。

關閉文件(Closing a file)
當文件讀寫操作完成之後,我們必須將文件關閉以使文件重新變爲可訪問的。關閉文件需要調用成員函數close(),它負責將緩存中的數據排放出來並關閉文件。它的格式很簡單:void close ();

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