C++primer第八章 IO庫 8.1 IO類

IO庫設施

  • istream? (輸入流)類型,提供輸入操作。
  • ostream (輸出流)類型,提供輸出操作。
  • cin,—個 istream對象,從標準輸入讀取數據。
  • cout, 一個ostream對象,向標準輸出寫入數據。
  • cerr, 一個。stream對象,通常用于輸出程序錯誤消息,寫入到標準錯誤。
  • >>運 算 符 ,用來從一個istream對象讀取輸入數據。
  • <<運算符,用來向一個stream對象寫入輸出數據。?
  • getline函數(參見3.3.2節,第 78頁),從一個給定的istream讀取一行數據, 存入一個給定的string對象中

8.1 IO類

  • iostream定義了用于讀寫流的基本類型,fstream定義了讀寫 命名文件的類型,sstream定義了讀寫內存string對象的類型

  • 為了支持使用寬字符的語言,標準庫定義了一組類型和對象來操縱wchar_t類型的 數 據 (參見2.1.1節,第 30頁)。寬字符版本的類型和函數的名字以一個w 開始。例如,wcin、wcout和 wcerr是分別對應cin、cout和 cerr的寬字符版對象。寬字符版本的類型和對象與其對應的普通char版本的類型定義在同一個頭文件中。例如,頭文件f stream 定義了 ifstream 和 wif stream 類型

IO類型間的關系

  • 概念上,設備類型和字符大小都不會影響我們要執行的IO 操作。例如,我們可以用>>讀取數據,而不用管是從一個控制臺窗口,一個磁盤文件,還是一個string 讀取。類似的,我們也不用管讀取的字符能存入一個char對象內,還是需要一個wchar_t對象來存儲。
  • 標準庫使我們能忽略這些不同類型的流之間的差異,這是通過繼承機制(inheritance) 實現的。利用模板(參見3.3節,第 87頁),我們可以使用具有繼承關系的類,而不必了解繼承機制如何工作的細節。我們將在第15章和18.3節 (第 710頁)介紹C++是如何支持繼承機制的。簡單地說,繼承機制使我們可以聲明一個特定的類繼承自另一個類。我們通常可以將一個派生類(繼承類)對象當作其基類(所繼承的類)對象來使用
  • 類 型ifstream和istringstream都繼承自istream。因此,我們可以像使用istream對象一樣來使用ifstream 和istringstream對象。也就是說,我們是如何使 用cin的,就可以同樣地使用這些類型的對象。例如,可以對一個ifstream 或istringstream對 象 調 用getline, 也 可 以 使 用>>從 一 個ifstream 或istringstream對象中讀取數據。類似的,類型ostringstream和ofstream都繼
    承自ostream 。因此,我們是如何使用cout的,就可以同樣地使用這些類型的對象。?
  • 本節剩下部分所介紹的標準庫流特性都可以無差別地應用于普通流、文件流和string流,以及char或寬字符流版本

?8.1.1? IO對象無拷貝或賦值

  • 如我們在7.1.3節(第234頁)所見,我們不能拷貝或對IO對象賦值
  • ofstream outl,out2;
  • outl=out2;//錯誤:不能對流對象賦值
  • ofstream print(ofstream);//錯誤:不能初始化ofstream參數
  • out2=print(out2);//錯誤:不能拷貝流對象
  • 由于不能拷貝IO對象,因此我們也不能將形參或返回類型設置為流類型(參見6.2.1節,第188頁)。進行IO操作的函數通常以引用方式傳遞和返回流讀寫一個IO對象會改變其狀態,因此傳遞和返回的引用不能是const的

