第一章 開始

我們的程序顯然必須:

  • 定義變量
  • 進(jìn)行輸入和輸出
  • 使用數(shù)據(jù)結(jié)構(gòu)保存數(shù)據(jù)
  • 檢測(cè)兩條記錄是否有相同的ISBN
  • 包含一個(gè)循環(huán)來(lái)處理銷售檔案中的每條記錄

1.1 編寫一個(gè)簡(jiǎn)單的C++程序

每個(gè)C++程序都包含一個(gè)或者多個(gè)函數(shù),其中一個(gè)必須命名為main。操作系統(tǒng)通過調(diào)用main來(lái)運(yùn)行C++程序。

下面是一個(gè)非常簡(jiǎn)單的main函數(shù),它什么也不干,只是返回給操作系統(tǒng)一個(gè)值:

int main() {
    return 0;
}

一個(gè)函數(shù)的定義包含四部分

  • 返回類型
  • 函數(shù)名
  • 一個(gè)括號(hào)包圍的形參列表
  • 函數(shù)體

main函數(shù)的返回類型必須為int,即整數(shù)類型。int類型是一種內(nèi)置類型即語(yǔ)言自身定義的類型。

函數(shù)定義的最后一個(gè)部分是函數(shù)體它是以包裹在花括號(hào)之內(nèi)的語(yǔ)句塊構(gòu)成的。

當(dāng)return語(yǔ)句包括一個(gè)值時(shí),此時(shí)返回值的類型必須與函數(shù)的返回類型相容。

大多數(shù)系統(tǒng)中,main函數(shù)的返回值被用來(lái)指示狀態(tài)。返回值0表明成功,非0的返回值含義由系統(tǒng)定義,通常用來(lái)指出錯(cuò)誤類型。

重要概念:類型

類型是程序設(shè)計(jì)最基本的概念之一,在本書中我們會(huì)反復(fù)遇到它。一種類型不僅定義了數(shù)據(jù)元素的內(nèi)容,還定義了這類數(shù)據(jù)上可以進(jìn)行的計(jì)算。

程序所處理的數(shù)據(jù)都保存在變量中,而每個(gè)變量都有自己的類型。如果一個(gè)名為v的變量的類型為T,我們通常說(shuō)“v具有類型T”,或等價(jià)的,“v是一個(gè)T類型的變量”。

1.1.1 編譯、運(yùn)行程序

編寫好程序之后,我們就需要編譯它。如何編譯程序依賴于你使用的操作系統(tǒng)和編譯器。

程序源文件命名約定

程序文件通常被稱為源文件。在大多數(shù)系統(tǒng)中,源文件的名字以一個(gè)后綴為結(jié)尾,后綴是由一個(gè)句點(diǎn)后接一個(gè)或多個(gè)字符組成的。不同的編譯器使用不同的后綴命名約定。

從命令行運(yùn)行編譯器

運(yùn)行GNU編譯器的命令是g++:g++ -o prog1 prog1.cc

1.1節(jié)練習(xí)

練習(xí) 1.1:查閱你使用的編譯器文檔,確定它所使用的文件命名約定。編譯并運(yùn)行第2也得main程序。

int main() {
    return 0;
}

// 編譯命令:g++ -std=c++11 main.cpp -o main
// 執(zhí)行命令:./main

練習(xí) 1.2:改寫程序,讓它返回-1.返回值-1通常被當(dāng)作錯(cuò)誤的標(biāo)識(shí)。重新編譯并運(yùn)行你的程序,觀察你的系統(tǒng)如何處理main返回的錯(cuò)誤標(biāo)識(shí)。

int main() {
    return -1;
}
// g++編譯器并沒有出現(xiàn)任何的異常

1.2 初識(shí)輸入輸出

C++語(yǔ)言并未定義任何輸入輸出語(yǔ)句,取而代之,包含了一個(gè)全面的標(biāo)準(zhǔn)庫(kù)來(lái)提供IO機(jī)制。

本書中很多示例都使用了iostream庫(kù)。iostream庫(kù)包含兩個(gè)基礎(chǔ)類型istream和ostream,分別表示輸入流和輸出流。一個(gè)流就是一個(gè)字符序列,是從IO設(shè)備讀出或?qū)懭隝O設(shè)備的。術(shù)語(yǔ)“流”想要表達(dá)的是,隨著時(shí)間的推移,字符是順序生成或者消耗的。

