91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

【C++探索之旅】第一部分第十課:文件讀寫,海闊憑魚躍

發布時間:2020-03-18 15:07:37 來源:網絡 閱讀:958 作者:frogoscar 欄目:移動開發

【C++探索之旅】第一部分第十課:文件讀寫,海闊憑魚躍


內容簡介

1、第一部分第十課:文件讀寫,海闊憑魚躍

2、第一部分第十一課預告:小練習,猜單詞



文件讀寫,海闊憑魚躍


上一課《【C++探索之旅】第一部分第九課:數組威武,動靜合一》中,我們學習了動態數組和靜態數組,也看到其實字符串很類似字符數組(到了之后的第二部分,學習面向對象,我們會知道其實string是一個類)。


到目前為止,我們寫的程序還比較簡單,當然了,因為我們剛開始學習C++嘛。但只要加以訓練,我們就慢慢地能夠寫一些真正的應用了。我們也開始逐漸了解C++的基礎知識了,不過缺了很重要的一環:與文件交互。


我們已經學會如何將信息輸出到控制臺(console)以及如何提取用戶在控制臺中輸入的數據(使用cin和cout)。但是,我們豈能就此罷休。想想我們 之前介紹過的一些程序,例如:記事本,一些IDE(VS, CodeBlocks, xCode, Eclipse, etc),繪圖軟件,等等,都能夠讀寫文件。


在游戲領域就更是如此啦(我知道一幫宅男已經激動了):游戲里的數據要保存,游戲的圖片,音樂,道具,等等。都需要存檔。


總之,如果一個軟件不會與文件交互,那么它的功能是比較有限的。


因此,一起來學習如何讀寫文件吧。你會發現,如果你掌握了cin和cout的用法,那其實你已經知道大半啦。



寫入文件


我們要讀寫文件,首先需要打開文件。就好像平時我們要記筆記一樣,你總得先打開筆記本吧,才能閱讀內容,或者往里面寫東西。


一旦文件被打開之后,接下來的操作就很類似之前用cin和cout來進行標準輸入和輸出了。我們又會與老朋友<<和>>見面。


用術語來說,我們會將一個程序和外界的通信方式用"流"來描述。流,英語是stream。記得嗎?我們要使用cin和cout,需要用


#include <iostream>


因為cin和cout定義在iostream這個C++的標準庫中。而這里的iostream就是input output stream的縮寫,表示"輸入輸出流"。所以,其實我們早就在不知不覺地接觸流的概念了。


在這一章中,我們要和文件交互,那么就需要文件流來幫忙了。聰明如你一定想到了,是的,文件的英語是file,那么文件流就是file stream。是不是很簡單呢?


因此,我們需要用到fstream這個標準庫,fstream就是file stream的縮寫。


當然了,如果你不是參加一個程序員的派對,也不需要顯得很專業,那么說"讀寫文件"就可以了。


fstream頭文件


在C++中,我們要使用一個功能,需要引入合適的頭文件。因此,我們在程序一開始須要這樣做:


#include <fstream>


接下來,我們就學習如何創建一個文件流,以便我們能讀寫文件。


以寫模式打開文件


流其實是對象,還記得我們說C++是一門面向對象的語言嗎?當然我們現在還不深究,要到第二部分講面向對象編程時才會暢聊類和對象。暫時只需要知道這些流其實都是C++的對象(不是找對象的對象,少年你想多了)。


也完全無需害怕,因為我們之后還會不斷提到流。暫時,只需把其看作比較高級的變量就可以了。這些文件流包含了文件的很多信息,提供給我們很多功能,例如可以關閉文件,在文件中移動,等等。


你 會看到,聲明一個流的對象,其實就和我們聲明變量一樣簡單。首先,我們來看看如何創建用于寫文件的流,須要用到ofstream,也就是output file stream,因為是從程序向文件輸入數據,因此對于程序來說是"出去"的流,因此是output(輸出),而不是input(輸入)。


話休絮煩。翠花,上"栗子":


#include <iostream>
#include <fstream>
using namespace std;

int main()
{   
    ofstream myStream("C:/Cpp/Files/scores.txt");   
    //聲明用于寫入文件的流,
    //此文件是在C盤下的Cpp文件夾的子文件夾Files中的scores.txt文件
    
    return 0;
}


在上面程序中,我在myStream后面的括號中指定了文件的路徑.這個路徑可以有兩種形式:


  • 絕對路徑:就是文件的所在,不過是從根文件夾開始的路徑。例如:C:/Cpp/Files/scores.txt

  • 相對路徑:也是文件的所在,不過是相對于你的程序的路徑。例如,你的程序位于C:/Cpp/,那么如果你的文件是在C:/Cpp/Files/scores.txt,你在程序里指定文件的相對路徑時就要寫 Files/scores.txt


