計算導論與C語言基礎6

冰冰愛編程 發佈 2022-04-11T03:06:50.170318+00:00

在講課內容裡頭,我們把它分成了四個階段 分別是感性認識,理性認識,函數,以及指針等等其它的部分,分成了這幾個階段 那麼作業練習,跟這個不同, 作業練習呢,我們把它大致分兩個階段,一個叫初級階段的作業練習 一個叫正常的作業練習,那麼在作業練習的初級階段 我不要求大家能夠獨立地寫出正確的電腦程式,我不作這個要求 在這個階段,我只希望你拿出你的興趣來 通過一種感性的方式儘可能多地去了解,去感受電腦程式 這是我在這一階段給大家的要求,從時間上講 雖然我們接下來講課內容要進入理性階段了, 但是我們的作業練習將長期處於初級階段,給大家 一個比較長的緩衝時間,利用這段時間去充分地感受程序,然後我們再慢慢地過渡到 正常的作業練習 我相信大家通過這個圖能夠明白我們目前所處的進度,總而言之,接下來講課內容要進入 理性認識機程序這個階段,但是我們作業練習將長期處於初級階段 在這個階段,我只希望你們通過感性的方式充分地去了解程序,就可以了。

理性認識C程序 導論

本次課幫助大家了解C語言的歷史,了解C語言規範(Specification)的版本演進,了解C語言的規範是一個「寬鬆」的規範;在此基礎上,我們將闡述一門程序設計語言所包含的四種基本成分(如上所述)。 焦點問題:為什麼相同的c程序在不同的C程序編譯器上,會編譯出不同的結果?

明確學習進度
好,同學們,我們 繼續往前推進我們的學習,那麼在開始這個新的部分之前 我們先來明確一下我們接下來的學習進度 明確一下我們處在什麼地方,將來 會怎麼去走,大家看這個圖,在這個圖上有兩條線 一條線是講課內容, 也就是在我們的課程裡頭要講述的知識 包含這些怎樣的進度 第二條線呢是作業練習。它的一個進度。在講課內容裡頭,我們把它分成了四個階段 分別是感性認識,理性認識,函數,以及指針等等其它的部分,分成了這幾個階段 那麼作業練習,

跟這個不同, 作業練習呢,我們把它大致分兩個階段,一個叫初級階段的作業練習 一個叫正常的作業練習,那麼在作業練習的初級階段 我不要求大家能夠獨立地寫出正確的電腦程式,我不作這個要求 在這個階段,我只希望你拿出你的興趣來 通過一種感性的方式儘可能多地去了解,去感受電腦程式 這是我在這一階段給大家的要求,

從時間上講 雖然我們接下來講課內容要進入理性階段了, 但是我們的作業練習將長期處於初級階段,給大家 一個比較長的緩衝時間,利用這段時間去充分地感受程序,然後我們再慢慢地過渡到 正常的作業練習 我相信大家通過這個圖能夠明白我們目前所處的進度,總而言之,接下來講課內容要進入 理性認識機程序這個階段,但是我們作業練習將長期處於初級階段 在這個階段,我只希望你們通過感性的方式充分地去了解程序,就可以了

C語言的由來


那好,在真正開始我們理性認識C程序之前, 我們這次課呢,我們先花一點時間來做一些預熱和準備 跟大家介紹一下,我們即將學習的 C程序設計語言。 OK。那麼C程序設計語言首先是一門高級程序設計語言。 什麼叫高級程序設計語言,待會我們再說。而且呢,根據這個網站的綜合統計, C程序設計語言仍然是全世界最通用的程序設計語言。 我們通過這個數據呢我們看的出來,接下來還有java,還有C++ PHP等等等等一系列的程序設計語言。

那麼有一種程序設計語言就是python。 python呢發展比較快,雖然比較新。但是呢,迅速地 受到人們的關注。如果有興趣的同學可以去關注一下python。 那在這個課上呢,當然我們要學的就是C語言了。 那我就想問一個問題。你知道,它為什麼要叫C語言嗎? 它為什麼不叫B語言,為什麼不叫D語言, 為什麼它要叫C語言呢?

