C++Primer學習筆記:第8章 IO庫

  • C++語言不直接處理輸入輸出,而是通過一族定義在標準庫中的類型來處理IO

    • iostream定義了用于讀寫流的基本類型
    • fstream定義了讀寫命名文件的類型
    • sstream定義了讀寫內存string對象的類型
  • 標準庫使得我們能夠忽略這些不同類型的流之間的差異,是通過繼承機制實現的

  • 不能拷貝或者對IO對象賦值,因此也不能將形式參數或者返回類型設置為流類型,進行IO操作的函數通常是已引用方式傳遞和返回流,讀寫一個IO對象會改變其狀態,因此傳遞和返回的引用不能是const

    strm::iostate	提供表達條件狀態的完整功能
    strm::badbit	用來指出流已經崩潰
    strm::failbit	用來指出一個IO操作失敗了
    strm::eofbit	用來指出流到達了文件結束
    strm::goodbit	用來指出流未處于錯誤狀態,此值保證為零
    s.eof()			若流s的eofbit置位,返回true
    s.fail()		
    s.bad()
    s.good()		若流s處于有效狀態,返回true
    s.clear()		所有條件狀態復位,將流的狀態設置為有效,返回void
    s.clear(flags)	根據給定的flags標志位將流s中對應條件狀態位復位
    s.setstate(flags)同上
    s.rdstate()		返回流s的當前條件狀態
    
    auto old_state = cin.rdstate();		//記住cin的當前狀態
    cin.clear()							//使cin有效
    process_input(cin);					//使用cin
    cin.setstate(old_state);			//將cin置為原有狀態
    cin.clear(cin.rdstate & ~cin.failbit & ~cin.badbit);	//復位failbit和badbit,保持eofbit不變
    
  • 通過緩沖機制,操作系統可以將程序的多個輸出操作組合成單一的系統級寫操作。(原因在于設備的寫操作可能很耗時)

  • 導致緩沖刷新的原因:

    • 程序正常結束,作為main函數的return操作的一部分,緩沖刷新被執行
    • 緩沖區滿
    • 使用操縱符endl顯式刷新緩沖區
    • 在每個輸出操作后,可以用操作符unitbuf設置流的內部狀態,來清空緩沖區(默認情況下cerr是設置unitbuf的,因此寫到cerr的內容都是立即刷新的)
    • 一個輸出流可能被關聯到另一個流。在這種情況下,當讀寫被關聯的流時,關聯到的流的緩沖區會被刷新
  • 除了endl外,還可以使用flushends刷新緩沖區,但是他們有不同的效果:

    cout << "hi" << endl;		//輸出"hi\n"
    cout << "hi" << flush;		//輸出"hi"
    cout << "hi" << ends;		//輸出"hi "
    
  • 如果想在每次輸出操作后都刷新緩沖區,我們可以使用unitbuf操縱符,它告訴流在接下來每次寫操作后都進行一次flush操作

    cout << unitbuf;	//所有輸出操作都會立即刷新緩沖區
    cout << nounitbuf;	//回到正常的緩沖方式
    
  • 調試/程序崩潰時要記得及時刷新緩沖區

  • 當一個輸入流被關聯到一個輸出流時,任何試圖從輸入流讀取數據的操作都會先刷新關聯的輸出流(例如cincout)。交互式系統通常應該關聯輸入流和輸出流。每個輸入流最多關聯到一個流,但多個流可以同時關聯到同一個ostream

    cin.tie();				//返回cin關聯的流,如果之前沒有關聯則返回空指針
    cin.tie(&cout);			//返回值同上,但是將cin與cout關聯
    ostream *old_tie = cin.tie(nullptr);	//取消關聯,同時保存關聯的流的指針
    cin.tie(old_tie);		//恢復關聯
    
  • 文件輸入輸出的流定義在頭文件fstream

    fstream fstrm;
    fstream fstrm(s);		打開名為s的文件,s可以是string類型或者是一個指向C風格字符串的指針,默認的文件模式mode依賴							fstream的類型
    fstream fstrm(s, mode);
    fstrm.open(s);			打開名為s的文件,并將文件與fstrm綁定,返回void
    fstrm.close();			關閉與fstrm綁定的文件,返回void
    fstrm.is_open(s);		返回一個bool,指出與fstrm關聯的文件是否打開成功且尚未關閉
    
  • 我們可以用fstream代替iostream&,即在需要接受一個iostream類型引用或者指針參數的函數可以用一個對應的fstreamsstream來調用

  • 在使用流之前檢查是一個好的習慣

  • 當一個fstream對象被銷毀時,close會自動被調用

  • 每個流都有一個關聯的文件模式,用來指出如何使用文件

    in			以讀方式打開,只可以對ifstream或fstream
    out			以寫方式打開,只可以對ofstream或fstream,默認情況下,即使我們沒有指定trunc,以out模式打開的文件也會被截				斷,為了保留以out模式打開的文件的內容,我們必須同時指定app,或者指定infstream默認關聯in和out
    app			每次操作均定位到文件末尾,只要trunc沒有被設定就可以設定,包含out
    ate			打開文件后立即定位到文件末尾
    trunc		截斷文件,只有當out也被設定時才能設定
    binary		以二進制方式進行IO
    
    //下面三種方式打開文件是等價的,都會截斷文件
    ofstream out("file");
    ofstream out("file", ofstream::out);
    ofstream out("file", ofstream::out | ofstream::trunc);
    //為了保留文件的內容,我們必須顯式指定app模式
    ofstream out("file", ofstream::app);
    ofstream out("file", ofstream::out | ofstream::app);
    
  • sstream頭文件定義了三個類型來支持內存IO,這些類型可以向string寫入數據,從string讀取數據

  • istringstreamstring讀取數據,ostringstreamstring寫入數據,stringstream既可以讀也可以寫

    sstream strm;		
    sstream strm(s);		strm保存string類型的s的拷貝
    strm.str()				返回strm保存的string的拷貝
    strm.str(s)				將string s拷貝到strm中,返回void
    

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383564.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383564.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383564.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++Primer學習筆記:第7章 類