自此,我們就可以使用這個文件流來寫文件啦。


如果文件不存在,那么會被自動創建。不過,至少指定的目錄要存在,不然會出現"目錄不存在"的錯誤。在我們上面的例子中,至少目錄C:/Cpp/Files必須事先存在。


在打開文件的時候,也會有其他問題。例如文件不屬于你,或者磁盤已滿,等等,總之,打開失敗。因此,我們為了保險起見,總要測試文件是否順利被打開。我們使用 if (myStream) 的方法來測試。


ofstream myStream("C:/Cpp/Files/scores.txt");  //試著打開這個文件

if(myStream)  //測試打開文件是否成功
{
    //一切順利,我們可以使用此文件了
}
else
{
    cout << "出錯: 無法打開此文件." << endl;
}


至此,我們已經做好了寫文件的準備工作。你會看到,接下來的操作還是有點眼熟的。


向流中寫入數據


前面我們說過寫入文件的操作就和以前我們使用cout類似。因此當我對你說要使用<<運算符來進行操作的時候,你應該不會太驚訝。


#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main()
{
    string const fileName("C:/Cpp/Files/scores.txt");
    ofstream myStream(fileName.c_str());
    
    if(myStream)    
    {
        myStream << "大家好,我是被寫入文件的一句話." << endl;
        myStream << 54.26 << endl;
        int age(23);
        myStream << "我" << age << "歲了." << endl;
    }
    else
    {
        cout << "出錯: 無法打開此文件." << endl;
    }
    
    return 0;
}


上面的程序中,可以看到我們首先聲明了一個string的變量,里面存放了C:/Cpp/Files/scores.txt這個字符串,不過之后在將其賦給ofstream的對象myStream時,我們卻用了c_str()這個函數,這是為什么呢?


其實,ofstream接受的參數是char *(暫時不需要知道是什么,馬上我們會學習指針的知識,到時就清楚了),c_str()函數就是用于將string轉換成char *


運行此程序,不出意外的話,你的電腦的C:/Cpp/Files/目錄下就會多出一個文件 scores.txt, 里面的內容如下所示:


【C++探索之旅】第一部分第十課:文件讀寫,海闊憑魚躍


你也來試試


你也可以寫一個程序,請求用戶輸入自己的名字和年齡,然后你的程序將這些信息寫入文件。


文件的不同打開模式


我們只需要再處理一個小問題:


假如文件已經存在,那怎么辦呢?


如果運行上面的已有程序,那么文件的內容會被刪除,然后替換為你寫入的內容。但是假如我們想要保留文件本來的內容,只是想在文件末尾追加我們的新內容呢?


不用怕,肯定有辦法的。只需要在打開文件的時候添加第二個參數,用于指明文件的打開模式,如下所示:


ofstream myStream("C:/Cpp/Files/scores.txt", ios::app);


app是英語append的縮寫,表示"追加",也就是說寫入的內容不會覆蓋原本文件里的內容,而是追加到文件末尾。



讀取文件


我們學習了如何寫文件,現在來學習如何讀取文件內容吧。你會看到,兩種操作是很類似的。


以讀的形式打開文件


之前我們用了ofstream的對象,那么這次就要用到ifstream的對象了,ifstream是input file stream的縮寫。當然也需要測試文件是否順利被打開。


ifstream myStream("C:/Cpp/Files/scores.txt");  //試著打開文件

if(myStream)
{
    //可以讀取文件
}
else
{
    cout << "出錯: 無法以讀的形式打開此文件." << endl;
}


沒有什么新的難點不是嗎?


接下來我們就可以讀取文件內容了。


要讀取文件內容,有三種不同的方式:

  1. 一行一行地讀取,用getline()函數

  2. 一個詞一個詞地讀取,用>>

  3. 一個字符一個字符地讀取,用get()函數


我們分別來學習這三種方式:


一行一行地讀取


第一種方式可以一次讀取整一行的內容,將其存儲在一個字符串里。舉例如下:


string line; // 儲存整行內容的字符串變量
getline(myStream, line); //讀取整一行,存儲到line中


此函數的原理和cin是類似的。


一個詞一個詞地讀取


第二種方式,其實你也早就知道了,畢竟聰慧如你嘛。舉例如下:


double number;
myStream >> number; //從文件中讀取一個浮點數
string word;
myStream >> word;    //從文件中讀取一個單詞


這 個方法會讀取當前所在的文件位置處的內容和之后的一個空格("詞"并不是我們平時說的一個單詞,而是以空格來分隔的,假如中間沒有空格,那么就是一個詞, 例如heusyg3這是一個詞,但是heu syg3卻被認為是兩個詞,因為中間存在空格)。讀取的內容根據變量的類型會被轉換成double,int,string,等等。