那麼接下來我們就來說一下這件事情。 要說這件事情,我們得從最基本的計算機語言開始說起 那計算機能夠接受的最基本的語言就是機器語言, 也就是010101這樣的字符串。我們可以看到比方說這一串字符串表示 把數據裝入寄存器0,底下這一串,表示數據裝入寄存器1, 然後呢以此類推。我們可以看到由0101這樣的字符串所構成的語言, 它也是一種語言,只不過它比較低級。我們把它叫做低級計算機語言。 看了這個呢大家可以感受到,如果我們每天寫程序,都寫0101這樣的字符串, 那是不是痛苦死啦,但是有一個人並不覺得這樣是痛苦的,待會我們再說他。 至少我們覺得這樣是,實在是痛苦死了。

所以人們為了提高寫程序的效率,不斷地去改良這些語言。 比方說在低級語言的基礎上,我們又發明出了彙編語言。像這樣的句子就是彙編語言。 load 0 a表示把數據a裝入寄存器0; load 1 b表示把數據b裝入寄存器1; mult 0 1把這兩個寄存器的數進行一個相乘的運算。 然後呢,把一個新的數據c裝入到寄存器1裡頭。寄存器0和1的數據相加, 結果保存在寄存器0裡頭,通過這種方式。 這個呀,比剛才我們看到的01字符串強多了, 至少我們能看懂這串是什麼意思了。有了很大的進步,但它仍然屬於低級語言。 那什麼叫高級語言啊?對比一下你就知道什麼叫高級語言了。 看這個,這是剛才的那一堆,二進位的字符串。 這是剛才我們所看到的,彙編語言的那段程序。

這個呢,是功能等價的c程序。d等於a乘以b加c。所以c程序看上去是不是比上面兩種語言 要簡單的多容易理解得多? 相對於剛才所謂的低級語言,這種語言 更有利於人們去理解和書寫它, 有利於提高程序開發的效率,所以我們把c語言稱作高級語言。 那麼在歷史上曾經誕生過很多 很多很多門的高級語言。在這呢,有一張圖。 這張圖呢,列出了,到目前為止,被人們提出過的各種高級程序設計語言 以及它們之間的演化關係。

由於這張圖實在是太大了,我沒辦法在這呈獻給大家, 於是呢我在這給了一個連結,大家如果感興趣的話,可以到這個連結來,去打開這張圖去看。 那這麼多的高級程序設計語言,我們不可能一一列數了。 那麼我們就來看一下,第一門高級程序設計語言。那這門程序設計語言叫什麼呢? 叫做FORTRAN, 是在1954到1956年,由ibm的一位非常著名的計算機學家, 叫做John Backus,他領導一個團隊創立出來的。







在那個時候啊,人們還不是特別看好,高級程序設計語言。比方說有一個人就覺得john backus所做的事情實在是沒有意義。 這個人是誰呢,是大家非常熟悉的,馮諾伊曼。 在john backus在IBM工作的時候, 馮諾伊曼已經是一個非常著名的計算機學家了。 於是呢,IBM就邀請馮諾伊曼去公司擔任顧問。 他經常來審查公司的各種的新的研究計劃。那麼當馮諾伊曼看到 john backus所做的這個研究的時候,看到他們正在搞一個叫fortran語言的時候, 他覺得絲毫沒有興趣。他反而去問john backus說你為什麼除了機器語言之外你總想搞點別的呢? 這種東西有用嗎?

所以他非常質疑john backus所做的這樣一件事情。 其實馮諾伊曼反對高級程序設計語言的這個觀點早就被人們所熟知了。 他有一個學生曾經設計了一個編譯程序,輔助人們把彙編語言編譯成二進位的代碼。 那麼馮諾伊曼發現這件事情之後,甚至跟這個學生說, 哎呀你把這麼寶貴的計算資源拿用來幹這個,幹這麼瑣碎的事情, 實在是沒有意義。這是馮諾伊曼當時對john bakus的評價。 但是呢,john backus這個人啊, 是一個非常有性格而倔強的人, 他小的時候是一個相當頑劣的人。 那個時候他覺得去上學最有意思的一件事情就是,學校里有那麼多的規矩可以去破壞, 他覺得這件事情非常的有意思。

