最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

如何用輕小說的方式學(xué)C++(五) 斐波那契與他的小兔子們

2019-09-22 01:49 作者:汐留楓Channel  | 我要投稿

剎那悄悄地瞥了一眼活動室內(nèi)。

黑燈瞎火,空無一人。

剎那松了一口氣,潛進(jìn)了活動室,正要摸開關(guān),發(fā)現(xiàn)燈突然就被兩位摯友給點亮了。


“剎那啊你發(fā)給我的那個程序什么意思?以為自己寫的復(fù)雜點我看不懂就會以為你是對的嗎?”

凜音跳了出來,一手叉腰一手直指剎那,仿佛名偵探推理完畢指著嫌疑人的那酷酷的動作。

“說過了要寫成特定的形式計算機才能讀得懂,你這亂寫肯定會出錯的!”

剎那羞愧地低下了頭。

因為回去以后把循環(huán)的語法忘得一干二凈,結(jié)果寫了很久都沒寫出來,最后不得不拜托隔壁班某位櫻姓同學(xué)的姐姐幫忙。傳說這位姐姐姓櫻名寧寧,也是半年前才開始自學(xué)C艸與游戲編程,現(xiàn)在卻已經(jīng)在Eagle Jump里面擔(dān)當(dāng)游戲開發(fā)。

大概過了十分鐘,這位姐姐把程序發(fā)了過來,剎那看也沒看就轉(zhuǎn)發(fā)給了凜音。

然后就有了剛才的一幕。


久遠(yuǎn)走上前看了一下程序,然后暴擊凜音:

“雖說肯定不是剎那寫的,但是這代碼毫無疑問是可以運行且正確的啊!”

“誒?!”

凜音一臉懵逼。這和說好的不一樣???

面對一臉懵逼的凜音,久遠(yuǎn)無奈地再重錘了凜音一拳:

“之前說了你想教剎那至少自己先把《C++ Primer》過一遍??!這些都是常規(guī)操作啊!”

“阿諾,很抱歉...我重寫就是了,不要責(zé)怪凜音醬了...”

剎那似乎是以為自己的無能牽扯了為師的凜音,這讓久遠(yuǎn)更是無奈了,只好對剎那說程序是對的不過下次要自己寫。


“那么,今天的主題是——斐波那契!”

“肥婆納妾?”

“是斐波那契!”

“我知道!是那個有一堆小兔子的吧!”

“知道就好講話了。那么今天的課題——求出斐波那契的前n項!”

“誒有n個數(shù)的話怎么存嘛?”

“這里就要請出——數(shù)組!”

“數(shù)組?”

“字面意思!數(shù)組!”


int a; //一個整形變量

int b[100]; //一個整形變量的數(shù)組

b[0]=100; //如此這般訪問。要注意,從0開始算,所以b[1]是第二個元素


“所以并沒有什么難的,那么讓我們開始吧!上次的循環(huán)沒忘吧?”

“...要是沒忘就交上次作業(yè)了。”

“呃...那么看這段吧?!?/p>


#include<iostream>

int main() {

????int a[1024],n;

????a[0]=1;

????a[1]=1;

????std::cin >> n;

????for(int j=2;j<n;++j) {

????????a[j]=a[j-1]+a[j-2];

?????}

????for(int j=0;j<n;++j) {

????????std::cout<<j<<" "<<a[j]<<std::endl;

????}

????return 0;

}


“嗯,看——不懂?!?/p>

凜音掀起了桌子。

“就是一個循環(huán)??!不停地把后兩項加到前面一項去??!”

(似懂非懂)

“另外,字符串也可以看成一個數(shù)組喲?!?/p>

(點頭)

“那么我們進(jìn)入到高精度加法吧。”

“...等等?高精度?”

“先說一句,int的取值范圍是-2147483648~2147483647內(nèi)”

“誒!第一次聽說?。∵€有這魔法一樣的數(shù)字是什么鬼!”

“[-2^31]~[2^31-1],合計2^32個數(shù),就是這么魔法。因為現(xiàn)在的電腦上int通常占用4個字節(jié),每個字節(jié)8個bit,也就是32個bit。”

“唔...暈了!”

“也沒要你記。現(xiàn)在你寫一個能夠進(jìn)行100位數(shù)以內(nèi)的加法的程序。”

“誒?!100位?!真的能算嗎?!我可以手算??!”

“前提是你手算的能有電腦快?!?/p>

剎那茫然地看著編輯器一閃一閃的光標(biāo)。


“補充一些關(guān)于std::string的東西吧?!?/p>

寫上#include<string>以后,你就可以用這個東西了?!?/p>


一些用法:

std::string a;

std::cin>>a; //輸入一個字符串。

a.length(); //能夠得到字符串的長度,類型是size_t,一般是unsigned int的重定義,即無符號整數(shù),能表示0~4294967295之間的數(shù)。通常也不會有這么長的字符串就是。