8.1.2條件狀態

  • IO操作一個與生俱來的問題是可能發生錯誤。一些錯誤是可恢復的,而其他錯誤則發生在系統深處,已經超出了應用程序可以修正的范圍。表8.2列出了IO類所定義的一些函數和標志,可以幫助我們訪問和操縱流的條件狀態(conditionstate)

  • 下面是一個IO錯誤的例子:int ival;cin >> ival;
  • 如果我們在標準輸入上鍵入Boo,讀操作就會失敗。代碼中的輸入運算符期待讀取一個int,但卻得到了一個字符B。這樣,cin會進入錯誤狀態。類似的,如果我們輸入一個文件結束標識,cin也會進入錯誤狀態。一個流一旦發生錯誤,其上后續的IO操作都會失敗。只有當一個流處于無錯狀態時,我們才可以從它讀取數據,向它寫入數據。由于流可能處于錯誤狀態,因此代碼通常應該在使用一個流之前檢查它是否處于良好狀態。確定一個流對象的狀態的最簡單的方法是將它當作一個條件來使用:
  • while(cin >> word)//ok:讀操作成功...
  • while循環檢查>>表達式返回的流的狀態。如果輸入操作成功,流保持有效狀態,則條件為真。

查詢流的狀態

  • 將流作為條件使用,只能告訴我們流是否有效,而無法告訴我們具體發生了什么。有時我們也需要知道流為什么失敗。例如,在鍵入文件結束標識后我們的應對措施,可能與遇到一個IO設備錯誤的處理方式是不同的。
  • IO庫定義了一個與機器無關的iostate類型,它提供了表達流狀態的完整功能。這個類型應作為一個位集合來使用,使用方式與我們在4.8節中(第137頁)使用quizl的方式一樣。IO庫定義了4個iostate類型的const expr值(參見2.4.4節,第58頁),表示特定的位模式。這些值用來表示特定類型的IO條件,可以與位運算符(參見4.8節,第137頁)一起使用來一次性檢測或設置多個標志位。
  • badbit表示系統級錯誤,如不可恢復的讀寫錯誤。通常情況下,一旦badbit被置位,流就無法再使用了。在發生可恢復錯誤后,failbit被置位,如期望讀取數值卻讀出一個字符等錯誤。這種問題通常是可以修正的,流還可以繼續使用。如果到達文件結束位置,eofbit和failbit都會被置位。goodbit的值為0,表示流未發生錯誤。如果badbit、failbit和eofbit任一個被置位,則檢測流狀態的條件會失敗
  • 標準庫還定義了一組函數來查詢這些標志位的狀態。操作good在所有錯誤位均未置位的情況下返回true,而bad、fail和eof則在對應錯誤位被置位時返回true。此外,在badbit被置位時,fail也會返回true。這意味著,使用good或fail是確定流的總體狀態的正確方法。實際上,我們將流當作條件使用的代碼就等價于!fail()而eof和bad操作只能表示特定的錯誤

管理條件狀態

  • 流對象的rdstate成員返回一個iostate值,對應流的當前狀態。setstate操作將給定條件位置位,表示發生了對應錯誤clear成員是一個重載的成員(參見6.4節,第206頁):它有一個不接受參數的版本,而另一個版本接受一個iostate類型的參數。clear不接受參數的版本清除(復位)所有錯誤標志位。執行clear()后,調用good會返回true。我們可以這樣使用這些成員:
  • //記住cin的當前狀態
  • auto old_state=cin.rdstate();//記住cin的當前狀態
  • cin.clear();//使cin有效
  • process_input(cin);//使用cin
  • cin.setstate(old_state);//將cin置為原有狀態
  • 帶參數的clear版本接受一個iostate值,表示流的新狀態。為了復位單一的條件狀態位,我們首先用rdstate讀出當前條件狀態,然后用位操作將所需位復位來生成新的狀態。例如,下面的代碼將failbit和badbit復位,但保持eofbit不變:
  • //復位failbit和badbit,保持其他標志位不變
  • cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);

?