類的基本思想是數據抽象data abstraction和封裝encapsulation。數據抽象是一種依賴于接口interface和實現implementation分離的編程技術 在類中&#xff0c;由類的設計者負責考慮類的實現過程&#xff0c;使用該類的程序員只需要抽象地思考類型做了什么&#xff0c;而無須了解…

每日一題:leetcode191.位1的個數

題目描述 題目分析 很自然地想到了二進制枚舉&#xff0c;直接循環檢查每一個二進制位。 class Solution { public:int hammingWeight(uint32_t n) {int ret 0;uint32_t t 1;for (int i 0; i < 32; i, t << 1) {if (n & t) {ret;}}return ret;} };AC之后看了…

每日一題:leetcode341.扁平化嵌套列表迭代器

題目描述 題目分析 這個題目自己大概花了一個小時&#xff0c;雖然是一遍AC&#xff0c;但是速度有點慢&#xff0c;太長時間不寫代碼導致自己對代碼不太敏感&#xff0c;寫起來慢騰騰的。 看到這個的想法就是&#xff0c;要用棧來保存列表的迭代器&#xff0c;這樣將孩子列表…

每日一題:leetcode82. 刪除排序鏈表中的重復元素 II

題目描述 題目分析 這才是正常的中等題難度嘛&#xff0c;昨天的中等題題解我半天看不懂。。。 首先&#xff0c;需要增加一個啞節點&#xff08;操作鏈表的常規操作&#xff09;&#xff0c;因為有可能刪除首節點&#xff0c;我們不想要為首節點添加單獨的邏輯。其次&#xf…

每日一題:leetcode456.132模式

題目描述 題目分析 我覺得這道題應該是我做過最難的中等題之一了&#xff0c;這是昨天的每日一題&#xff0c;但是昨天用nlogn的做法做出來以后在看題解&#xff0c;發現有些看不懂&#xff08;覺得題解有點故弄玄虛&#xff09;。然后今天中午又花了一點時間才搞懂&#xff0…

leetcode283.移動零

題目描述 題目分析 在寫簡單題放松&#xff0c;看到這道題第一個想法是用STL庫函數&#xff0c;雖然知道大概要用雙指針之類的&#xff0c;但是庫函數爽哇。 class Solution { public:void moveZeroes(vector<int>& nums) {stable_sort(nums.begin(), nums.end(), …

每日一題:leetcode61.旋轉鏈表

題目描述 題目分析 很容易發現&#xff0c;如果k是n的整數倍&#xff0c;相當于沒有移動。這樣直接對k%n使得k在一個可以接受的范圍。 因為是順序移動&#xff0c;各元素之間的相對位置保持不變&#xff0c;所以就想著將鏈表先變成一個環。然后再移動頭指針&#xff0c;最后再…

每日一題:leetcode173.二叉搜索樹迭代器

題目描述 題目分析 更加地覺得編程重要的不在于如何寫代碼&#xff0c;用什么具體的技巧&#xff0c;編碼本身只是一種將思維呈現的方式&#xff0c;但是如果思維是不清晰的&#xff0c;那么就算懂得再多的編碼的奇技淫巧也是沒有什么幫助的。相反&#xff0c;如果有一個清晰的…

Ubuntu20.04 Clion/Pycharm/IDEA 輸入中文+光標跟隨解決方案