後來它參軍進入了醫學院。他又覺得醫學院所教授的那些東西不鼓勵人們去 思考,只是死記硬背,於是呢,很快就退學了。 那麼退學以後呢,他又想去搞一些高保真的音響,那個時候還沒有高保真的音響, 他想自己去搞,於是呢對電路等等產生了很強的興趣。 隨著他對電路的研究呢,他發現其實 真正有用的東西是數學,於是他又去學習數學。之後呢,非常偶然的一次機會, 那麼john backus得到了一個面試機會進入了ibm。 對於這樣的一個人來說,他想做的事情你是擋不住的。於是john backus 還是領導他的團隊搞出了fortran語言。

那麼fortran語言呢在整個計算機發展歷史上具有非常非常重要的地位, 他是第一門高級程序設計語言。那麼到目前為止, fortran這門語言人們仍然在使用,特別是在數學計算領域。 因為fortran它是特別適合用來做數學計算, 這是1954年前後所發生的事情。那麼到了1960年, 有一個非常著名的計算機學家,叫做alan perlis。 他呢,在1960年巴黎的軟體專家討論會上, 發表了一篇著名的報告。叫做算法語言 algol 60報告。 這篇報告宣告了一門新的程式語言的誕生,這就是algol 60。.algol 60呢在電腦程式設計語言的發展史上 具有非常重要的地位,它的誕生具有很大的影響力。

甚至於,後來有的計算機學家, 比方說迪傑斯特拉他就講過一句話:「algol 60的提出 標誌著計算科學的誕生。 通過這個呢我們就可以感受到algol 60在整個計算機科學的發展史上,重要的地位。 那麼在這呢,還值得一提的就是這篇報告。 alan perlis的這篇報告寫的非常的好。 那麼有報導就說,這篇報告的優雅一致和連貫使得alan perlis 立刻確立了他在計算機領域的地位。那麼這篇報告呢在英特網上就可以找得著, 大家如果感興趣的話可以拿這篇報告來觀摩一下。 那么正因為algol 60所具有的重要地位和影響力,人們又把它簡稱為A語言。 那麼有了A語言以後呢,1963年劍橋大學又在algol 60的基礎上,推出了 一門新的語言,叫做combined programming language, 簡稱CPL。

但是當時呢他們搞得這個語言太複雜了。後來到1967年的時候有一個非常著名的教授,叫做martin richards。 他呢又對CPL做了一個簡化, 提出來了basic CPL。basic CPL呢在當時迅速的引起了人們的關注, 成為當時比較流行第一門程序設計語言。 那麼時間再往前發展,到了1970年, 在1970年的時候在貝爾實驗室, 又是貝爾實驗室。我曾經講過在計算機的發展史上,貝爾實驗室 做出了巨大的貢獻。那個時候呢貝爾實驗室有一個人,叫做ken thompson, 就是左邊的這位老兄了,他呢,ken thompson當時在貝爾實驗室工作。 那麼在一個項目結束以後,ken thompson有一些時間上的空餘。

於是他就想, 我能不能寫一個遊戲玩一玩,於是呢他就找來了一台機器, 叫做PDP-7,這是一台當時被淘汰的機器。 當時呢已經被淘汰了,閒置那兒不用。於是呢, ken thompson就把這台機器找來,說想要在這台機器上寫個遊戲玩一玩。 但是他發現這台機器上沒有一個合用的機器作業系統,於是呢他就想出來說, 我幹嘛不在這台機器上寫個新的作業系統呢。寫作業系統又發現沒有特別合用的語言, 於是,ken thompson就在剛才我們提到的basic BPL的基礎上進行進一步的簡化, 簡化出來一門新的語言叫做B語言. 然後利用這個B語言在那台已經被淘汰的機器上寫了一個作業系統。這個作業系統的名字叫做UNIX. UNIX在計算機作業系統的發展史上具有不可撼動的地位。