a[100]; //字符串第101個元素的值。(要從0號開始算,所以是第101個)


ざわざわ~

ざわざわ~

“動手!能寫多少寫多少!”凜音咆哮。


#include<iostream>

#include<string>

int main() {

???? std::string a,b;

???? std::cin>>a>>b;

???? size_t aLen = a.length();

???? size_t bLen = b.length();

???? size_t maxLen = aLen > bLen ? aLen : bLen;

????.......


“寫不下去了!怎么做嘛...”

“提示,先倒序,這樣進(jìn)位可以往后面進(jìn)。”


???? ......

???? int ia[101],ib[101];

???? for(int i=0;i<aLen;++i) {

???????? ia[i] = a[aLen-i-1];

???? }

???? for(int i=0;i<bLen;++i) {

???????? ib[i] = b[bLen-i-1];

???? }

“?!@里要注意,字符的'0'的值并不是0喲。”

“什么意思?”

“有個東西叫ASCII碼,把常見的一些字符與具體的二進(jìn)制數(shù)值做了一個映射。比如字符0的ASCII是48號,A是65,a是97等。所以要改成這樣:”


???? ......

???? int ia[101],ib[101];

???? for(int i=0;i<aLen;++i) {

???????? ia[i] = a[aLen-i-1] - '0';

???? }

???? for(int i=0;i<bLen;++i) {

???????? ib[i] = b[bLen-i-1] - '0';

???? }

“沒必要去背那個表,寫成 '0' 機器自動就會認(rèn)出來并且當(dāng)成常量處理的?!?/p>

繼續(xù):

???? for(int i=0;i<maxLen;++i) {

???????? ia[i]=ia[i]+ib[i];

?????????if(ia[i]>9) {

???????????? ia[i]=ia[i]-10;

???????????? ++ia[i+1];

???????? } //進(jìn)位

???? }

“至此運算就全部做完了,不過還需要輸出。綜上所述:”


#include<iostream>

#include<string>

int main() {

???? std::string a,b;

???? std::cin>>a>>b;

???? size_t aLen = a.length();

???? size_t bLen = b.length();

???? size_t maxLen = aLen > bLen ? aLen : bLen;

???? int ia[101]={0},ib[101]={0}; //數(shù)組元素全部清零

???? for(int i=0;i<aLen;++i) {

???????? ia[i] = a[aLen-i-1] - '0';

???? }

???? for(int i=0;i<bLen;++i) {

???????? ib[i] = b[bLen-i-1] - '0';

???? } //倒序

???? for(int i=0;i<maxLen;++i) {

???????? ia[i]=ia[i]+ib[i];

???????? if(ia[i]>9) {

???????????? ia[i]=ia[i]-10;

???????????? ++ia[i+1];

???????? } //進(jìn)位

???? }

???? int i;

???? for(i=maxLen-1;i>0;--i) {

???????? if(ia[i]!=0) break; //break的意思是跳出這一層循環(huán)

???? }

???? for(;i>=0;--i) {

???????? std::cout<<ia[i];

???? }

???? return 0;

}


“作為今天的第一個作業(yè),思考一下輸出的時候為什么要這兩個循環(huán)吧~”

“誒?!”

“那么進(jìn)入今天的第二個部分——遞歸!”

“遞歸?好像數(shù)學(xué)課里面有聽到過,唔...”

“遞歸就是說一個函數(shù)自己調(diào)用自己~”

“誒那不會一直調(diào)用下去嗎?!”

“所以有個東西叫遞歸出口啊~”

“誒?”

“比如斐波那契數(shù)列求第n項可以這么寫:”


int fib(int n) {

???? if(n==1 || n==2) return 1;

???? else return fib(n-1)+fib(n-2);

}


“可以看到,fib這里自己調(diào)用了自己兩次,然后把值加起來返回。正可謂數(shù)學(xué)里面的A[n]=A[n-1]+A[n-2]”

(似懂非懂)

“那個...凜音醬啊,這里這么多n...不會互相覆蓋嗎?”

“你還記得我之前說的實際參數(shù)與形式參數(shù)嗎?”

“忘了?!?/p>

“就是說,這些東西里面互相不干擾,會進(jìn)行替換的。這里的參數(shù)n只是一個標(biāo)記,當(dāng)你運行fib(n-1)的時候,相當(dāng)于新開了一個副本,又有一個新的n,我們姑且記作n'吧,它的值是n-1。然后在n'的里面,又有fib(n'-1),記作n",以此類推。”

“好厲害??!那就是說會有很多個n嘍?”

“的確。”

“好我們來算一下fib(10000)吧!”


Segmentation fault (core dumped)


“誒?!出錯了?!”

“這也引出另一個話題。正是因為計算機要給這些n存位置,包括你新調(diào)用一次fib就會多一些數(shù)據(jù),當(dāng)這些數(shù)據(jù)太大了以后就會炸掉。所以——盡量避免遞歸。”

(雖然不懂但還是點點頭吧)

“但是遞歸的確是一個解決的思路。并且——遞歸與循環(huán)等價?!?/p>

“等價?”

“那么今天的第二個作業(yè)~禁止使用for do-for while以及goto,實現(xiàn)1到100的求和?!?/p>

“誒?!”


【久遠(yuǎn)的小課堂】



圖片來自某三次元傻屌同學(xué)。

從命名上可以看出有多嚴(yán)重的心理問題

[注意: 不是所有的編譯器都支持寬字符標(biāo)識符的,寫代碼請還是好好用字母]


這一次我就對剎那不知從哪里搞來的代碼進(jìn)行剖析。

聽不懂也沒事,聽個響也行。


先從main過程入手,可以看到main里面僅僅是對另一個過程的調(diào)用。那么讓我們來看一下這個“有多嚴(yán)重的心理問題()”

這個過程里面只有一個循環(huán),for(auto 問題 : 心理問題() );

剎那你應(yīng)該還記得之前凜音說到的那個帶冒號的范圍for吧,這里就出現(xiàn)了。

冒號的意思表示,前面的這個變量取變后面這個范圍的所有的值,并且進(jìn)行一些操作。這里直接寫分號不進(jìn)行任何操作,所以僅僅是給“問題”賦上全部的值以后結(jié)束。

然后,自然而然地我們會看到心理問題,即上面的struct。

final的意思表示不允許被繼承,關(guān)于繼承我們會放到之后的類來講。

可以看到,心理問題里面有三個部分:類“草”的定義,begin方法及end方法。


通常而言,我們進(jìn)行for操作的,都是一個集合,比如數(shù)組啊容器啊之類的,但是也不是一定的,只要一個數(shù)據(jù)結(jié)構(gòu)滿足一定的條件,我們就可以for,即begin、end還有operator++。

begin返回一個泛迭代器,你可以理解為一個名片,名片上面印著第一個元素的姓名、地址等很多信息。end則是最后一個元素。operator++則代表你可以獲得下一個名片。

在這個例子里面,“草”就是這個名片的種類。你會不停地拿到像“草”一樣的名片。當(dāng)執(zhí)行operator++時,草里面的i會自增。顯然,循環(huán)是要停下來的,那么就是在operator!=為假(即now==end)時停止。if(i==100) goto end;可以看到end后面的return false;

即循環(huán)100次以后會結(jié)束循環(huán)。

這里有個template,以及后面的一些type_traits內(nèi)的模板,這是一個典型的錯誤用法,不過鑒于不會對這里造成什么影響我就不去說了。


“草”是個名片,但是你肯定要根據(jù)名片去找具體的元素。每找一次,就調(diào)用一次operator*,可以看到operator*會返回一個デデドン類型的元素。循環(huán)100次,則會生成100個デデドン。

在類與對象里,對象死亡后有個東西叫“析構(gòu)函數(shù)”,格式就是一個波浪號~加上類的名字デデドン。后面的noexcept(false)表示允許拋出異常。通常而言析構(gòu)函數(shù)是不允許拋出異常的,因為會造成異常語句之后的語句沒法正確執(zhí)行,這里顯然不知道為什么就給允許了。再后面看似有個while,實際如果順利的話只會執(zhí)行一次——

std::cout<<"まわれ";

執(zhí)行完畢后,會返回std::cout也是說過的。那么,把std::cout轉(zhuǎn)換為bool的時候,會根據(jù)這個流是否依然有效來轉(zhuǎn)換。如果順利輸出了,那么就是true,取反感嘆號后變成false,結(jié)束循環(huán);但是一旦沒順利輸出,則會一直死循環(huán)在這,直到引發(fā)異常。

生成100個對象,那么這100個對象死的時候也會輸出100個まわれ。


綜上,這個程序順利的話能正常運行完畢。

如何用輕小說的方式學(xué)C++(五) 斐波那契與他的小兔子們的評論 (共 條)

分享到微博請遵守國家法律
庆安县| 龙江县| 来凤县| 盘锦市| 思茅市| 怀集县| 花垣县| 临朐县| 雅安市| 华容县| 洪江市| 烟台市| 博白县| 邹平县| 大安市| 都安| 元谋县| 宁明县| 樟树市| 荆州市| 诸暨市| 莲花县| 新野县| 石家庄市| 古浪县| 怀化市| 广南县| 焉耆| 马边| 洛浦县| 鄂州市| 恩施市| 永胜县| 卓尼县| 会昌县| 满洲里市| 盐亭县| 达尔| 休宁县| 邢台县| 新野县|