一個字符一個字符地讀取


第三種方式,我們之前沒學過,不過也很簡單就是了。舉例如下:


char a;
myStream.get(a);


上面的代碼讀取一個字符,將其存儲在char型變量a中。


這個方法可以讀取所有字符,不管是字母,空格,回車符,制表符,等等。


還記得在【C++探索之旅】第一部分第五課:簡易計算器中, 我們學習過cin的用法嗎?還記得我們說過在cin>>和getline之間需要使用cin.ignore()嗎?因此,這里我們從一個詞一 個詞地讀取(用cin>>)轉換到一行一行地讀取(用getline()),也需要在之間加入ignore()。不過,因為我們這里是在讀取 文件,所以不能用cin.ignore(),而要使用ifstream的ignore方法,如下所示:


ifstream myStream("C:/Cpp/Files/scores.txt");

string word;
myStream >> word;          //讀取一個詞

myStream.ignore();        //改變讀取方式

string line;
getline(myStream, line); //讀取一整行


一次讀取整個文件


很多時候,我們會希望讀取整個文件。我們已經學習了如何讀取文件,但是還沒學習當到達文件結尾時,如何停止。


為 了獲知我們是否還可以繼續讀取,可以用getline函數的返回值。getline函數的返回值是一個bool(布爾值),如果等于true,還可以繼續 讀,說明還沒到文件末尾;如果等于false,那么說明已經讀取了文件的最后一行或者出錯了。在false的情況下,就不能再繼續讀取了。


還記得我們學過的循環嗎?只要還沒到達文件末尾(getline函數返回是true),我們就繼續讀取文件。while循環就是最好的選擇啦。看如下例子:


#include <iostream>
#include <fstream>
#include <string>
using namespace std; 

int main()
{
   ifstream file("C:/Cpp/Files/scores.txt"); // 嘗試打開文件
   
   if(file)
   {
      //文件順利打開,可以讀取了
      
      string line;  //存儲讀取的一整行的變量
      
      while(getline(file, line))  //只要沒到達文件末尾,我們就一直一行一行地讀取
      {
         cout << line << endl;
         //在控制臺顯示讀取的行
         //或者隨便你拿這一行干什么,由你決定
      }
   }
   else
   {
      cout << "出錯: 無法以讀的形式打開此文件." << endl;
   }
   
   return 0;
}


一旦我們讀取了這些行,我們就可以非常方便地操作它們了。在上面的例子中,我們只是把讀取的每一行顯示在控制臺中,但是你可以隨便怎么用。



一些小技巧


這一課的最后,我們來學習幾個小技巧,這樣文件讀寫我們就學習得差不多了。


提前關閉文件


我們已經知道怎么打開一個文件,但還沒演示如何關閉文件。倒不是因為我忘記了,而是之前關閉文件顯得沒有那么必要。一旦我們跳出了文件流聲明的區塊,打開的文件就會被自動關閉。例如:


void f()
{
   ofstream myStream("C:/Cpp/Files/scores.txt"); //打開文件
   
   // 操作文件
   
}  //當我們跳出這個函數,文件就自動被關閉了


因此,并不需要做任何操作來顯式地關閉文件。


但是,有時候我們想要提前關閉文件,在它被自動關閉前。為了達到這個目的,我們必須"不擇手段"... 哦,不是,是使用close函數。例如:


void f()
{   
    ofstream myStream("C:/Cpp/Files/scores.txt");  
    //打開文件C:/Cpp/Files/scores.txt
    
    //使用文件   
    
    myStream.close();  //關閉文件
    //自此,我們將不能再往文件里寫東西了
}


同樣地,我們也可以推遲打開文件。用open函數。例如:


void f(){   
    ofstream myStream;  //聲明文件流,但沒有綁定文件
    myStream.open("C:/Cpp/Files/scores.txt");  
    //打開文件C:/Cpp/Files/scores.txt

    //使用文件   

   myStream.close();  //關閉文件   
   //自此,我們將不能再往文件里寫東西了
}


正如你所見,以上的操作都很簡單。然而,在大部分時候,沒必要使用open和close函數來顯示地打開和關閉文件。


文件里的游標


我們再來深入一些技術細節,"研究"一下文件的讀取是怎么運作的。


你還記得平時用文本編輯器的時候,我們在編輯文本時總會有一個一閃一閃的光標(cursor),指示了我們當前編輯的位置嗎?如下圖所示:


【C++探索之旅】第一部分第十課:文件讀寫,海闊憑魚躍

可以看到,目前光標位于Oscar的后面。


在C++中操作文件時,也是同樣的原理。有一個游標(cursor)一直指示當前在文件中的位置。