標(biāo)準(zhǔn)輸入輸出對(duì)象

標(biāo)準(zhǔn)庫(kù)定義了4個(gè)IO對(duì)象。為了處理輸入,我們使用一個(gè)名為cin的istream類型的對(duì)象。這個(gè)對(duì)象也被稱為標(biāo)準(zhǔn)輸入。對(duì)于輸出,我們使用一個(gè)名為cout的ostream類型的對(duì)象。

當(dāng)我們讀取cin,數(shù)據(jù)將從程序正在運(yùn)行的窗口讀入,當(dāng)我們像cout、cerr和clog寫入數(shù)據(jù)時(shí),將會(huì)寫到同一個(gè)窗口。

一個(gè)使用IO庫(kù)的程序

通過使用IO庫(kù),我們可以擴(kuò)展main程序,使之能提事用戶輸入兩個(gè)數(shù),然后輸出他們的和:

#include <iostream>

int main() {
    std::cout << "Enter two numbers: " << std::endl;
    int v1 = 0;
    int v2 = 0;
    std::cin >> v1 >> v2;
    std::cout << "The sum of " << v1 << " and " << v2
              << " is " << v1 + v2 << std::endl;
    return 0;
}

程序的第一行#include <iostream>告訴編譯器想要使用iostream庫(kù)。尖括號(hào)中的名字指出了一個(gè)頭文件。每個(gè)使用標(biāo)準(zhǔn)庫(kù)設(shè)施的程序都必須包含相關(guān)的頭文件。#include指令和頭文件的名字必須寫在同一行中。通常情況下,#include指令必須出現(xiàn)在所有函數(shù)之外。我們一般將一個(gè)程序所有的#include指令都放在源文件卡是的位置。

向流寫入數(shù)據(jù)

在C++中,一個(gè)表達(dá)式產(chǎn)生一個(gè)計(jì)算結(jié)果,它由一個(gè)或者多個(gè)運(yùn)算對(duì)象和運(yùn)算符組成。

輸出運(yùn)算符(>>)接受兩個(gè)運(yùn)算對(duì)象:左側(cè)的運(yùn)算對(duì)象必須是一個(gè)ostream對(duì)象,右側(cè)的運(yùn)算對(duì)象是要打印的值。此運(yùn)算符將給定的值寫到給定的ostream對(duì)象中。計(jì)算結(jié)果就是我們寫入給定值的那個(gè)ostream對(duì)象。

第四行的語(yǔ)句我們可以等價(jià)的寫成:

std::cout << "Enter two numbers:";
std::cout << std::endl;

字符串字面值常量:是一對(duì)用雙引號(hào)包圍的字符序列。

std::endl:操縱符,寫入endl的效果是結(jié)束當(dāng)前行并將與設(shè)備關(guān)聯(lián)的緩沖區(qū)中的內(nèi)容刷到設(shè)備中。緩沖區(qū)刷新操作可以保證到目前為止程序所產(chǎn)生的所有輸出都真正寫入輸出流中,而不是僅停留在內(nèi)存中等待寫入流。

使用標(biāo)準(zhǔn)庫(kù)中的名字

命名空間可以幫助我們避免不經(jīng)意的名字定義沖突,以及使用庫(kù)中相同名字導(dǎo)致的沖突。標(biāo)準(zhǔn)庫(kù)定義的所有名字都在命名空間std中。

如果想使用一個(gè)命名空間中的名字,則必須使用namespace::name這樣的形式,也就是作用域運(yùn)算符::來(lái)指出特定的命名空間。

從流中讀取數(shù)據(jù)

輸入運(yùn)算符(>>)與輸出運(yùn)算符類似,它接受一個(gè)istream對(duì)象作為其左側(cè)運(yùn)算對(duì)象,接受一個(gè)對(duì)象作為其右側(cè)運(yùn)算對(duì)象。他從給定的istream中讀入數(shù)據(jù),并存入給定的對(duì)象中。

我們可以將語(yǔ)句等價(jià)的寫成:

std::cin >> v1;
std::cin >> v2;
完成程序

剩下的就是計(jì)算結(jié)果了。

1.2節(jié)練習(xí)

練習(xí) 1.3:編寫程序,在標(biāo)準(zhǔn)輸出上打印Hello, World。

#include <iostream>

int main() {
    std::cout << "Hello, World" << std::endl;
    return 0;
}