8 .1 .3 管理輸出緩沖

  • 每個輸出流都管理一個緩沖區,用來保存程序讀寫的數據。例如,如果執行下面的代碼
  • os << "please enter a value: **;
  • 文本串可能立即打印出來,但也有可能被操作系統保存在緩沖區中,隨后再打印。有了緩沖機制,操作系統就可以將程序的多個輸出操作組合成單一的系統級寫操作。由于設備的寫操作可能很耗時,允許操作系統將多個輸出操作組合為單一的設備寫操作可以帶來很大的性能提升。緩沖區只有被數據填滿,才會刷新緩沖區,將數據寫到指定的文件中
  • 導致緩沖刷新(即,數據真正寫到輸出設備或文件)的原因有很多:
  • 1,程序正常結束,作為main函數的return操作的一部分,緩沖刷新被執行
  • 2,緩沖區滿時,需要刷新緩沖,而后新的數據才能繼續寫入緩沖區。
  • 3,我們可以使用操縱符如endl(參見1.2節,第6頁)來顯式刷新緩沖區
  • 4,在每個輸出操作之后,我們可以用操縱符unitbuf設置流的內部狀態,來清空緩沖區。默認情況下,對cerr是設置unitbuf的,因此寫到cerr的內容都是立即刷新的。
  • 5,一個輸出流可能被關聯到另一個流。在這種情況下,當讀寫被關聯的流時,關聯到的流的緩沖區會被刷新。例如,默認情況下,cin和cerr都關聯到cout。因此,讀cin或寫cerr都會導致cout的緩沖區被刷新。

刷新輸出緩沖區

  • 我們己經使用過操縱符endl,它完成換行并刷新緩沖區的工作。IO庫中還有兩個類似的操縱符:flush和ends。flush刷新緩沖區,但不輸出任何額外的字符;ends向緩沖區插入一個空字符,然后刷新緩沖區
  • cout<<"hi!”<<endl;//輸出hi和一個換行,然后刷新緩沖區
  • cout<<“hi!”<<flush;//輸出hi,然后刷新緩沖區,不附加任何額外字符
  • cout<<"hi!"<<ends;//輸出hi和一個空字符,然后刷新緩沖區

unitbuf操縱符

  • 如果想在每次輸出操作后都刷新緩沖區,我們可以使用unitbuf操縱符。它告訴流在接下來的每次寫操作之后都進行一次flush操作。而nounitbuf操縱符則重置流,使其恢復使用正常的系統管理的緩沖區刷新機制
  • cout<<unitbuf;//所有輸出操作后都會立即刷新緩沖區
  • //任何輸出都立即刷新,無緩沖
  • cout<<nounitbuf;//回到正常的緩沖方式

警告:如果程序崩潰,輸出緩沖區不會被刷新

  • 如果程序異常終止,輸出緩沖區是不會被刷新的,,當一個程序崩潰后,它所輸出的數據很可能停留在輸出緩沖區中等待打印。
  • 當調試一個已經崩潰的程序時,需要確認那些你認為已經輸出的數據確實已經刷新了。否則,可能將大量時間浪費在追蹤代碼為什么沒有執行上,而實際上代碼已經執行了,只是程序崩潰后緩沖區沒有被刷新,輸出數據被掛起沒有打印而已

關聯輸入和輸出流

  • 當一個輸入流被關聯到一個輸出流時,任何試圖從輸入流讀取數據的操作都會先刷新關聯的輸出流。標準庫將cout和cin關聯在一起,因此下面語句
  • cin>>ival;導致cout的緩沖區被刷新。
  • 交互式系統通常應該關聯輸入流和輸出流。這意味著所有輸出,包括用戶提示信息,都會在讀操作之前被打印出來
  • tie有兩個重載的版本(參見6.4節,第206頁):一個版本不帶參數,返回指向輸出流的指針。如果本對象當前關聯到一個輸出流,則返回的就是指向這個流的指針,如果
    對象未關聯到流,則返回空指針。
  • tie的第二個版本接受一個指向。stream的指針,將自己關聯到此ostreamo即,x.tie(&o)將流x關聯到輸出流O.我們既可以將一個istream對象關聯到另一個ostream,也可以將一個ostream關聯到另一個ostream:
  • cin.tie(&cout);//僅僅是用來展示:標準庫將cin和cout關聯在一起
  • //old_tie指向當前關聯到cin的流(如果有的話)
  • ostream*old_tie=cin.tie(nullptr);//cin不再與其他流關聯
  • //將cin與cerr關聯;這不是一個好主意,因為cin應該關聯到cout
  • cin.tie(&cerr);//讀取cin會刷新cerr而不是cout
  • cin.tie(old_tie);//重建cin和cout間的正常關聯
  • 在這段代碼中,為了將一個給定的流關聯到一個新的輸出流,我們將新流的指針傳遞給了tie。為了徹底解開流的關聯,我們傳遞了一個空指針。每個流同時最多關聯到一個流,但多個流可以同時關聯到同一個ostream。

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

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

