1 00:00:00,000 --> 00:00:03,000 [Powered by Google Translate] [4]週 2 00:00:03,000 --> 00:00:05,000 [戴維·J·馬蘭] [哈佛大學] 3 00:00:05,000 --> 00:00:08,000 這是CS50。[CS50.TV] 4 00:00:08,000 --> 00:00:12,000 >> 好吧,這是CS50,這是第4週開始, 5 00:00:12,000 --> 00:00:16,000 這是最慢的可能的排序算法之一。 6 00:00:16,000 --> 00:00:19,000 哪一個是,我們只能眼睜睜的看著嗎? 7 00:00:19,000 --> 00:00:24,000 這是冒泡排序,以大O(N ^ 2)+總和, 8 00:00:24,000 --> 00:00:28,000 而事實上,我們是不是唯一的,在這個世界上似乎知道 9 00:00:28,000 --> 00:00:30,000 什麼是冒泡排序,或它的運行時間。 10 00:00:30,000 --> 00:00:33,000 事實上,這是與谷歌的埃里克·施密特(Eric Sc​​hmidt)接受記者採訪時 11 00:00:33,000 --> 00:00:45,000 和前參議員巴拉克·奧巴馬只不過幾年前。 12 00:00:45,000 --> 00:00:48,000 >> 現在,參議員,你在谷歌, 13 00:00:48,000 --> 00:00:54,000 面試的,我喜歡把總統。 14 00:00:54,000 --> 00:00:58,000 現在,它是很難得到一份工作作為總統,你現在正在經歷的嚴峻考驗。 15 00:00:58,000 --> 00:01:00,000 它也很難在谷歌找到一份工作。 16 00:01:00,000 --> 00:01:05,000 我們有問題,我們要求我們的候選人的問題, 17 00:01:05,000 --> 00:01:10,000 而這一次是從拉里·施維默。 18 00:01:10,000 --> 00:01:14,000 你們覺得我在開玩笑嗎?就在這裡。 19 00:01:14,000 --> 00:01:18,000 排序一百萬的32位整數的最有效的方法是什麼? 20 00:01:18,000 --> 00:01:21,000 [笑聲] 21 00:01:21,000 --> 00:01:24,000 良好 22 00:01:24,000 --> 00:01:26,000 對不起。>>不,不,不,不。 23 00:01:26,000 --> 00:01:34,000 我認為,冒泡排序是錯誤的方式去。 24 00:01:34,000 --> 00:01:39,000 >> 來吧,告訴他這? 25 00:01:39,000 --> 00:01:43,000 上週還記得我們休息了一下,從代碼中,至少一天, 26 00:01:43,000 --> 00:01:46,000 並開始專注於一些更高層次的想法和​​解決問題的更一般的 27 00:01:46,000 --> 00:01:49,000 的上下文中搜索和排序, 28 00:01:49,000 --> 00:01:53,000 我們介紹的東西,我們沒有一巴掌這個名字在上週, 29 00:01:53,000 --> 00:01:56,000 但漸近符號,大O,大歐米茄, 30 00:01:56,000 --> 00:02:00,000 有時大的θ符號,而這些人根本方法 31 00:02:00,000 --> 00:02:02,000 描述的算法的運行時間, 32 00:02:02,000 --> 00:02:05,000 需要多少時間的一種算法來運行。 33 00:02:05,000 --> 00:02:08,000 >> 你可能還記得,你談到的運行時間的大​​小 34 00:02:08,000 --> 00:02:11,000 的投入,我們一般稱之為N,什麼問題可能是, 35 00:02:11,000 --> 00:02:13,000 其中,n是多少人在房間裡, 36 00:02:13,000 --> 00:02:17,000 在電話簿的頁面的數量,我們開始寫東西了 37 00:02:17,000 --> 00:02:21,000 像O(N ^ 2)或O(n)或O(n日誌n), 38 00:02:21,000 --> 00:02:24,000 即使在數學沒有相當的工作如此完美 39 00:02:24,000 --> 00:02:28,000 為² - N / 2或類似的東西 40 00:02:28,000 --> 00:02:31,000 相反,我們會扔掉一些低階, 41 00:02:31,000 --> 00:02:34,000 和動機是我們真的想要一個 42 00:02:34,000 --> 00:02:37,000 客觀地評估排序 43 00:02:37,000 --> 00:02:39,000 程序的性能或算法的性能 44 00:02:39,000 --> 00:02:42,000 在一天結束的時候有沒有做的,例如, 45 00:02:42,000 --> 00:02:45,000 今天你的電腦速度。 46 00:02:45,000 --> 00:02:47,000 >> 例如,如果實現冒泡排序, 47 00:02:47,000 --> 00:02:50,000 或者你在今天的計算機上,實現合併排序或選擇排序, 48 00:02:50,000 --> 00:02:53,000 在2 GHz計算機,並運行它, 49 00:02:53,000 --> 00:02:56,000 需要一定的秒數,明年有一個3 GHz 50 00:02:56,000 --> 00:02:59,000 4 GHz的電腦,你可能會然後聲稱:“哇,我的算法 51 00:02:59,000 --> 00:03:03,000 是現在的兩倍快,“在現實中顯然不是這樣。 52 00:03:03,000 --> 00:03:06,000 這只是在硬件變得更快,但你的電腦 53 00:03:06,000 --> 00:03:10,000 並沒有,所以我們真的要扔掉的東西一樣 54 00:03:10,000 --> 00:03:13,000 乘2或3的倍數,當涉及到描述 55 00:03:13,000 --> 00:03:17,000 的速度有多快或慢的算法是真的只是集中 56 00:03:17,000 --> 00:03:20,000 在n或某些因素, 57 00:03:20,000 --> 00:03:24,000 其一些功率中的種類的情況下,從上週。 58 00:03:24,000 --> 00:03:27,000 回想一下,歸併排序的幫助 59 00:03:27,000 --> 00:03:31,000 我們能夠這樣做大大優於冒泡排序,選擇排序 60 00:03:31,000 --> 00:03:33,000 甚至插入排序。 61 00:03:33,000 --> 00:03:36,000 >> 我們得到了n日誌n,並再次, 62 00:03:36,000 --> 00:03:39,000 記得,日誌n一般是指生長 63 00:03:39,000 --> 00:03:43,000 更慢則n,所以n日誌n迄今還是不錯的 64 00:03:43,000 --> 00:03:45,000 因為它是比n²少。 65 00:03:45,000 --> 00:03:47,000 但要實現n日誌n歸併排序 66 00:03:47,000 --> 00:03:51,000 什麼是基本的想法,我們必須充分利用胚芽 67 00:03:51,000 --> 00:03:54,000 我們還利用在0週嗎? 68 00:03:54,000 --> 00:03:58,000 我們是怎麼解決的排序問題,巧妙地與歸併排序? 69 00:03:58,000 --> 00:04:04,000 什麼是重要的見解,也許? 70 00:04:04,000 --> 00:04:07,000 任何人在所有。 71 00:04:07,000 --> 00:04:09,000 好吧,讓我們退後一步。 72 00:04:09,000 --> 00:04:11,000 你自己的話描述歸併排序。 73 00:04:11,000 --> 00:04:15,000 它是如何工作的? 74 00:04:15,000 --> 00:04:17,000 好了,我們將排回0週。 75 00:04:17,000 --> 00:04:19,000 好吧,是的。 76 00:04:19,000 --> 00:04:22,000 [聽不見的學生] 77 00:04:22,000 --> 00:04:26,000 好了,好了,所以我們的數字數組劃分成2個。 78 00:04:26,000 --> 00:04:29,000 我們整理的那件,然後我們合併, 79 00:04:29,000 --> 00:04:33,000 我們已經看到了這個想法之前,這個大的問題 80 00:04:33,000 --> 00:04:36,000 和切碎成一個問題,這個大,這個大。 81 00:04:36,000 --> 00:04:38,000 >> 調出電話簿例如。 82 00:04:38,000 --> 00:04:42,000 回想一下自我計數算法從數週前, 83 00:04:42,000 --> 00:04:45,000 這裡總結了這個偽所以合併排序。 84 00:04:45,000 --> 00:04:48,000 當你給定的n個元素,首先是仔細檢查。 85 00:04:48,000 --> 00:04:51,000 如果N <2,沒有做任何事情在所有 86 00:04:51,000 --> 00:04:55,000 因為如果n <2,那麼顯然,n是0或1, 87 00:04:55,000 --> 00:04:57,000 因此,如果是0或1,沒有什麼排序。 88 00:04:57,000 --> 00:04:59,000 你就大功告成了。 89 00:04:59,000 --> 00:05:01,000 您的列表是平凡的排序。 90 00:05:01,000 --> 00:05:04,000 否則,如果你有2個或更多的元素,然後再劃分 91 00:05:04,000 --> 00:05:06,000 分為兩半,左邊和右邊。 92 00:05:06,000 --> 00:05:09,000 排序每個這些半部,然後合併排序條件半部。 93 00:05:09,000 --> 00:05:13,000 但這裡的問題是,乍看之下,這感覺就像我們撐船。 94 00:05:13,000 --> 00:05:17,000 如果我問你,這n個元素進行排序,這是一個循環的定義 95 00:05:17,000 --> 00:05:22,000 你告訴我,“好吧,好吧,我們將那些N / 2和那些N / 2個元素進行排序,” 96 00:05:22,000 --> 00:05:27,000 然後我的下一個問題將是:“好,你是怎麼排序的n / 2個元素?” 97 00:05:27,000 --> 00:05:30,000 >> 但是,由於這項計劃的結構, 98 00:05:30,000 --> 00:05:33,000 因為有這個基礎的情況下,可以這麼說, 99 00:05:33,000 --> 00:05:39,000 這種特殊情況下,如果n <2回一些固定的值,如立即說。 100 00:05:39,000 --> 00:05:42,000 不回應與相同的圓形的答案。 101 00:05:42,000 --> 00:05:46,000 這個過程中,這種週期性終將結束。 102 00:05:46,000 --> 00:05:50,000 如果我問你“排序n個元素,”和你說,“好吧,整理這些N / 2” 103 00:05:50,000 --> 00:05:53,000 然後你說,“很好,排序這些N / 4,N / 8,N/16,” 104 00:05:53,000 --> 00:05:56,000 最終你會除以一個足夠大的數 105 00:05:56,000 --> 00:05:59,000 ,你將有只有1元左,在這一點,你可以說, 106 00:05:59,000 --> 00:06:02,000 “這裡,這裡是一個有序的單個元素。” 107 00:06:02,000 --> 00:06:06,000 然後該算法的輝煌在這裡是從這一事實派生 108 00:06:06,000 --> 00:06:09,000 一旦你把所有這些單獨排序的列表, 109 00:06:09,000 --> 00:06:12,000 所有這一切都是大小為1,這似乎是無用的, 110 00:06:12,000 --> 00:06:15,000 一旦你開始把它們合併,將它們合併 111 00:06:15,000 --> 00:06:19,000 建立終於搶在視頻的最後排序的名單。 112 00:06:19,000 --> 00:06:22,000 >> 但這樣的想法遠遠超出了排序。 113 00:06:22,000 --> 00:06:26,000 有這種想法,在這個程序稱為遞歸嵌入, 114 00:06:26,000 --> 00:06:29,000 是一個程序,讓你的想法, 115 00:06:29,000 --> 00:06:32,000 解決一些問題,你叫你自己, 116 00:06:32,000 --> 00:06:36,000 或把你是一個函數的編程語言的上下文中, 117 00:06:36,000 --> 00:06:39,000 為了解決一個問題,你的函數調用自己 118 00:06:39,000 --> 00:06:42,000 一而再,再而三,但你的功能 119 00:06:42,000 --> 00:06:44,000 不能稱自己為無限多次。 120 00:06:44,000 --> 00:06:47,000 最終,你必須走出谷底,可以這麼說, 121 00:06:47,000 --> 00:06:49,000 並有一些硬編碼的基本條件, 122 00:06:49,000 --> 00:06:53,000 在這一點上停止這樣要求自己,整個過程 123 00:06:53,000 --> 00:06:56,000 其實最終停止。 124 00:06:56,000 --> 00:06:58,000 這究竟是什麼意思,遞歸? 125 00:06:58,000 --> 00:07:01,000 >> 讓我們來看看,如果我們可以做一個簡單的,簡單的例子,比方說, 126 00:07:01,000 --> 00:07:03,000 3人,在這裡我在舞台上,如果有人很舒服。 127 00:07:03,000 --> 00:07:06,000 1,來時,2和3上。 128 00:07:06,000 --> 00:07:09,000 如果你要來這裡。 129 00:07:09,000 --> 00:07:12,000 如果你想站在旁邊,我在這裡行,假設手頭上的問題 130 00:07:12,000 --> 00:07:15,000 是非常平凡的人誰是這裡數一數。 131 00:07:15,000 --> 00:07:18,000 但坦率地說,我累了,所有這些計數的例子。 132 00:07:18,000 --> 00:07:21,000 這將需要一些時間,1,2,點,點,點。 133 00:07:21,000 --> 00:07:23,000 這是怎麼回事採取永遠。 134 00:07:23,000 --> 00:07:25,000 我寧願只平底船這個問題的幫助下,你叫什麼名字? 135 00:07:25,000 --> 00:07:27,000 >>薩拉,薩拉。所有權利。 136 00:07:27,000 --> 00:07:29,000 凱利。>>凱利? 137 00:07:29,000 --> 00:07:31,000 >> >>威利,莎拉,凱莉和威利,威利。 138 00:07:31,000 --> 00:07:34,000 現在,我一直在問的問題,有人 139 00:07:34,000 --> 00:07:37,000 有多少人在這個舞台上,我不知道。 140 00:07:37,000 --> 00:07:40,000 這是一個很長的列表,所以不是我會做這一招。 141 00:07:40,000 --> 00:07:43,000 我要問旁邊的人給我做的大部分工作, 142 00:07:43,000 --> 00:07:46,000 有一次她做的大部分工作 143 00:07:46,000 --> 00:07:49,000 我會做最少的工作,只需添加1 144 00:07:49,000 --> 00:07:51,000 她的回答是,所以在這裡我們去。 145 00:07:51,000 --> 00:07:54,000 我一直在問有多少人在舞台上演出。 146 00:07:54,000 --> 00:07:57,000 有多少人在舞台上你左邊的嗎? 147 00:07:57,000 --> 00:08:00,000 我的左邊?>>好吧,但不要欺騙。 148 00:08:00,000 --> 00:08:04,000 這是很好的,這是正確的,但如果我們要繼續這樣的邏輯 149 00:08:04,000 --> 00:08:08,000 讓我們假設你同樣希望能撐船你左邊的這個問題, 150 00:08:08,000 --> 00:08:11,000 因此,而不是答案直接去前進,只是推卸責任。 151 00:08:11,000 --> 00:08:14,000 哦,很多人都為我的左邊嗎? 152 00:08:14,000 --> 00:08:16,000 有多少人是左邊? 153 00:08:16,000 --> 00:08:18,000 1。 154 00:08:18,000 --> 00:08:27,000 [笑聲] 155 00:08:27,000 --> 00:08:30,000 好了,所以0,所以現在什麼威利已完成 156 00:08:30,000 --> 00:08:33,000 你回到你的答案這方向說0。 157 00:08:33,000 --> 00:08:36,000 現在,你應該怎麼辦?>> 1。 158 00:08:36,000 --> 00:08:39,000 好了,你是1,所以你說,“好吧,我要加1 159 00:08:39,000 --> 00:08:41,000 威利的計數,“1 + 0。 160 00:08:41,000 --> 00:08:43,000 您現在所以你正確的答案是現在, 161 00:08:43,000 --> 00:08:45,000 1。“和我的是2。 162 00:08:45,000 --> 00:08:48,000 好,所以你會覺得前面的回答1, 163 00:08:48,000 --> 00:08:51,000 加入少量的工作,你想要做的,這是+1。 164 00:08:51,000 --> 00:08:55,000 您現在有2個,然後把我哪個值? 165 00:08:55,000 --> 00:08:57,000 3,我的意思是,很抱歉,2。 166 00:08:57,000 --> 00:08:59,000 好。 167 00:08:59,000 --> 00:09:02,000 >> 好了,我們擁有0到左邊。 168 00:09:02,000 --> 00:09:05,000 然後我們有1,然後再加2, 169 00:09:05,000 --> 00:09:07,000 現在你遞過來的2號, 170 00:09:07,000 --> 00:09:10,000 所以我說,沒關係,+1,3。 171 00:09:10,000 --> 00:09:13,000 確實有3人,站在我旁邊的這個舞台上, 172 00:09:13,000 --> 00:09:16,000 因此,我們可以很明顯這樣做非常線性, 173 00:09:16,000 --> 00:09:19,000 非常顯而易見的方式,但我們真的什麼呢? 174 00:09:19,000 --> 00:09:21,000 我們採取了一個大小為3最初的問題。 175 00:09:21,000 --> 00:09:24,000 然後,我們把它弄壞了一個問題分解成大小為2, 176 00:09:24,000 --> 00:09:27,000 然後一個問題大小為1,然後在最後的基本情況 177 00:09:27,000 --> 00:09:29,000 是真的,哦,還有一個人也沒有, 178 00:09:29,000 --> 00:09:33,000 在這一點威利有效地返回一個硬編碼的答案了幾次, 179 00:09:33,000 --> 00:09:36,000 第二個,然後向上冒泡,冒泡,冒泡, 180 00:09:36,000 --> 00:09:39,000 然後以增加一個額外的1在這 181 00:09:39,000 --> 00:09:41,000 我們已經實現了這個遞歸的基本思想。 182 00:09:41,000 --> 00:09:44,000 >> 現在,在這種情況下,它並沒有真正解決的一個問題 183 00:09:44,000 --> 00:09:46,000 任何更有效地發揮作用,那麼我們迄今為止見過的。 184 00:09:46,000 --> 00:09:48,000 但仔細想想,我們所做的舞台上迄今為止的算法。 185 00:09:48,000 --> 00:09:51,000 我們有8個紙寫在黑板上, 186 00:09:51,000 --> 00:09:55,000 視頻時,肖恩一直在尋找的7號,他真的什麼? 187 00:09:55,000 --> 00:09:58,000 ,他沒有做任何形式的鴻溝和征服。 188 00:09:58,000 --> 00:10:01,000 他沒有做任何形式的遞歸。 189 00:10:01,000 --> 00:10:03,000 相反,他只是做這個線性算法。 190 00:10:03,000 --> 00:10:07,000 但是,當我們的思想介紹舞台上的排序數字生活上週 191 00:10:07,000 --> 00:10:09,000 然後我們有這種本能的中間, 192 00:10:09,000 --> 00:10:13,000 在這一點,我們有一個小的列表大小為4或另一個列表的大小為4, 193 00:10:13,000 --> 00:10:17,000 然後我們有相同的問題,所以我們重複,重複,重複。 194 00:10:17,000 --> 00:10:19,000 換句話說,我們遞歸。 195 00:10:19,000 --> 00:10:24,000 非常感謝您給我們的3名志願者在這裡展示我們的遞歸。 196 00:10:24,000 --> 00:10:28,000 >> 讓我們來看看如果我們不能更具體一點, 197 00:10:28,000 --> 00:10:30,000 解決問題了,我們可以很輕鬆地做, 198 00:10:30,000 --> 00:10:34,000 但我們將使用它作為實現這一基本思路的墊腳石。 199 00:10:34,000 --> 00:10:37,000 如果我想的一串數字來計算的總和, 200 00:10:37,000 --> 00:10:39,000 例如,如果你通過在3號, 201 00:10:39,000 --> 00:10:42,000 我想給你3西格瑪的價值, 202 00:10:42,000 --> 00:10:46,000 所以總和3 + 2 + 1 + 0。 203 00:10:46,000 --> 00:10:48,000 我想要得到的答案6 204 00:10:48,000 --> 00:10:51,000 讓我們來實現這個sigma函數,這個求和函數 205 00:10:51,000 --> 00:10:54,000 ,再次取入輸入,然後返回求和 206 00:10:54,000 --> 00:10:57,000 這一數字一直下降到0。 207 00:10:57,000 --> 00:10:59,000 我們可以做到這一點非常簡單,對不對? 208 00:10:59,000 --> 00:11:01,000 我們能做到這一點,一些種循環結構, 209 00:11:01,000 --> 00:11:04,000 所以,讓我繼續前進,趕快開始。 210 00:11:04,000 --> 00:11:07,000 >> 包括stdio.h中。 211 00:11:07,000 --> 00:11:09,000 讓我讓我自己到這裡主要工作。 212 00:11:09,000 --> 00:11:12,000 讓我們拯救為sigma.c。 213 00:11:12,000 --> 00:11:14,000 然後,我要在這裡,我要聲明的廉政n, 214 00:11:14,000 --> 00:11:18,000 我要做到以下幾點,而用戶不配合。 215 00:11:18,000 --> 00:11:22,000 當用戶還沒有給我一個正數 216 00:11:22,000 --> 00:11:26,000 讓我繼續前進,促使他們為n =調用getInt, 217 00:11:26,000 --> 00:11:28,000 並讓我給他們一些指示做什麼, 218 00:11:28,000 --> 00:11:33,000 因此我們知道printf(“請正整數”)。 219 00:11:33,000 --> 00:11:39,000 只是像這樣簡單的東西比較的時候,我們打了14行 220 00:11:39,000 --> 00:11:42,000 現在,我們有可能在n為正整數。 221 00:11:42,000 --> 00:11:44,000 >> 現在,讓我們用它做什麼。 222 00:11:44,000 --> 00:11:50,000 讓我繼續和計算的總和,所以int總和=Σ(N)。 223 00:11:50,000 --> 00:11:54,000 Sigma是求和,所以我只是寫愛好者。 224 00:11:54,000 --> 00:11:56,000 我們只把它西格瑪有。 225 00:11:56,000 --> 00:11:58,000 的總和,現在我要打印出來的結果, 226 00:11:58,000 --> 00:12:08,000 printf(“請的總和為%d \ n”,總結)。 227 00:12:08,000 --> 00:12:11,000 然後我就返回0的良好措施。 228 00:12:11,000 --> 00:12:15,000 除了有趣的部分,我們所做的一切,這個程序需要, 229 00:12:15,000 --> 00:12:18,000 這實際上是實施六西格瑪的功能。 230 00:12:18,000 --> 00:12:22,000 >> 讓我走在這裡的底部,並讓我申報功能標準差。 231 00:12:22,000 --> 00:12:26,000 它採取了一個整數類型的變量, 232 00:12:26,000 --> 00:12:30,000 和什麼樣的數據類型,我想大概是從Σ返回嗎? 233 00:12:30,000 --> 00:12:34,000 詮釋,因為我想它符合我的期望,第15行。 234 00:12:34,000 --> 00:12:37,000 在這裡,讓我繼續前進,實現這 235 00:12:37,000 --> 00:12:41,000 一個非常簡單的方法。 236 00:12:41,000 --> 00:12:45,000 >> 讓我們繼續前進,並說int總和= 0, 237 00:12:45,000 --> 00:12:47,000 現在我要在這兒有一個小的循環 238 00:12:47,000 --> 00:12:50,000 會說這樣的事情, 239 00:12:50,000 --> 00:13:01,000 (INT I = 0; I <=數字,我+ +)之和+ =。 240 00:13:01,000 --> 00:13:05,000 然後我將返回總和。 241 00:13:05,000 --> 00:13:07,000 我可以在任何數量的方式實現這個。 242 00:13:07,000 --> 00:13:09,000 我可以使用一個while循環。 243 00:13:09,000 --> 00:13:11,000 我可以跳過的總和變量,如果我真的想, 244 00:13:11,000 --> 00:13:15,000 但在短期,我們只需要一個函數,如果我不混日子聲明總和為0。 245 00:13:15,000 --> 00:13:18,000 然後,它會遍歷並貫穿數,從0 246 00:13:18,000 --> 00:13:23,000 在每次迭代補充說,目前的價值總和,然後返回總和。 247 00:13:23,000 --> 00:13:25,000 >> 現在,有輕微優化了。 248 00:13:25,000 --> 00:13:29,000 這可能是一個死不瞑目,但就這樣吧。這就是現在的罰款。 249 00:13:29,000 --> 00:13:32,000 我們至少徹底和投0中一路就到了。 250 00:13:32,000 --> 00:13:34,000 並不難,很簡單, 251 00:13:34,000 --> 00:13:37,000 但事實證明,我們的sigma函數有同樣的機會 252 00:13:37,000 --> 00:13:39,000 我們在這裡所做過的舞台上。 253 00:13:39,000 --> 00:13:42,000 在舞台上,我們就只能有多少人在我旁邊, 254 00:13:42,000 --> 00:13:47,000 而如果我們想數一數3 + 2 + 1 255 00:13:47,000 --> 00:13:51,000 同樣,我們可以下降到0平底船的功能 256 00:13:51,000 --> 00:13:55,000 相反,我會形容為遞歸。 257 00:13:55,000 --> 00:13:57,000 下面讓我們做一個快速的完整性檢查,確保我沒有混日子。 258 00:13:57,000 --> 00:14:00,000 >> 我知道有這個程序,至少有一件事我沒有做錯。 259 00:14:00,000 --> 00:14:04,000 當我按下回車鍵,我會得到什麼樣的罵我嗎? 260 00:14:04,000 --> 00:14:06,000 我該怎麼大叫:約? 261 00:14:06,000 --> 00:14:11,000 是啊,我忘了原型,所以我用西格瑪第15行調用的函數, 262 00:14:11,000 --> 00:14:16,000 但它沒有宣布,直到第22行,所以我最好主動去這裡 263 00:14:16,000 --> 00:14:22,000 聲明原型,我會說:INTΣ(整型數),就是這樣。 264 00:14:22,000 --> 00:14:24,000 它的實施在底部。 265 00:14:24,000 --> 00:14:27,000 >> 或者我可以解決這個問題的另一種方式, 266 00:14:27,000 --> 00:14:30,000 我可以移動的功能在那裡,這是不壞, 267 00:14:30,000 --> 00:14:32,000 但至少當你的程序開始長,坦率地說, 268 00:14:32,000 --> 00:14:35,000 我覺得有一定的價值,總是有主的頂部 269 00:14:35,000 --> 00:14:38,000 讓你的讀者可以打開該文件,然後立即看到 270 00:14:38,000 --> 00:14:40,000 什麼是程序做,而不必通過搜索 271 00:14:40,000 --> 00:14:42,000 尋找,主要功能。 272 00:14:42,000 --> 00:14:49,000 讓我們深入到我的終端窗口,在這裡,試圖使SIGMA西格瑪, 273 00:14:49,000 --> 00:14:51,000 我搞砸了。 274 00:14:51,000 --> 00:14:55,000 隱式聲明的函數調用getInt我忘了做什麼? 275 00:14:55,000 --> 00:14:57,000 [聽不見的學生] 276 00:14:57,000 --> 00:15:00,000 好,顯然是一個常見的錯誤,讓我們把這個在這裡, 277 00:15:00,000 --> 00:15:04,000 cs50.h,現在讓我們回到我的終端窗口。 278 00:15:04,000 --> 00:15:08,000 >> 我會清除屏幕,我會重新運行西格瑪。 279 00:15:08,000 --> 00:15:11,000 它似乎已編譯的。讓我跑去標準差。 280 00:15:11,000 --> 00:15:15,000 我會輸入數字3,我沒得到6,所以不是嚴格的檢查, 281 00:15:15,000 --> 00:15:18,000 但它至少乍一看似乎是工作,但現在讓我們撕裂它除了, 282 00:15:18,000 --> 00:15:21,000 讓我們再次,利用遞歸的想法, 283 00:15:21,000 --> 00:15:24,000 在一個非常簡單的背景,所以,在幾個星期的時間 284 00:15:24,000 --> 00:15:27,000 當我們開始探索愛好者的數據結構陣列 285 00:15:27,000 --> 00:15:30,000 我們有另一個工具箱中的工具,用以 286 00:15:30,000 --> 00:15:33,000 操作這些數據結構,正如我們將看到的。 287 00:15:33,000 --> 00:15:36,000 這是迭代的方法,基於循環的方法。 288 00:15:36,000 --> 00:15:39,000 >> 讓我,而不是現在這樣做。 289 00:15:39,000 --> 00:15:44,000 讓我可以這樣說,數字的總和 290 00:15:44,000 --> 00:15:48,000 下降到0真的是同樣的事情, 291 00:15:48,000 --> 00:15:53,000 數+Σ(數量 - 1)。 292 00:15:53,000 --> 00:15:57,000 換句話說,就像在舞台上,我踢了我旁邊的人, 293 00:15:57,000 --> 00:16:00,000 而他們又不停地踢,直到我們終於走出谷底,威利, 294 00:16:00,000 --> 00:16:03,000 返回一個硬編碼的答案,如0。 295 00:16:03,000 --> 00:16:07,000 現在,我們同樣踢西格瑪 296 00:16:07,000 --> 00:16:10,000 最初被稱為相同的功能,但這裡的關鍵洞察力 297 00:16:10,000 --> 00:16:12,000 是我們,而不是調用標準差相同。 298 00:16:12,000 --> 00:16:14,000 我們不及格的n。 299 00:16:14,000 --> 00:16:17,000 我們清楚地傳遞 - 1, 300 00:16:17,000 --> 00:16:20,000 所以一個略小的問題,稍小的問題。 301 00:16:20,000 --> 00:16:23,000 >> 不幸的是,這是不完全的解決方案,但和之前我們解決 302 00:16:23,000 --> 00:16:26,000 什麼可能會跳出你們中的一些明顯 303 00:16:26,000 --> 00:16:28,000 讓我繼續前進,重新運行使。 304 00:16:28,000 --> 00:16:30,000 它似乎是編譯好的。 305 00:16:30,000 --> 00:16:32,000 讓我重新運行西格瑪6。 306 00:16:32,000 --> 00:16:37,000 哎呀,讓我重新運行西格瑪6。 307 00:16:37,000 --> 00:16:42,000 這之前我們已經看到,儘管偶然一次為好。 308 00:16:42,000 --> 00:16:48,000 為什麼我得到這個神秘的分割故障?是啊。 309 00:16:48,000 --> 00:16:50,000 [聽不見的學生] 310 00:16:50,000 --> 00:16:53,000 有沒有鹼的情況下,更具體地,可能發生的事情嗎? 311 00:16:53,000 --> 00:16:58,000 這是一個症狀,什麼樣的行為呢? 312 00:16:58,000 --> 00:17:00,000 說大聲一點。 313 00:17:00,000 --> 00:17:02,000 [聽不見的學生] 314 00:17:02,000 --> 00:17:05,000 這是一個無限循環,有效地無限循環的問題 315 00:17:05,000 --> 00:17:08,000 當它們涉及在這種情況下,一個函數遞歸調用自身, 316 00:17:08,000 --> 00:17:10,000 每次你調用一個函數,會發生什麼? 317 00:17:10,000 --> 00:17:13,000 好了,回想起我們提出了如何在一台電腦的內存。 318 00:17:13,000 --> 00:17:16,000 我們說,有這樣的內存塊,叫做堆棧的底部, 319 00:17:16,000 --> 00:17:19,000 每次你調用一個函數多一點的內存被放 320 00:17:19,000 --> 00:17:24,000 這個所謂的堆棧,其中包含該函數的局部變量或參數, 321 00:17:24,000 --> 00:17:27,000 因此,如果SIGMA調用SIGMA西格瑪來電要求西格瑪 322 00:17:27,000 --> 00:17:29,000  要求SIGMA這個故事的結束? 323 00:17:29,000 --> 00:17:31,000 >> 那麼,它最終超支總額 324 00:17:31,000 --> 00:17:33,000 ,你必須提供給您的計算機的內存。 325 00:17:33,000 --> 00:17:37,000 您溢出的部分,你應該留在, 326 00:17:37,000 --> 00:17:40,000 你得到這個分割故障,核心轉儲, 327 00:17:40,000 --> 00:17:43,000 什麼是核心轉儲的意思是,我現在有一個文件名為核心 328 00:17:43,000 --> 00:17:46,000 這是一個文件,包含零和一 329 00:17:46,000 --> 00:17:49,000 實際上在未來將是有用診斷。 330 00:17:49,000 --> 00:17:52,000 如果這不是很明顯,你在哪裡,你的錯誤是 331 00:17:52,000 --> 00:17:54,000 實際上,你可以做一些取證分析,可以這麼說, 332 00:17:54,000 --> 00:17:58,000 這一核心轉儲文件,這,又是一大堆的零和一 333 00:17:58,000 --> 00:18:02,000 你的程序在內存中,基本上代表了 334 00:18:02,000 --> 00:18:05,000 墜毀在這樣的時刻。 335 00:18:05,000 --> 00:18:11,000 >> 這裡的修復,我們不能只是一味地返回西格瑪, 336 00:18:11,000 --> 00:18:14,000 的數目+西格瑪一個略小的問題。 337 00:18:14,000 --> 00:18:16,000 我們需要有一些基本情況, 338 00:18:16,000 --> 00:18:19,000 什麼的基本情況大概是什麼? 339 00:18:19,000 --> 00:18:22,000 [聽不見的學生] 340 00:18:22,000 --> 00:18:25,000 好了,只要數是積極的,我們其實應該返回這一點, 341 00:18:25,000 --> 00:18:29,000 或者換一種說法,如果數字是多少,說,<= 0 342 00:18:29,000 --> 00:18:32,000 你知道嗎,我會繼續前進,返回0, 343 00:18:32,000 --> 00:18:36,000 很像威利,和其他人,我要繼續前進 344 00:18:36,000 --> 00:18:41,000 並將此,所以它不是,要短得多 345 00:18:41,000 --> 00:18:44,000 比,我們掀起了第一個使用for循環的迭代版本, 346 00:18:44,000 --> 00:18:48,000 但請注意,這種優雅。 347 00:18:48,000 --> 00:18:51,000 而不是返回一些數字,並執行所有的數學 348 00:18:51,000 --> 00:18:54,000 並加入了局部變量 349 00:18:54,000 --> 00:18:57,000 相反,你說:“好吧,如果這是一個超級簡單的問題, 350 00:18:57,000 --> 00:19:01,000 像<0,讓我立即返回0。“ 351 00:19:01,000 --> 00:19:03,000 >> 我們不會去打擾支持負數, 352 00:19:03,000 --> 00:19:05,000 所以我要硬編碼的值為0。 353 00:19:05,000 --> 00:19:08,000 但是,除此之外,要實現這個想法的總結 354 00:19:08,000 --> 00:19:11,000 所有這些數字放在一起,可以有效地一小口 355 00:19:11,000 --> 00:19:14,000 出了問題,就像我們在這裡所做過的舞台上, 356 00:19:14,000 --> 00:19:18,000 然後平底船剩下的問題,旁邊的人, 357 00:19:18,000 --> 00:19:20,000 但在這種情況下一個人是自己。 358 00:19:20,000 --> 00:19:22,000 這是一個具有相同名稱的功能。 359 00:19:22,000 --> 00:19:25,000 只要把它體積更小,小的問題,每次 360 00:19:25,000 --> 00:19:28,000 即使我們沒有很正式的事情在這裡的代碼 361 00:19:28,000 --> 00:19:33,000 這究竟是怎麼回事0週的電話簿。 362 00:19:33,000 --> 00:19:36,000 這究竟是怎麼回事,在過去的幾週裡,肖恩 363 00:19:36,000 --> 00:19:39,000 和我們尋找數字的示威。 364 00:19:39,000 --> 00:19:42,000 它的問題,劃分了一遍又一遍。 365 00:19:42,000 --> 00:19:44,000 >> 換句話說,現在有一種方法翻譯 366 00:19:44,000 --> 00:19:47,000 這個現實世界的結構,這種更高的層次結構 367 00:19:47,000 --> 00:19:51,000 分而治之,一遍又一遍的東西 368 00:19:51,000 --> 00:19:56,000 在代碼中,所以這是隨著時間的推移,我們將再次看到的東西。 369 00:19:56,000 --> 00:20:00,000 現在,順便說一句,如果你是新遞歸,你應該至少現在明白了 370 00:20:00,000 --> 00:20:02,000 為什麼這很有趣。 371 00:20:02,000 --> 00:20:05,000 我要訪問google.com, 372 00:20:05,000 --> 00:20:17,000 我要尋找一些技巧和竅門遞歸進入。 373 00:20:17,000 --> 00:20:21,000 告訴你旁邊的人,如果他們不是剛才笑。 374 00:20:21,000 --> 00:20:23,000 你的意思是遞歸? 375 00:20:23,000 --> 00:20:25,000 難道你的意思是啊,我們走吧。 376 00:20:25,000 --> 00:20:28,000 好了,現在剩下的大家。 377 00:20:28,000 --> 00:20:30,000 某處有一個小的嵌入式復活節彩蛋在谷歌。 378 00:20:30,000 --> 00:20:33,000 順便說一句,我們把課程的網站上的鏈接 379 00:20:33,000 --> 00:20:36,000 今天只是這個網格的各種排序算法, 380 00:20:36,000 --> 00:20:39,000 其中一些我們看起來在最後一周,但這種可視化有什麼好處 381 00:20:39,000 --> 00:20:43,000 當你試圖周圍包裹你的心有關的各種事情算法 382 00:20:43,000 --> 00:20:46,000 我知道,你可以很容易地現在就開始與不同類型的輸入。 383 00:20:46,000 --> 00:20:50,000 所有的輸入反轉,輸入大多排序條件,輸入隨機的,等等。 384 00:20:50,000 --> 00:20:53,000 當你再次嘗試,區分這些東西在你的心中 385 00:20:53,000 --> 00:20:57,000 實現了課程網站的講座上,該URL 386 00:20:57,000 --> 00:21:00,000 可能會幫助你通過其中的一些原因。 387 00:21:00,000 --> 00:21:05,000 >> 今天,我們終於得到了一段時間後要解決這個問題, 388 00:21:05,000 --> 00:21:08,000 這是交換功能,這只是沒有工作, 389 00:21:08,000 --> 00:21:12,000 和什麼是最根本的問題,這個功能交換, 390 00:21:12,000 --> 00:21:15,000 目標,其中的時間是,再次,交換的值,在這裡和這裡 391 00:21:15,000 --> 00:21:17,000 如出現這種情況呢? 392 00:21:17,000 --> 00:21:20,000 這實際上並沒有工作。為什麼呢? 393 00:21:20,000 --> 00:21:22,000 是啊。 394 00:21:22,000 --> 00:21:28,000 [聽不見的學生] 395 00:21:28,000 --> 00:21:31,000 沒錯,這bugginess的解釋 396 00:21:31,000 --> 00:21:34,000 簡直是因為當你調用函數在C 397 00:21:34,000 --> 00:21:38,000 這些功能需要的參數,就像A和B, 398 00:21:38,000 --> 00:21:42,000 你是通過你的任何值,該功能提供副本。 399 00:21:42,000 --> 00:21:46,000 你是不是自己提供的原始值, 400 00:21:46,000 --> 00:21:49,000 所以我們看到這在buggyc的背景下, 401 00:21:49,000 --> 00:21:52,000 buggy3.c,這看起來有點像這樣。 402 00:21:52,000 --> 00:21:57,000 >> 回想一下,我們有x和y分別初始化為1和2。 403 00:21:57,000 --> 00:21:59,000 然後,我們打印出它們是什麼。 404 00:21:59,000 --> 00:22:03,000 然後,我要求我的x,y調用swap交換他們的。 405 00:22:03,000 --> 00:22:06,000 但問題是,交換的工作, 406 00:22:06,000 --> 00:22:10,000 但只有在交換的範圍的函數本身。 407 00:22:10,000 --> 00:22:13,000 只要我們打了40行這些交換值 408 00:22:13,000 --> 00:22:16,000 被扔掉了,所以沒有什麼 409 00:22:16,000 --> 00:22:21,000 在實際上改變了原有的功能,主要是在所有, 410 00:22:21,000 --> 00:22:26,000 所以,如果你認為這看起來像在我們的記憶中 411 00:22:26,000 --> 00:22:29,000 如果此電路板的左手側表示- 412 00:22:29,000 --> 00:22:33,000 我會盡我所能為大家看到這如果左側董事會 413 00:22:33,000 --> 00:22:37,000 代表,說,你的RAM,堆棧增長了這種方式, 414 00:22:37,000 --> 00:22:43,000 和我們調用一個函數像主,主有2個局部變量,x和y, 415 00:22:43,000 --> 00:22:48,000 讓我們在這裡描述為x,讓我們在這裡描述為y, 416 00:22:48,000 --> 00:22:55,000 ,讓我們把值1和2中,所以在此主要是, 417 00:22:55,000 --> 00:22:58,000 當主呼叫交換功能的操作系統 418 00:22:58,000 --> 00:23:02,000 給自己的大片的內存堆棧上的交換功能, 419 00:23:02,000 --> 00:23:04,000 它自己的堆棧幀,可以這麼說。 420 00:23:04,000 --> 00:23:08,000 它也分配這些32位的int型。 421 00:23:08,000 --> 00:23:11,000 它發生在A和B,但是這完全是任意的。 422 00:23:11,000 --> 00:23:13,000 它可以叫他們為所欲為,但會發生什麼,當主 423 00:23:13,000 --> 00:23:19,000 調用swap是需要1,把一個副本,將副本。 424 00:23:19,000 --> 00:23:23,000 >> 掉期為1的局部變量,不過,叫什麼?>> TMP。 425 00:23:23,000 --> 00:23:27,000 TMP,所以讓我給了自己另一個32位, 426 00:23:27,000 --> 00:23:29,000 我做了什麼在這個功能嗎? 427 00:23:29,000 --> 00:23:34,000 我,詮釋TMP說得到,因此有1,所以我這樣做時,我們上次播放的這個例子。 428 00:23:34,000 --> 00:23:39,000 然後得到b,所以b是2,所以現在變成2個, 429 00:23:39,000 --> 00:23:42,000 現在b得到溫度,因此溫度是1, 430 00:23:42,000 --> 00:23:44,000 所以現在B變成這樣。 431 00:23:44,000 --> 00:23:46,000 這是偉大的。它的工作。 432 00:23:46,000 --> 00:23:49,000 但是,當盡快在函數返回 433 00:23:49,000 --> 00:23:52,000 交換的存儲器有效地消失,以便它可以被重用 434 00:23:52,000 --> 00:23:58,000 由一些在未來的其他功能,和主要是顯然完全不變。 435 00:23:58,000 --> 00:24:00,000 我們需要一種從根本上解決此問題, 436 00:24:00,000 --> 00:24:03,000 今天我們就終於有辦法這樣做,據此 437 00:24:03,000 --> 00:24:06,000 我們可以引進一些所謂的指針。 438 00:24:06,000 --> 00:24:09,000 事實證明,我們可以解決這個問題 439 00:24:09,000 --> 00:24:12,000 而不是通過在x和y的副本 440 00:24:12,000 --> 00:24:18,000 而是通過在哪,你想,交換功能? 441 00:24:18,000 --> 00:24:20,000 是啊,什麼的地址嗎? 442 00:24:20,000 --> 00:24:22,000 我們還沒有真正談過地址在很多細節, 443 00:24:22,000 --> 00:24:25,000 但如果這個黑板代表我的電腦的內存 444 00:24:25,000 --> 00:24:28,000 當然,我們可以開始編號,我的內存中的字節 445 00:24:28,000 --> 00:24:31,000 並說,這是字節#1,這是字節#2,#3字節, 446 00:24:31,000 --> 00:24:35,000 字節第4字節#2億元,如果我有2 GB的RAM, 447 00:24:35,000 --> 00:24:38,000 所以我們當然可以拿出一些任意的編號方案 448 00:24:38,000 --> 00:24:41,000 在我的電腦的內存中的所有單個字節。 449 00:24:41,000 --> 00:24:43,000 >> 什麼,如果不是,當我打電話交換 450 00:24:43,000 --> 00:24:47,000 在x和y的副本,而不是通 451 00:24:47,000 --> 00:24:51,000 為什麼不要我,而不是通過在這裡的x的地址, 452 00:24:51,000 --> 00:24:55,000 地址為y這裡,基本上郵政的地址 453 00:24:55,000 --> 00:24:59,000 因為x和y交換,如果他的通知 454 00:24:59,000 --> 00:25:01,000 x和y的存儲器中的地址; 455 00:25:01,000 --> 00:25:04,000 然後交換,如果我們把他訓練的一點點, 456 00:25:04,000 --> 00:25:07,000 他有可能開車到該地址,可以這麼說, 457 00:25:07,000 --> 00:25:11,000 X,和有改變,然後開車到y的地址, 458 00:25:11,000 --> 00:25:16,000 數,即使沒有實際得到,自己這些值的副本, 459 00:25:16,000 --> 00:25:19,000 因此,即使我們談到這個作為主要的記憶體 460 00:25:19,000 --> 00:25:23,000 作為交換的內存,強大的和危險的C 461 00:25:23,000 --> 00:25:28,000 的是,任何函數可以觸摸內存在計算機中的任何地方, 462 00:25:28,000 --> 00:25:32,000 這是強大的,你可以做很花哨的東西,計算機程序C. 463 00:25:32,000 --> 00:25:36,000 這是很危險的,因為你也可以很容易搞砸了。 464 00:25:36,000 --> 00:25:39,000 事實上,一個最常見的方式的方案,這些天被利用 465 00:25:39,000 --> 00:25:42,000 仍是一個程序員沒有意識到 466 00:25:42,000 --> 00:25:45,000 他或她被允許的數據 467 00:25:45,000 --> 00:25:49,000 要被寫入存儲器中的一個位置不打算。 468 00:25:49,000 --> 00:25:51,000 >> 例如,他或她聲明一個數組大小為10 469 00:25:51,000 --> 00:25:56,000 但後​​來意外地試圖把11個字節到該數組的內存, 470 00:25:56,000 --> 00:25:59,000 你開始接觸的內存部分不再有效。 471 00:25:59,000 --> 00:26:02,000 只是為了上下文此,有些人可能知道, 472 00:26:02,000 --> 00:26:06,000 軟件經常會提示您輸入序列號或註冊鍵, 473 00:26:06,000 --> 00:26:08,000 的Photoshop和Word這樣的程序。 474 00:26:08,000 --> 00:26:12,000 存在裂縫,你們有些人知道,網上,您可以運行一個小程序, 475 00:26:12,000 --> 00:26:14,000 瞧,沒有更多的請求的序列號。 476 00:26:14,000 --> 00:26:16,000 如何工作? 477 00:26:16,000 --> 00:26:21,000 在許多情況下,這些東西都只是尋求在電腦 478 00:26:21,000 --> 00:26:24,000 在計算機的實際零和一的文本段 479 00:26:24,000 --> 00:26:28,000 其中是,其中被請求的序列號的功能, 480 00:26:28,000 --> 00:26:31,000 您覆蓋空間,在程序運行時, 481 00:26:31,000 --> 00:26:33,000 你可以找出其中的關鍵是實際存儲 482 00:26:33,000 --> 00:26:37,000 使用一些所謂的調試器,你可以破解軟件的方式。 483 00:26:37,000 --> 00:26:40,000 這是不是說,這是我們的目標,在未來幾天, 484 00:26:40,000 --> 00:26:42,000 但它具有非常現實世界的後果。 485 00:26:42,000 --> 00:26:45,000 這發生的涉及盜竊軟件, 486 00:26:45,000 --> 00:26:47,000 但也有妥協的整個機器。 487 00:26:47,000 --> 00:26:50,000 >> 事實上,當網站這幾天都在利用 488 00:26:50,000 --> 00:26:53,000 和妥協的數據被洩露和被竊取密碼 489 00:26:53,000 --> 00:26:58,000 這往往涉及到一個人的記憶管理不善, 490 00:26:58,000 --> 00:27:01,000 或者,在數據庫的情況下,未能預見 491 00:27:01,000 --> 00:27:03,000 對抗性的輸入,所以更多的是在未來幾週內, 492 00:27:03,000 --> 00:27:07,000 但現在只是一個先睹為快的那種傷害,你可以做 493 00:27:07,000 --> 00:27:11,000 不太了解引擎蓋下是如何工作的。 494 00:27:11,000 --> 00:27:14,000 讓我們去了解,這是為什麼打破 495 00:27:14,000 --> 00:27:17,000 一個工具,將成為越來越多的有用 496 00:27:17,000 --> 00:27:19,000 因為我們的課程變得更加複雜。 497 00:27:19,000 --> 00:27:21,000 到目前為止,當你在你的程序中有一個錯誤 498 00:27:21,000 --> 00:27:23,000 你如何調試了嗎? 499 00:27:23,000 --> 00:27:25,000 你有什麼技術迄今為止,無論是你的TF教 500 00:27:25,000 --> 00:27:27,000 或只是自學成才的嗎? 501 00:27:27,000 --> 00:27:29,000 [學生]的printf。 502 00:27:29,000 --> 00:27:31,000 printf的,因此我們知道printf有可能是你的朋友,如果你想看到的 503 00:27:31,000 --> 00:27:33,000 這是怎麼回事,在你的程序 504 00:27:33,000 --> 00:27:36,000 你只是在這裡把輸出,輸出在這裡,輸出在這裡。 505 00:27:36,000 --> 00:27:38,000 然後運行它,你會得到一大堆的東西在屏幕上 506 00:27:38,000 --> 00:27:43,000 ,然後你可以用它來推斷出什麼是真正在你的程序錯誤。 507 00:27:43,000 --> 00:27:45,000 >> printf的往往是一個非常強大的東西, 508 00:27:45,000 --> 00:27:47,000 但它是一個非常手動過程。 509 00:27:47,000 --> 00:27:49,000 你必須把這裡的printf,是printf這裡, 510 00:27:49,000 --> 00:27:51,000 如果你把它裡面的一個循環,你可能會得到100行 511 00:27:51,000 --> 00:27:53,000 的輸出,你就必須通過篩選。 512 00:27:53,000 --> 00:27:58,000 這不是一個非常用戶友好的調試程序或互動機制, 513 00:27:58,000 --> 00:28:00,000 但幸運的是存在替代品。 514 00:28:00,000 --> 00:28:03,000 有一個程序,例如,GDB,GNU調試器, 515 00:28:03,000 --> 00:28:06,000 這是一個有點神秘的,你如何使用它。 516 00:28:06,000 --> 00:28:08,000 這是一個有點複雜,但坦率地說, 517 00:28:08,000 --> 00:28:11,000 這是一個的東西在那裡,如果你把在本週和未來 518 00:28:11,000 --> 00:28:14,000 額外的一小時了解類似GDB 519 00:28:14,000 --> 00:28:18,000 從長遠來看,它可能會為你節省幾十個小時, 520 00:28:18,000 --> 00:28:21,000 所以,讓我給你一個傳情的這個東西是如何工作的。 521 00:28:21,000 --> 00:28:23,000 >> 我在我的終端窗口。 522 00:28:23,000 --> 00:28:26,000 讓我繼續前進,編譯這個程序,buggy3。 523 00:28:26,000 --> 00:28:28,000 這已經是最新的。 524 00:28:28,000 --> 00:28:31,000 讓我運行它,就像我們做了一段時​​間後,而事實上,它打破了。 525 00:28:31,000 --> 00:28:34,000 但是,這是為什麼?也許是我搞砸了交換功能。 526 00:28:34,000 --> 00:28:37,000 也許它的A和B。我不是很感動他們周圍是否正確。 527 00:28:37,000 --> 00:28:39,000 讓我繼續這樣做。 528 00:28:39,000 --> 00:28:43,000 而不是僅僅buggy3,而不是讓我運行這個程序,GDB, 529 00:28:43,000 --> 00:28:48,000 我要告訴它運行buggy3, 530 00:28:48,000 --> 00:28:52,000 我要包括一個命令行參數,TUI, 531 00:28:52,000 --> 00:28:55,000 我們會把這規格提醒未來的問題。 532 00:28:55,000 --> 00:28:57,000 而現在這個黑和白的接口彈出,再次, 533 00:28:57,000 --> 00:28:59,000 是有點勢​​不可擋,因為這一切 534 00:28:59,000 --> 00:29:02,000 保修信息到這裡,但至少有一些熟悉的東西。 535 00:29:02,000 --> 00:29:04,000 在窗口頂部的是我的實際代碼, 536 00:29:04,000 --> 00:29:08,000 如果我向上滾動,在這裡讓我滾動到最頂端的我的文件, 537 00:29:08,000 --> 00:29:11,000 而事實上,在此窗口底部有buggy3.c,並通知 538 00:29:11,000 --> 00:29:13,000 我有這樣的GDB提示。 539 00:29:13,000 --> 00:29:16,000 >> 這是我的正常的約翰·哈佛提示不一樣的。 540 00:29:16,000 --> 00:29:19,000 這是一個提示,是怎麼回事,讓我來控制GDB。 541 00:29:19,000 --> 00:29:21,000 GDB調試器。 542 00:29:21,000 --> 00:29:24,000 調試器是一個程序,讓你走過 543 00:29:24,000 --> 00:29:27,000 一行行的執行你的程序行, 544 00:29:27,000 --> 00:29:30,000 前進的道路上,做任何你想要的程序, 545 00:29:30,000 --> 00:29:33,000 即使調用函數,或尋找,更重要的是, 546 00:29:33,000 --> 00:29:35,000 在各種變量的值。 547 00:29:35,000 --> 00:29:37,000 讓我們繼續前進,並做到這一點。 548 00:29:37,000 --> 00:29:40,000 我會繼續前進,在運行中輸入GDB的提示符下, 549 00:29:40,000 --> 00:29:43,000 所以注意在屏幕的左下方,我輸入的運行, 550 00:29:43,000 --> 00:29:45,000 和我已經打輸入,和什麼做呢? 551 00:29:45,000 --> 00:29:50,000 它的字面運行我的程序,但我並沒有真正看到很多在這裡 552 00:29:50,000 --> 00:29:55,000 因為我還沒有告訴調試器 553 00:29:55,000 --> 00:29:57,000 暫停在一個特定的時刻。 554 00:29:57,000 --> 00:29:59,000 只需鍵入運行,運行該程序。 555 00:29:59,000 --> 00:30:01,000 我沒有看到任何東西。我不能操縱它。 556 00:30:01,000 --> 00:30:03,000 >> 而是讓我這樣做。 557 00:30:03,000 --> 00:30:08,000 在此GDB提示符下,讓我,而不是鍵入突破,進入。 558 00:30:08,000 --> 00:30:10,000 這不是我的意思是什麼類型的。 559 00:30:10,000 --> 00:30:13,000 讓我們,而不是主要鍵入休息。 560 00:30:13,000 --> 00:30:15,000 換句話說,我想設置一個斷點, 561 00:30:15,000 --> 00:30:18,000 這是恰當地命名,是因為它會破壞或暫停 562 00:30:18,000 --> 00:30:21,000 執行你的程序在特定的地方。 563 00:30:21,000 --> 00:30:23,000 主要是我的函數的名稱。 564 00:30:23,000 --> 00:30:25,000 請注意,GDB是非常聰明的。 565 00:30:25,000 --> 00:30:28,000 想通了,主要發生在大約在第18行開始 566 00:30:28,000 --> 00:30:32,000 的buggy3.c,然後注意到這裡在左上角 567 00:30:32,000 --> 00:30:34,000 B +第18行是正確的旁邊。 568 00:30:34,000 --> 00:30:38,000 那是在提醒我,我已經在第18行設置一個斷點。 569 00:30:38,000 --> 00:30:42,000 這一次,當我鍵入run,我要運行我的程序 570 00:30:42,000 --> 00:30:45,000 直到它擊中斷點, 571 00:30:45,000 --> 00:30:48,000 這樣的程序將暫停,我在第18行。 572 00:30:48,000 --> 00:30:50,000 在這裡,我們去運行。 573 00:30:50,000 --> 00:30:53,000 什麼也沒有發生,但通知左下角 574 00:30:53,000 --> 00:30:58,000 啟動程序,buggy3,斷點1在主在buggy3.c第18行。 575 00:30:58,000 --> 00:31:00,000 我現在能做些什麼呢? 576 00:31:00,000 --> 00:31:03,000 >> 請注意,我可以開始輸入打印類的東西, 577 00:31:03,000 --> 00:31:08,000 不是printf,打印x,而現在很奇怪。 578 00:31:08,000 --> 00:31:11,000 1美元的僅僅是一個好奇心,我們會看到 579 00:31:11,000 --> 00:31:14,000 每次你打印的東西,你會得到一個新的美元價值。 580 00:31:14,000 --> 00:31:18,000 這是如此,你可以參考以前的值,以防萬一, 581 00:31:18,000 --> 00:31:21,000 但現在打印告訴我的是,在這個故事中的點x的值 582 00:31:21,000 --> 00:31:26,000 顯然是134514032。 583 00:31:26,000 --> 00:31:29,000 什麼?在哪裡,即使是從何而來呢? 584 00:31:29,000 --> 00:31:31,000 [聽不見的學生] 585 00:31:31,000 --> 00:31:34,000 事實上,這就是我們要調用一個垃圾值,我們還沒有談到這一點, 586 00:31:34,000 --> 00:31:37,000 但原因,你初始化變量 587 00:31:37,000 --> 00:31:40,000 顯然,讓他們有一定的價值,你希望他們有。 588 00:31:40,000 --> 00:31:44,000 但問題是這樣,就可以聲明變量 589 00:31:44,000 --> 00:31:46,000 像我剛才在我的適馬的例子 590 00:31:46,000 --> 00:31:48,000 實際上是給他們一個值。 591 00:31:48,000 --> 00:31:50,000 回想我做了什麼,在這裡西格瑪。 592 00:31:50,000 --> 00:31:52,000 我宣布n,但是什麼樣的價值,我給它呢? 593 00:31:52,000 --> 00:31:56,000 沒有,因為我知道,在接下來的幾行 594 00:31:56,000 --> 00:31:59,000 調用getInt會照顧的問題,把裡面的值的n。 595 00:31:59,000 --> 00:32:02,000 >> 但在這一點上在第11行的故事 596 00:32:02,000 --> 00:32:05,000 和線12和線13和第14行 597 00:32:05,000 --> 00:32:08,000 在那些幾行n的值是什麼? 598 00:32:08,000 --> 00:32:10,000 在C語言中,你只是不知道。 599 00:32:10,000 --> 00:32:14,000 這是一些垃圾的價值,有些完全是隨機的數字 600 00:32:14,000 --> 00:32:17,000 剩下的基本上是從以前的一些功能 601 00:32:17,000 --> 00:32:21,000 已運行,這樣你的程序運行 602 00:32:21,000 --> 00:32:24,000 記得函數獲取函數,函數,函數。 603 00:32:24,000 --> 00:32:27,000 所有這些幀被放到內存中,然後這些函數的返回, 604 00:32:27,000 --> 00:32:31,000 就像我建議用橡皮擦最終被重複使用他們的記憶。 605 00:32:31,000 --> 00:32:37,000 好了,它只是恰巧在這個程序,這個變量x 606 00:32:37,000 --> 00:32:41,000 似乎已經包含了一些垃圾的價值,如134514032 607 00:32:41,000 --> 00:32:44,000 從以前的一些功能,而不是我寫的。 608 00:32:44,000 --> 00:32:47,000 這可能是有效的操作系統的東西來, 609 00:32:47,000 --> 00:32:49,000 引擎蓋下的一些功能。 610 00:32:49,000 --> 00:32:52,000 >> 好了,這很好,但現在,讓我們進入到下一行。 611 00:32:52,000 --> 00:32:55,000 如果我在我的GDB提示符中鍵入“下一步”,我按下回車鍵, 612 00:32:55,000 --> 00:32:58,000 注意突出顯示向下移動到第19行, 613 00:32:58,000 --> 00:33:01,000 但合乎邏輯的言下之意是,第18行 614 00:33:01,000 --> 00:33:06,000 現在已經執行完畢,所以如果我再輸入“打印X” 615 00:33:06,000 --> 00:33:10,000 我現在應該看到,事實上,我做的。 616 00:33:10,000 --> 00:33:14,000 同樣,美元的東西是一個GDB提醒你的方式 617 00:33:14,000 --> 00:33:17,000 打印的歷史是什麼,你已經完成了。 618 00:33:17,000 --> 00:33:21,000 現在讓我和打印輸出Y,而事實上,y是一些瘋狂的價值,以及, 619 00:33:21,000 --> 00:33:24,000 但沒有什麼大不了的,因為在第19行中,我們將其分配給 620 00:33:24,000 --> 00:33:27,000 值2,所以讓我再次鍵入“下一步”。 621 00:33:27,000 --> 00:33:29,000 現在,我們正上的printf線。 622 00:33:29,000 --> 00:33:31,000 讓我做打印x。 623 00:33:31,000 --> 00:33:34,000 讓我做印刷品Y。坦率地說,我有點累了印刷本。 624 00:33:34,000 --> 00:33:38,000 讓我,而不是鍵入“顯示x”和“顯示Y” 625 00:33:38,000 --> 00:33:41,000 現在每次我在未來鍵入命令 626 00:33:41,000 --> 00:33:45,000 我會想起什麼x和y,x和y,x和y是什麼。 627 00:33:45,000 --> 00:33:48,000 >> 我還可以,順便說一句,在“信息當地人類型。” 628 00:33:48,000 --> 00:33:50,000 信息是一種特殊的命令。 629 00:33:50,000 --> 00:33:52,000 當地人意味著它讓我看到局部變量。 630 00:33:52,000 --> 00:33:55,000 以防萬一我忘了這是一個瘋狂的,複雜的功能 631 00:33:55,000 --> 00:33:57,000 我或其他人編寫的信息當地人會告訴你 632 00:33:57,000 --> 00:34:00,000 什麼是這裡面的本地函數的所有局部變量 633 00:34:00,000 --> 00:34:03,000 如果你想閒逛,你可能會關心。 634 00:34:03,000 --> 00:34:07,000 現在,printf是執行,所以讓我繼續前進,只需鍵入“未來”。 635 00:34:07,000 --> 00:34:10,000 因為我們是在這樣的環境中,我們實際上沒有看到它 636 00:34:10,000 --> 00:34:14,000 執行下來,但要注意它變得有點錯位。 637 00:34:14,000 --> 00:34:17,000 但是請注意,它的首要屏幕上出現, 638 00:34:17,000 --> 00:34:21,000 所以它不是一個完美的方案,但是這沒關係,因為我可以隨時閒逛 639 00:34:21,000 --> 00:34:23,000 如果我想使用打印。 640 00:34:23,000 --> 00:34:26,000 >> 讓我再輸入下,現在這裡是最有趣的部分。 641 00:34:26,000 --> 00:34:29,000 在這一點上在故事y是2,x是1, 642 00:34:29,000 --> 00:34:32,000 的建議,並再次, 643 00:34:32,000 --> 00:34:35,000 這是自動顯示的原因是因為我使用的命令 644 00:34:35,000 --> 00:34:40,000 顯示x和顯示Y,I型下的那一刻 645 00:34:40,000 --> 00:34:43,000 x和y在理論上應該成為交換。 646 00:34:43,000 --> 00:34:45,000 現在,我們已經知道這是不會的情況下, 647 00:34:45,000 --> 00:34:49,000 但我們會看到一個時刻,我們如何能更深入地找出原因,這是真的。 648 00:34:49,000 --> 00:34:54,000 下一步,不幸的是,Y仍然是2,x是1,我可以證實盡可能多的。 649 00:34:54,000 --> 00:34:56,000 打印x,印刷品Y。 650 00:34:56,000 --> 00:34:59,000 事實上,沒有交換實際上已經發生了,所以讓我們開始這個問題。 651 00:34:59,000 --> 00:35:01,000 顯然,交換被打破了。 652 00:35:01,000 --> 00:35:04,000 的,而不是讓我們再次鍵入“運行”。 653 00:35:04,000 --> 00:35:07,000 讓我說是的,我要重新啟動它從一開始,進入。 654 00:35:07,000 --> 00:35:09,000 >> 現在,我回來了在第18行。 655 00:35:09,000 --> 00:35:11,000 現在,注意到x和y的值再次是垃圾。 656 00:35:11,000 --> 00:35:15,000 下一步,下一步,下一步,下一步。 657 00:35:15,000 --> 00:35:17,000 如果我感到無聊,我也只需要輸入n轉到下一個。 658 00:35:17,000 --> 00:35:21,000 您可以縮寫,以最短的字符序列。 659 00:35:21,000 --> 00:35:23,000 現在被破壞掉。 660 00:35:23,000 --> 00:35:25,000 我們來看看,而不是輸入下, 661 00:35:25,000 --> 00:35:30,000 現在,我要輸入步驟,加強,使我裡面的這個函數 662 00:35:30,000 --> 00:35:33,000 這樣我就可以穿過它,所以我打步驟,然後輸入。 663 00:35:33,000 --> 00:35:37,000 注意突出跳下在我的程序中第36行。 664 00:35:37,000 --> 00:35:39,000 現在的局部變量是什麼? 665 00:35:39,000 --> 00:35:41,000 信息本地人。 666 00:35:41,000 --> 00:35:43,000 沒有,只是還沒有,因為我們還沒有得到該行, 667 00:35:43,000 --> 00:35:47,000 所以讓我們繼續前進,並說:“下一個。” 668 00:35:47,000 --> 00:35:50,000 現在,我們似乎,有tmp目錄,打印TMP。 669 00:35:50,000 --> 00:35:52,000 垃圾的價值,對不對?我是這麼認為的。 670 00:35:52,000 --> 00:35:55,000 如何打印,打印B,1和2嗎? 671 00:35:55,000 --> 00:35:58,000 在某一時刻,只要我再輸入下 672 00:35:58,000 --> 00:36:02,000 tmp是將要採取的值為1,希望, 673 00:36:02,000 --> 00:36:05,000 因為tmp目錄將被分配的值。 674 00:36:05,000 --> 00:36:08,000 >> 現在,讓我們做打印,頁B, 675 00:36:08,000 --> 00:36:11,000 但現在打印tmp,以及它的確是1。 676 00:36:11,000 --> 00:36:14,000 讓我做下一個。讓我做下一個。 677 00:36:14,000 --> 00:36:16,000 我已經完成了交換功能。 678 00:36:16,000 --> 00:36:19,000 我還在裡面,它在第40行,所以讓我打印, 679 00:36:19,000 --> 00:36:22,000 打印B,我不關心tmp是什麼。 680 00:36:22,000 --> 00:36:27,000 它看起來像掉期是正確的,當談到交換a和b。 681 00:36:27,000 --> 00:36:31,000 但是,如果我現在鍵入下,我跳回到第25行, 682 00:36:31,000 --> 00:36:34,000 當然,如果我在x和印刷品Y型 683 00:36:34,000 --> 00:36:38,000 他們仍然是不變的,所以我們沒有固定的問題。 684 00:36:38,000 --> 00:36:41,000 但診斷也許這GDB程序 685 00:36:41,000 --> 00:36:44,000 至少我們已經變得更近了一步的了解 686 00:36:44,000 --> 00:36:47,000 這是怎麼回事錯誤,不亂拋垃圾,我們把一個printf的代碼, 687 00:36:47,000 --> 00:36:50,000 輸出,輸出,然後運行一遍又一遍 688 00:36:50,000 --> 00:36:52,000 試圖找出什麼地方出了錯。 689 00:36:52,000 --> 00:36:55,000 >> 我要繼續前進並退出這完全退出。 690 00:36:55,000 --> 00:36:57,000 這是怎麼回事,然後說,“要離開嗎?”是。 691 00:36:57,000 --> 00:37:00,000 現在,我回到了我的正常提示,我使用GDB。 692 00:37:00,000 --> 00:37:03,000 順便說一句,你不需要使用這個TUI標誌。 693 00:37:03,000 --> 00:37:07,000 事實上,如果你忽略它,你基本上是在屏幕的下半部分。 694 00:37:07,000 --> 00:37:11,000 如果我然後鍵入突破主,然後運行 695 00:37:11,000 --> 00:37:15,000 我仍然可以運行我的程序,但它會做的是文本上 696 00:37:15,000 --> 00:37:18,000 你給我的當前行一次一個。 697 00:37:18,000 --> 00:37:21,000 TUI,文本用戶界面, 698 00:37:21,000 --> 00:37:25,000 只能說明你的程序一次,這可能是有點概念上更容易。 699 00:37:25,000 --> 00:37:27,000 不過說實在的,我只是做下一個,下一個,下一個, 700 00:37:27,000 --> 00:37:30,000 我看到一個在一個時間線,如果我真的想看看會發生什麼 701 00:37:30,000 --> 00:37:35,000 我可以輸入列表,看到一大堆的相鄰線路。 702 00:37:35,000 --> 00:37:39,000 >> 有一個視頻,我們問過,你看問題集3 703 00:37:39,000 --> 00:37:43,000 內特覆蓋一些GDB的複雜性, 704 00:37:43,000 --> 00:37:46,000 這是一個人的東西,說實話,你的一些不平凡的百分比 705 00:37:46,000 --> 00:37:49,000 再也不會去碰GDB,這將是一件壞事 706 00:37:49,000 --> 00:37:53,000 因為從字面上你會花更多的時間,這學期 707 00:37:53,000 --> 00:37:56,000 追錯誤,那麼你如果你把在這半小時/小時 708 00:37:56,000 --> 00:38:00,000 本週和下週的學習,獲得舒適的使用GDB。 709 00:38:00,000 --> 00:38:02,000 printf的是你的朋友。 710 00:38:02,000 --> 00:38:05,000 GDB現在應該是你的朋友。 711 00:38:05,000 --> 00:38:08,000 >> 對GDB的任何問題? 712 00:38:08,000 --> 00:38:12,000 這裡有一個快速的一些最強大,最有用的命令列表。 713 00:38:12,000 --> 00:38:15,000 是啊。>>你可以打印一個字符串? 714 00:38:15,000 --> 00:38:17,000 你可以打印一個字符串?當然可以。 715 00:38:17,000 --> 00:38:19,000 它不具有只是整數。 716 00:38:19,000 --> 00:38:22,000 如果一個變量s是一個字符串類型的打印小號。 717 00:38:22,000 --> 00:38:24,000 它會告訴你是什麼字符串變量。 718 00:38:24,000 --> 00:38:26,000 [聽不見的學生] 719 00:38:26,000 --> 00:38:28,000 它會給你的地址和字符串本身。 720 00:38:28,000 --> 00:38:32,000 它會告訴你。 721 00:38:32,000 --> 00:38:34,000 最後一件事,只是因為這是好知道的太多。 722 00:38:34,000 --> 00:38:37,000 回溯和框架,讓我潛入這是最後一次, 723 00:38:37,000 --> 00:38:39,000 GDB完全相同的程序。 724 00:38:39,000 --> 00:38:44,000 讓我繼續運行的文本用戶界面版本, 725 00:38:44,000 --> 00:38:46,000 打破為主。 726 00:38:46,000 --> 00:38:49,000 讓我繼續前進,再次運行。我在這裡。 727 00:38:49,000 --> 00:38:55,000 現在讓我去下一個,下一個,下一個,下一個,下一個步驟中,輸入。 728 00:38:55,000 --> 00:39:00,000 >> 現在假設我現在在交換故意的,但我很喜歡“媽的,什麼是x的值嗎?” 729 00:39:00,000 --> 00:39:02,000 我不能做X了。 730 00:39:02,000 --> 00:39:05,000 我不能做y,因為他們不在範圍內。 731 00:39:05,000 --> 00:39:07,000 他們不是在上下文中,但沒有問題。 732 00:39:07,000 --> 00:39:09,000 我可以輸入回溯。 733 00:39:09,000 --> 00:39:13,000 這說明我已經執行了這個時間點的所有的功能。 734 00:39:13,000 --> 00:39:16,000 請注意,一個在底部,主,線與主 735 00:39:16,000 --> 00:39:18,000 這裡是我們的圖片的底部。 736 00:39:18,000 --> 00:39:22,000 事實上,交換與交換在它上面的內存是它上面的線, 737 00:39:22,000 --> 00:39:26,000 如果我想暫時回到主,我可以說,“框架”。 738 00:39:26,000 --> 00:39:30,000 幾號?主要是幀#1。 739 00:39:30,000 --> 00:39:32,000 我要繼續前進,並說:“第1幀”。 740 00:39:32,000 --> 00:39:36,000 >> 現在我的主,我可以打印x,我可以印刷品Y, 741 00:39:36,000 --> 00:39:40,000 但我無法打印或b。 742 00:39:40,000 --> 00:39:43,000 但我可以的,如果我說,“好吧,請等待一分鐘。交換在哪裡?” 743 00:39:43,000 --> 00:39:46,000 讓我繼續說:“第0幀。” 744 00:39:46,000 --> 00:39:48,000 現在我回來了,我想是的,和順便說一句, 745 00:39:48,000 --> 00:39:52,000 也有其他命令一樣,如果你​​真的感到無聊打字下一步,下一步,下一步,下一步, 746 00:39:52,000 --> 00:39:56,000 一般情況下,你可以說“下一個10的事情,”和,將逐步在未來10行。 747 00:39:56,000 --> 00:39:59,000 你也可以寫“繼續”時,你真的厭倦了單步運行它。 748 00:39:59,000 --> 00:40:05,000 繼續運行你的程序沒有中斷,直到碰到另一個斷點, 749 00:40:05,000 --> 00:40:07,000 無論是在一個循環或降低在你的程序中。 750 00:40:07,000 --> 00:40:11,000 >> 在這種情況下,我們繼續到最後,程序正常退出。 751 00:40:11,000 --> 00:40:13,000 這是一種奇特的方式,劣質的過程。 752 00:40:13,000 --> 00:40:16,000 只要你的程序正常退出。 753 00:40:16,000 --> 00:40:24,000 更多的視頻和調試會話來。 754 00:40:24,000 --> 00:40:26,000 這是一個很大。 755 00:40:26,000 --> 00:40:35,000 讓我們把我們的5分鐘的休息時間,在這裡,我們將返回結構和文件。 756 00:40:35,000 --> 00:40:38,000 >> 如果你已經一頭扎進這個星期的pset中 757 00:40:38,000 --> 00:40:41,000 你就會知道,我們使用的分佈代碼, 758 00:40:41,000 --> 00:40:45,000 為出發點,一些新的技術,我們為您提供的源代碼。 759 00:40:45,000 --> 00:40:50,000 特別是,我們推出了一個新的關鍵字稱為struct結構, 760 00:40:50,000 --> 00:40:53,000 這樣我們就可以創建自定義的各種變量。 761 00:40:53,000 --> 00:40:57,000 我們還介紹了文件I / O,文件輸入和輸出的概念, 762 00:40:57,000 --> 00:41:00,000 這是使我們能夠保存狀態 763 00:41:00,000 --> 00:41:03,000 爭奪董事會光盤上的文件 764 00:41:03,000 --> 00:41:06,000 這樣的教學研究員,我可以理解 765 00:41:06,000 --> 00:41:09,000 你的程序內部發生了什麼事情,而無需手動播放 766 00:41:09,000 --> 00:41:11,000 幾十場比賽的爭奪。 767 00:41:11,000 --> 00:41:13,000 我們可以做更多automatedly的。 768 00:41:13,000 --> 00:41:18,000 >> 這個想法的結構解決了一個相當引人注目的問題。 769 00:41:18,000 --> 00:41:21,000 假設我們要實現的一些程序 770 00:41:21,000 --> 00:41:25,000 ,不知怎的,對學生的信息跟踪, 771 00:41:25,000 --> 00:41:28,000 和學生可能具有,例如,一個ID,一個名稱 772 00:41:28,000 --> 00:41:31,000 和一所房子在哈佛這樣的地方,所以這3個信息 773 00:41:31,000 --> 00:41:34,000 我們要保持周圍,所以讓我繼續前進,開始在這裡寫了一個小程序, 774 00:41:34,000 --> 00:41:38,000 包括stdio.h中。 775 00:41:38,000 --> 00:41:42,000 讓我包括cs50.h.的 776 00:41:42,000 --> 00:41:44,000 然後開始我的主要功能。 777 00:41:44,000 --> 00:41:46,000 我不會打擾任何命令行參數, 778 00:41:46,000 --> 00:41:49,000 在這裡,我想有一個學生,所以我說 779 00:41:49,000 --> 00:41:54,000 一個學生都有一個名字,所以我會說“字符串名稱。” 780 00:41:54,000 --> 00:41:59,000 然後我說一個學生,也有一個ID,所以int ID, 781 00:41:59,000 --> 00:42:03,000 學生有一所房子,所以我也說“字符串房子。” 782 00:42:03,000 --> 00:42:06,000 然後,我會為了這些更乾淨一點是這樣的。 783 00:42:06,000 --> 00:42:11,000 好吧,現在我有3個變量代表一個學生,這樣的學生。“ 784 00:42:11,000 --> 00:42:15,000 >> 現在我要來填充這些值,所以讓我繼續前進,這樣說 785 00:42:15,000 --> 00:42:18,000 “ID = 123”。 786 00:42:18,000 --> 00:42:21,000 名稱是會得到大衛。 787 00:42:21,000 --> 00:42:24,000 比方說,房子是會得到奧美, 788 00:42:24,000 --> 00:42:31,000 ,然後我要做的事情,隨意如printf(“%s, 789 00:42:31,000 --> 00:42:37,000 的ID是%d,住在%s。 790 00:42:37,000 --> 00:42:41,000 現在,我要在這裡堵塞,一前一後? 791 00:42:41,000 --> 00:42:47,000 姓名,身份證,房屋返回0。 792 00:42:47,000 --> 00:42:50,000 好吧,除非在此我搞砸了 793 00:42:50,000 --> 00:42:54,000 我認為我們有一個不錯的方案,存儲一個學生。 794 00:42:54,000 --> 00:42:57,000 當然,這不是那麼有趣。如果我想有2名學生? 795 00:42:57,000 --> 00:42:59,000 這沒什麼大不了的。我可以支持2人。 796 00:42:59,000 --> 00:43:03,000 讓我去,並強調這一點,去這裡, 797 00:43:03,000 --> 00:43:09,000 我可以說“ID = 456”像羅布人住在華盛頓州Kirkland的人。 798 00:43:09,000 --> 00:43:12,000 >> 好了,等待,但我不能把這些同樣的事情, 799 00:43:12,000 --> 00:43:15,000 它看起來像我要複製, 800 00:43:15,000 --> 00:43:19,000 所以讓我說,這將是大衛的變量, 801 00:43:19,000 --> 00:43:23,000 並讓我得到一些副本,這些羅布。 802 00:43:23,000 --> 00:43:27,000 我們會打電話給這些Rob的,但,這是行不通的,現在 803 00:43:27,000 --> 00:43:33,000 因為我已經等待,讓我們改變了我的ID1,name1和house1。 804 00:43:33,000 --> 00:43:35,000 羅布將是2,2。 805 00:43:35,000 --> 00:43:42,000 我已經改變了這裡,這裡,這裡,這裡,這裡,這裡。 806 00:43:42,000 --> 00:43:45,000 等待,湯米?讓我們再這樣做。 807 00:43:45,000 --> 00:43:49,000 顯然,如果你仍然認為這是一個很好的方式,這樣做,不是的話, 808 00:43:49,000 --> 00:43:52,000 所以複製/粘貼壞。 809 00:43:52,000 --> 00:43:55,000 但是,我們解決了這一個星期前。 810 00:43:55,000 --> 00:43:59,000 >> 我們的解決方案時,我們希望有相同的數據類型的多個實例嗎? 811 00:43:59,000 --> 00:44:01,000 [學生]一個數組。 812 00:44:01,000 --> 00:44:03,000 一個數組,所以讓我嘗試清理它。 813 00:44:03,000 --> 00:44:07,000 讓我為自己出一些空間的頂部,而不是讓我在這裡做。 814 00:44:07,000 --> 00:44:12,000 我們會打電話給這些人,而不是我會說“詮釋IDS,” 815 00:44:12,000 --> 00:44:14,000 我要支持我們現在。 816 00:44:14,000 --> 00:44:18,000 我會說“字符串名稱”,我會支持我們, 817 00:44:18,000 --> 00:44:22,000 然後,我會說“字符串的房子,”我要支持我們。 818 00:44:22,000 --> 00:44:26,000 現在,在這裡,而不是大衛得到他自己的局部變量 819 00:44:26,000 --> 00:44:28,000 我們可以擺脫這些。 820 00:44:28,000 --> 00:44:30,000 這感覺很好,我們正在清理這個。 821 00:44:30,000 --> 00:44:35,000 然後,我可以說大衛將是[0]和名稱[0] 822 00:44:35,000 --> 00:44:38,000 房子[0]。 823 00:44:38,000 --> 00:44:41,000 然後搶,我們同樣可以省了。 824 00:44:41,000 --> 00:44:46,000 讓我們把這個在這裡,所以他是怎麼回事,隨意入侵檢測系統[1]。 825 00:44:46,000 --> 00:44:50,000 他的名字[1] 826 00:44:50,000 --> 00:44:53,000 然後最後,房屋[1]。 827 00:44:53,000 --> 00:44:57,000 >> 還是有點繁瑣,現在我已經明白這一點, 828 00:44:57,000 --> 00:45:03,000 因此,讓我們說:“名[0],ID [0],房屋[0] 829 00:45:03,000 --> 00:45:06,000 的複數此。 830 00:45:06,000 --> 00:45:09,000 入侵檢測系統,入侵檢測系統,入侵檢測系統。 831 00:45:09,000 --> 00:45:12,000 再次,我這樣做,如此反复,我已經訴諸再次複製/粘貼, 832 00:45:12,000 --> 00:45:14,000 所以賠率是有另一種解決方案。 833 00:45:14,000 --> 00:45:18,000 我也許可以清理,進一步加快循環或類似的東西, 834 00:45:18,000 --> 00:45:21,000 總之,這是好一點,但仍然感覺像 835 00:45:21,000 --> 00:45:24,000 我訴諸複製/粘貼,但即使這樣,我要求, 836 00:45:24,000 --> 00:45:27,000 是不是真的從根本上正確的解決方案,因為 837 00:45:27,000 --> 00:45:29,000 如果某個時候,我們決定你知道嗎? 838 00:45:29,000 --> 00:45:32,000 我們真的應該存儲電子郵件地址為大衛和Rob 839 00:45:32,000 --> 00:45:34,000 每個人都在這個程序。 840 00:45:34,000 --> 00:45:36,000 我們也應當存儲的電話號碼。 841 00:45:36,000 --> 00:45:39,000 我們也應該儲存緊急聯絡電話號碼。 842 00:45:39,000 --> 00:45:41,000 我們有所有這些作品,我們要存儲的數據, 843 00:45:41,000 --> 00:45:43,000 那麼你如何去這樣做呢? 844 00:45:43,000 --> 00:45:46,000 >> 可以聲明另一個數組中的頂部,然後手動添加 845 00:45:46,000 --> 00:45:49,000 [0],[1]的電子郵件地址的電子郵件地址 846 00:45:49,000 --> 00:45:51,000 大衛和Rob等等。 847 00:45:51,000 --> 00:45:56,000 但真的只是一個假設這樣的設計 848 00:45:56,000 --> 00:45:59,000 我使用的是榮譽系統知道 849 00:45:59,000 --> 00:46:03,000 [i]的每個的多個陣列 850 00:46:03,000 --> 00:46:06,000 恰好指的是同一個人, 851 00:46:06,000 --> 00:46:10,000 [0] IDS中的編號為123, 852 00:46:10,000 --> 00:46:13,000 我要去承擔,名字[0] 853 00:46:13,000 --> 00:46:16,000 是同一個人的名字和房子[0] 854 00:46:16,000 --> 00:46:21,000 是同一個人的房子等等,我創造的所有的不同的陣列。 855 00:46:21,000 --> 00:46:24,000 但是請注意,有沒有根本的聯繫 856 00:46:24,000 --> 00:46:27,000 除這3個信息,id,name和房子, 857 00:46:27,000 --> 00:46:32,000 即使我們正在努力模型,這個程序是實體,而不是數組。 858 00:46:32,000 --> 00:46:35,000 數組是這一綱領性的方式這樣做。 859 00:46:35,000 --> 00:46:38,000 我們真正想要的模型在我們的節目是一個人 860 00:46:38,000 --> 00:46:41,000 像大衛一樣,像Rob內,其中一個人 861 00:46:41,000 --> 00:46:46,000 或封裝的名稱和ID和一所房子。 862 00:46:46,000 --> 00:46:49,000 >> 我們可以以某種方式表達這種思想的封裝 863 00:46:49,000 --> 00:46:52,000 由此一個人有一個ID,一個名稱和一個房子 864 00:46:52,000 --> 00:46:55,000 而不是這個黑客真的,我們只是 865 00:46:55,000 --> 00:46:58,000 相信,支架的東西 866 00:46:58,000 --> 00:47:02,000 指的是同一人在這些不同的陣列的實體? 867 00:47:02,000 --> 00:47:04,000 事實上,我們可以做到這一點。 868 00:47:04,000 --> 00:47:08,000 讓我去上面的主,現在,讓我創建自己的數據類型 869 00:47:08,000 --> 00:47:10,000 確實是第一次。 870 00:47:10,000 --> 00:47:14,000 我們使用這種技術的爭奪, 871 00:47:14,000 --> 00:47:17,000 但在這裡,我要繼續前進,並創建一個數據類型, 872 00:47:17,000 --> 00:47:19,000 你知道嗎,我現在就打電話給學生或個人, 873 00:47:19,000 --> 00:47:23,000 我要使用typedef定義一個類型。 874 00:47:23,000 --> 00:47:25,000 我會說,這是一個結構, 875 00:47:25,000 --> 00:47:29,000 那麼這個結構類型的學生,我們會說, 876 00:47:29,000 --> 00:47:31,000 即使這是一個對我來說有點過時了。 877 00:47:31,000 --> 00:47:33,000 我們會說:“int的ID。” 878 00:47:33,000 --> 00:47:35,000 我們會說:“字符串名稱。” 879 00:47:35,000 --> 00:47:37,000 然後,我們會說:“的字符串房子,” 880 00:47:37,000 --> 00:47:40,000 所以現在年底的這幾行代碼 881 00:47:40,000 --> 00:47:45,000 我剛才教鐺存在 882 00:47:45,000 --> 00:47:49,000 除了int類型的數據類型,除了字符串,除了增加一倍,除了花車。 883 00:47:49,000 --> 00:47:54,000 >> 11在時間線的這一刻,現在有一個新的數據類型,稱為學生, 884 00:47:54,000 --> 00:47:58,000 現在我學生可以聲明一個變量,任何地方,我想, 885 00:47:58,000 --> 00:48:01,000 所以讓我向下滾動這裡的人。 886 00:48:01,000 --> 00:48:05,000 現在我可以擺脫這種,我可以回去大衛在這裡, 887 00:48:05,000 --> 00:48:10,000 和大衛,其實我可以說,大衛, 888 00:48:10,000 --> 00:48:13,000 我們可以從字面上命名變量照顧自己, 889 00:48:13,000 --> 00:48:16,000 將是類型的學生。 890 00:48:16,000 --> 00:48:18,000 這可能看起來有點怪,但是這還不是全部,不同的 891 00:48:18,000 --> 00:48:22,000 作為一個int或一個字符串或浮點數申報的東西。 892 00:48:22,000 --> 00:48:24,000 碰巧的是被稱為學生的現在, 893 00:48:24,000 --> 00:48:28,000 如果我想這種結構把裡面的東西 894 00:48:28,000 --> 00:48:31,000 我現在要使用新的語法,但它是非常簡單的, 895 00:48:31,000 --> 00:48:39,000 david.id = 123,david.name =“大衛”在資本ð, 896 00:48:39,000 --> 00:48:42,000 david.house =“奧美” 897 00:48:42,000 --> 00:48:46,000 現在我可以擺脫這東西在這裡。 898 00:48:46,000 --> 00:48:51,000 請注意,我們現在已經重新設計我們的計劃確實是一個更好的方法 899 00:48:51,000 --> 00:48:54,000 現在,我們的節目反映了真實的世界。 900 00:48:54,000 --> 00:48:57,000 >> 有一個現實世界的概念,一個人或一個學生。 901 00:48:57,000 --> 00:49:02,000 在這裡,我們有一個人或更具體的學生的C版本。 902 00:49:02,000 --> 00:49:05,000 裡面的那個人是這些相關的特性, 903 00:49:05,000 --> 00:49:10,000 ID,名稱和房子,所以羅布基本上變成同樣的事情,在這裡, 904 00:49:10,000 --> 00:49:14,000 讓學生搶,現在rob.id的= 456, 905 00:49:14,000 --> 00:49:17,000 rob.name =“搶”。 906 00:49:17,000 --> 00:49:20,000 事實上,該變量被稱為羅布是一種毫無意義的。 907 00:49:20,000 --> 00:49:22,000 我們可以把它叫做x或y或z。 908 00:49:22,000 --> 00:49:25,000 我們只是把它命名為搶在語義上是一致的, 909 00:49:25,000 --> 00:49:28,000 但真正的名字是裡面​​的那場, 910 00:49:28,000 --> 00:49:30,000 所以現在我有這個。 911 00:49:30,000 --> 00:49:33,000 這也是不覺得自己是最優秀的設計,我已經硬編碼的大衛。 912 00:49:33,000 --> 00:49:35,000 我硬編碼的羅布。 913 00:49:35,000 --> 00:49:39,000 我還是要採取一些複製和粘貼的時候,我想新的變量。 914 00:49:39,000 --> 00:49:43,000 此外,我顯然給每個變量的名稱, 915 00:49:43,000 --> 00:49:46,000 即使我寧願描述這些變量 916 00:49:46,000 --> 00:49:48,000  更一般的學生。 917 00:49:48,000 --> 00:49:52,000 >> 現在,我們可以合併的想法,一直致力於為我們的 918 00:49:52,000 --> 00:49:56,000 ,而是說:“你知道嗎,給我一個變量所謂的學生, 919 00:49:56,000 --> 00:50:01,000 ,讓我們有它的大小為3,“所以現在我可以進一步細化此, 920 00:50:01,000 --> 00:50:04,000 擺脫手動聲明的大衛, 921 00:50:04,000 --> 00:50:08,000 相反,我可以說學生一樣的東西[0]在這裡。 922 00:50:08,000 --> 00:50:11,000 然後,我可以說,學生[0]在這裡, 923 00:50:11,000 --> 00:50:14,000 學生[0]在這裡,等等,我可以去轉轉 924 00:50:14,000 --> 00:50:16,000 和清理羅布。 925 00:50:16,000 --> 00:50:19,000 我也可以去,現在可能增加循環 926 00:50:19,000 --> 00:50:23,000 使用GetString和調用getInt從用戶獲取這些值。 927 00:50:23,000 --> 00:50:27,000 我可以加上一個常數,因為這是不好的做法 928 00:50:27,000 --> 00:50:29,000 硬編碼的,有些像在這裡任意數量 929 00:50:29,000 --> 00:50:33,000 ,然後只需記住,你應該不超過3名學生在。 930 00:50:33,000 --> 00:50:36,000 它可能是更好的在我的文件的頂部使用#define 931 00:50:36,000 --> 00:50:40,000 因素說了出來,的確,讓我去和推廣。 932 00:50:40,000 --> 00:50:43,000 >> 讓我打開了一個例子,在今天的 933 00:50:43,000 --> 00:50:46,000 例子提前structs1。 934 00:50:46,000 --> 00:50:49,000 這是一個比較完整的程序,使用#定義在這裡 935 00:50:49,000 --> 00:50:51,000 並說,我們要默認​​情況下,有3名學生。 936 00:50:51,000 --> 00:50:54,000 在這裡,我聲明一個類學生的價值, 937 00:50:54,000 --> 00:50:57,000 所以教室裡的學生,現在我使用的是循環 938 00:50:57,000 --> 00:51:00,000 只是為了使代碼更優雅的一點,填充類 939 00:51:00,000 --> 00:51:05,000 與用戶的輸入,所以循環從i = 0上的學生,它是3。 940 00:51:05,000 --> 00:51:07,000 然後,我提示用戶在這個版本中 941 00:51:07,000 --> 00:51:10,000  什麼是學生的ID,我得到它與調用getInt。 942 00:51:10,000 --> 00:51:13,000 什麼是學生的名字,然後我得到它的GetString。 943 00:51:13,000 --> 00:51:15,000 學生的家是什麼?我得到它的GetString。 944 00:51:15,000 --> 00:51:19,000 然後在底部在這裡,我決定改變 945 00:51:19,000 --> 00:51:22,000 我如何打印這些和實際使用的循環, 946 00:51:22,000 --> 00:51:24,000 我是誰打印? 947 00:51:24,000 --> 00:51:27,000 根據我的評論我打印Mather中的任何人, 948 00:51:27,000 --> 00:51:30,000 這就是它所以羅布和Tommy等等,其實湯米的Mather中。 949 00:51:30,000 --> 00:51:34,000 湯米和大衛將被打印在這種情況下,這是怎麼工作的? 950 00:51:34,000 --> 00:51:40,000 我們還沒有看到這個功能,但猜測這是什麼做的。 951 00:51:40,000 --> 00:51:42,000 比較字符串。 952 00:51:42,000 --> 00:51:45,000 >> 如何比較字符串,因為事實證明,這是一個有點非明顯 953 00:51:45,000 --> 00:51:49,000 如果返回0,表示的字符串是相等的。 954 00:51:49,000 --> 00:51:53,000 如果返回-1,這意味著人來之前,其他的字母順序, 955 00:51:53,000 --> 00:51:57,000 如果返回+1,這意味著其他的字來按字母順序 956 00:51:57,000 --> 00:52:00,000 前,你可以看看網上的手冊頁 957 00:52:00,000 --> 00:52:04,000 它說,看究竟哪一種方式是,但是這一切現在正在做的是 958 00:52:04,000 --> 00:52:09,000 如果[i]的房子是等於“奧美” 959 00:52:09,000 --> 00:52:13,000 然後繼續前進,打印出來,並在奧美也是如此。 960 00:52:13,000 --> 00:52:16,000 但在這裡我們還沒有看到過的東西,我們會回到這個。 961 00:52:16,000 --> 00:52:21,000 我不記得曾經在我的程序中做到這一點。 962 00:52:21,000 --> 00:52:24,000 免費顯然是指內存,釋放內存, 963 00:52:24,000 --> 00:52:31,000 但什麼記憶,我明顯地釋放在這個循環的底部,這個程序嗎? 964 00:52:31,000 --> 00:52:34,000 它看起來像我釋放一個人的名字 965 00:52:34,000 --> 00:52:37,000 和一個人的房子,但為什麼會這樣? 966 00:52:37,000 --> 00:52:41,000 >> 原來,這幾個星期,你已經使用GetString 967 00:52:41,000 --> 00:52:45,000 我們已經被引入到你的程序中的每一個錯誤。 968 00:52:45,000 --> 00:52:51,000 GetString的設計分配內存,因此它可以返回一個字符串, 969 00:52:51,000 --> 00:52:55,000 像大衛一樣,羅布,和你就可以做任何你想要的 970 00:52:55,000 --> 00:52:59,000 以該字符串在你的程序中,因為我們已經為您保留內存。 971 00:52:59,000 --> 00:53:02,000 問題是每到這個時候,你需要調用getString 972 00:53:02,000 --> 00:53:05,000 GetString的作者,​​我們已經要求操作系統 973 00:53:05,000 --> 00:53:07,000 給我們一個位RAM的字符串。 974 00:53:07,000 --> 00:53:09,000 給我們一個位的RAM,這一個字符串。 975 00:53:09,000 --> 00:53:11,000 給我們一些更多的RAM,這一個字符串。 976 00:53:11,000 --> 00:53:13,000 你,程序員,從來沒有做什麼 977 00:53:13,000 --> 00:53:15,000 給我們,恢復記憶, 978 00:53:15,000 --> 00:53:17,000 所以這幾個星期,你寫的所有程序 979 00:53:17,000 --> 00:53:20,000 有什麼所謂的內存的飛躍,讓他們繼續使用 980 00:53:20,000 --> 00:53:24,000 越來越多的內存每次調用GetString,這很好。 981 00:53:24,000 --> 00:53:27,000 我們刻意做的第一週,因為它是不是很有趣 982 00:53:27,000 --> 00:53:29,000 有擔心的字符串是來自哪裡。 983 00:53:29,000 --> 00:53:34,000 所有你想要的是這個詞搶回來當用戶鍵入它。 984 00:53:34,000 --> 00:53:38,000 >> 但是向前發展,我們現在必須開始對這個變得越來越複雜。 985 00:53:38,000 --> 00:53:42,000 任何時候,我們分配內存,我們最終把它。 986 00:53:42,000 --> 00:53:45,000 否則,在現實世界中,在您的Mac或PC,你可能偶爾有經驗豐富的 987 00:53:45,000 --> 00:53:50,000 在您的計算機可能爛尾最終的症狀 988 00:53:50,000 --> 00:53:54,000 或愚蠢的紡紗沙灘球只是佔用計算機的 989 00:53:54,000 --> 00:53:56,000 全部精力,你不能做的事情。 990 00:53:56,000 --> 00:54:00,000 這可以解釋為任意數量的錯誤,但在這些可能的錯誤 991 00:54:00,000 --> 00:54:03,000 事情稱為內存洩漏,有人是誰寫的一塊軟件 992 00:54:03,000 --> 00:54:07,000 你不記得,以便釋放內存 993 00:54:07,000 --> 00:54:10,000 他或她問的操作系統, 994 00:54:10,000 --> 00:54:14,000 不使用GetString,因為這是一個CS50的事情,但使用類似的功能 995 00:54:14,000 --> 00:54:16,000 問操作系統的內存。 996 00:54:16,000 --> 00:54:19,000 如果你或他們搞砸了,從來沒有真正返回該內存 997 00:54:19,000 --> 00:54:24,000 一個程序,可以減緩放緩和減慢的症狀, 998 00:54:24,000 --> 00:54:26,000 除非你記得打電話免費。 999 00:54:26,000 --> 00:54:28,000 >> 我們會回來的時候,為什麼你會打電話免費, 1000 00:54:28,000 --> 00:54:32,000 但讓​​我們繼續前進的好措施,並嘗試運行特定的程序。 1001 00:54:32,000 --> 00:54:35,000 這被稱為structs1,請輸入。 1002 00:54:35,000 --> 00:54:40,000 讓我繼續運行structs1的,123,大衛·馬瑟 1003 00:54:40,000 --> 00:54:47,000 456,789,羅布·柯克蘭, 1004 00:54:47,000 --> 00:54:50,000 湯米·馬瑟,我們看到大衛的Mather中,湯米Mather中。 1005 00:54:50,000 --> 00:54:53,000 這僅僅是一個小的完整性檢查程序的工作。 1006 00:54:53,000 --> 00:54:56,000 現在,不幸的是,這個方案是一個有點沮喪, 1007 00:54:56,000 --> 00:55:00,000 我做過的一切工作,我輸入了9種不同的字符串,點擊進入, 1008 00:55:00,000 --> 00:55:04,000 被告知是誰在奧美,但很明顯,我知道是誰在奧美已經定了,因為我輸入的。 1009 00:55:04,000 --> 00:55:07,000 至少這將是很好,如果這個計劃更像是一個數據庫 1010 00:55:07,000 --> 00:55:10,000 它實際上還記得我所輸入的 1011 00:55:10,000 --> 00:55:12,000 所以我永遠不會再有輸入這些學生記錄。 1012 00:55:12,000 --> 00:55:15,000 也許這是像registrarial系統。 1013 00:55:15,000 --> 00:55:21,000 >> 為此,我們可以使用這種技術被稱為文件I / O,文件輸入和輸出, 1014 00:55:21,000 --> 00:55:24,000 一個非常通用的方法,說任何時候你想要讀取文件或寫入文件 1015 00:55:24,000 --> 00:55:26,000 一組特定的功能,你可以做到這一點。 1016 00:55:26,000 --> 00:55:29,000 讓我繼續並打開這個例子structs2.c, 1017 00:55:29,000 --> 00:55:33,000 這幾乎是相同的,但讓我們來看看它現在所做的。 1018 00:55:33,000 --> 00:55:36,000 在該文件的頂部,我宣布一個班的學生。 1019 00:55:36,000 --> 00:55:38,000 我然後填充類用戶的輸入, 1020 00:55:38,000 --> 00:55:41,000 所以這些代碼行之前是完全一樣的。 1021 00:55:41,000 --> 00:55:45,000 然後,如果我向下滾動,在這裡我打印大家誰是Mather中任意像以前一樣, 1022 00:55:45,000 --> 00:55:47,000 但是,這是一個有趣的新功能。 1023 00:55:47,000 --> 00:55:51,000 這兩行代碼是新的,他們在這裡介紹一些, 1024 00:55:51,000 --> 00:55:55,000 FILE,全部大寫,並且它有*在這裡也。 1025 00:55:55,000 --> 00:55:58,000 讓我搬過來,*在這裡。 1026 00:55:58,000 --> 00:56:00,000 >> 這個功能,我們還沒有看到之前,FOPEN, 1027 00:56:00,000 --> 00:56:03,000 但它意味著打開文件,讓我們翻閱這些, 1028 00:56:03,000 --> 00:56:05,000 這是我們會回來的東西在未來的pset, 1029 00:56:05,000 --> 00:56:10,000 但此行基本上是在這裡打開一個名為“數據庫, 1030 00:56:10,000 --> 00:56:13,000 具體地說,它以這樣一種方式,它可以做它打開? 1031 00:56:13,000 --> 00:56:15,000 [聽不見的學生] 1032 00:56:15,000 --> 00:56:19,000 對,所以“W”只是意味著它告訴操作系統 1033 00:56:19,000 --> 00:56:21,000 以這樣的方式,我可以寫它,打開此文件。 1034 00:56:21,000 --> 00:56:23,000 我不想讀它。我不想只是來看看。 1035 00:56:23,000 --> 00:56:26,000 我想改變它,添加的東西可能, 1036 00:56:26,000 --> 00:56:28,000 和文件將被稱為數據庫。 1037 00:56:28,000 --> 00:56:30,000 這可能是什麼。 1038 00:56:30,000 --> 00:56:32,000 這可能是database.txt。這可能是分貝。 1039 00:56:32,000 --> 00:56:37,000 如foo這可能是一個詞,但我隨意選擇命名的文件數據庫。 1040 00:56:37,000 --> 00:56:42,000 這是一個小的完整性檢查,我們會回來的很詳細隨著時間的推移, 1041 00:56:42,000 --> 00:56:47,000 如果fp文件指針,不等於NULL,這意味著一切都很好。 1042 00:56:47,000 --> 00:56:51,000 >> 長話短說,像fopen的功能有時會失敗。 1043 00:56:51,000 --> 00:56:53,000 可能是文件不存在。也許你的磁盤空間。 1044 00:56:53,000 --> 00:56:55,000 也許你沒有該文件夾的權限, 1045 00:56:55,000 --> 00:56:58,000 因此,如果FOPEN返回null的東西糟糕的事情發生。 1046 00:56:58,000 --> 00:57:02,000 相反,如果FOPEN沒有返回null一切都很好 1047 00:57:02,000 --> 00:57:04,000 我就可以開始寫這個文件。 1048 00:57:04,000 --> 00:57:06,000 這裡有一個新的伎倆。 1049 00:57:06,000 --> 00:57:08,000 這是一個for循環遍歷每個學生, 1050 00:57:08,000 --> 00:57:10,000 這看起來如此的相似,我們做了什麼之前, 1051 00:57:10,000 --> 00:57:15,000 但這個函數是一個表姐的printf稱為fprintf文件輸出, 1052 00:57:15,000 --> 00:57:18,000 並注意在只有2種方式是不同的。 1053 00:57:18,000 --> 00:57:20,000 一,它開始用f代替p, 1054 00:57:20,000 --> 00:57:23,000 但後​​來它的第一個參數顯然是什麼? 1055 00:57:23,000 --> 00:57:25,000 [學生]文件。這是一個文件。 1056 00:57:25,000 --> 00:57:30,000 這件事稱為FP,我們將最終梳理出一個文件指針是什麼, 1057 00:57:30,000 --> 00:57:35,000 但現在FP僅僅代表我已經打開的文件, 1058 00:57:35,000 --> 00:57:41,000 fprintf這裡說的文件打印用戶的ID,而不是在屏幕上。 1059 00:57:41,000 --> 00:57:44,000 打印用戶的名稱的文件,而不是在屏幕上, 1060 00:57:44,000 --> 00:57:47,000 房子的文件,而不是在屏幕上,然後在這裡,很明顯, 1061 00:57:47,000 --> 00:57:50,000 關閉該文件,​​然後在這裡釋放內存。 1062 00:57:50,000 --> 00:57:53,000 >> 這個版本2和版本1之間的唯一區別 1063 00:57:53,000 --> 00:57:58,000 是fopen和引進此文件* 1064 00:57:58,000 --> 00:58:01,000 這個概念fprintf,讓我們看看最終的結果是什麼。 1065 00:58:01,000 --> 00:58:03,000 讓我進入我的終端窗口。 1066 00:58:03,000 --> 00:58:06,000 讓我跑structs2,進入。 1067 00:58:06,000 --> 00:58:09,000 看起來一切都很好。讓我們重新運行structs2。 1068 00:58:09,000 --> 00:58:15,000 123,456,羅布·柯克蘭,大衛·馬瑟, 1069 00:58:15,000 --> 00:58:19,000 789,湯米·馬瑟進入。 1070 00:58:19,000 --> 00:58:23,000 看起來像它的表現是相同的,但如果我現在做的LS 1071 00:58:23,000 --> 00:58:28,000 注意到什麼文件是在這裡,在我所有的代碼,數據庫, 1072 00:58:28,000 --> 00:58:32,000 讓我們打開的是,gedit的數據庫,看看。 1073 00:58:32,000 --> 00:58:34,000 這不是最性感的文件格式。 1074 00:58:34,000 --> 00:58:38,000 這真的是每行,每行一條數據線, 1075 00:58:38,000 --> 00:58:42,000 但那些你們誰使用Excel或CSV文件,逗號分隔值, 1076 00:58:42,000 --> 00:58:47,000 當然,我可以用fprintf,而不是可能做這樣的事情 1077 00:58:47,000 --> 00:58:50,000 這樣我就可以創建一個Excel文件,相當於 1078 00:58:50,000 --> 00:58:53,000 分離用逗號,不只是新的生產線。 1079 00:58:53,000 --> 00:58:56,000 >> 在這種情況下,如果我,而不是使用逗號,而不是新的生產線 1080 00:58:56,000 --> 00:59:01,000 我可以從字面上如果我在Excel中打開該數據庫文件,而不是看起來像這樣。 1081 00:59:01,000 --> 00:59:03,000 總之,現在我們有能力寫入文件 1082 00:59:03,000 --> 00:59:07,000 我們現在可以開始持久化數據,保持光盤上 1083 00:59:07,000 --> 00:59:10,000 這樣我們就可以保持信息的周圍一遍又一遍。 1084 00:59:10,000 --> 00:59:14,000 注意其他的東西,現在有點熟悉的一對夫婦。 1085 00:59:14,000 --> 00:59:16,000 在這個C文件的頂部,我們有一個typedef 1086 00:59:16,000 --> 00:59:21,000 因為我們想創建一個數據類型,它表示一個字, 1087 00:59:21,000 --> 00:59:25,000 所以這種類型被稱為字,和內部的這種結構 1088 00:59:25,000 --> 00:59:27,000 這是一個小票友。 1089 00:59:27,000 --> 00:59:30,000 為什麼一個字組成的,顯然是一個數組? 1090 00:59:30,000 --> 00:59:33,000 什麼是一個詞,僅僅憑直覺? 1091 00:59:33,000 --> 00:59:35,000 >> 這是一個字符數組。 1092 00:59:35,000 --> 00:59:37,000 這是一個字符序列,背靠背。 1093 00:59:37,000 --> 00:59:41,000 全部大寫的字母恰好是我們武斷地說,最大長度 1094 00:59:41,000 --> 00:59:44,000 任何字在字典中,我們使用的爭奪。 1095 00:59:44,000 --> 00:59:46,000 為什麼我有一個+1? 1096 00:59:46,000 --> 00:59:48,000 空字符。 1097 00:59:48,000 --> 00:59:51,000 記得當我們做了Bananagrams的例子,我們需要一個特殊的值 1098 00:59:51,000 --> 00:59:55,000 的詞語的結尾處,以跟踪 1099 00:59:55,000 --> 00:59:59,000 在的話實際上結束的情況下,作為問題集規範說 1100 00:59:59,000 --> 01:00:03,000 在這裡,我們正在與一個給定的單詞一個布爾值, 1101 01:00:03,000 --> 01:00:05,000 一個標誌,可以這麼說,真或假。 1102 01:00:05,000 --> 01:00:09,000 你有沒有發現這個詞,因為我們意識到 1103 01:00:09,000 --> 01:00:13,000 我們真正需要的一種方式記憶不僅是一個字是在爭奪 1104 01:00:13,000 --> 01:00:15,000 但是否你的人,已經找到了 1105 01:00:15,000 --> 01:00:20,000 所以,如果你發現這個詞“:”你不能只鍵入,進入,進入,進入 1106 01:00:20,000 --> 01:00:23,000 並得到3分,3分,3分,3分。 1107 01:00:23,000 --> 01:00:26,000 我們希望能夠黑名單這個詞通過設置一個布爾值, 1108 01:00:26,000 --> 01:00:29,000 為true,如果你已經發現了,所以這就是為什麼我們 1109 01:00:29,000 --> 01:00:31,000 封裝在該結構中。 1110 01:00:31,000 --> 01:00:35,000 >> 現在,在這裡爭奪,這種結構稱為字典。 1111 01:00:35,000 --> 01:00:39,000 缺少這裡是字的typedef,因為在這種情況下 1112 01:00:39,000 --> 01:00:43,000 我們需要封裝的一本字典的想法, 1113 01:00:43,000 --> 01:00:46,000 和一本字典包含了一大堆的話, 1114 01:00:46,000 --> 01:00:49,000 這個數組所暗示的,和那些話是多少呢? 1115 01:00:49,000 --> 01:00:51,000 好吧,不管說這個變量的大小。 1116 01:00:51,000 --> 01:00:53,000 但我們只需要一個字典。 1117 01:00:53,000 --> 01:00:55,000 我們並不需要的數據類型稱為字典。 1118 01:00:55,000 --> 01:00:58,000 我們只需要其中的一個,所以在C 1119 01:00:58,000 --> 01:01:03,000 如果你不說的typedef,你剛才說的結構,然後在大括號中 1120 01:01:03,000 --> 01:01:05,000 你把你的變量,然後你把這個名字。 1121 01:01:05,000 --> 01:01:09,000 這是聲明一個變量稱為字典 1122 01:01:09,000 --> 01:01:11,000 像這樣的。 1123 01:01:11,000 --> 01:01:16,000 與此相反,這些行調用Word創建一個可重複使用的數據結構 1124 01:01:16,000 --> 01:01:19,000 您可以創建多個副本,就像我們創建 1125 01:01:19,000 --> 01:01:22,000 學生的多個副本。 1126 01:01:22,000 --> 01:01:24,000 >> 這是什麼最終讓我們做什麼? 1127 01:01:24,000 --> 01:01:30,000 讓我回去,比方說,一個簡單的例子,從簡單的時代, 1128 01:01:30,000 --> 01:01:34,000 讓我開了,讓我們說,compare1.c。 1129 01:01:34,000 --> 01:01:38,000 的問題,在這裡實際上是剝開 1130 01:01:38,000 --> 01:01:41,000 層的一個字符串,並開始起飛訓練車輪 1131 01:01:41,000 --> 01:01:44,000 因為它把一個字符串的所有時間 1132 01:01:44,000 --> 01:01:47,000 我們承諾在第1週真的只是一個暱稱, 1133 01:01:47,000 --> 01:01:51,000 CS50庫的東西,看起來多了幾分神秘的代名詞, 1134 01:01:51,000 --> 01:01:53,000 是char *,我們已經看到了這顆恆星。 1135 01:01:53,000 --> 01:01:55,000 我們看到它在文件中。 1136 01:01:55,000 --> 01:01:59,000 >> 現在,讓我們看到為什麼我們一直躲在這個細節有一段時間了。 1137 01:01:59,000 --> 01:02:02,000 這裡是一個名為compare1.c, 1138 01:02:02,000 --> 01:02:07,000 它顯然要求用戶為2個字符串,s和t, 1139 01:02:07,000 --> 01:02:11,000 然後,它試圖比較這些字符串平等的第26行, 1140 01:02:11,000 --> 01:02:14,000 如果他們是平等的說,“你輸入同樣的事情。” 1141 01:02:14,000 --> 01:02:17,000 如果他們不相等,它說,“您輸入不同的事情。” 1142 01:02:17,000 --> 01:02:19,000 讓我繼續運行這個程序。 1143 01:02:19,000 --> 01:02:23,000 讓我進入我的源目錄,做一個比較1。編譯沒問題。 1144 01:02:23,000 --> 01:02:25,000 讓我運行比較。 1145 01:02:25,000 --> 01:02:27,000 我會放大,進入。 1146 01:02:27,000 --> 01:02:29,000 說些什麼。 HELLO。 1147 01:02:29,000 --> 01:02:32,000 我會說些什麼了。 HELLO。 1148 01:02:32,000 --> 01:02:34,000 我絕對沒有輸入不同的東西。 1149 01:02:34,000 --> 01:02:37,000 >> 讓我再試一次。 BYE BYE。 1150 01:02:37,000 --> 01:02:40,000 絕對沒有什麼不同,所以在這裡發生了什麼事? 1151 01:02:40,000 --> 01:02:44,000 那麼,什麼是真正被比較的第26行嗎? 1152 01:02:44,000 --> 01:02:46,000 [聽不見的學生] 1153 01:02:46,000 --> 01:02:49,000 是的,所以它變成了一個字符串,數據類型,是一種善意的謊言。 1154 01:02:49,000 --> 01:02:53,000 一個字符串,是一個char *,但什麼是一個char *? 1155 01:02:53,000 --> 01:02:56,000 ,正如他們所說的,是一個char *指針, 1156 01:02:56,000 --> 01:03:00,000 和一個指針是一個有效的地址, 1157 01:03:00,000 --> 01:03:05,000 一筆在內存中的位置,如果你恰好有輸入一個字,如HELLO, 1158 01:03:05,000 --> 01:03:08,000 回憶起過去的討論中的字符串 1159 01:03:08,000 --> 01:03:16,000 之類的詞,這是HELLO。 1160 01:03:16,000 --> 01:03:19,000 請記住,一個詞可以表示喜歡HELLO 1161 01:03:19,000 --> 01:03:22,000 作為一個字符數組,這樣 1162 01:03:22,000 --> 01:03:25,000 然後用一個特殊字符結束時稱為空字符, 1163 01:03:25,000 --> 01:03:27,000 \表示。 1164 01:03:27,000 --> 01:03:29,000 實際上是一個字符串是什麼? 1165 01:03:29,000 --> 01:03:32,000 請注意,這是多的內存塊, 1166 01:03:32,000 --> 01:03:36,000 而事實上,它的結束是唯一的已知的,一旦你通過整個字符串 1167 01:03:36,000 --> 01:03:38,000 尋找特殊的NULL字符。 1168 01:03:38,000 --> 01:03:41,000 但是,如果這是一個從我的電腦的內存中的內存塊, 1169 01:03:41,000 --> 01:03:44,000 讓我們武斷地說,這個字符串只是很幸運, 1170 01:03:44,000 --> 01:03:47,000 它被認為是放置在開始的時候,我的電腦的RAM。 1171 01:03:47,000 --> 01:03:54,000 這是字節0,1,2,3,4,5,6 ... 1172 01:03:54,000 --> 01:04:02,000 >> 當我說類似的GetString和我做字符串s = GetString的 1173 01:04:02,000 --> 01:04:04,000 什麼是真正的回來了嗎? 1174 01:04:04,000 --> 01:04:08,000 為這些過去的幾個星期,真的被儲存在s 1175 01:04:08,000 --> 01:04:13,000 是不是這個字符串本身,而是在這種情況下,被存儲的是 1176 01:04:13,000 --> 01:04:18,000 因為GetString的確實數0 1177 01:04:18,000 --> 01:04:20,000 它是物理上不返回一個字符串。 1178 01:04:20,000 --> 01:04:22,000 甚至沒有真正概念上的意義。 1179 01:04:22,000 --> 01:04:24,000 它的回報率是多少。 1180 01:04:24,000 --> 01:04:28,000 這個數字是在內存中的地址, 1181 01:04:28,000 --> 01:04:32,000 字符串s,然後,如果我們剝開這層,字符串並不真正存在。 1182 01:04:32,000 --> 01:04:35,000 這只是一個簡化的CS50庫中。 1183 01:04:35,000 --> 01:04:38,000 >> 這真的是所謂的char *。 1184 01:04:38,000 --> 01:04:41,000 字符是有道理的,因為什麼是一個詞,像HELLO? 1185 01:04:41,000 --> 01:04:44,000 嗯,這是一系列的字符,字符系列。 1186 01:04:44,000 --> 01:04:47,000 字符*表示一個字符的地址, 1187 01:04:47,000 --> 01:04:50,000 所以這是什麼意思返回一個字符串? 1188 01:04:50,000 --> 01:04:53,000 一個不錯的,簡單的方法,返回一個字符串, 1189 01:04:53,000 --> 01:04:57,000 而不是試圖找出如何我返回到5或6個不同的字節 1190 01:04:57,000 --> 01:05:01,000 讓我回到哪個字節的地址? 1191 01:05:01,000 --> 01:05:03,000 第一個。 1192 01:05:03,000 --> 01:05:06,000 換句話說,讓我給你一個字符在內存中的地址。 1193 01:05:06,000 --> 01:05:10,000 這就是字符“*”代表一個單一的字符在內存中的地址。 1194 01:05:10,000 --> 01:05:12,000 調用該變量s。 1195 01:05:12,000 --> 01:05:15,000 存放在那個特定的地址,我隨意說的是0, 1196 01:05:15,000 --> 01:05:19,000 只是為了讓事情簡單,但在現實中,它通常是一個比較大的數字。 1197 01:05:19,000 --> 01:05:21,000 >> 等待一分鐘。 1198 01:05:21,000 --> 01:05:23,000 如果你只給我的第一個字符的地址,我怎麼知道的地址是什麼 1199 01:05:23,000 --> 01:05:25,000 第二個字符,第三,第四和第五? 1200 01:05:25,000 --> 01:05:27,000 [聽不見的學生] 1201 01:05:27,000 --> 01:05:31,000 你只知道結尾的字符串的方法是通過這個方便的竅門, 1202 01:05:31,000 --> 01:05:35,000 因此,當你使用的東西像printf,printf的變相作為它的參數, 1203 01:05:35,000 --> 01:05:39,000 還記得我們用%s佔位符,然後你傳遞 1204 01:05:39,000 --> 01:05:41,000 變量的存儲字符串。 1205 01:05:41,000 --> 01:05:47,000 你真正傳遞的是該字符串的第一個字符的地址。 1206 01:05:47,000 --> 01:05:50,000 的printf然後使用for循環或while循環在收到該地址, 1207 01:05:50,000 --> 01:05:53,000 例如,0,所以讓我現在這樣做, 1208 01:05:53,000 --> 01:06:02,000 輸出(“%s \ n”); 1209 01:06:02,000 --> 01:06:07,000 當我調用printf(“%s \ n”);我真正提供輸出與 1210 01:06:07,000 --> 01:06:13,000 在s中的第一個字符的地址,在這種任意的情況下,這是H。 1211 01:06:13,000 --> 01:06:16,000 >> printf的知道如何顯示在屏幕上,究竟是什麼? 1212 01:06:16,000 --> 01:06:19,000 的人誰執行printf的實現了一個while循環或循環 1213 01:06:19,000 --> 01:06:23,000 說這個字符等於空字符? 1214 01:06:23,000 --> 01:06:25,000 如果沒有,打印。這個怎麼樣? 1215 01:06:25,000 --> 01:06:28,000 如果不能打印,打印出來,打印出來,打印出來。 1216 01:06:28,000 --> 01:06:32,000 哦,這是特殊的。停止打印,並返回給用戶。 1217 01:06:32,000 --> 01:06:35,000 這是字面上所有的引擎蓋下發生的, 1218 01:06:35,000 --> 01:06:38,000 這是一個很大消化的第一天,一類, 1219 01:06:38,000 --> 01:06:43,000 但現在它是真正了解一切的基石 1220 01:06:43,000 --> 01:06:46,000 已經持續我們的電腦的內存內的, 1221 01:06:46,000 --> 01:06:49,000 ,最終,我們會逗除了一點點幫助 1222 01:06:49,000 --> 01:06:51,000 我們的一個朋友在斯坦福大學。 1223 01:06:51,000 --> 01:06:56,000 >> 在斯坦福大學的教授尼克Parlante已經這樣做了精彩的視頻序列 1224 01:06:56,000 --> 01:06:58,000 從各種不同的語言,介紹 1225 01:06:58,000 --> 01:07:00,000 這個小的黏土動畫人物Binky。 1226 01:07:00,000 --> 01:07:03,000 你的聲音,聽到在短短的幾秒鐘先睹為快 1227 01:07:03,000 --> 01:07:05,000 是斯坦福大學教授,你要 1228 01:07:05,000 --> 01:07:07,000 現在只有5或6秒的這一權利, 1229 01:07:07,000 --> 01:07:09,000 但是這是說明我們將結束今天 1230 01:07:09,000 --> 01:07:11,000 (星期三)開始。 1231 01:07:11,000 --> 01:07:15,000 我給你賓基,預覽的指針樂趣。 1232 01:07:15,000 --> 01:07:18,000 [♪音樂♪]教授Parlante]嘿,賓基。 1233 01:07:18,000 --> 01:07:21,000 喚醒。它的時間的指針樂趣。 1234 01:07:21,000 --> 01:07:24,000 [賓基]那是什麼?了解指針嗎? 1235 01:07:24,000 --> 01:07:26,000 哦,好極了! 1236 01:07:26,000 --> 01:07:29,000 >> 我們將看到你在週三。 1237 01:07:29,000 --> 01:07:32,000 [CS50.TV]