UNIX是當時,甚至現在,最先進的作業系統之一。那麼說到這呢我們不禁要感嘆一下, 你看 ken thompson為了玩一個遊戲帶來了多少的成果啊。 那麼接下來有時間的時候我們會再推出一個專題, 就是關於作業系統的。到時候我們就可以講授一下作業系統的發展歷史。那麼到了1972年的時候, 貝爾實驗室的另一位同事,叫做Dennis Ritchie, 就是右邊的這位老兄了, 他呢,發現ken thompson做的事情非常的有意思,於是他也加入進來。 於是呢兩個人在ken thompson所開發的這個b語言的基礎上, 繼續發展和完善, 提出了一門新的語言,後來把它稱為C語言。 並且呢,他們用C語言重寫了UNIX。 那麼用C語言所重新開發的這個UNIX的版本, 成為後來在全世界,具有巨大影響力的作業系統。

那麼,成為, 用C語言重新編寫的這個UNIX的版本, 成為後來在全世界有巨大影響力的作業系統。 這就是C語言和UNIX的來歷。 為了表彰這兩位計算機科學家所作出的巨大貢獻, 那麼在1999年的時候呢,當時的美國總統柯林頓授予他們國家技術獎章。 那麼在網上有一個關於UNIX的一個簡單的介紹,大家可以通過這個網址去訪問一下。 在這,我想提示大家一點。你觀察到了沒? 這兩位老兄都留有巨大的鬍子。這個在計算機語言的發展歷史上是一個特別有意思的現象。 後來人們發現,所有,留有大鬍子的人所提出來的程序設計語言, 都會在後來變得特別的流行,這是一個特別有意思的現象。 甚至於呢,後來有一些程序語言的發明者, 為了能夠使自己發明的語言更加的流行,也留起了大鬍子。

C語言的標準




那麼c語言提出之後呢,隨著技術的不斷發展,曾經衍生過不同的版本。什麼叫做版本呢? 作為一門程序設計語言, 為了保證人們寫出來的語言都能夠滿足統一的要求 也同時保證編譯器 能夠按照統一的標準來進行編譯,那人們必須要給程序設計語言 立一個規範,制定一個標準,來說明到底這門語言長成什麼樣子 那麼在C語言的發展歷史上就有過不同的版本 比方說,在C語言剛剛提出的時候,在1978年的時候,Ritchie 和另外一個人就寫了一本書 叫The C Programming Language。這是一本非常有名的書了。

雖然當時還沒有任何一個國際組織出來給 C 語言立一個規範 但是當時這本書卻成為 C 語言事實上的一個規範 後來人們把這一版的 C 稱為 K & R C。 那麼到了1989年的時候有一個標準化組織ANSI


ANSI是美國國家標準學會的簡稱,就是 America National Standards Institute ANSI 大家可以理解是為專門制定標準的這麼一個組織。 在1989年的時候ANCI首先對 C 語言進行了標準化,也就是說,制定了一個標準 它對 K & R C 進行了擴展,增加了一些新的特性 也規定了一套標準的函數庫,形成了一個新的標準。 同時呢,另外一個組織是ISO。ISO我相信大家比較熟悉了,就是國際標準化組織 那麼前面我們提到的ANSI實際上是國際標準化組織(ISO)的一個成員。國際標準化組織 專門成立了一個工作組,叫做WG14工作組。它呢 來制定國際標準的 C 語言規範。這個小組在ANSI標準的基礎上,進行了少量的修改,在1990年的時候通過了第一個關於 C 語言的國際化標準叫做 ISO 9899:1990。