相關文章

2014年英語一作文partB漫畫作文

題目 Write an essay of 160-200 words based on the following drawing.In your essay you should describe the drawing brieflyexplain its intended meaning,give your comments 做題點 1.使用三段式,第一段:圖片內容;第二段:圖片暗示;第三段:寫自己的評論 2.描述圖片…

Spring Cloud 系列之 Nacos 配置中心

目錄一、Nacos簡介二、Nacos安裝及配置1、環境準備2、安裝包下載&#xff08;1&#xff09;源碼方式&#xff08;2&#xff09;發行包方式3、啟動Nacos服務4、Nacos數據庫配置&#xff08;1&#xff09;MySQL數據源&#xff08;2&#xff09;初始化 MySQL 數據庫&#xff08;3&…

C++primer第八章 IO庫 8.2 文件輸入輸出

8.2文件輸入輸出 頭文件fstream定義了三個類型來支持文件IO&#xff1a;ifstream從一個給定文件讀取數據&#xff0c;ofstream向一個給定文件寫入數據&#xff0c;以及fstream可以讀寫給定文件。在17.5.3節中&#xff08;第676頁&#xff09;我們將介紹如何對同一個文件流既讀…

codeforces 112A-C語言解題報告

112A題目網址 題目解析 1.輸入兩行字符串,不區分大小寫地使用字典序去比較大小 A<B -1 A>B 1 AB 0 舉例: 輸入 abcdefg AbCdEfF 輸出 1 2.字典序:在遇到第一個不同的字符時,比較的大小,就是字符串的大小 列舉法: 1.列出所有情況 1)a[i]是大寫,b[i]是小寫 a[i]轉換為小…

SpringBoot 集成 Nacos

目錄一、前言二、Nacos集成1、引入Nacos依賴2、設置Nacos配置3、加載Nacos配置中心配置項4、Nacos集成驗證5、Nacos配置中心配置項動態生效Nacos安裝詳見&#xff1a;Spring Cloud 系列之 Nacos 配置中心 一、前言 上一篇已經講解了怎樣安裝安裝、啟動、配置 Nacos&#xff0c…

C++primer第八章 IO庫 8.3string流

8.3string流 sstream頭文件定義了三個類型來支持內存IO,這些類型可以向string寫入數據,從string讀取數據&#xff0c;就像string是一個IO流一樣。istringstream從string讀取數據&#xff0c;ostringstream向string寫入數據&#xff0c;而頭文件stringstream既可從string讀數據…

英語口語海報演講--東軟

海報 海報上的內容 Nuclear waste water 1.Damage the devastating impact of nuclear radiation on the world 2.Marine life genetically mutated or dead 3.water resources polluted water resources 4.the future of humanity genetic damage/food and environment destr…

Java中 List、Set、Map遍歷方式以及性能比較

目錄一、簡介二、遍歷方式1、ArrayList遍歷方式&#xff08;1&#xff09;for循環遍歷&#xff08;2&#xff09;foreach循環遍歷&#xff08;3&#xff09;Iterator迭代器遍歷2、LinkedList遍歷方式&#xff08;1&#xff09;for循環遍歷&#xff08;2&#xff09;foreach循環…

codeforces 263A-C語言解題報告

263A題目網址 題目解析 1.輸入5*5的矩陣(下標從到5),包含24個0和一個1,問如何移動最小的次數(i相鄰行或列)可以讓1位于3行3列 舉例: 輸入: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 輸出: 3 注意點 1.因為數組是從0開始的,所以減2就行 row-2col-2 2.使用整型二維…

一個DEMO讓你徹底理解線程池