例如,當我們運行這一行的時候:


ifstream file("C:/Cpp/Files/scores.txt");


文件C:/Cpp/Files/scores.txt會被打開,游標會定位于文件最開始處。


如果之后我們讀取第一個詞,就會讀取到Oscar這個詞。讀取完之后,我們的游標就會位于下一個單詞的開始處了,如下圖所示:


【C++探索之旅】第一部分第十課:文件讀寫,海闊憑魚躍

可以看到,現在游標位于is這第二個詞的開始處了。然后我們可以接著讀取第二個詞,第三個,... 一直到文件結束。


但如果這樣的話,我們只能按順序讀取文件,這可太束縛了。我們需要自由,需要飛翔,"在你的心上,自由地飛翔~" (小編,你的藥已經準備好了...)


幸好,我們能夠在文件中移動,說到移動,那就是移動那個cursor(游標)了。例如,我們可以說"我要移動到距離文件開始處20個字符的地方",或者"我要從當前位置前進32個字符"。這樣,我們就可以很方便地讀取我們真正想要的內容了。


首先,我們要了解游標目前位于哪里。然后才能正確地移動。


獲得在文件中的位置


有一個方法可以獲知當前我們的游標位于文件的第幾個字符處(從文件開始處算起)。不過,對于輸入文件流(ifstream)和輸出文件流(ofstream),所用的函數不一樣,而且名字也有點古怪,我們列在下面:


針對ifstream

針對ofstream

tellg()

tellp()


然而,這兩個函數的使用方法完全一樣。因此只介紹其中一個就可以了。舉例如下:


ofstream file("C:/Cpp/Files/scores.txt");
int position = file.tellp(); //獲取當前位置
cout << "目前位于文件中的第" << position << "個字符處." << endl;


在文件中移動


用于在文件中移動的函數也有兩個,成對的,每一個對應一種流的形式:


針對ifstream

針對ofstream

seekg()

seekp()


用法和之前的兩個函數類似。


這兩個函數接受兩個參數:一個是在文件中的位置,另一個是相對文件中的位置的距離數(字符數/字節數)。


myStream.seekp(numberOfCharacters, position);


對于此函數的position參數,有三種可能的位置:


  • 文件開始處 : ios::beg ;

  • 文件末尾處 : ios::end ;

  • 當前位置 : ios::cur.


例如,我想要移動到距離文件開始處10個字符的地方,我會這么做:


myStream.seekp(10, ios::beg);


假如我想要移動到距離當前游標所在位置的20個字符處,我會這么做:


myStream.seekp(20, ios::cur);


相信你已經理解啦。


獲知文件大小(所包含字節數)


這第三個小技巧需要用到前兩個。為了獲知文件的大小,我們首先移動到文件末尾,然后詢問我們所在的位置。你知道怎么做了嗎?一起來看看吧:


#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ifstream file("C:/Cpp/Files/scores.txt");  //打開文件
    
    file.seekg(0, ios::end);  //移動到文件末尾
    
    int size;
    size = file.tellg();
    //在文件結尾處調用tellg這個函數,以獲得目前位于第幾個字符處,因此也就知道了文件的大小
    
    cout << "文件的大小是: " << size << "個字節." << endl;
    
    return 0;
}


好了,我們學完了文件讀寫的大致概念。不過肯定不只于此,還有很多知識點需要慢慢在實踐中去探索。



總結


  1. 在C++中,為了能讀寫文件,需要引入fstream頭文件。

  2. 為了寫入文件,我們需要創建一個ofstream對象;為了讀取文件,我們需要創建一個ifstream對象。

  3. 寫入文件的操作其實很類似 cout :  myStream << "文本";  讀取文件的操作其實很類似 cout :  myStream >> variable;

  4. 可以用getline()函數一行一行地讀取文件。

  5. 游標(cursor)指示了寫入操作或讀取操作時,在文件中的位置。如果需要,可以移動這個游標。



第一部分第十一課預告


今天的課就到這里,一起加油吧!

下一課我們學習:小練習,猜單詞

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

都昌县| 陇西县| 重庆市| 密云县| 永顺县| 铅山县| 内丘县| 楚雄市| 雷州市| 沁源县| 江门市| 吉木乃县| 谷城县| 牙克石市| 佛冈县| 宿州市| 台山市| 江达县| 四子王旗| 绍兴县| 临洮县| 兰坪| 石景山区| 正镶白旗| 垫江县| 屏东市| 高雄县| 句容市| 巴林右旗| 公主岭市| 大理市| 江西省| 杭锦后旗| 韩城市| 会同县| 南乐县| 平顺县| 元氏县| 武山县| 霍林郭勒市| 梁河县|