練習(xí) 1.4:我們的程序使用加法運(yùn)算符+來(lái)將兩個(gè)數(shù)相加。編寫程序使用乘法運(yùn)算符*,來(lái)打印兩個(gè)數(shù)的積。

#include <iostream>

int main() {
    std::cout << "Enter two numbers: " << std::endl;
    int v1 = 0;
    int v2 = 0;
    std::cin >> v1 >> v2;
    std::cout << "The product of " << v1 << " and " << v2
              << " is " << v1 * v2 << std::endl;
    return 0;
}

練習(xí) 1.5:我們將所有輸出操作放在一條很長(zhǎng)的語(yǔ)句中。重寫程序,將每個(gè)運(yùn)算對(duì)象的打印操作放在一條獨(dú)立的語(yǔ)句中。

#include <iostream>

int main() {
    std::cout << "Enter two numbers: " << std::endl;
    int v1 = 0;
    int v2 = 0;
    std::cin >> v1 >> v2;
    std::cout << "The sum of ";
    std::cout << v1;
    std::cout << " and ";
    std::cout << v2;
    std::cout << " is ";
    std::cout << v1 + v2;
    std::cout << std::endl;
    return 0;
}

練習(xí) 1.6:解釋下面的程序片段是否合法。

std::cout << "The sum of" << v1;
          << " and " << v2;
          << " is " << v1 + v2 << std::endl;

不合法,因?yàn)樵诿啃姓Z(yǔ)句后面寫上分號(hào)的話代表了一條獨(dú)立的語(yǔ)句。應(yīng)當(dāng)修改為:

std::cout << "The sum of" << v1
          << " and " << v2
          << " is " << v1 + v2 << std::endl;

1.3 注釋簡(jiǎn)介

錯(cuò)誤的注釋比完全沒有注釋更加糟糕。當(dāng)修改代碼時(shí),不要忘記同時(shí)更新注釋。

C++中注釋的種類

C++中有兩種注釋:單行注釋界定符對(duì)注釋。