目錄一、簡介二、線程池任務場景場景一&#xff1a;提交5個任務&#xff0c;執行總耗時500ms場景二&#xff1a;提交10個任務&#xff0c;執行總耗時500ms場景三&#xff1a;提交11個任務&#xff0c;執行總耗時1000ms場景四&#xff1a;提交20個任務&#xff0c;執行總耗時100…

C++primer第九章 順序容器 9.1 順序容器概述 9.2容器庫概覽

一個容器就是一些特定類型對象的集合。順序容器(sequentialcontainer)為程序員提供了控制元素存儲和訪問順序的能力。這種順序不依賴于元素的值&#xff0c;而是與元素加入容器時的位置相對應。與之相對的&#xff0c;我們將在第11章介紹的有序和無序關聯容器&#xff0c;則根據…

SpringBoot 啟動報錯:Failed to configure a DataSource: ‘url‘ attribute is not specified and no emb

目錄一、報錯日志二、原因分析三、問題排查四、解決方案方案一&#xff1a;如果項目不需要數據庫相關信息就排除此類的autoconfig方案二&#xff1a;配置文件添加數據庫鏈接信息方案三&#xff1a;配置pom.xml中yml或者properties掃描一、報錯日志 **************************…

codeforces 339A-C語言解題報告

339A題目網址 題目解析 1.輸入如321的式子,升序排序(從小到大)成123 舉例: 輸入: 11313 輸出: 11133 2.對字符串進行排序采取拍冒泡排序算法 char c0; for(i0;i<strlen(s)-1;i) {for(j0;j<strlen(s)-1;j){if(s[j]>s[j1]){cs[j];s[j]s[j1];s[j1]c;}} }代碼 #includ…

C++primer第九章 順序容器 9.3 順序容器操作

9.3順序容器操作 順序容器和關聯容器的不同之處在于兩者組織元素的方式。這些不同之處直接關系到了元素如何存儲、訪問、添加以及刪除。上一節介紹了所有容器都支持的操作&#xff08;羅列于表9.2&#xff08;第295頁&#xff09;&#xff09;。本章剩余部分將介紹順序容器所特…

SpringBoot 集成Nacos報錯(一)

目錄配置信息報錯信息解決方案配置信息 <project><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.2</version><relativePath/></parent>…

C++primer第九章 順序容器 9.4 vector對象是如何增長的

為了支持快速隨機訪問&#xff0c;vector將元素連續存儲&#xff0c;每個元素緊挨著前一個元素存儲。通常情況下&#xff0c;我們不必關心一個標準庫類型是如何實現的&#xff0c;而只需關心它如何使用。然而&#xff0c;對于vector和string,其部分實現滲透到了接口中。假定容器…

codeforces 281A-C語言解題報告

281A題目網址 題目解析 1.字符串首字母大寫 代碼 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> int main() {char s[1000]{\0};scanf("%s",s);if(s[0]>A&&s[0]<Z){printf("%s",s…

SpringBoot 配置文件bootstrap和application的區別

目錄一、SpringBoot配置文件二、bootstrap和application區別三、bootstrap和application的應用場景一、SpringBoot配置文件 bootstrap&#xff08;.yml 或者 .properties&#xff09; application&#xff08;.yml 或者 .properties&#xff09; 二、bootstrap和application區…

C++primer第九章 順序容器 9.5 額外的string操作

除了順序容器共同的操作之外&#xff0c;string類型還提供了一些額外的操作。這些操作中 的大部分要么是提供string類和C 風格字符數組之間的相互轉換,要么是增加了允許我們用下標代替迭代器的版本。標準庫string類型定義了大量函數。幸運的是&#xff0c;這些函數使用了重復的…

Zookeeper Mac下安裝操作

目錄一、下載Zookeeper二、修改配置1、設置啟動配置文件2、修改配置三、啟動Zookeeper服務命令1、bin目錄下執行&#xff08;1&#xff09;啟動Zookeeper命令&#xff08;2&#xff09;查看Zookeeper狀態命令&#xff08;3&#xff09;停止Zookeeper命令2、配置環境變量執行&am…