這是第一個國際化的 C 語言標準。 在1989年,人們又對這個標準進行了比較大的修改 推出了一個新的版本,就是ISO 9899:1999。 那麼這個版本後來變成特別通行的一個版本,人們把它俗稱為 C 99版。 那麼目前為止最新的 C 語言國家標準是哪個呢? 是2001年12月8日通過的一個新的版本 叫做ISO IEC 9899:2011 那麼目前為止關於 C 語言的國際規範最新的版本就是C11 在這裡我給了一個連結,通過這個連結,大家就可以訪問到國際標準化組織 關於 C 語言的這個規範。當然,如果你如果要 download 這個規範的話是要付錢的 不過,你可以在 Internet 上找到 free 版本下來觀摩一下 那麼在這裡有一個情況需要特別說明一下。

什麼事情呢?在這需要特別說明的是 雖然我們有一個國際標準來定義 C 語言,也就是說, C 語言長成什麼樣子,這個國際標準應該是清清楚楚定義的 但是,現有的國際標準對 C 語言的定義 卻是相當的寬泛。也就是說,定義的方式相當寬泛。 什麼叫寬泛,舉個例子,比如說關於數據類型,它定義 long型數據 長度不短於 int 型就可以了。 再比如,short 型不長於 int 型就可以了。這會導致一個什麼狀況呢 舉個簡單的例子,比方說,對於整型的變量 int 型

int 型是我們寫程序裡面定義整數變量經常遇到的一種類型。對於int 型的變量,在 Turbo C 裡面 Turbo C是一個 C 程序的編譯平台。 在這個平台裡面,它占多大空間呢?占16個 bit,16位。 然而在VC 裡面,我們都知道,一個整型變量卻占有32位 沒關係,聽不明白沒關係,你只要知道在不同的開發平台上關於整型變量的定義是不同的 那會導致一個什麼結果呢?相同的程序在不同的編譯器上運行 可能會有不同的解釋 從而造成相同的程序在不同的平台上的 運行結果也有可能是不同的 我們經常會碰到一個作業題,為什麼我在這個編譯器上編譯通過了,在另一個編譯器上就編譯不通過了呢 就是這個原因,因為 C 語言的規範定義的太寬泛 所以,造成了不同的編譯器實際的標準是不同的。

所以呢在不同編譯器上編譯出來的結果是不同的,在不同平台上運行的結果也是不同的。 當然了,這個情況不會經常發生。 比方說,在我們已知的這幾個編譯平台上,可能在這幾點上存在一些不同。 比方說,剛剛我們講過的,整型變量的定義。 對於++、- - 這樣運算符的解釋,還有呢,在輸入輸出賦值順序方面也有點不同 再就是,浮點計算精度方面也可能存在一些不同。 有同學可能問了,存在這麼多不同,那在寫程序的時候很容易 造成在這個平台上通過了在那個平台上就通過不了啊 不是的。首先,我們所使用的這幾個平台是非常非常接近的,不太容易出現這樣的狀況 第二呢,在布置作業或讓大家寫程序的時候 我們會有意識地避開可能編譯上存在不同規範的地方 以避免造成這樣的問題。這裡特別說明,讓大家知道這個事情

下面,我們接著說 C 程序設計語言的發展歷史。 有了 C 程序設計語言了, 我們就知道很快也會有 C++了。 在1979年的時候,又是貝爾實驗室的一位科學家,叫做Bjarne Stroustrup,簡稱 BS 他開發了一門語言,被稱為 C with Classes。 這門語言就是在 C 語言的基礎上,增加了面向對象的特性 於是,後來演變為 C++。 在這門語言成熟以後呢,在1985年的時候,Bjarne博士完成了一部巨著,就是 C++ Programming Language 這也是一本非常非常著名的書。這本著作把 C++語言推向了全世界 與 C 語言相同,人們也為 C++ 語言定義了相應的國際標準 比如說,在1998年的時候ISO頒布了第一份 C++ 的國際標準,叫做 ISO/IEC 14882-1998。