單行注釋:雙斜線(//)開始,以換行符結(jié)束。當(dāng)前行右側(cè)所有的內(nèi)容都會(huì)被編譯器忽略。這種注釋可以包含任何的文本,包括額外的雙斜線。

界定符注釋對(duì):這種方式繼承自C語(yǔ)言,以/開始,以/結(jié)束,可以包含除了*/之外的任何內(nèi)容。包括換行符。

當(dāng)注釋界定符跨越多行時(shí),最好能顯式指出其內(nèi)部的程序行都屬于多行注釋的一部分。我們所采用的風(fēng)格是:注釋內(nèi)的每行都以一個(gè)星號(hào)開頭,從而指出整個(gè)范圍都是多行注釋的一部分

注釋界定符不能嵌套

一個(gè)注釋不能嵌套在另一個(gè)注釋之內(nèi)。如果進(jìn)行嵌套會(huì)產(chǎn)生很復(fù)雜的錯(cuò)誤。

我們通常需要在調(diào)試期間注釋掉一些代碼。由于這些代碼可能包含界定符形式的注釋,所以我們使用單行注釋的方法來(lái)進(jìn)行操作。

1.3節(jié)練習(xí)

練習(xí) 1.7:編譯一個(gè)包含不正確的嵌套注釋的程序,觀察編譯器返回的錯(cuò)誤信息。

// filename: a.cpp
int main() {
    /* */ */
    return 0;
}

// a.cpp: In function 'int main()':
// a.cpp:2:12: error: expected primary-expression before '/' token
//      /* */ */
//             ^
// a.cpp:3:5: error: expected primary-expression before 'return'
//      return 0;
//      ^~~~~~

練習(xí) 1.8:指出下列哪些輸出語(yǔ)句是合法的(如果有的話):

std::cout << "/*"; // 合法

std::cout << "*/"; // 合法

std::cout << /* "*/" */; // 非法
// 應(yīng)當(dāng)修正為:std::cout << "*/";
    
std::cout << (/* "*/)" /* "(/*" */); // 合法

1.4 控制流

語(yǔ)句一般是順序執(zhí)行的:語(yǔ)句塊的第一條語(yǔ)句首先執(zhí)行,然后是第二條語(yǔ)句,依此類推。

1.4.1 while語(yǔ)句

while語(yǔ)句反復(fù)執(zhí)行一段代碼,直到給定的條件為假為止。

#include <iostream>

int main() {
    int sum = 0;
    int val = 1;
    // 只要val的值小于等于10,while循環(huán)就會(huì)持續(xù)執(zhí)行
    while (val <= 10) {
        sum += val;
        ++val;
    }
    std::cout << "Sum of 1 to 10 inclusive is ";
              << sum << std::endl;
    return 0;
}

while語(yǔ)句的形式為:

while (condition) {
    statements;
}

while語(yǔ)句的執(zhí)行過程是交替的檢測(cè)condition條件和執(zhí)行關(guān)聯(lián)的語(yǔ)句statements,直至condition為假時(shí)停止。所謂條件就是產(chǎn)生真或者假的結(jié)果的表達(dá)式。只要condition為真,statements就會(huì)被執(zhí)行。

條件中使用了小于等于運(yùn)算符來(lái)比較val和10的大小關(guān)系。

所謂語(yǔ)句塊,就是用花括號(hào)包圍的零條或者多條語(yǔ)句的序列。語(yǔ)句塊也是語(yǔ)句的一種,在任何要求使用語(yǔ)句的地方都可以使用語(yǔ)句塊。

復(fù)合賦值運(yùn)算符:將其右側(cè)的運(yùn)算對(duì)象加到左側(cè)運(yùn)算對(duì)象上,將結(jié)果保存到左側(cè)的運(yùn)算對(duì)象中。

前置遞增運(yùn)算符:將運(yùn)算對(duì)象的值增加1。

1.4.1節(jié)練習(xí)

練習(xí) 1.9:編寫程序,使用while循環(huán)將50到100的整數(shù)相加。

#include <iostream>

int main() {
    int sum = 0;
    int val = 50;
    while (val <= 100) {
        sum += val;
        ++val;
    }
    std::cout << "Result: " << sum << std::endl;
    return 0;
}

練習(xí) 1.10:除了++運(yùn)算符將運(yùn)算對(duì)象的值增加1之外,還有一個(gè)遞減運(yùn)算符--實(shí)現(xiàn)將值減少1。編寫程序,使用遞減運(yùn)算符在循環(huán)中按遞減順序打印出10到0之間的整數(shù)。

#include <iostream>

int main() {
    int val = 10;
    while (val >= 0) {
        std::cout << val << " ";
        --val;
    }
    std::cout << std::endl;
    return 0;
}

練習(xí) 1.11:編寫程序,提示用戶輸入兩個(gè)整數(shù),打印出這兩個(gè)整數(shù)所指定的范圍內(nèi)的所有整數(shù)。

#include <iostream>

int main() {
    std::cout << "Enter two numbers: ";
    int begin = 0;
    int end = 0;
    std::cin >> begin >> end;
    while (begin < end) {
        std::cout << begin << " ";
        ++begin;
    }
    std::cout << std::endl;
    return 0;
}

1.4.2 for語(yǔ)句

每個(gè)for語(yǔ)句都包含了兩部分,循環(huán)頭和循環(huán)體。循環(huán)頭控制循環(huán)體的執(zhí)行次數(shù),它由三部分組成:一個(gè)初始化語(yǔ)句、一個(gè)循環(huán)條件以及一個(gè)表達(dá)式。

定義在初始化語(yǔ)句中的變量只能在for循環(huán)之內(nèi)使用,在循環(huán)結(jié)束之后是不能使用的。初始化語(yǔ)句只在for循環(huán)入口處執(zhí)行一次。

循環(huán)體每次執(zhí)行之前都會(huì)檢查循環(huán)條件。如果條件為真然后就依次執(zhí)行循環(huán)體和表達(dá)式,直到循環(huán)條件為假。

簡(jiǎn)要重述一下for循環(huán)的總體執(zhí)行流程:

  1. 執(zhí)行初始化語(yǔ)句,初始化語(yǔ)句中的變量只能在循環(huán)內(nèi)使用。
  2. 檢測(cè)循環(huán)條件是否為真,如果為真就依次執(zhí)行循環(huán)體和表達(dá)式,否則退出循環(huán)。
  3. 重復(fù)2。
1.4.2節(jié)練習(xí)

練習(xí) 1.12:下面的for循環(huán)完成了什么功能?sum的終值是多少?

int sum = 0;
for (int i = -100; i <= 100; ++i) {
    sum += i;
}

這個(gè)for循環(huán)的功能是將-100到100的整數(shù)全部相加起來(lái),最后的終值是0。

練習(xí) 1.13:使用for循環(huán)重做1.4.1節(jié)中的所有練習(xí)(第11頁(yè))。

// 練習(xí) 1.9:編寫程序,使用while循環(huán)將50到100的整數(shù)相加。
#include <iostream>
int main() {
    int sum = 0;
    for (int val = 50; val <= 100; ++val) {
        sum += val;
    }
    std::cout << "Ans: " << sum << std::endl;
    return 0;
}

// 練習(xí) 1.10:除了++運(yùn)算符將運(yùn)算對(duì)象的值增加1之外,還有一個(gè)遞減運(yùn)算符--實(shí)現(xiàn)將值減少1。
// 編寫程序,使用遞減運(yùn)算符在循環(huán)中按遞減順序打印出10到0之間的整數(shù)。
#include <iostream>
int main() {
    for (int val = 10; val >= 0; --val) {
        std::cout << val << " ";
    }
    std::cout << std::endl;
}

// 練習(xí) 1.11:編寫程序,提示用戶輸入兩個(gè)整數(shù),打印出這兩個(gè)整數(shù)所指定的范圍內(nèi)的所有整數(shù)。
#include <iostream>
int main() {
    std::cout << "Enter two numbers: ";
    int begin = 0;
    int end = 0;
    for (std::cin >> begin >> end; begin <= end; ++begin) {
        std::cout << begin << " ";
    }
    std::cout << std::endl;
    return 0;
}

練習(xí) 1.14:對(duì)比f(wàn)or循環(huán)和while循環(huán),兩種形式的優(yōu)缺點(diǎn)各是什么?

while循環(huán)一定會(huì)先檢查循環(huán)條件。
for循環(huán)支持你寫一些初始化的條件和斷后表達(dá)式。
https://stackoverflow.com/questions/2950931/for-vs-while-in-c-programming

練習(xí) 1.15:編寫程序,包含第14頁(yè)“再探編譯”中討論的常見錯(cuò)誤。熟悉編譯器生成的錯(cuò)誤信息。

No Present

1.4.3 讀取數(shù)量不定的輸入數(shù)據(jù)

我們可以將標(biāo)準(zhǔn)輸入語(yǔ)句當(dāng)作循環(huán)語(yǔ)句的條件來(lái)完成不定量的數(shù)據(jù)輸入。

當(dāng)我們使用一個(gè)istream對(duì)象作為條件時(shí),其效果是檢測(cè)流的狀態(tài)。如果流是有效的,即流未遇到錯(cuò)誤,那么檢測(cè)成功。當(dāng)遇到文件結(jié)束符,或者遇到一個(gè)無(wú)效的輸入時(shí),istream對(duì)象的狀態(tài)會(huì)變?yōu)闊o(wú)效。處于無(wú)效狀態(tài)的istream對(duì)象會(huì)使條件變?yōu)榧佟?/p>

1.4.3節(jié)練習(xí)

練習(xí) 1.16:編寫程序,從cin讀取一組數(shù),輸出其和。

#include <iostream>

int main() {
    int sum = 0;
    int val = 0;
    while (std::cin >> val) {
        sum += val;
    }
    std::cout << "The sum is " << sum << std::endl;
    return 0;
}

1.4.4 if語(yǔ)句

if語(yǔ)句也對(duì)一個(gè)條件進(jìn)行求值。如果條件為真,則執(zhí)行程序塊;否則不執(zhí)行程序塊或者執(zhí)行else塊中的語(yǔ)句。

1.4.4節(jié)練習(xí)

練習(xí) 1.17:如果輸入的所有值都是相等的,本節(jié)的程序會(huì)輸出什么?如果沒有重復(fù)值,輸出又會(huì)是怎樣的?

如果所有的值都是相等的,程序只會(huì)打印一行
如果所有值都不一樣,那么每個(gè)單詞打印一行并標(biāo)明一次

練習(xí)1.18:編譯并運(yùn)行本節(jié)的程序,給它輸入全部相等的值。再次運(yùn)行程序,輸入沒有重復(fù)的值。

#include <iostream>

int main() {
    int current_value = 0;
    int current_count = 0;
    int last_value = 0;
    if (std::cin >> current_value) {
        ++current_count;
        last_value = current_value;
        while (std::cin >> current_value) {
            if (current_value == last_value) {
                ++current_count;
            } else {
                std::cout << last_value << " occurs ";
                std::cout << current_count;
                std::cout << ((current_count > 1) ? " times" : " time");
                std::cout << std::endl;
                last_value = current_value;
                current_count = 1;
            }
        }
        std::cout << last_value << " occurs ";
        std::cout << current_count;
        std::cout << ((current_count > 1) ? " times" : " time");
        std::cout << std::endl;
    }
    return 0;
}

// 1 1 1 1 1 1^Z
// 1 occurs 6 times

// 1 2 3 4 5^Z
// 1 occurs 1 time
// 2 occurs 1 time
// 3 occurs 1 time
// 4 occurs 1 time
// 5 occurs 1 time

練習(xí) 1.19:修改你為1.4.1節(jié)練習(xí)1.10(第11頁(yè))所編寫的程序(打印一個(gè)范圍內(nèi)的數(shù)),使其能夠處理用戶輸入的第一個(gè)數(shù)比第二個(gè)數(shù)小的情況。

#include <iostream>

int main() {
    int value_one = 0;
    int value_two = 0;
    std::cout << "Enter two numbers: ";
    std::cin >> value_one >> value_two;
    if (value_one < value_two) {
        while (value_one <= value_two) {
            std::cout << value_one << " ";
            ++value_one;
        }
    } else {
        while (value_two <= value_one) {
            std::cout << value_two << " ";
            ++value_two;
        }
    }
    std::cout << std::endl;
    return 0;
}
C++程序的縮進(jìn)與格式

C++程序很大程度上是格式自由的,也就是說(shuō),我們?cè)谀睦锓胖没ɡㄌ?hào)、縮進(jìn)、注釋以及換行符通常不會(huì)影響程序的語(yǔ)義。

其他的格式總是存在的。當(dāng)你要選擇一種風(fēng)格時(shí),就要堅(jiān)持使用。

1.5 類簡(jiǎn)介

在C++中,我們通過定義一個(gè)類來(lái)定義自己的數(shù)據(jù)結(jié)構(gòu)。一個(gè)類定義了一個(gè)類型,以及于其關(guān)聯(lián)的一組操作。

習(xí)慣上,我們約定C++的頭文件被定義成.hpp后綴的文件。

1.5.1 Sales_item類

每個(gè)類實(shí)際上都定義了一個(gè)新的類型,其類型名就是類名。因此,我們的Sales_item類定義了一個(gè)名為Sales_item的類型。與內(nèi)置類型一樣,我們可以定義類類型的變量:

Sales_item item;

這個(gè)表達(dá)式聲明了一個(gè)Sales_item類型的對(duì)象。

關(guān)鍵概念:類定義了行為

類Sales_item的作者定義了類對(duì)象可以執(zhí)行的所有動(dòng)作。一般而言,類的作者決定了類類型對(duì)象上可以使用的所有操作。

下面的程序從標(biāo)準(zhǔn)輸入中讀入數(shù)據(jù),存入一個(gè)Sales_item對(duì)象中,然后將Sales_item的內(nèi)容寫回到標(biāo)準(zhǔn)輸出中:

#include <iostream>
#include "Sales_item.h"

int main() {
    Sales_item book;
    // 以下兩個(gè)操作需要涉及運(yùn)算符的重載
    std::cin >> book; // 這里需要自己自定義標(biāo)準(zhǔn)輸入的輸入方式
    std::cout << book << std::endl; // 這里也需要自定義標(biāo)準(zhǔn)輸出的方式
    return 0;
}

包含來(lái)自標(biāo)準(zhǔn)庫(kù)的頭文件時(shí)需要使用尖括號(hào)包圍,對(duì)于不屬于標(biāo)準(zhǔn)庫(kù)的文件,則需要使用雙引號(hào)來(lái)包圍。

自定義類的對(duì)象的四則運(yùn)算同樣需要在類中進(jìn)行運(yùn)算符的重載。

1.5.1節(jié)練習(xí)

練習(xí) 1.20:編寫程序讀取一組銷售記錄,將每條記錄打印到標(biāo)準(zhǔn)輸出上。

#include <iostream>
#include <list>
#include <Sales_item.h>

int main()
{
    Sales_item book;
    std::list<Sales_item> book_list;
    while (std::cin >> book) {
        book_list.push_back(book);
    }
    for (auto item : book_list) {
        std::cout << item << std::endl;
    }
    return 0;
}

練習(xí) 1.21:編寫程序,讀取兩個(gè)ISBN的相同的Sales_item對(duì)象,輸出它們的和。

#include <iostream>
#include "Sales_item.h"
#include <list>

int main()
{
    std::list<Sales_item> book_list;
    Sales_item book;
    std::cout << "Enter the first book:";
    std::cin >> book;
    book_list.push_back(book);
    std::cout << "Enter the second book:";
    std::cin >> book;
    book_list.push_back(book);
    if (book_list[0].isbn() == book_list[1].isbn()) {
        std::cout << book_list[0] + book_list[1] << std::endl;
    } else {
        std::cout << "Error: isbns are not same."
    }
    return 0;
}

練習(xí) 1.22:編寫程序,讀取多個(gè)具有相同ISBN的銷售記錄,輸出所有記錄的和。

#include <iostream>
#include "Sales_item.h"

int main()
{
    Sales_item book;
    Sales_item temp;
    std::cin >> book;
    while (std::cin >> temp) {
        if (temp.isbn() == book.isbn()) {
            book = book + temp;
        } else {
            break;
        }
    }
    std::cout << book << std::endl;
    return 0;
}

1.5.2 初識(shí)成員函數(shù)

如果想要將兩個(gè)Sales_item對(duì)象相加的程序首先應(yīng)該檢查兩個(gè)對(duì)象是否具有想通的ISBN。

#include <iostream>
#include "Sales_item.h"

int main()
{
    Sales_item item1;
    Sales_item item2;
    std::cin >> item1 >> item2;
    // 首先檢查item1和item2是否表示相同的書
    if (item1.isbn() == item2.isbn()) {
        std::cout << item1 + item2 << std::endl;
        return 0;
    } else {
        std::cerr << "Data must refer to same ISBN" << std::endl;
        return -1; // 返回-1表示失敗
    }
}
什么是成員函數(shù)

成員函數(shù)是定義為類的一部分的函數(shù),有時(shí)也被稱為方法。我們通常使用類對(duì)象來(lái)調(diào)用成員函數(shù)。使用點(diǎn)運(yùn)算符( . )來(lái)表達(dá)我們需要通過一個(gè)對(duì)象來(lái)調(diào)用成員函數(shù)來(lái)獲取這個(gè)對(duì)象的屬性。點(diǎn)運(yùn)算符只能用于類類型的對(duì)象。其左側(cè)運(yùn)算對(duì)象必須是一個(gè)類類型的對(duì)象,右側(cè)運(yùn)算對(duì)象必須是該類型的一個(gè)成員名,運(yùn)算結(jié)果為右側(cè)運(yùn)算對(duì)象的指定成員

當(dāng)使用點(diǎn)運(yùn)算符訪問一個(gè)成員函數(shù)時(shí),通常我們需要調(diào)用這個(gè)函數(shù)。我們使用調(diào)用運(yùn)算符( () )來(lái)調(diào)用一個(gè)函數(shù)(也就是一個(gè)可以被調(diào)用的對(duì)象)。調(diào)用運(yùn)算符是一對(duì)圓括號(hào),里面放置實(shí)參(argument)列表(可能為空)。

1.5.2節(jié)練習(xí)

練習(xí) 1.23:編寫程序,讀取多條銷售記錄,并統(tǒng)計(jì)每個(gè)ISBN(每本書)有幾條銷售記錄。

#include <iostream>
#include <list>
#include <string>
#include "Sales_item.h"

struct BookInfo
{
    BookInfo(std::string i, int a) : 
        isbn(i), amount(a) { }
    std::string isbn() const { return isbn; }
    std::string isbn;
    int amount;
};

int main()
{
    std::list<BookInfo> book_infos;
    Sales_item temp_book;
    while (std::cin >> temp_book) {
        bool is_found = false;
        for (auto item : book_infos) {
            if (temp_book.isbn() == item.isbn()) {
                item.amount += 1;
                is_found = true;
                break;
            }
        }
        if (!is_found) {
            book_infos.push_back(BookInfo(temp_book.isbn(), 1));
        }
    }
    for (auto item : book_infos) {
        std::cout << item.isbn() << " " << item.amount << std::endl;
    }
    return 0;
}

練習(xí) 1.24:輸入表示多個(gè)ISBN的多條銷售記錄來(lái)測(cè)試上一個(gè)程序,每個(gè)ISBN的記錄應(yīng)該聚在一起。

// 以上的程序可以接受不同的輸入方式

1.6 書店程序

樹上的書店程序還沒有練習(xí)1.23的復(fù)雜……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容