ibus輸入法&#xff08;棄用&#xff09; 之前一直用的搜狗輸入法&#xff0c;但是搜狗輸入法無法在Jetbrains全家桶下使用&#xff0c;但是又需要輸入中文&#xff0c;沒有辦法我只能下載了谷歌輸入法&#xff0c;十分難用&#xff0c;但是也沒有其他辦法&#xff0c;經常到網…

leetcode11.盛最多水的容器

題目描述 題目分析 看到題目后第一個想法當然是O(n2)O(n^2)O(n2)的&#xff0c;但是數據范圍是3e4&#xff0c;應該會超時&#xff0c;而且這種數據范圍也不是讓暴力求解的 。 相當于求解∑i<jmax((j?i)?min(a[i],a[j]))\sum_{i<j}{max((j-i)*min(a[i],a[j]))}∑i<…

每日一題:leetcode190.顛倒二進制位

題目描述 題目分析 題目本身很簡單&#xff0c;沒覺得有什么技巧可以再進行優化了&#xff0c;覺得位運算是無法打亂相對順序的&#xff0c;而這里需要進行鏡像顛倒的操作。因此就踏實地寫了一個循環。 在使用位運算得到每一位的時候&#xff0c;我吸取了經驗&#xff0c;用一…

結構屈曲分析

結構屈曲分析主要用于判定結構受載后是否有失穩風險&#xff0c;作為工程應用&#xff0c;一般分為線性屈曲分析和非線性屈曲分析。 線性屈曲分析需要具備較多的前提條件&#xff0c;如載荷無偏心、材料無缺陷等&#xff0c;在實際工程應用中結構制作過程和加載方式很難達到線性…

每日一題:leetcode74.搜索二維矩陣

題目描述 題目分析 感覺這是一個放錯標簽的簡單題。題目非常簡單&#xff0c;思路應該很明確是二分&#xff0c;我很快寫了一個&#xff08;雖然不小心把!打成調試了一會&#xff09;。 class Solution { public:bool searchMatrix(vector<vector<int>>& mat…

每日一題:leetcode90.子集貳

題目描述 題目分析 感覺這道題讓自己對枚舉排列有了一個更好的認識&#xff0c;感覺自己的這種思路不錯。 假設沒有重復元素&#xff08;退化成78.子集&#xff09;&#xff0c;我們應該怎么做&#xff1f;初始的時候冪集中只有一個空集&#xff0c;然后對每個元素&#xff0…

每日一題:leetcode1006.笨階乘

題目描述 題目分析 因為順序一定且沒有括號&#xff0c;所以邏輯很簡單。我們要順序處理的矛盾在于&#xff0c;減號后面會再出現乘法和除法&#xff0c;我們不妨將對乘法和除法用一個臨時值進行計算&#xff0c;計算結束后再合并到值里面&#xff0c;一般來講乘法和除法的處理…

每日一題:leetcode80.刪除有序數組中的重復元素貳

題目描述 題目分析 又是一道貼錯標簽的簡單題&#xff0c;很明顯的雙指針&#xff0c;我的做法是用兩個變量保存是否需要記錄&#xff0c;官方題解的做法是直接判斷&#xff0c;人家的高明一些 class Solution { public:int removeDuplicates(vector<int>& nums) {…

每日一題:leetcode81.搜索旋轉排序數組Ⅱ

題目描述 題目分析 不含重復元素的題解&#xff08;leetcode33&#xff09; 這道題也是我們算法課的一道編程題&#xff0c;寫完以后發現當時的思路和現在沒有什么變化&#xff0c;果然是自己啊。我的想法是先判斷區間整體是升序的還是旋轉的&#xff0c;如果是升序的就按照正…

C++ JSON庫:JSON for Morden C++

緒論 最近因為項目的需要&#xff0c;需要對JSON進行一定的數據處理&#xff0c;因為想要用C進行編碼&#xff0c;便對C的JSON庫進行的調研&#xff0c;發現這個庫比較好用&#xff1a;JSON for Morder C。 使用指南 想要使用這個json庫&#xff0c;只需要在源文件中包含jso…

Linux信號實現精確到微秒的sleep函數:通過sigsuspend函數解決時序競態問題

原理就是先使用定時器定時&#xff0c;然后再使用pause函數或者sigsuspend函數主動阻塞掛起&#xff0c;最終恢復現場。 如果使用pause函數的話&#xff0c;優點是使用簡單&#xff0c;缺點是有可能產生時序競態&#xff0c;導致進程一直阻塞下去&#xff1a;在定時和掛起之間…

Linux創建多個子進程并通過捕獲SIGCHLD信號進行非阻塞回收

我們通過fork函數創建多個子進程&#xff0c;并通過exec函數族在子進程中進行其他的工作&#xff0c;但是為了避免僵尸進程&#xff0c;我們要對子進程進行回收。常用的回收方式是wait或者waitpid進行阻塞回收&#xff0c;因為如果非阻塞回收很難把握時機&#xff0c;而阻塞回收…