這是第一份關於C++ 的標準 有的同學可能要問,ISO我們知道是國際標準化組織的簡稱,那IEC是什麼呢 IEC是國際電工委員會的簡稱,就是International Electro Technical Commission IEC也是一個國際標準化的組織,它經常和 ISO 聯合發布一些標準 比方說,C++ 的標準就是 ISO 和 IEC 聯合發布的 關於C++ 最新的國際標準是2011年9月1日發布的 這個標準的號碼是ISO/IEC 14882-2011 也就是,人們經常說的 C++ 2011標準 這是關於 C++的最新標準 那麼關於這個標準,我同樣是給了一個連結,是國際標準化組織下面的連結 通過這個連結大家可以訪問到這個標準。

當然,閱讀關於一個程序設計語言的標準是一件非常痛苦的事情 比方說,C++ 這份標準它的正文的長度大約有1180頁 加上附錄以後,大概有1330多頁,所以閱讀這樣一份標準確實需要很多的時間 OK,這是關於 C 語言和 C++ 語言的發展歷史 那麼接下來,我們就要明確一個問題了,我們學的到底是 C 語言還是 C++ 語言啊? 雖然在講課的過程中我們提到過這個問題 但是,我看到有的同學在問,所以,我們在這裡再做一個回答 C 語言和 C++ 語言有一個這樣的關係,也就是說,C 語言可以看做是 C++ 語言的一個部分 當然,就它的發展歷史而言也確實是這樣的。C++ 語言是在原有 C 語言的基礎上擴展起來的 但是值得注意的是,C++ 語言規範和 C 語言規範是兩個不同的規範


它們之間是互相獨立的。也就是說,準確的說法應該是 C++ 語言支持了 C 語言所有的特性,應該這樣說 為了便於大家理解,我們就可以告訴他,我們要學習的是在 C++ 語言的環境中,學習 C++ 語言中C語言的部分。這就是我們的學習目標。 OK

C語言的構成


那在明確了我們的學習目標之後啊,接下來我們就要討論 一個很重要的問題,那就是到底應該如何學習一門程式語言呢 那有的同學會說了,這個問題不是 討論過了嗎?啊,為什麼現在又要來討論呢,我在這兒做一個特別的說明,這兒我們所說的 如何學習一門程式語言,指的是如何學習一門程式語言的語法知識


語法知識,而且呢,我們需要做一個特別的說明,就是說 我們底下所給出來的這個建議,不僅適用於C語言, 啊,也同樣適用於其他高級程序設計語言 我們應該按照一個什麼樣的思路去學習呢? 那我們當然就要看一下,在程式語言裡頭,到底有哪些東西 在中國的計算機界,有這樣一本書,叫做,計算機科學技術百科全書 那這本書呢,在中國的計算機科學技術領域 是具有一定的權威性的,那在這本書裡面 關於程序設計語言的構成,就有一段這樣的描述 這個描述是這樣來說的,語言的種類啊,千差萬別 但是,一般說來,基本的成分,不外四種,哪四種呢?

第一種,數據成分 第二種,運算成分,第三種,控制成分,第四種,傳輸成分 啊,這個話,我覺得,講的非常的精闢,這就告訴我們 你如果,想要學習一門程式語言的話 那麼,你就應該學習它的這四個部分,當你熟悉了 一門程式語言的這四個部分之後,你對這一門程式語言也就有一 個比較全面的了解了,那通過這個定義,我們同樣可以明白 這樣一件事情,也就是說啊, 如果你想學習一門高級程序設計語言,你關注這四個部分就可以了 啊,你比方說,讓我現在去學一門新的程序設計語言,我就會主動的從這 四個方面來了解這一門程式語言 哪四個方面呢?在數據成分,我會關注到底有哪些數據類型啊 這些數據類型是如何被使用的啊,它是怎麼去定義的呀, 在使用過程中,應該遵守一些什麼樣的規則呀?

這是第一個方面。第二個方面,在運算方面,我到底有哪一些運算符號,是我可以使用的啊 這些符號應該怎樣去使用啊,這是運算方面 控制成分,控制成分我很清楚,因為我們講過,所有的控制成分不外乎三種,順序,分支,循環 那我就會關注,對於這一門程序設計語言而言 這三種類型的控制語句,到底是如何寫的呀 它們到底按什麼格式去寫的啊?應該怎麼去使用啊 第四個部分,關於傳輸成分,也就是說,我想知道,在這一門 語言裡頭啊,在程序中,是如何輸入和輸出數據的 啊,也就是說,如果讓我來學習一門語言的話 那我就會從這四個方面去 尋找這些答案,

在這呢,我特別想跟大家推薦啊,這種方法,如果我們學習一門 程式語言,我們就可以從這四個方面去了解這個程序設計語言 就OK了,了解了這四個部分之後,你對這個程序設計語言就已經有一個相對比較 全面的認識了,那麼好,接下來呢,就讓我們開 始從C程序設計語言的這四個方面來理性的 認識一下C程序設計語言,接下來,我們要進入理性認識 C程序階段的這個學習了,好,那麼今天的課呢 就到這,那麼我們還會在編程作業部分,給大家 布置相應的程序抄寫題和練習題

編程作業: 理性認識C程序 導論 抄寫題
抄寫題#1:細菌實驗分組
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
有一種細菌分為A、B兩個亞種,它們的外在特徵幾乎完全相同,僅僅在繁殖能力上有顯著差別,A亞種繁殖能力非常強,B亞種的繁殖能力很弱。在一次為時一個小時的細菌繁殖實驗中,實驗員由於疏忽把細菌培養皿搞亂了,請你編寫一個程序,根據實驗結果,把兩個亞種的培養皿重新分成兩組。

細菌繁殖能力(繁殖率)的量化標準為一個小時內細菌數量增長的比例(繁殖率 = 一小時後細菌數量 / 原本細菌數量)。

兩個亞種繁殖能力差異很大,這意味著對於任意兩個同種細菌培養皿的繁殖率的測量值之間的差異要小於任意兩個異種細菌培養皿繁殖率的測量值之間的差異。即:

輸入
輸入有多行,第一行為整數n(n≤100),表示有n個培養皿。

其餘n行,每行有三個整數,分別代表培養皿編號,試驗前細菌數量,試驗後細菌數量。假設試驗沒有誤差。

輸出
輸出有多行:

第一行輸出A亞種培養皿的數量,其後每行輸出A亞種培養皿的編號,按繁殖率升序排列。

然後一行輸出B亞種培養皿的數量,其後每行輸出B亞種培養皿的編號,也按繁殖率升序排列。

樣例輸入

5
1 10 3456
2 10 5644
3 10 4566
4 20 234
5 20 232

樣例輸出

3
1
3
2
2
5
4

提示
亞種內部,細菌繁殖能力差異遠遠小於亞種之間細菌繁殖能力的差異。

也就是說,亞種間任何兩組細菌的繁殖率之差都比亞種內部兩組細菌的繁殖率之差大。

請完全按照如下的程序書寫代碼,並在書寫的過程中體會優秀的代碼風格:

#include <iostream>
using namespace std;
int main() {
  int n; // n為細菌的數量
  // id記錄細菌的編號, rate記錄細菌的繁殖率,第i個細菌對應id[i]和rate[i]
  int id[100];
  double rate[100];

  cin >> n;
  for (int i = 0; i < n; i++) {
    int initial, final;
    cin >> id[i] >> initial >> final;
    rate[i] = (double)final / initial;
  }  

// 對整個細菌排序
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n - i - 1; j++) {
      if (rate[j + 1] > rate[j]) {
        int tmpId = id[j];
        id[j] = id[j + 1];
        id[j + 1] = tmpId;
        double tmpRate = rate[j];
        rate[j] = rate[j + 1];
        rate[j + 1] = tmpRate;
      }
    }
  }  

// 記錄最大的差
  double maxDiff = 0;
  // 和最大差的下標
  int maxDiffIndex = 0;
  for (int i = 0; i < n - 1; i++) {
    double diff = rate[i] - rate[i + 1];
    if (maxDiff < diff) {
      maxDiff = diff;
      maxDiffIndex = i;
    }  
  }
  
  //輸出繁殖率較大的那組細菌
  cout << maxDiffIndex + 1 << endl;
  for (int i = maxDiffIndex; i >= 0; i--) {
    cout << id[i] << endl;
  }

  //輸出繁殖率較小的那組細菌
  cout << n - maxDiffIndex - 1 << endl;
  for (int i = n - 1; i >= maxDiffIndex + 1; i--) {
    cout << id[i] << endl;
  }
  return 0;
}

編程作業: 理性認識C程序 導論 編程題
編程題#1:蘋果和蟲子
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
你買了一箱n個蘋果,很不幸的是買完時箱子裡混進了一條蟲子。蟲子每x小時能吃掉一個蘋果,假設蟲子在吃完一個蘋果之前不會吃另一個,那麼經過y小時你還有多少個完整的蘋果?

輸入
輸入僅一行,包括n,x和y(均為整數)。

輸出
輸出也僅一行,剩下的蘋果個數

樣例輸入

第一組
10 4 9
第二組
10 4 36
第三組
10 4 100

樣例輸出

第一組
7
第二組
1
第三組
0

提示
注意:是要求完整的蘋果數。

編程題#2:大象喝水
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
一隻大象口渴了,要喝20升水才能解渴,但現在只有一個深h厘米,底面半徑為r厘米的小圓桶(h和r都是整數)。問大象至少要喝多少桶水才會解渴。

輸入
輸入有一行:包行兩個整數,以一個空格分開,分別表示小圓桶的深h和底面半徑r,單位都是厘米。

輸出
輸出一行,包含一個整數,表示大象至少要喝水的桶數。

樣例輸入

第一組
23 11
第二組
1 1

樣例輸出

第一組
3
第二組
6367

提示
如果一個圓桶的深為h厘米,底面半徑為r厘米,那麼它最多能裝Pi * r * r * h立方厘米的水。(設Pi=3.14159)

1升 = 1000毫升

1毫升 = 1 立方厘米

來源
計算概論化學學院期末考試

編程題#3:最高的分數
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
孫老師講授的《計算概論》這門課期中考試剛剛結束,他想知道考試中取得的最高分數。因為人數比較多,他覺得這件事情交給計算機來做比較方便。你能幫孫老師解決這個問題嗎?

輸入
輸入兩行,第一行為整數n(1 <= n < 100),表示參加這次考試的人數.第二行是這n個學生的成績,相鄰兩個數之間用單個空格隔開。所有成績均為0到100之間的整數。

輸出
輸出一個整數,即最高的成績。

樣例輸入

5
85 78 90 99 60

樣例輸出

99

編程題#4:最大奇數與最小偶數之差的絕對值
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
輸入6個正整數,且這6個正整數中至少存在一個奇數和一個偶數。

設這6個正整數中最大的奇數為a,最小的偶數為b,求出|a-b|的值

輸入
輸入為一行,6個正整數,且6個正整數都小於100

輸入保證這6個數中至少存在一個奇數和一個偶數

輸出
輸出為一行,輸出最大的奇數與最小的偶數之差的絕對值

樣例輸入

第一組
1 2 3 4 5 6
第二組
1 6 3 8 5 10

樣例輸出

第一組
3
第二組
1

編程題#5:分離整數的各個數位
來源: POJ (Coursera聲明:在POJ上完成的習題將不會計入Coursera的最後成績。)

注意: 總時間限制: 1000ms 內存限制: 65536kB

描述
從鍵盤輸入一個任意的三位整數,要求正確地分離出它的百位、十位和個位數,並分別在屏幕上輸出,輸出採用每行輸出一個數的方式,不帶其它符號。

輸入
一個任意的三位整數

輸出
一個任意的三位整數

樣例輸入

123

樣例輸出

1
2
3
關鍵字: