1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [第5條 - 更舒適] 2 00:00:02,500 --> 00:00:04,690 [羅布·鮑登 - 哈佛大學] 3 00:00:04,690 --> 00:00:07,250 [這是CS50。 - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> 就像我在我的電子郵件中說,有很多的東西,你可以使用 5 00:00:14,250 --> 00:00:17,060 其他比設備實際做的習題集。 6 00:00:17,060 --> 00:00:19,910 我們建議你這樣做只是因為它在家電,那麼我們就可以更容易地幫助您 7 00:00:19,910 --> 00:00:22,070 我們知道如何去上班。 8 00:00:22,070 --> 00:00:26,950 但是,作為一個例子,你可以做的事情,如果說,你不能夠訪問 9 00:00:26,950 --> 00:00:31,570 的設備或您要在科學中心地下室 - 10 00:00:31,570 --> 00:00:33,090 其實他們有設備 - 11 00:00:33,090 --> 00:00:35,150 如果你想在任何地方工作。 12 00:00:35,150 --> 00:00:42,370 一個例子是,你看到/聽到的SSH? 13 00:00:44,380 --> 00:00:47,780 SSH是基本上是一樣的東西連接。 14 00:00:47,780 --> 00:00:51,340 其實,現在我SSHed插入設備。 15 00:00:51,340 --> 00:00:54,290 我從來沒有直接在產品中。 16 00:00:55,930 --> 00:01:01,060 這裡是家電,如果你看這裡,你看到這個IP地址。 17 00:01:01,060 --> 00:01:03,650 我從來沒有在設備本身; 18 00:01:03,650 --> 00:01:08,840 我總是iTerm2窗口/終端窗口。 19 00:01:08,840 --> 00:01:15,910 可以SSH到的IP地址,SSH jharvard@192.168.129.128。 20 00:01:15,910 --> 00:01:20,390 我記得這個數字很容易,因為它是一個很好的模式。 21 00:01:20,390 --> 00:01:24,920 但是,這將問我,我的密碼,現在我在家電。 22 00:01:24,920 --> 00:01:33,060 基本上,在這一點上,如果打開了一個終端設備本身的內部, 23 00:01:33,060 --> 00:01:36,350 這個接口,但是你會使用它,是完全一樣的 24 00:01:36,350 --> 00:01:40,010 使用的接口,我在這裡,但現在你SSHed。 25 00:01:42,240 --> 00:01:44,920 你沒有SSH的設備。 26 00:01:44,920 --> 00:01:52,360 我敢肯定,你必須在默認情況下,另一個地方,你可以SSH是一個例子 - 27 00:01:52,360 --> 00:01:55,020 哦。更大。 28 00:01:55,020 --> 00:02:01,130 所有的人都應該有默認情況下,FAS FAS服務器的帳戶。 29 00:02:01,130 --> 00:02:06,840 對於我來說,我會SSH的rbowden@nice.fas.harvard.edu。 30 00:02:06,840 --> 00:02:11,610 它會問你的第一次,和你說的話。 31 00:02:11,610 --> 00:02:15,840 我的密碼,只是將我的FAS密碼。 32 00:02:15,840 --> 00:02:22,650 所以現在,我SSHed漂亮的服務器,和我想在這裡,我可以做任何事情。 33 00:02:22,650 --> 00:02:28,560 很多類,你可能需要像124,有你上傳的東西在這裡 34 00:02:28,560 --> 00:02:30,950 提交您的問題集。 35 00:02:30,950 --> 00:02:34,100 但說你沒有訪問您的設備。 36 00:02:34,100 --> 00:02:37,910 然後你就可以像在這裡做的事情,它會說 - 37 00:02:37,910 --> 00:02:42,160 這僅僅是我們部分的問題。 38 00:02:42,160 --> 00:02:45,070 它會問你做到這一點的設備。 39 00:02:45,070 --> 00:02:47,790 相反,我會做它的服務器上。 40 00:02:47,790 --> 00:02:50,560 我要解壓縮。 41 00:02:50,560 --> 00:02:55,670 這個問題將是你已經習慣了使用的東西,例如gedit 42 00:02:55,670 --> 00:02:58,160 或其他組件內。 43 00:02:58,160 --> 00:03:01,830 你不會的FAS服務器上。 44 00:03:01,830 --> 00:03:04,110 這一切都只是將這個文本界面。 45 00:03:04,110 --> 00:03:09,180 所以,你可以任何一個,努力學習,他們有一個文本編輯器。 46 00:03:09,180 --> 00:03:12,130 他們有納米。 47 00:03:12,130 --> 00:03:14,990 納米通常是很容易使用。 48 00:03:14,990 --> 00:03:19,470 您可以使用箭頭,然後鍵入正常。 49 00:03:19,470 --> 00:03:21,250 因此,並不難。 50 00:03:21,250 --> 00:03:24,720 如果你想獲得真正看中的,你可以使用Emacs, 51 00:03:24,720 --> 00:03:29,850 我也許不應該打開了,因為我什至不知道如何關閉Emacs的。 52 00:03:29,850 --> 00:03:32,760 控制X,控制C?是啊。 53 00:03:32,760 --> 00:03:35,310 或者你也可以使用vim,這是我使用。 54 00:03:35,310 --> 00:03:37,800 所以這些都是你的選擇。 55 00:03:37,800 --> 00:03:43,830 如果你不想這樣做,你也可以,如果你manual.cs50.net - 56 00:03:43,830 --> 00:03:45,410 哦。 57 00:03:45,410 --> 00:03:49,920 在PC上,你可以使用SSH使用PuTTY 58 00:03:49,920 --> 00:03:51,940 你要單獨下載。 59 00:03:51,940 --> 00:03:55,460 在Mac上,你可以在默認情況下使用的終端或你可以下載iTerm2, 60 00:03:55,460 --> 00:03:58,490 這是一個很好的,看中的終端。 61 00:03:58,490 --> 00:04:03,780 如果你去到manual.cs50.net,你會看到一個鏈接到記事本+ +, 62 00:04:03,780 --> 00:04:07,120 這是你可以在PC上使用。 63 00:04:07,120 --> 00:04:13,340 它可以讓你SFTP從記事本+ +,這基本上是SSH。 64 00:04:13,340 --> 00:04:17,750 這是什麼讓你這樣做是在本地編輯您的文件, 65 00:04:17,750 --> 00:04:20,670 然後,每當你想將它們保存,它會保存到nice.fas中, 66 00:04:20,670 --> 00:04:23,670 然後,你可以運行它們。 67 00:04:23,670 --> 00:04:26,880 在Mac上相當於將是TextWrangler。 68 00:04:26,880 --> 00:04:28,760 因此,它可以讓你做同樣的事情。 69 00:04:28,760 --> 00:04:32,800 它可以讓你在本地編輯文件,將它們保存到nice.fas, 70 00:04:32,800 --> 00:04:35,730 然後,你可以運行它們。 71 00:04:35,730 --> 00:04:40,400 所以,如果你遇到難題沒有設備,你有這些選項 72 00:04:40,400 --> 00:04:44,230 還是做你的問題集。 73 00:04:44,230 --> 00:04:48,250 一個問題是,你不會有CS50庫 74 00:04:48,250 --> 00:04:51,580 因為nice.fas默認情況下,不具備這一點。 75 00:04:51,580 --> 00:04:55,970 您可以下載的CS50庫 - 76 00:04:55,970 --> 00:04:58,470 我不認為我需要在這一點上。 77 00:04:58,470 --> 00:05:03,270 你可以下載的的CS50庫和複製到nice.fas, 78 00:05:03,270 --> 00:05:07,450 我認為在這一點上,我們不使用它了呢。 79 00:05:07,450 --> 00:05:12,720 或者,如果我們這樣做,你的時間可以被取代它 80 00:05:12,720 --> 00:05:18,480 反正的CS50庫中的功能的實現。 81 00:05:18,480 --> 00:05:21,370 因此,不應該有那麼多的限制。 82 00:05:21,370 --> 00:05:23,710 就是這樣。 83 00:05:26,460 --> 00:05:29,820 >> 我會回去的設備,現在我們將盡一切設備。 84 00:05:29,820 --> 00:05:37,510 我們的部分問題,在開始的時候,就像我在我的電子郵件中說, 85 00:05:37,510 --> 00:05:43,620 我們要談一個短你應該看。 86 00:05:43,620 --> 00:05:51,980 我們有重定向和管道這三個問題。 87 00:05:51,980 --> 00:05:56,070 >> 在這流功能,如輸出默認情況下寫的? 88 00:05:56,070 --> 00:05:59,130 所以流。什麼是流? 89 00:06:06,520 --> 00:06:15,100 甲流是基本上一樣,只是一些 - 90 00:06:15,100 --> 00:06:21,450 它甚至不是一個源1s和0s。 91 00:06:21,450 --> 00:06:24,920 這裡要求的是標準輸出流。 92 00:06:24,920 --> 00:06:27,250 因此,標準輸出流,當你寫它, 93 00:06:27,250 --> 00:06:30,940 它出現在屏幕上。 94 00:06:30,940 --> 00:06:36,860 標準輸出流,這意味著你只寫1“和”0“到它, 95 00:06:36,860 --> 00:06:40,220 標準輸出的另一端從該流中讀取數據。 96 00:06:40,220 --> 00:06:43,540 這只是一個字符串1s和0s。 97 00:06:43,540 --> 00:06:45,570 你可以寫流,或者你可以從數據流中讀取 98 00:06:45,570 --> 00:06:47,950 根據流實際上是什麼。 99 00:06:47,950 --> 00:06:52,800 其他兩個默認流的標準和標準錯誤。 100 00:06:52,800 --> 00:06:57,540 標準的是每當你的GetString,它正在等待你輸入的東西。 101 00:06:57,540 --> 00:07:01,570 因此,它在等著你,它實際上是在等待標準, 102 00:07:01,570 --> 00:07:04,880 這是真的,你會得到什麼,當你在鍵盤上輸入。 103 00:07:04,880 --> 00:07:07,530 你輸入標準英寸 104 00:07:07,530 --> 00:07:10,050 標準錯誤是基本上等同於標準輸出, 105 00:07:10,050 --> 00:07:13,280 但它的專業,當您打印到標準錯誤, 106 00:07:13,280 --> 00:07:16,770 你應該只打印錯誤消息,該 107 00:07:16,770 --> 00:07:20,200 這樣你就可以區分常規消息打印到屏幕上 108 00:07:20,200 --> 00:07:24,560 對誤差取決於他們是否去到標準輸出和標準錯誤的消息。 109 00:07:24,560 --> 00:07:28,660 文件了。 110 00:07:28,660 --> 00:07:32,440 標準輸出,標準和標準錯誤是特別的流, 111 00:07:32,440 --> 00:07:36,810 但實際上任何文件,當你打開一個文件時,它變成一個字節流 112 00:07:36,810 --> 00:07:40,740 在那裡你可以從該流中讀取。 113 00:07:40,740 --> 00:07:47,770 您,在大多數情況下,只是覺得一個文件的字節流。 114 00:07:47,770 --> 00:07:51,190 所以他們寫什麼流在默認情況下?標準輸出。 115 00:07:51,190 --> 00:07:56,980 >> >和>>之間的區別是什麼? 116 00:07:58,140 --> 00:08:03,710 沒有人事先觀看視頻?好吧。 117 00:08:03,710 --> 00:08:10,960 >將是如何重定向到文件, 118 00:08:10,960 --> 00:08:15,240 >>也將輸出重定向到文件中, 119 00:08:15,240 --> 00:08:17,820 但它的,而不是要追加到文件。 120 00:08:17,820 --> 00:08:23,430 例如,讓我們說,我正好有字典在這裡, 121 00:08:23,430 --> 00:08:27,020 唯一的字典裡面的東西是貓,貓,狗,魚,狗。 122 00:08:27,020 --> 00:08:31,530 一個命令,你必須在命令行是貓, 123 00:08:31,530 --> 00:08:34,539 只是要打印在一個文件中。 124 00:08:34,539 --> 00:08:40,679 所以當我說貓字典,它要打印的貓,貓,狗,魚,狗。這是所有的貓做。 125 00:08:40,679 --> 00:08:46,280 這意味著,貓,貓,狗,魚,狗,它打印到標準輸出。 126 00:08:46,280 --> 00:08:53,240 如果我不是要重定向到一個文件中,我可以使用>將它重定向到任何該文件是。 127 00:08:53,240 --> 00:08:56,460 我會打電話給該文件的文件。 128 00:08:56,460 --> 00:09:00,320 所以,現在如果我LS,我會看到我有一個新的文件名為文件。 129 00:09:00,320 --> 00:09:05,700 如果我打開它,它將會有什麼貓放在命令行。 130 00:09:05,700 --> 00:09:11,040 所以,現在如果我這樣做了,那麼它的輸出重定向到文件, 131 00:09:11,040 --> 00:09:13,930 和我有同樣的事情。 132 00:09:13,930 --> 00:09:17,910 所以,從技術上來說,它完全推翻了我們什麼。 133 00:09:17,910 --> 00:09:22,970 我們會看到,如果我改變了字典,我拿出狗。 134 00:09:22,970 --> 00:09:29,980 現在,如果我們貓詞典到文件中,我們將有新的版本與狗刪除。 135 00:09:29,980 --> 00:09:32,400 因此,它完全覆蓋。 136 00:09:32,400 --> 00:09:36,640 相反,如果我們使用“>>”,這是怎麼回事追加文件。 137 00:09:36,640 --> 00:09:40,860 現在,打開文件,我們可以看到,我們有同樣的事情兩次印刷 138 00:09:40,860 --> 00:09:44,920 有一次,因為它是,那麼我們就追加到原來的。 139 00:09:44,920 --> 00:09:48,130 所以,這就是>和>>。 140 00:09:48,130 --> 00:09:50,580 請問下一個要求 - 它不要求它。 141 00:09:50,580 --> 00:09:59,050 >> 我們有另一種是<,如果標準輸出重定向, 142 00:09:59,050 --> 00:10:01,970 <將被重定向標準英寸 143 00:10:01,970 --> 00:10:12,050 讓我們來看看,如果我們有一個例子。 144 00:10:14,750 --> 00:10:16,930 我可以寫一個真正的快速。 145 00:10:17,870 --> 00:10:25,700 讓我們任何文件hello.c。 146 00:10:56,060 --> 00:10:59,070 相對直截了當文件。 147 00:10:59,070 --> 00:11:03,570 我只是一個字符串,然後打印“Hello”無論我剛剛輸入的字符串是。 148 00:11:03,570 --> 00:11:07,990 因此,請hello,然後。/個招呼。 149 00:11:07,990 --> 00:11:10,720 現在,它提示我輸入的東西, 150 00:11:10,720 --> 00:11:15,070 這意味著它等待的東西,將予訂立標準英寸 151 00:11:15,070 --> 00:11:20,450 因此,進入任何我想要的標準。我們要好好說“你好”,羅布! 152 00:11:20,450 --> 00:11:23,310 然後打印到標準輸出您好,來搶! 153 00:11:23,310 --> 00:11:28,860 如果我這樣做。/ hello,然後重定向, 154 00:11:30,740 --> 00:11:34,310 現在你可以只從一個文件重定向。 155 00:11:34,310 --> 00:11:41,720 所以,如果我把一些文件,TXT,我把羅布, 156 00:11:41,720 --> 00:11:52,300 如果我跑個招呼,然後重定向到的文件文本。/打招呼,它會說“你好”,搶!立即。 157 00:11:52,300 --> 00:11:57,160 當它第一次得到的GetString和它的等待標準, 158 00:11:57,160 --> 00:12:01,730 標準中不再等待鍵盤上的數據,從而得到進入。 159 00:12:01,730 --> 00:12:05,980 相反,我們從文件中讀取TXT重定向標準。 160 00:12:05,980 --> 00:12:10,290 因此,它會讀取TXT的文件,這僅僅是行搶, 161 00:12:10,290 --> 00:12:13,380 那麼它會打印Hello,羅布! 162 00:12:13,380 --> 00:12:18,180 如果我想,我也可以做。/你好TXT 163 00:12:18,180 --> 00:12:21,500 然後指出它的標準印刷,您好,這是來搶! 164 00:12:21,500 --> 00:12:24,700 我可以重定向到它自己的文件。 165 00:12:24,700 --> 00:12:29,790 我只需要調用的文件招呼 - 不,我不會,因為這是可執行文件 - txt2。 166 00:12:29,790 --> 00:12:40,150 現在,,txt2是要輸出/你好 00:12:43,520 >> 有問題嗎? 168 00:12:45,900 --> 00:12:49,090 >> 好吧。那麼在這裡,我們有管道。 169 00:12:49,090 --> 00:12:53,510 管道的最後一個單元的重定向。 170 00:12:53,510 --> 00:12:58,750 >> 哦。我想一個單位的重定向,如果不是你2>, 171 00:12:58,750 --> 00:13:01,070 重定向標準錯誤。 172 00:13:01,070 --> 00:13:06,280 因此,如果發生了標準錯誤,它會不會被投入txt2。 173 00:13:06,280 --> 00:13:12,480 但是請注意,如果我這樣做2>,然後它仍然印刷您好,來搶!在命令行 174 00:13:12,480 --> 00:13:18,600 因為我只重定向標準錯誤,我不重定向標準輸出。 175 00:13:18,600 --> 00:13:22,210 標準錯誤和標準輸出是不同的。 176 00:13:24,210 --> 00:13:27,080 如果你想真正寫入到標準錯誤, 177 00:13:27,080 --> 00:13:35,080 然後我可以改變這是fprintf到stderr。 178 00:13:35,080 --> 00:13:37,850 所以,默認情況下,打印輸出到標準輸出。 179 00:13:37,850 --> 00:13:41,720 如果我想手動打印到標準錯誤,那麼我必須使用fprintf 180 00:13:41,720 --> 00:13:45,010 並指定我要打印到的。 181 00:13:45,010 --> 00:13:49,720 相反,如果我做了fprintf標準輸出,那麼這基本上等同於printf的。 182 00:13:49,720 --> 00:13:55,530 ,但fprintf標準錯誤。 183 00:13:57,790 --> 00:14:03,650 所以,現在,如果我重定向到txt2,您好,來搶!還是會被印在命令行 184 00:14:03,650 --> 00:14:08,270 ,因為它的打印到標準錯誤,我只重定向標準輸出。 185 00:14:08,270 --> 00:14:16,420 如果我現在將標準錯誤重定向,現在也沒有打印出來,和txt2將是你好,搶! 186 00:14:16,420 --> 00:14:21,910 那麼現在,你可以打印你的實際標準錯誤的錯誤 187 00:14:21,910 --> 00:14:24,720 打印您的的常規郵件到標準輸出。 188 00:14:24,720 --> 00:14:31,420 所以當你運行你的程序,你可以運行它。/您好,這類型的2> 189 00:14:31,420 --> 00:14:33,800 讓你的程序將正常運行, 190 00:14:33,800 --> 00:14:38,400 但任何錯誤消息,讓你可以檢查你的錯誤日誌中, 191 00:14:38,400 --> 00:14:44,500 這樣的錯誤,然後看後,你的錯誤,文件中有任何錯誤發生。 192 00:14:45,200 --> 00:14:47,540 >> 有問題嗎? 193 00:14:47,540 --> 00:14:58,070 >> 最後一個是管道,你能想到的,所承擔的標準,從一個命令 194 00:14:58,070 --> 00:15:01,210 和它的標準中的下一個命令。 195 00:15:01,210 --> 00:15:05,570 這裡是一個例子,echo是一個命令行的東西 196 00:15:05,570 --> 00:15:11,840 這只是呼應,我把什麼作為它的參數。我不會把引號。 197 00:15:11,840 --> 00:15:16,150 回音胡說,胡說,胡說,只是要打印等等,等等,等等。 198 00:15:16,150 --> 00:15:20,600 在此之前,當我說,我只好把羅布到一個txt文件 199 00:15:20,600 --> 00:15:28,830 因為我只能重定向txt文件,而不是,/如果我呼應羅布 200 00:15:28,830 --> 00:15:35,520 然後通過管道到/個招呼,這也將做同樣類型的東西。 201 00:15:35,520 --> 00:15:39,160 這是此命令的輸出,迴聲羅布, 202 00:15:39,160 --> 00:15:43,610 並用它作為輸入/個招呼。 203 00:15:44,790 --> 00:15:49,560 你可以認為它是第一個到一個文件重定向迴聲羅布 204 00:15:49,560 --> 00:15:54,160 ,然後輸入/你好,文件只是輸出。 205 00:15:54,160 --> 00:15:57,850 但它需要的臨時文件的圖片。 206 00:16:01,890 --> 00:16:04,460 >> 該問題嗎? 207 00:16:04,460 --> 00:16:07,150 >> 接下來的問題是會涉及到這一點。 208 00:16:07,150 --> 00:16:15,310 管道,你可以用它來尋找一個稱為names.txt的文件的唯一名稱是什麼? 209 00:16:15,310 --> 00:16:24,160 ,我們將要在這裡使用的命令是唯一的,因此uniq中,然後廁所。 210 00:16:24,160 --> 00:16:28,840 你可以做男人的uniq的實際看是什麼做的, 211 00:16:28,840 --> 00:16:34,840 它只是將篩選相鄰的匹配行從輸入。 212 00:16:34,840 --> 00:16:40,690 男子廁所是要打印的換行,字和字節計數的每個文件。 213 00:16:40,690 --> 00:16:43,760 我們將要使用的是最後一個排序, 214 00:16:43,760 --> 00:16:47,410 這是怎麼回事,只是txt文件的行進行排序。 215 00:16:47,410 --> 00:16:58,080 如果我做一些txt文件,的names.txt,它的羅布,張宇,約瑟夫,張宇,約瑟夫,RJ,羅布, 216 00:16:58,080 --> 00:17:03,910 我想在這裡做什麼的,是在這個文件中找到的唯一名稱。 217 00:17:03,910 --> 00:17:08,750 那麼應該怎樣的答案呢? >> [學生] 4。 >>呀。 218 00:17:08,750 --> 00:17:13,780 它應該是4,因為羅布,湯米,約瑟夫,RJ是在這個文件中只有唯一的名稱。 219 00:17:13,780 --> 00:17:20,180 第一步,如果我只是做的字數的names.txt, 220 00:17:20,180 --> 00:17:24,290 這實際上是告訴了我一切。 221 00:17:24,290 --> 00:17:32,560 其實,這是印刷 - 讓我們來看看,男人WC - 換行,單詞和字節計數。 222 00:17:32,560 --> 00:17:38,270 如果我只在乎線,然後我就可以做WC-L names.txt。 223 00:17:41,730 --> 00:17:44,300 所以這是第1步。 224 00:17:44,300 --> 00:17:50,510 但我不希望到廁所 - 1 names.txt,因為names.txt只包含了所有的名字, 225 00:17:50,510 --> 00:17:54,170 我要過濾掉任何非唯一的。 226 00:17:54,170 --> 00:18:01,200 所以,如果我做的uniq names.txt,不很給我我想要的 227 00:18:01,200 --> 00:18:03,760 因為重複的名稱仍然存在。 228 00:18:03,760 --> 00:18:07,690 這是為什麼? uniq的是為什麼不這樣做我想要什麼? 229 00:18:07,690 --> 00:18:10,500 [學生]重複[聽不清] >>呀。 230 00:18:10,500 --> 00:18:16,370 記住的uniq手冊頁說,過濾器相鄰的匹配行。 231 00:18:16,370 --> 00:18:19,680 他們是不相鄰的,所以它不會過濾。 232 00:18:19,680 --> 00:18:31,100 如果我先對它們進行排序,排序names.txt是打算把所有重複的行。 233 00:18:31,100 --> 00:18:34,450 所以,現在排序names.txt是。 234 00:18:34,450 --> 00:18:40,550 我將要使用的uniq的,這是| uniq的輸入。 235 00:18:40,550 --> 00:18:43,390 這給了我約瑟夫,RJ,搶奪,湯米, 236 00:18:43,390 --> 00:18:49,260 我想使用這個輸入到wc-L, 237 00:18:49,260 --> 00:18:52,740 這是要給我4。 238 00:18:52,740 --> 00:18:56,930 喜歡它說,在這裡,你可以使用什麼樣的管道? 239 00:18:56,930 --> 00:19:01,390 你可以做很多的事情,比如使用一系列的命令 240 00:19:01,390 --> 00:19:05,130 在您使用一個命令的輸出作為下一個命令的輸入。 241 00:19:05,130 --> 00:19:08,780 你可以做很多事情,很多聰明的事情。 242 00:19:08,780 --> 00:19:11,440 >> 有問題嗎? 243 00:19:12,910 --> 00:19:14,600 好吧。 244 00:19:14,600 --> 00:19:17,880 這是它的管道和重定向。 245 00:19:18,370 --> 00:19:24,090 >> 現在我們的實際的東西,編碼的東西。 246 00:19:24,090 --> 00:19:29,100 本PDF裡面,你會看到這個命令, 247 00:19:29,100 --> 00:19:32,950 你要運行此命令在您的設備。 248 00:19:36,240 --> 00:19:42,250 wget是命令只是從互聯網上得到的東西,基本上, 249 00:19:42,250 --> 00:19:45,180 所以wget和URL。 250 00:19:45,180 --> 00:19:49,110 如果你到這個URL在瀏覽器中,它會下載該文件。 251 00:19:49,110 --> 00:19:52,510 我只是點擊就可以了,所以對我來說,它下載的文件。 252 00:19:52,510 --> 00:19:55,650 但是,寫的那個東西的wget內的終端 253 00:19:55,650 --> 00:19:58,620 只是要下載到您的終端。 254 00:19:58,620 --> 00:20:02,750 我有section5.zip的,和你要解壓section5.zip的, 255 00:20:02,750 --> 00:20:06,520 這是給你一個文件夾,名為第5章, 256 00:20:06,520 --> 00:20:11,550 這是我們要使用它裡面的所有的文件。 257 00:20:33,380 --> 00:20:37,710 隨著這些項目的文件名稱所暗示的,他們是一個有點缺陷, 258 00:20:37,710 --> 00:20:40,990 所以,你的任務是要弄清楚為什麼使用gdb。 259 00:20:40,990 --> 00:20:44,560 每個人都有他們下載/知道如何讓他們下載 260 00:20:44,560 --> 00:20:47,480 設備到他們的嗎?好吧。 261 00:20:47,480 --> 00:20:56,400 >> 運行./buggy1,它會說分割故障(核心轉儲) 262 00:20:56,400 --> 00:21:00,500 任何時候你得到一個segfault,這是一個不好的事情。 263 00:21:00,500 --> 00:21:03,810 在什麼情況下,你得到一個segfault? 264 00:21:03,810 --> 00:21:08,210 [學生]:取消引用一個空指針。 >>呀。所以這是一個例子。 265 00:21:08,210 --> 00:21:11,580 解引用一個空指針,你會得到一個segfault。 266 00:21:11,580 --> 00:21:16,720 一個segfault手段是你感動的回憶,你不應該接觸。 267 00:21:16,720 --> 00:21:21,350 因此,釋放空指針動人的地址為0, 268 00:21:21,350 --> 00:21:28,060 基本上,現在所有的電腦說,地址為0的內存,你不應該接觸。 269 00:21:28,060 --> 00:21:31,920 所以這就是為什麼一個空指針解引用一個segfault。 270 00:21:31,920 --> 00:21:37,210 當你的事發生在初始化的指針,那麼它有一個垃圾值, 271 00:21:37,210 --> 00:21:41,520 因此,當您嘗試取消引用它,在所有的可能性你感動的回憶 272 00:21:41,520 --> 00:21:43,540 這是在中間的地方。 273 00:21:43,540 --> 00:21:45,650 如果你碰巧很幸運,垃圾的價值 274 00:21:45,650 --> 00:21:48,440 發生點在堆棧上或東西的地方, 275 00:21:48,440 --> 00:21:50,820 那麼當你解引用指針,你還沒有初始化, 276 00:21:50,820 --> 00:21:52,730 什麼都不會出問題。 277 00:21:52,730 --> 00:21:55,480 但是,如果它指向的棧和堆之間的某個地方,說, 278 00:21:55,480 --> 00:21:59,850 它指向只是到別的地方,沒有被使用你的程序, 279 00:21:59,850 --> 00:22:02,240 那麼你感動的回憶,你不應該接觸和你的段錯誤。 280 00:22:02,240 --> 00:22:06,370 當你寫一個遞歸函數,遞歸太多次 281 00:22:06,370 --> 00:22:08,720 堆棧的增長過大,堆棧碰撞到的東西 282 00:22:08,720 --> 00:22:12,270 它不應該被碰撞,你感動的回憶,你不應該接觸, 283 00:22:12,270 --> 00:22:14,810 因此你段錯誤。 284 00:22:14,810 --> 00:22:17,010 這是一個segfault。 285 00:22:17,010 --> 00:22:21,810 >> 這是同樣的道理,如果你有這樣的字符串 - 286 00:22:21,810 --> 00:22:23,930 讓我們回到前面的程序。 287 00:22:23,930 --> 00:22:28,530 在hello.c的,我只是要別的東西。 288 00:22:28,530 --> 00:22:33,770 的char * s =“世界你好!”; 289 00:22:33,770 --> 00:22:42,310 如果我使用的東西或S * S = [0] ='X'; 290 00:22:42,310 --> 00:22:47,290 所以一定要打招呼,/你好,為什麼是段錯誤? 291 00:22:48,410 --> 00:22:51,250 為什麼這個段錯誤呢? 292 00:22:55,660 --> 00:22:57,890 你會想到什麼事情發生呢? 293 00:22:57,890 --> 00:23:06,640 如果我做了printf的(“%s \ n”);你會想到要打印的嗎? 294 00:23:06,640 --> 00:23:09,930 [學生] X打招呼。 >>呀。 295 00:23:09,930 --> 00:23:15,140 現在的問題是,當你聲明一個這樣的字符串, 296 00:23:15,140 --> 00:23:18,190 s是一個指針,要在棧上, 297 00:23:18,190 --> 00:23:25,880 什麼s指向的是這個字符串包含在只讀存儲器。 298 00:23:25,880 --> 00:23:30,560 因此,只要名稱,只讀存儲器,你應該得到的想法 299 00:23:30,560 --> 00:23:33,010 如果你試圖改變什麼只讀存儲器, 300 00:23:33,010 --> 00:23:36,670 你正在做的事情你不應該做的內存和段錯誤。 301 00:23:36,670 --> 00:23:45,360 這實際上是一個很大的區別的char *和char []。 302 00:23:45,360 --> 00:23:48,790 所以個char [],現在這個字符串將被放在堆棧中, 303 00:23:48,790 --> 00:23:53,960 且堆棧無法讀取,這意味著,這應該工作完全正常。 304 00:23:55,500 --> 00:23:57,370 它。 305 00:23:57,370 --> 00:24:06,250 請記住,當我這樣做的char * s =“世界你好!”,S本身是在棧上 306 00:24:06,250 --> 00:24:10,390 但s指向其他地方,其他地方恰好是只讀。 307 00:24:10,390 --> 00:24:15,640 但個char []是在棧上的東西。 308 00:24:17,560 --> 00:24:21,760 所以這是一個segfault發生的另一個例子。 309 00:24:21,760 --> 00:24:27,820 >> ,我們看到./buggy1導致一個segfault。 310 00:24:27,820 --> 00:24:31,810 從理論上講,你不應該看buggy1.c立即。 311 00:24:31,810 --> 00:24:35,170 相反,我們將看看它通過gdb的。 312 00:24:35,170 --> 00:24:37,750 請注意,當你得到分割故障(核心轉儲), 313 00:24:37,750 --> 00:24:40,850 你得到這個文件,這裡所說的核心。 314 00:24:40,850 --> 00:24:45,200 如果我們的ls-l,我們可以看到,核心通常是一個相當大的文件。 315 00:24:45,200 --> 00:24:51,580 這是該文件的字節數,所以它看起來像它的250歲的千字節為單位。 316 00:24:51,580 --> 00:24:56,120 這樣做的原因是什麼實際上是核心轉儲 317 00:24:56,120 --> 00:25:01,410 是當你的程序崩潰時,你的程序的內存狀態 318 00:25:01,410 --> 00:25:05,230 剛剛被複製,並粘貼到該文件中。 319 00:25:05,230 --> 00:25:07,270 它被傾倒到該文件中。 320 00:25:07,270 --> 00:25:13,060 這個程序,運行時,正巧有一個約250千字節的內存使用情況, 321 00:25:13,060 --> 00:25:17,040 所以這是什麼得到了傾入這個文件。 322 00:25:17,040 --> 00:25:23,630 現在,你可以看一下該文件,如果我們做GDB buggy1核心。 323 00:25:23,630 --> 00:25:30,130 我們可以做gdb的buggy1,將只啟動gdb的定期, 324 00:25:30,130 --> 00:25:33,800 使用buggy1作為它的輸入文件。 325 00:25:33,800 --> 00:25:38,260 但是,如果你GDB buggy1的核心,那麼它明確要啟動GDB 326 00:25:38,260 --> 00:25:40,330 看,核心文件。 327 00:25:40,330 --> 00:25:45,560 你說buggy1手段gdb的都知道,該核心文件來從buggy1程序,。 328 00:25:45,560 --> 00:25:49,580 GDB buggy1核心是要立即給我們帶來 329 00:25:49,580 --> 00:25:52,060 的地方發生的程序終止。 330 00:25:57,720 --> 00:26:02,340 我們在這裡看到的信號,分割故障終止程序。 331 00:26:02,340 --> 00:26:10,110 我們碰巧看到的組裝線,這可能是非常有幫助的。 332 00:26:10,110 --> 00:26:15,360 但是,如果你鍵入BT或回溯,這將是功能 333 00:26:15,360 --> 00:26:19,430 這樣,就為我們提供了我們當前的堆棧幀的列表。 334 00:26:19,430 --> 00:26:23,150 所以回溯。它看起來像我們只有兩個堆棧幀。 335 00:26:23,150 --> 00:26:26,310 首先是我們的主要的堆棧幀, 336 00:26:26,310 --> 00:26:29,810 第二個是,我們正好是在這個函數的堆棧幀, 337 00:26:29,810 --> 00:26:34,440 看起來我們只需要的彙編代碼。 338 00:26:34,440 --> 00:26:38,050 所以,讓我們回到我們的主要功能, 339 00:26:38,050 --> 00:26:42,300 做到這一點,我們可以做的第1幀,我覺得我們也可以做下來, 340 00:26:42,300 --> 00:26:45,160 但我幾乎從來沒有辦下來 - 或上升。是啊。 341 00:26:45,160 --> 00:26:50,710 向上和向下。最多給你帶來一個堆棧幀,同比下降給你帶來了一個堆棧幀。 342 00:26:50,710 --> 00:26:53,240 我傾向於從來沒有使用它。 343 00:26:53,240 --> 00:26:59,120 我只是具體說,這是去的幀標記為1的第1幀。 344 00:26:59,120 --> 00:27:01,750 第1幀,將要帶給我們的到主堆棧幀, 345 00:27:01,750 --> 00:27:05,570 在這裡,它說發生在我們的代碼行。 346 00:27:05,570 --> 00:27:07,950 如果我們想要一對夫婦更行代碼列表,我們可以說, 347 00:27:07,950 --> 00:27:11,280 而這會給我們周圍所有的代碼行。 348 00:27:11,280 --> 00:27:13,360 我們segfaulted該生產線為6: 349 00:27:13,360 --> 00:27:17,360 (STRCMP(“CS50石頭”,ARGV [1])== 0)。 350 00:27:17,360 --> 00:27:24,130 如果沒有明顯的是,你可以得到它直接從這裡只是想,為什麼segfaulted。 351 00:27:24,130 --> 00:27:28,800 但是,我們可以把它一步,說,“我為什麼要ARGV [1]段錯誤呢?” 352 00:27:28,800 --> 00:27:38,830 讓我們打印的argv [1],它看起來像它的0x0,這是空指針。 353 00:27:38,830 --> 00:27:44,750 我們strcmping CS50石塊和空,所以會出現段錯誤。 354 00:27:44,750 --> 00:27:48,280 又為什麼是argv [1]為空? 355 00:27:48,640 --> 00:27:51,280 [學生]:因為我們沒有給它任何命令行參數。 356 00:27:51,280 --> 00:27:53,390 是啊。我們沒有給它任何命令行參數。 357 00:27:53,390 --> 00:27:58,460 所以./buggy1的argv [0]是./buggy1。 358 00:27:58,460 --> 00:28:02,100 它不會有一個argv [1],因此,會出現段錯誤。 359 00:28:02,100 --> 00:28:07,450 但是,如果不是,我做的只是CS50,它會說你得到D 360 00:28:07,450 --> 00:28:09,950 ,因為這是它應該做的。 361 00:28:09,950 --> 00:28:15,240 在buggy1.c看,它應該打印“你得到一個D” - 362 00:28:15,240 --> 00:28:20,820 如果argv [1],而不是“CS50岩石”,“你得到了D”,否則,你會得到一個A!“ 363 00:28:20,820 --> 00:28:25,660 因此,如果我們要一個一個,我們需要的比較結果為真, 364 00:28:25,660 --> 00:28:28,710 這意味著,它比較為0。 365 00:28:28,710 --> 00:28:31,100 的argv [1]因此,需要將“CS50岩石”。 366 00:28:31,100 --> 00:28:35,660 如果你在命令行上要做到這一點,你需要使用\逃跑的空間。 367 00:28:35,660 --> 00:28:41,690 因此,CS50 \岩石,你會得到一個A! 368 00:28:41,690 --> 00:28:44,060 如果你不這樣做的反斜杠,為什麼不工作? 369 00:28:44,060 --> 00:28:47,190 [學生]:這是兩個不同的參數。 >>呀。 370 00:28:47,190 --> 00:28:52,540 的argv [1]將是CS50,和argv [2]將是岩石。好吧。 371 00:28:52,540 --> 00:28:56,470 >> 現在./buggy2是再次向段錯誤。 372 00:28:56,470 --> 00:29:01,880 ,其核心文件,而不用打開它,我們就打開了buggy2直接, 373 00:29:01,880 --> 00:29:05,000 所以GDB buggy2。 374 00:29:05,000 --> 00:29:09,590 現在,如果我們運行我們的程序,那麼它會說程序收到信號SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 這是段錯誤的信號,這是它發生在發生。 376 00:29:15,530 --> 00:29:21,250 我們回溯看,我們看到我們在功能oh_no, 377 00:29:21,250 --> 00:29:23,900 這是所謂的由函數極小,這是所謂的由函數binky, 378 00:29:23,900 --> 00:29:26,460 被稱為主。 379 00:29:26,460 --> 00:29:31,680 我們也可以看到這些功能的參數。 380 00:29:31,680 --> 00:29:34,680 極小和賓基的參數為1。 381 00:29:34,680 --> 00:29:44,390 如果我們列出的功能oh_no,我們看到,oh_no,只是做的char * s = NULL; 382 00:29:44,390 --> 00:29:47,410 * s =“BOOM”; 383 00:29:47,410 --> 00:29:50,330 為什麼會失敗呢? 384 00:29:54,330 --> 00:29:58,380 [學生]無法取消引用空指針? >>呀。 385 00:29:58,380 --> 00:30:06,090 這只是說s是NULL,無論如果出現這種情況,是一個char **, 386 00:30:06,090 --> 00:30:12,070 這取決於你如何解釋它,它可能是一個指向一個指針,指向一個字符串的指針 387 00:30:12,070 --> 00:30:15,550 或一個字符串數組。 388 00:30:15,550 --> 00:30:21,430 s為null,* S是一個空指針解引用, 389 00:30:21,430 --> 00:30:24,800 所以這是要崩潰。 390 00:30:24,800 --> 00:30:27,540 這是一個最快捷的方法,你可以可能出現段錯誤。 391 00:30:27,540 --> 00:30:31,300 這只是宣布一個空指針,並立即段錯誤。 392 00:30:31,300 --> 00:30:34,570 這是什麼oh_no。 393 00:30:34,570 --> 00:30:43,400 如果我們去了一個框架,然後,我們將要進入的功能,稱為oh_no。 394 00:30:43,400 --> 00:30:44,830 我需要做下來​​。 395 00:30:44,830 --> 00:30:48,610 如果你不輸入命令,你只要再次按下Enter鍵, 396 00:30:48,610 --> 00:30:52,350 它只是重複前面的命令,你跑了。 397 00:30:52,350 --> 00:30:56,610 我們在第1幀。 398 00:30:56,610 --> 00:31:04,650 上市這一框架內,我們在這裡看到的是我們的功能。 399 00:31:04,650 --> 00:31:08,520 你可以打列表,或者你可以做的清單2​​0,它會列出。 400 00:31:08,520 --> 00:31:13,640 該函數的極小的說,如果我是1,然後去的oh_no功能, 401 00:31:13,640 --> 00:31:15,960 其他緊身的功能。 402 00:31:15,960 --> 00:31:18,700 我們知道,我是1,因為我們在這裡碰巧看到 403 00:31:18,700 --> 00:31:22,560 被稱為參數1,極小的。 404 00:31:22,560 --> 00:31:27,560 或者你也可以不打印我,它會說我是1。 405 00:31:27,560 --> 00:31:33,770 目前,我們正在極小,如果我們去了另一個框架,我們知道我們將最終在賓基。 406 00:31:33,770 --> 00:31:36,600 最多。現在,我們在binky。 407 00:31:36,600 --> 00:31:41,340 列出這個功能 - 在上半場結束前把我的清單 - 408 00:31:41,340 --> 00:31:52,670 它開始了,如果我是0,然後,我們將調用它oh_no,否則打電話極小。 409 00:31:52,670 --> 00:31:57,000 我們知道,我是1,因此它被稱為極小的。 410 00:31:57,000 --> 00:32:05,030 ,現在我們在主,主要是int i =蘭特()%3; 411 00:32:05,030 --> 00:32:08,790 這僅僅是給你一個隨機數是0,1或2。 412 00:32:08,790 --> 00:32:12,780 這將調用binky與數字,它會返回0。 413 00:32:12,780 --> 00:32:16,700 見到這種情景, 414 00:32:16,700 --> 00:32:19,880 步行通過的程序不運行它立即,手動 415 00:32:19,880 --> 00:32:25,400 在主,你可以設置一個破發點,這意味著當我們運行程序 416 00:32:25,400 --> 00:32:31,020 你的程序運行,直到它擊中了一個破發點。 417 00:32:31,020 --> 00:32:35,450 因此,運行程序,它會運行,然後它會為主打功能,並停止運行。 418 00:32:35,450 --> 00:32:44,700 現在,我們的主要內,步驟或未來將會給我們帶來的下一行代碼。 419 00:32:44,700 --> 00:32:47,050 你可以做的步驟或未來。 420 00:32:47,050 --> 00:32:51,800 單擊Next,現在我已經設置的rand()%3,這樣我們就可以打印i的值, 421 00:32:51,800 --> 00:32:55,280 它會說我是1。 422 00:32:55,280 --> 00:32:58,110 現在它無論我們使用下一個或步驟。 423 00:32:58,110 --> 00:33:01,000 我想它在上一個重要的,但我們希望下次使用。 424 00:33:01,000 --> 00:33:06,000 如果我們使用步驟,我們進入的功能,這意味著在實際的東西看 425 00:33:06,000 --> 00:33:07,940 內發生的事情的binky。 426 00:33:07,940 --> 00:33:10,510 如果我們用下,那麼就意味著在功能 427 00:33:10,510 --> 00:33:14,070 只是去我們的主函數中的代碼的下一行。 428 00:33:14,070 --> 00:33:17,900 在這條線就在這裡,我是在它說的rand()%3; 429 00:33:17,900 --> 00:33:21,320 如果我這樣做的一步,將進入實施蘭特 430 00:33:21,320 --> 00:33:25,110 並期待在那裡發生了什麼事,我可以通過rand函數的步驟。 431 00:33:25,110 --> 00:33:26,920 但我不關心rand函數。 432 00:33:26,920 --> 00:33:30,190 我只想去到下一行代碼的主,所以我用下。 433 00:33:30,190 --> 00:33:35,800 但我現在關心的binky功能,所以我想步入。 434 00:33:35,800 --> 00:33:37,730 現在,我在binky。 435 00:33:37,730 --> 00:33:42,040 的第一行代碼是怎麼說的(我== 0),我走了一步, 436 00:33:42,040 --> 00:33:44,930 我們可以看到,我們結束了在極小的。 437 00:33:44,930 --> 00:33:51,620 如果我們列出的東西,我們可以看到,它檢查是i = 0。 438 00:33:51,620 --> 00:33:55,470 我是不等於0,所以去的其他條件, 439 00:33:55,470 --> 00:33:59,540 要調用極小的(I)。 440 00:33:59,540 --> 00:34:04,030 你可能會感到困惑。 441 00:34:04,030 --> 00:34:07,380 如果你只是直接看這些線,你可能會認為,如果(我== 0) 442 00:34:07,380 --> 00:34:10,800 好,那我走了一步,現在我在極小的(I), 443 00:34:10,800 --> 00:34:14,120 你可能會認為一定意味著i = 0或東西。 444 00:34:14,120 --> 00:34:18,980 它只是意味著它知道它可以直接粘到線極小的(I)。 445 00:34:18,980 --> 00:34:23,300 由於i是不為0時,下一個步驟是不會結束的else。 446 00:34:23,300 --> 00:34:26,239 Else是不是要停在一條線。 447 00:34:26,239 --> 00:34:31,570 它只是要去到下一行,它實際上可以執行,這是極小的(I)。 448 00:34:31,570 --> 00:34:36,090 步入極小的(I),我們可以看到,如果(我== 1)。 449 00:34:36,090 --> 00:34:42,670 我們知道I = 1,所以當我們一步,我們知道我們要在oh_no 450 00:34:42,670 --> 00:34:46,489 因為I = 1調用函數oh_no,你可以進入, 451 00:34:46,489 --> 00:34:52,969 這是要設置的char * s = NULL,並立即“BOOM”。 452 00:34:54,270 --> 00:34:59,690 然後尋找在實施buggy2, 453 00:34:59,690 --> 00:35:04,590 這一點,我只是得到一個隨機數 - 0,1或2 - 呼叫賓基, 454 00:35:04,590 --> 00:35:10,610 如果我是0它要求oh_no的,否則它會調用極小,來了這裡。 455 00:35:10,610 --> 00:35:18,100 如果i是1,呼叫oh_no,否則打電話緊身,這即將在這裡, 456 00:35:18,100 --> 00:35:20,460 如果是2,調用oh_no。 457 00:35:20,460 --> 00:35:24,720 我什至不認為有一種方法 - 458 00:35:24,720 --> 00:35:30,030 有沒有人看到這是一個程序,不會出現段錯誤的一種方式嗎? 459 00:35:30,030 --> 00:35:37,530 因為除非我失去了一些東西,如果我是0,你馬上就會出現段錯誤, 460 00:35:37,530 --> 00:35:41,250 否則你去一個函數,如果我是你段錯誤, 461 00:35:41,250 --> 00:35:44,540 否則,你去給一個函數,如果我是2段錯誤。 462 00:35:44,540 --> 00:35:46,810 所以無論你做什麼,你段錯誤。 463 00:35:46,810 --> 00:35:52,380 >> 我想修復它,而不是做的char * s = NULL的方式之一, 464 00:35:52,380 --> 00:35:55,610 你可以MALLOC該字符串的空間。 465 00:35:55,610 --> 00:36:04,230 我們可以做的malloc(大小) - 大小是什麼? 466 00:36:09,910 --> 00:36:15,190 [學生](字符)* 5? “這似乎不是嗎? 467 00:36:15,190 --> 00:36:21,060 我假定這將工作,如果我真的跑了,但它不是我在尋找什麼。 468 00:36:24,400 --> 00:36:32,940 看看s的類型。讓我們增加對int *,所以int * X。 469 00:36:32,940 --> 00:36:35,600 我會做的malloc(sizeof(int)的的)。 470 00:36:35,600 --> 00:36:40,490 或者,如果我想要一個數組5,我會做(如sizeof(int)* 5); 471 00:36:40,490 --> 00:36:44,210 如果我有一個int **嗎? 472 00:36:46,260 --> 00:36:49,140 那我的malloc嗎? 473 00:36:49,140 --> 00:36:53,510 [學生]大小的指針。 >>呀。 (如sizeof(int *)); 474 00:36:53,510 --> 00:36:56,960 同樣的事情在這裡。 475 00:36:56,960 --> 00:37:01,280 我想(如sizeof(char *)的); 476 00:37:06,170 --> 00:37:12,840 這是怎麼回事“轟”的指針,該指針指向分配空間。 477 00:37:12,840 --> 00:37:15,330 我並不需要分配空間的“BOOM” 478 00:37:15,330 --> 00:37:17,210 因為這基本上是我在說什麼之前 479 00:37:17,210 --> 00:37:20,870 對char * x =“BOOM”。 480 00:37:20,870 --> 00:37:27,950 “BOOM”已經存在。它發生在存在內存中的只讀區域。 481 00:37:27,950 --> 00:37:35,200 但它已經存在,這意味著這行代碼,如果s是一個char **, 482 00:37:35,200 --> 00:37:43,900 * S是一個char *,你設置這個char *到指向“BOOM”。 483 00:37:43,900 --> 00:37:50,040 如果我想複製到s的“BOOM”,那我就需要為s分配空間。 484 00:37:55,170 --> 00:38:03,900 * S =我會做的malloc(sizeof(字符)* 5)的; 485 00:38:03,900 --> 00:38:06,210 為什麼? 486 00:38:06,210 --> 00:38:10,860 為什麼不是4?它看起來像“BOOM”是4個字符。 >> [學生] NULL字符。 487 00:38:10,860 --> 00:38:14,580 是啊。需要空字符的字符串。 488 00:38:14,580 --> 00:38:23,590 現在,我可以做類似的strcat - 複製一個字符串的功能是什麼? 489 00:38:23,590 --> 00:38:28,520 [學生]京華山一? “STRCPY。 490 00:38:28,520 --> 00:38:32,700 男人的strcpy。 491 00:38:36,120 --> 00:38:39,590 因此,STRCPY或strncpy()函數。 492 00:38:39,590 --> 00:38:43,410 strncpy()函數是一個比較安全的,因為你可以指定到底有多少個字符, 493 00:38:43,410 --> 00:38:46,190 但在這裡並不重要,因為我們知道。 494 00:38:46,190 --> 00:38:50,340 因此,strcpy和尋找的參數。 495 00:38:50,340 --> 00:38:53,100 第一個參數是我們的目標。 496 00:38:53,100 --> 00:38:56,770 第二個參數是我們的源代碼。 497 00:38:56,770 --> 00:39:10,310 我們要複製到我們的目的地* S的指針“BOOM”。 498 00:39:10,310 --> 00:39:19,820 你為什麼要做到這一點,而不是正是我們之前用的strcpy 499 00:39:19,820 --> 00:39:22,800 * S =“BOOM”? 500 00:39:22,800 --> 00:39:28,630 是有原因的,你可能想這樣做,但是那是什麼原因呢? 501 00:39:28,630 --> 00:39:31,940 [學生]如果你想改變一些東西在“BOOM”。 >>呀。 502 00:39:31,940 --> 00:39:37,950 現在,我可以做一些事情,比如s [0] ='X'; 503 00:39:37,950 --> 00:39:48,190 ,因為點的堆的堆,空間,s是指向 504 00:39:48,190 --> 00:39:52,320 是一個指針,更在堆上的空間,這是存儲“BOOM”。 505 00:39:52,320 --> 00:39:55,150 因此,這“轟”的副本被存儲在堆中。 506 00:39:55,150 --> 00:39:58,780 “BOOM”在我們的計劃在技術上是有兩個副本。 507 00:39:58,780 --> 00:40:03,500 這只是這個“BOOM”字符串常量的第一個, 508 00:40:03,500 --> 00:40:09,250 和“嘭”的第二個副本,,STRCPY創建“嘭”的副本。 509 00:40:09,250 --> 00:40:13,100 但是,“嘭”的副本存儲在堆中,堆,你是自由的改變。 510 00:40:13,100 --> 00:40:17,250 堆是只讀的,因此這意味著,S [0] 511 00:40:17,250 --> 00:40:20,500 是打算讓你改變了價值的“BOOM”。 512 00:40:20,500 --> 00:40:23,130 這將讓你改變這些字符。 513 00:40:23,130 --> 00:40:26,640 >> 有問題嗎? 514 00:40:27,740 --> 00:40:29,290 好吧。 515 00:40:29,290 --> 00:40:35,500 >> 到buggy3,讓GDB buggy3。 516 00:40:35,500 --> 00:40:39,840 我們只要運行它,我們可以看到,我們得到一個segfault。 517 00:40:39,840 --> 00:40:46,550 如果我們回溯,有只有兩個函數。 518 00:40:46,550 --> 00:40:52,970 如果我們進入到我們的主函數中,我們看到,我們segfaulted在這條線。 519 00:40:52,970 --> 00:41:00,180 因此,只要在這條線,(線= 0; FGETS這東西不等於NULL; 520 00:41:00,180 --> 00:41:03,770 線+ +)。 521 00:41:03,770 --> 00:41:08,010 我們的前一幀被稱為_IO_fgets的。 522 00:41:08,010 --> 00:41:10,720 你會看到有很多內置的C函數, 523 00:41:10,720 --> 00:41:15,350 當你得到段錯誤,會有非常神秘的功能名稱 524 00:41:15,350 --> 00:41:18,090 像這個_IO_fgets。 525 00:41:18,090 --> 00:41:21,770 但是,這是怎麼回事涉及到這FGETS通話。 526 00:41:21,770 --> 00:41:25,850 內的某處在這裡,我們是段錯誤。 527 00:41:25,850 --> 00:41:30,340 如果我們對fgets的觀點看,我們可以打印緩衝區。 528 00:41:30,340 --> 00:41:41,180 讓我們打印 - 哦,不。 529 00:41:48,980 --> 00:41:51,900 打印不完全一樣,我希望它去上班。 530 00:41:55,460 --> 00:41:58,000 讓我們來看看在實際的程序。 531 00:42:02,200 --> 00:42:09,640 緩衝區是一個字符數組。這是一個128個字符的字符數組。 532 00:42:09,640 --> 00:42:14,980 所以,當我說,打印緩衝區,它要打印的這128個字符, 533 00:42:14,980 --> 00:42:18,300 我的猜測是期望是什麼。 534 00:42:18,300 --> 00:42:21,390 我一直在尋找的是打印緩衝區的地址, 535 00:42:21,390 --> 00:42:23,680 但是,這並不真正告訴了我很多。 536 00:42:23,680 --> 00:42:30,770 所以,當我碰巧在這裡說×緩衝液,它讓我看到0xbffff090, 537 00:42:30,770 --> 00:42:38,690 其中,如果你還記得從早期的一些點,Oxbffff往往是一個堆棧上下的區域。 538 00:42:38,690 --> 00:42:46,020 該協議棧往往只是根據0xc000開始的地方。 539 00:42:46,020 --> 00:42:51,890 看到這個地址,我知道該緩衝區在堆棧上正在發生的事情。 540 00:42:51,890 --> 00:43:04,500 重新啟動我的程序運行起來,緩衝,我們看到的是這個字符序列 541 00:43:04,500 --> 00:43:06,530 幾乎是毫無意義的。 542 00:43:06,530 --> 00:43:12,270 然後打印文件,這是什麼文件是什麼樣子? 543 00:43:15,120 --> 00:43:17,310 [學生] NULL。 >>呀。 544 00:43:17,310 --> 00:43:22,610 文件是一個的類型FILE *,所以它是一個指針, 545 00:43:22,610 --> 00:43:26,610 該指針的值是空的。 546 00:43:26,610 --> 00:43:33,240 所以FGETS會嘗試讀取該指針以間接的方式, 547 00:43:33,240 --> 00:43:37,320 但為了訪問該指針,它有取消對它的引用。 548 00:43:37,320 --> 00:43:40,550 或者,為了訪問它應該被人指指點點,解引用它。 549 00:43:40,550 --> 00:43:43,810 因此,它釋放空指針,它的segfaults。 550 00:43:46,600 --> 00:43:48,730 我可以重新啟動它。 551 00:43:48,730 --> 00:43:52,170 如果我們打破我們的重點和運行, 552 00:43:52,170 --> 00:43:57,320 第一行代碼是char *文件名=“nonexistent.txt”; 553 00:43:57,320 --> 00:44:00,870 這應該給一個相當大的提示,這個計劃失敗的原因。 554 00:44:00,870 --> 00:44:06,080 鍵入下,我到下一行,我打開這個文件, 555 00:44:06,080 --> 00:44:11,140 然後我立刻進入我們的產品線,其中一次我打了未來,它會出現段錯誤。 556 00:44:11,140 --> 00:44:16,880 有沒有人想拋出一個原因,我們可能會段錯誤? 557 00:44:16,880 --> 00:44:19,130 [學生]文件不存在。 >>呀。 558 00:44:19,130 --> 00:44:22,250 這應該是一個提示 559 00:44:22,250 --> 00:44:29,570 每當你打開一個文件時,你需要檢查文件是否存在。 560 00:44:29,570 --> 00:44:31,510 所以在這裡,“nonexistent.txt”; 561 00:44:31,510 --> 00:44:34,700 當我們閱讀FOPEN文件名,我們就需要說 562 00:44:34,700 --> 00:44:45,870 (文件== NULL)說printf(“請文件不存在!” 563 00:44:45,870 --> 00:44:56,340 - 更好 - 文件名);返回1; 564 00:44:56,340 --> 00:45:00,300 所以,現在我們要檢查是否為NULL 565 00:45:00,300 --> 00:45:03,930 之前,實際上繼續,並試圖讀取該文件。 566 00:45:03,930 --> 00:45:08,800 我們可以重新創建它,只是看到這樣的作品。 567 00:45:11,020 --> 00:45:14,970 我打算包括一個新的生產線。 568 00:45:21,090 --> 00:45:25,290 所以,現在nonexistent.txt不存在。 569 00:45:26,890 --> 00:45:30,040 這樣的事情,您應經常檢查。 570 00:45:30,040 --> 00:45:33,870 您應經常檢查,看看FOPEN返回NULL。 571 00:45:33,870 --> 00:45:38,170 您應經常檢查,以確定的malloc不返回NULL, 572 00:45:38,170 --> 00:45:41,410 否則,你段錯誤。 573 00:45:42,200 --> 00:45:45,930 >> 現在buggy4.c。 574 00:45:49,190 --> 00:45:58,440 運行。我猜這是等待輸入或可能無限循環。 575 00:45:58,440 --> 00:46:01,870 是的,它是無限循環。 576 00:46:01,870 --> 00:46:05,560 所以buggy4。它看起來像我們的無限循環。 577 00:46:05,560 --> 00:46:12,590 我們可以突破,主要運行我們的程序。 578 00:46:12,590 --> 00:46:20,180 在gdb,只要你使用的縮寫是明確的 579 00:46:20,180 --> 00:46:23,420 或者,他們會為您提供特別的縮寫, 580 00:46:23,420 --> 00:46:29,020 那麼你就可以使用n下次使用,而不必輸入下所有的方式。 581 00:46:29,020 --> 00:46:33,730 現在,我已經打了N一次,我可以只按下回車鍵繼續下 582 00:46:33,730 --> 00:46:36,640 而不是打n輸入n輸入,n輸入。 583 00:46:36,640 --> 00:46:44,630 它看起來像我在某種循環的設置陣列[i]為0。 584 00:46:44,630 --> 00:46:50,510 它看起來像我從來沒有打破這循環中。 585 00:46:50,510 --> 00:46:54,780 如果我打印我,所以我是2的話,我會去下。 586 00:46:54,780 --> 00:46:59,250 我要打印我,我是3,然後我會去下。 587 00:46:59,250 --> 00:47:05,360 我要打印我和我的3。下一步,打印我,我是4。 588 00:47:05,360 --> 00:47:14,520 實際上,打印sizeof(陣列)的,所以陣列的大小是20。 589 00:47:16,310 --> 00:47:32,870 但它看起來像有一些特殊的gdb命令下去,直到事情發生。 590 00:47:32,870 --> 00:47:37,620 這就像設置條件變量的值。但我不記得它是什麼。 591 00:47:37,620 --> 00:47:44,100 因此,如果我們繼續下去 - 592 00:47:44,100 --> 00:47:47,120 你剛才說什麼?你帶來了什麼呢? 593 00:47:47,120 --> 00:47:50,500 [學生]不顯示我添加 - “”是啊。因此,顯示我可以幫忙。 594 00:47:50,500 --> 00:47:54,530 如果我們只是顯示我會把這裡i的值是什麼 595 00:47:54,530 --> 00:47:56,470 所以我沒有把它打印出來,每次。 596 00:47:56,470 --> 00:48:02,930 如果我們只是繼續下一個,我們看到0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3,4,5。 597 00:48:02,930 --> 00:48:08,530 有些事情正在發生可怕的錯誤,而我正在被重置為0。 598 00:48:13,330 --> 00:48:22,220 在buggy4.c,我們看到的情況是int數組[5]; 599 00:48:22,220 --> 00:48:26,200 (i = 0; <= sizeof(數組)的,我+ +) 600 00:48:26,200 --> 00:48:28,550 陣列[i] = 0; 601 00:48:28,550 --> 00:48:31,390 這是錯在這裡,我們看到了什麼? 602 00:48:31,390 --> 00:48:39,480 作為一個提示,當我在做gdb的buggy4 - 讓我們將主要的運行 - 603 00:48:39,480 --> 00:48:45,980 我也只看到打印sizeof(數組)的條件是什麼,我終於爆發。 604 00:48:47,690 --> 00:48:51,100 我在哪裡?我跑了嗎? 605 00:48:51,100 --> 00:48:54,280 我沒有申報。 606 00:48:54,280 --> 00:48:58,680 因此,打印大小(數組)和20, 607 00:48:58,680 --> 00:49:06,690 這是意料之中的,因為我的數組的大小是5,它是由5個整數, 608 00:49:06,690 --> 00:49:12,410 所以,整個事情應該是5 * sizeof(int)的的字節,其中的sizeof(int)往往是4。 609 00:49:12,410 --> 00:49:14,780 因此,大小(陣列)是20。 610 00:49:14,780 --> 00:49:17,420 應該是什麼內容呢? 611 00:49:17,420 --> 00:49:21,720 [學生]將是sizeof(int)。 “是啊,/是sizeof(int)。 612 00:49:21,720 --> 00:49:30,630 它看起來像有一個問題在這裡。我想這應該是< 613 00:49:30,630 --> 00:49:36,960 因為它幾乎總是<永不<=。 614 00:49:36,960 --> 00:49:44,860 現在,讓我們來想想這是為什麼居然斷。 615 00:49:44,860 --> 00:49:53,370 沒有任何人有猜測為什麼我重置為0到每個迭代循環嗎? 616 00:50:01,300 --> 00:50:09,350 內這裡發生的事情是,唯一陣列[i]被設置為0。 617 00:50:09,350 --> 00:50:15,350 不知何故,這行代碼導致我們的詮釋,我將其設置為0。 618 00:50:16,730 --> 00:50:23,130 [學生]難道是我這部分的記憶,因為它的首要 619 00:50:23,130 --> 00:50:27,970 當它認為它的下一個元素的數組? >> [鮑登]是的。 620 00:50:27,970 --> 00:50:33,880 當我們超越我們的陣列, 621 00:50:33,880 --> 00:50:39,870 不知何故,我們覆蓋的空間,是壓倒一切的我的價值。 622 00:50:39,870 --> 00:50:48,030 所以,如果我們看一下為buggy4,打破主體,運行, 623 00:50:48,030 --> 00:50:53,120 讓我們打印i的地址。 624 00:50:53,120 --> 00:50:57,280 看起來就像是bffff124。 625 00:50:57,280 --> 00:51:03,930 現在,讓我們打印的地址的數組[0]。 110。 626 00:51:03,930 --> 00:51:06,290 怎麼樣[1]? 114。 627 00:51:06,290 --> 00:51:07,920 [2],118。 628 00:51:07,920 --> 00:51:14,530 11c中,120。陣列[5] bfff124。 629 00:51:14,530 --> 00:51:26,990 因此,陣列[5],因為我,這意味著該數組[5]我有相同的地址。 630 00:51:26,990 --> 00:51:30,720 如果他們有相同的地址,他們是同樣的事情。 631 00:51:30,720 --> 00:51:38,410 所以,當我們陣列[5]為0,我們正在設置i為0。 632 00:51:38,410 --> 00:51:46,070 如果您認為有關這方面的堆棧, 633 00:51:46,070 --> 00:51:55,590 詮釋我首先聲明,這意味著我得到了一些堆棧空間。 634 00:51:55,590 --> 00:52:04,730 陣列[5],20個字節被分配在棧上分配。 635 00:52:04,730 --> 00:52:08,400 所以,我首先被分配,那麼這20個字節被分配。 636 00:52:08,400 --> 00:52:11,400 所以,我前陣發生, 637 00:52:11,400 --> 00:52:19,230 因為,就像我上週表示,在技術堆棧向下增長的, 638 00:52:19,230 --> 00:52:28,520 當你對數組的索引,我們也能保證這個數組中的第0個位置 639 00:52:28,520 --> 00:52:31,970 總是發生之前,數組中的第一個位置。 640 00:52:31,970 --> 00:52:35,900 這是我畫了上週的種。 641 00:52:35,900 --> 00:52:42,210 請注意,在底部我們的地址為0,並在頂部,我們有地址最大。 642 00:52:42,210 --> 00:52:44,880 該協議棧始終是越來越大了下來。 643 00:52:48,100 --> 00:52:53,500 比方說,我們分配給我。 644 00:52:53,500 --> 00:52:59,680 我們分配整數i,這意味著我們只能說,這裡整數,我被分配。 645 00:52:59,680 --> 00:53:06,420 然後我們分配了5個整數組成的數組,這意味著底下的, 646 00:53:06,420 --> 00:53:11,230 由於堆棧的增長,這5個整數如何分配。 647 00:53:11,230 --> 00:53:15,900 但是,由於陣列是如何工作的,我們保證在數組中的第一個位置 648 00:53:15,900 --> 00:53:22,260 總是有的地址小於數組中的第二件事情。 649 00:53:22,260 --> 00:53:28,270 因此,數組中的位置始終為0,首先發生在內存中, 650 00:53:28,270 --> 00:53:30,700 而數組中的位置發生後, 651 00:53:30,700 --> 00:53:33,310 數組中的位置2具有發生之後, 652 00:53:33,310 --> 00:53:37,900 這意味著,數組中的位置0將發生的地方,在這裡, 653 00:53:37,900 --> 00:53:40,690 數組中的位置會發生以上, 654 00:53:40,690 --> 00:53:45,530 因為移動意味著更高的地址以來的最高地址是在這裡。 655 00:53:45,530 --> 00:53:50,490 所以數組[0]在這裡,數組[1]起來這裡,陣列[2]起來這裡,陣列[3]在這裡。 656 00:53:50,490 --> 00:53:55,620 請注意之前,我們如何分配的整數,我在這裡, 657 00:53:55,620 --> 00:54:01,040 隨著我們進一步到我們的數組,我們正在越來越接近我們的整數i。 658 00:54:01,040 --> 00:54:07,640 碰巧的是該數組[5],這是超出了我們的數組中的一個位置, 659 00:54:07,640 --> 00:54:13,010 正是在那裡我正好是整數分配。 660 00:54:13,010 --> 00:54:16,920 所以,這點,我們碰巧被擊中的堆棧空間 661 00:54:16,920 --> 00:54:21,680 被分配的整數i,我們設置為0。 662 00:54:21,680 --> 00:54:26,160 >> 這是如何工作的。有問題嗎?是啊。 663 00:54:26,160 --> 00:54:30,710 [學生]不要介意。好吧。 664 00:54:30,710 --> 00:54:33,090 [學生]:你如何避免這些類型的錯誤呢? 665 00:54:33,090 --> 00:54:41,190 這些排序的錯誤?不要使用C語言作為編程語言。 666 00:54:41,190 --> 00:54:45,840 使用一種語言,數組邊界檢查。 667 00:54:45,840 --> 00:54:55,900 只要你小心,你只需要你的數組的邊界,以避免過去。 668 00:54:55,900 --> 00:54:58,300 [學生]所以,在這裡,當我們走過你的數組的邊界 - 669 00:54:58,300 --> 00:55:01,840 鮑登這就是事情開始出錯。 >> [學生]:哦,好吧。 670 00:55:01,840 --> 00:55:05,730 只要你留在分配的內存為您的陣列,你的罰款。 671 00:55:05,730 --> 00:55:12,400 但是C沒有錯誤檢查。如果我這樣做陣列[1000],它會很高興地只需要修改無論發生什麼事 - 672 00:55:12,400 --> 00:55:16,500 它進入陣列的開頭,然後它進入1000位置後,將其設置為0。 673 00:55:16,500 --> 00:55:20,000 它沒有做任何檢查,哦,這不居然有1000的東西在裡面。 674 00:55:20,000 --> 00:55:22,750 1000是遠遠超出我應該改變什麼, 675 00:55:22,750 --> 00:55:26,940 而Java或什麼的,你會得到數組的界限指標 676 00:55:26,940 --> 00:55:29,820 或指數範圍異常。 677 00:55:29,820 --> 00:55:33,950 這就是為什麼有很多的高級語言有這些東西 678 00:55:33,950 --> 00:55:37,340 如果你超越了數組界限,你失敗了 679 00:55:37,340 --> 00:55:40,070 所以,你不能改變的東西從下面你 680 00:55:40,070 --> 00:55:42,590 事情就遠不如剛剛得到一個異常 681 00:55:42,590 --> 00:55:44,940 他說,你去結束之後的數組。 682 00:55:44,940 --> 00:55:50,970 [學生]因此,我們應該只是改變了<=只是<? >> [鮑登]是啊。 683 00:55:50,970 --> 00:55:54,800 它應該是“大小(數組)/ sizeof(廉政); 684 00:55:54,800 --> 00:55:59,560 大小(數組)是20,但我們只希望5。 >> [學生]。 685 00:55:59,560 --> 00:56:04,060 還有問題嗎?好吧。 686 00:56:04,060 --> 00:56:07,380 >> [學生]:我有一個問題。 >>呀。 687 00:56:07,380 --> 00:56:16,440 [學生]:什麼是實際的數組變量? 688 00:56:16,440 --> 00:56:20,000 [鮑登]究竟什麼是數組嗎? 689 00:56:20,000 --> 00:56:24,930 數組本身是一個符號。 690 00:56:24,930 --> 00:56:31,490 這僅僅是我們所引用的20個字節的開始地址。 691 00:56:31,490 --> 00:56:38,070 你可以認為它是一個指針,但它是一個常量指針。 692 00:56:38,070 --> 00:56:44,140 只要東西被編譯,變量數組不存在了。 693 00:56:44,140 --> 00:56:48,210 [學生]那麼,它是如何找到數組的大小嗎? 694 00:56:48,210 --> 00:56:54,130 數組的大小是指,該塊的大小,符號是指。 695 00:56:54,130 --> 00:57:01,240 當我做的東西像printf(“%p \ n”,陣列); 696 00:57:01,240 --> 00:57:05,140 讓我們來運行它。 697 00:57:12,960 --> 00:57:15,530 我剛剛做了什麼錯了嗎? 698 00:57:15,530 --> 00:57:19,220 陣列的陣列“在這裡聲明。 699 00:57:20,820 --> 00:57:23,200 哦,在這裡。 700 00:57:23,200 --> 00:57:31,250 鐺是聰明的,和它發生,請注意,我宣布5個元素的數組作為 701 00:57:31,250 --> 00:57:34,540 但我索引到位置1000。 702 00:57:34,540 --> 00:57:38,450 它可以這樣做,因為這些都只是常量。 703 00:57:38,450 --> 00:57:43,370 它只能走這麼遠,我注意到,超出了數組界限。 704 00:57:43,370 --> 00:57:46,880 但是請注意,當我們有我是不正確的, 705 00:57:46,880 --> 00:57:51,040 ,它可能無法確定我能承擔多少值, 706 00:57:51,040 --> 00:57:55,540 所以也不能確定,我打算結束之後的數組。 707 00:57:55,540 --> 00:57:59,430 這只是鐺聰明的。 708 00:57:59,430 --> 00:58:03,340 >> 但現在buggy4。那麼,還有什麼我做錯了什麼? 709 00:58:03,340 --> 00:58:05,970 庫函數printf的'隱式聲明。 710 00:58:05,970 --> 00:58:14,960 我想#包括的。 711 00:58:14,960 --> 00:58:18,710 好吧。現在運行buggy4。 712 00:58:18,710 --> 00:58:24,840 打印值的數組像我在這裡做的,打印出來作為一個指針 713 00:58:24,840 --> 00:58:30,060 打印出一些東西,看起來像這樣 - bfb8805c - 這是一些地址 714 00:58:30,060 --> 00:58:33,450 這是在堆棧上下的區域。 715 00:58:33,450 --> 00:58:41,820 數組本身是這樣一個指針,但它不是一個實際的指針, 716 00:58:41,820 --> 00:58:45,410 因為常規的指針,我們可以改變的。 717 00:58:45,410 --> 00:58:54,700 陣列僅僅是一些常數。 20塊的開始在地址0xbfb8805c的內存。 718 00:58:54,700 --> 00:59:09,020 所以bfb8805c通過這個地址+20或我猜-20 - 719 00:59:09,020 --> 00:59:17,400 這個數組分配的內存。 720 00:59:17,400 --> 00:59:20,350 數組,變量本身不存儲任何地方。 721 00:59:20,350 --> 00:59:27,660 當你在編譯時,編譯器 - 手一揮 - 722 00:59:27,660 --> 00:59:33,060 但編譯器將只使用它知道數組是。 723 00:59:33,060 --> 00:59:36,090 它知道該數組的開始, 724 00:59:36,090 --> 00:59:40,910 ,因此它可以做的事情在一定的偏移量從這個開始。 725 00:59:40,910 --> 00:59:43,960 它並不需要一個變量本身代表陣列。 726 00:59:43,960 --> 00:59:53,730 但是,當我做一些事情,如int * p =陣列,p是一個指針,它指向該數組, 727 00:59:53,730 --> 00:59:57,830 現在p實際上不存在在棧上。 728 00:59:57,830 --> 01:00:01,950 我將p。我可以做p = malloc的。 729 01:00:01,950 --> 01:00:06,500 因此,它最初指向陣列,現在它指向的堆一些空間。 730 01:00:06,500 --> 01:00:09,620 我不能這樣做陣列= malloc的。 731 01:00:09,620 --> 01:00:13,710 如果鐺是聰明的,它會衝我喊了蝙蝠的權利。 732 01:00:17,000 --> 01:00:21,430 其實,我敢肯定,海灣合作委員會將做到這一點。 733 01:00:21,430 --> 01:00:25,010 因此,數組類型為int [5]“是不可轉讓的。 734 01:00:25,010 --> 01:00:28,040 您無法分配到一個數組類型的東西 735 01:00:28,040 --> 01:00:30,500 因為數組是一個常數。 736 01:00:30,500 --> 01:00:34,760 這是一個符號引用這20個字節。我不能改變它。 737 01:00:34,760 --> 01:00:37,690 >> [學生]數組的大小是存儲在哪裡? 738 01:00:37,690 --> 01:00:40,670 鮑登這不是存儲在任何位置。這時候,它的編譯。 739 01:00:40,670 --> 01:00:46,310 那麼,是存儲數組的大小? 740 01:00:46,310 --> 01:00:51,870 您可以使用sizeof(數組)的函數,數組聲明本身的內部。 741 01:00:51,870 --> 01:01:03,150 所以,如果我做了一些功能,foo和我這樣做(int數組[]) 742 01:01:03,150 --> 01:01:10,450 輸出(“%d \ n”,sizeof(數組)的); 743 01:01:10,450 --> 01:01:21,330 然後,我在這裡調用foo(數組); 744 01:01:21,330 --> 01:01:24,840 裡面的這個功能 - 讓我們來運行它。 745 01:01:34,200 --> 01:01:36,840 這是再聰明的鏗鏘。 746 01:01:36,840 --> 01:01:43,890 它告訴我的sizeof數組函數參數 747 01:01:43,890 --> 01:01:46,690 將返回了'int *'的大小。 748 01:01:46,690 --> 01:01:55,150 這將是一個錯誤,如果它不是我希望發生的。 749 01:01:55,150 --> 01:01:58,960 關閉Werror。 750 01:02:14,950 --> 01:02:17,590 警告。警告罰款。 751 01:02:17,590 --> 01:02:19,960 它仍然會編譯,只要它有一個警告。 752 01:02:19,960 --> 01:02:22,910 。/ a.out的打印4。 753 01:02:22,910 --> 01:02:28,650 生成的警告,是一個明確的指標,出了什麼問題。 754 01:02:28,650 --> 01:02:34,120 int數組只是要打印的大小(*)。 755 01:02:34,120 --> 01:02:39,790 即使我把陣列[5]在這裡,它仍然只是要打印的大小(*)。 756 01:02:39,790 --> 01:02:47,440 因此,只要你把它傳遞到一個函數,數組和指針的區別 757 01:02:47,440 --> 01:02:49,670 是不存在的。 758 01:02:49,670 --> 01:02:52,640 這恰好是一個數組,在堆棧上聲明, 759 01:02:52,640 --> 01:02:58,300 但只要我們把這個值,0xbf胡說,胡說,胡說到這個函數, 760 01:02:58,300 --> 01:03:03,350 那麼這個指針指向該數組在堆棧中。 761 01:03:03,350 --> 01:03:08,310 因此,這意味著,大小只適用於被宣布的陣列的功能, 762 01:03:08,310 --> 01:03:11,230 這意味著,當你在編譯此功能, 763 01:03:11,230 --> 01:03:17,330 鐺“時,通過這個功能,它認為數組是一個int數組大小為5。 764 01:03:17,330 --> 01:03:20,640 那麼它看到的大小(數組)。嗯,這是20。 765 01:03:20,640 --> 01:03:26,440 這實際上是大小基本上幾乎所有的情況下。 766 01:03:26,440 --> 01:03:31,150 sizeof是一個函數,它是一個運營商。 767 01:03:31,150 --> 01:03:33,570 你不調用sizeof函數。 768 01:03:33,570 --> 01:03:38,280 如sizeof(int),編譯器會翻譯到4。 769 01:03:41,480 --> 01:03:43,700 明白了嗎?好吧。 770 01:03:43,700 --> 01:03:47,520 >> [學生]那麼,什麼是大小(陣列)之間的區別主要在富? 771 01:03:47,520 --> 01:03:52,840 這是因為我們說,這是int *類型的sizeof(數組)的, 772 01:03:52,840 --> 01:03:57,120 而數組在這裡是不是int *類型,它是一個int數組。 773 01:03:57,120 --> 01:04:04,540 >> [學生]所以,如果你有參數的數組[],而不是int *數組, 774 01:04:04,540 --> 01:04:09,230 這意味著,你仍然可以改變,因為現在它是一個指針數組嗎? 775 01:04:09,230 --> 01:04:14,250 鮑登]像這樣嗎? >> [學生]是啊。你可以改變數組內的功能呢? 776 01:04:14,250 --> 01:04:18,420 鮑登在這兩種情況下,你可以改變陣列。 777 01:04:18,420 --> 01:04:23,130 在這兩種情況下,你是說數組[4] = 0。 778 01:04:23,130 --> 01:04:26,590 [學生]但你可以使陣列點別的東西嗎? 779 01:04:26,590 --> 01:04:30,230 鮑登哦。是啊。在這兩種情況下 - >> [學生]是啊。 780 01:04:30,230 --> 01:04:38,410 鮑登]數組[]和int *數組之間的區別,是沒有的。 781 01:04:38,410 --> 01:04:42,570 在這裡,您還可以得到一些多維數組 782 01:04:42,570 --> 01:04:47,050 一些方便的語法,但它仍然只是一個指針。 783 01:04:47,050 --> 01:04:56,400 這意味著,我可以自由地做陣列的malloc(如sizeof(int));現在指向別的地方。 784 01:04:56,400 --> 01:04:59,610 但就像是如何工作的,永遠總是, 785 01:04:59,610 --> 01:05:03,210 改變這種陣列,使其指向其他的東西 786 01:05:03,210 --> 01:05:07,570 不改變這個數組,在這裡,因為它是一個副本的說法, 787 01:05:07,570 --> 01:05:10,780 它不是一個指針,這樣的說法。 788 01:05:10,780 --> 01:05:16,070 而實際上,隨著越來越多的跡象表明,它是完全一樣的 - 789 01:05:16,070 --> 01:05:21,100 我們已經看到了印刷陣列打印 - 790 01:05:21,100 --> 01:05:31,410 如果我們打印的地址數組的數組的地址或地址 791 01:05:31,410 --> 01:05:36,290 無論是那些? 792 01:05:41,770 --> 01:05:45,220 讓我們忽略這一項。 793 01:05:48,140 --> 01:05:51,660 好吧。這是罰款。現在,運行。/ a.out的。 794 01:05:51,660 --> 01:06:00,220 印刷陣列,然後打印該數組的地址,同樣的事情。 795 01:06:00,220 --> 01:06:02,870 陣列根本就不存在。 796 01:06:02,870 --> 01:06:08,190 它知道,當你打印數組,你要打印的符號,指的是那些20個字節。 797 01:06:08,190 --> 01:06:11,940 好,打印的地址的數組,數組的操作是不存在的。 798 01:06:11,940 --> 01:06:17,200 它不會有一個地址,所以它只是打印這20個字節的地址。 799 01:06:20,820 --> 01:06:28,150 只要你編譯,想在你的編譯buggy4。/ a.out格式, 800 01:06:28,150 --> 01:06:30,340 數組是不存在的。 801 01:06:30,340 --> 01:06:33,640 指針存在。數組沒有。 802 01:06:34,300 --> 01:06:38,060 代表該數組的內存塊仍然存在, 803 01:06:38,060 --> 01:06:43,270 但該類型的變量數組和變量不存在。 804 01:06:46,260 --> 01:06:50,270 這些都是像數組和指針之間的主要區別 805 01:06:50,270 --> 01:06:55,590 只要你調用函數,沒有任何區別。 806 01:06:55,590 --> 01:07:00,460 但裡面被聲明為數組本身的功能,大小不同的方式工作 807 01:07:00,460 --> 01:07:05,190 因為你打印的類型的大小,而不是塊的大小, 808 01:07:05,190 --> 01:07:08,950 你不能改變它,因為它是一個符號。 809 01:07:08,950 --> 01:07:14,370 打印的東西打印的東西和地址同樣的事情。 810 01:07:14,370 --> 01:07:18,480 而這幾乎是它。 811 01:07:18,480 --> 01:07:20,820 [學生]你能說更多的時間嗎? 812 01:07:21,170 --> 01:07:24,170 我可能錯過了一些東西。 813 01:07:24,170 --> 01:07:29,260 印刷的數組的數組和地址打印同樣的事情, 814 01:07:29,260 --> 01:07:33,180 而如果你打印的指針與指針的地址, 815 01:07:33,180 --> 01:07:36,010 打印一件事你指向的地址, 816 01:07:36,010 --> 01:07:40,360 其他打印的指針在棧上的地址。 817 01:07:40,360 --> 01:07:47,040 你可以改變一個指針,你不能改變數組的象徵。 818 01:07:47,740 --> 01:07:53,270 和sizeof指針要打印該指針類型的大小。 819 01:07:53,270 --> 01:07:57,470 所以int * p的大小(P),打印4張, 820 01:07:57,470 --> 01:08:04,110 但int數組[5]打印sizeof(數組)的打印20。 821 01:08:04,110 --> 01:08:07,480 [學生] int數組[5]將打印20? “是的。 822 01:08:07,480 --> 01:08:13,300 這就是為什麼內的buggy4的時候,它使用的是大小(陣列) 823 01:08:13,300 --> 01:08:16,660 這是我做<20,這是不是我們想要的。 824 01:08:16,660 --> 01:08:20,880 我們希望I <5。 >> [學生]好吧。 825 01:08:20,880 --> 01:08:25,569 [鮑登然後,一旦你開始傳遞的功能, 826 01:08:25,569 --> 01:08:34,340 如果我們這樣做* P =陣列; 827 01:08:34,340 --> 01:08:39,779 這個函數裡面,我們基本上可以使用p和陣列完全相同的方式, 828 01:08:39,779 --> 01:08:43,710 除了的sizeof問題和不斷變化的問題。 829 01:08:43,710 --> 01:08:49,810 但是p [0] = 1;說陣列[0] = 1是相同的; 830 01:08:49,810 --> 01:08:55,600 只要我們說富(數組)或者foo(P); 831 01:08:55,600 --> 01:08:59,760 裡面的函數foo,這是兩次相同的呼叫。 832 01:08:59,760 --> 01:09:03,350 這兩個調用之間沒有任何區別。 833 01:09:07,029 --> 01:09:11,080 >> 每個人都好?好吧。 834 01:09:14,620 --> 01:09:17,950 我們有10分鐘。 835 01:09:17,950 --> 01:09:28,319 >> 我們將嘗試拿到通過這個黑客打字員程序, 836 01:09:28,319 --> 01:09:32,350 本網站,去年或什麼的就出來了。 837 01:09:34,149 --> 01:09:41,100 這只是應該像你輸入隨機它打印出來 - 838 01:09:41,100 --> 01:09:46,729 無論它發生在已加載的文件是什麼,它看起來像你打字。 839 01:09:46,729 --> 01:09:52,069 它看起來像某種操作系統代碼。 840 01:09:53,760 --> 01:09:56,890 這就是我們要實現的。 841 01:10:08,560 --> 01:10:11,690 你應該有一個二進制可執行文件hacker_typer 842 01:10:11,690 --> 01:10:14,350 是發生在一個單一的參數,“黑客類型的文件。” 843 01:10:14,350 --> 01:10:16,480 運行可執行程序,應清除屏幕 844 01:10:16,480 --> 01:10:20,850 然後打印出傳入的文件,每次用戶按下一個鍵一個字符。 845 01:10:20,850 --> 01:10:24,990 所以,你按什麼鍵,它應該扔掉,而不是從文件打印字符 846 01:10:24,990 --> 01:10:27,810 這是參數。 847 01:10:29,880 --> 01:10:34,350 我幾乎會告訴你,我們需要知道的東西是什麼。 848 01:10:34,350 --> 01:10:36,440 但是,我們要檢查的termios庫。 849 01:10:36,440 --> 01:10:44,840 在我的整個生活,我從來沒有使用這個庫,所以它具有非常小的目的。 850 01:10:44,840 --> 01:10:48,610 但是,這將是圖書館內,我們可以用它來扔掉你打的字符 851 01:10:48,610 --> 01:10:52,390 當你輸入到標準英寸 852 01:10:56,970 --> 01:11:05,840 所以hacker_typer.c,我們會想包括的。 853 01:11:05,840 --> 01:11:12,870 的手冊頁的termios的 - 我猜測它的終端OS或東西 - 854 01:11:12,870 --> 01:11:16,240 我不知道如何讀它。 855 01:11:16,240 --> 01:11:21,040 在此,它說,包括這2個文件,所以我們將做到這一點。 856 01:11:37,620 --> 01:11:46,820 >> 第一件事,第一,我們要在一個單一的說法,這是我們要打開的文件。 857 01:11:46,820 --> 01:11:52,420 那麼,我該怎麼辦?我該如何檢查,看看我有一個參數呢? 858 01:11:52,420 --> 01:11:56,480 [學生],如果argc等於它。 >> [鮑登]是啊。 859 01:11:56,480 --> 01:12:21,250 所以,如果(ARGC = 2)輸出(“用法:%s [文件打開]”)。 860 01:12:21,250 --> 01:12:32,750 所以,現在如果我沒有提供第二個參數 - 哦,我需要新的生產線 - 861 01:12:32,750 --> 01:12:36,240 你會看到它說,使用/ hacker_typer, 862 01:12:36,240 --> 01:12:39,770 第二個參數應該是我要打開的文件。 863 01:12:58,430 --> 01:13:01,260 現在我該怎麼辦? 864 01:13:01,260 --> 01:13:08,490 我想從這個文件中讀取。我如何從文件中讀取嗎? 865 01:13:08,490 --> 01:13:11,920 [學生]:你先打開它。 >>呀。 866 01:13:11,920 --> 01:13:15,010 所以FOPEN。 FOPEN看是什麼樣的? 867 01:13:15,010 --> 01:13:22,980 [學生]文件名。 >> [鮑登] filename是要ARGV [1]。 868 01:13:22,980 --> 01:13:26,110 [學生],然後你想用它做什麼,所以 - >> [鮑登]是啊。 869 01:13:26,110 --> 01:13:28,740 所以,如果你不記得,你可能只是做男人FOPEN, 870 01:13:28,740 --> 01:13:32,960 它的將是一個const char * path的路徑是文件名, 871 01:13:32,960 --> 01:13:34,970 為const char *模式。 872 01:13:34,970 --> 01:13:38,660 如果你碰巧不記得是什麼模式,那麼你可以看看模式。 873 01:13:38,660 --> 01:13:44,660 裡面的手冊頁,斜線字符是什麼,你可以用它來搜索東西。 874 01:13:44,660 --> 01:13:49,790 所以,我鍵入搜索模式/模式。 875 01:13:49,790 --> 01:13:57,130 N和N是什麼,你可以用它來通過搜索匹配週期。 876 01:13:57,130 --> 01:13:59,800 在這裡,它說,指向一個字符串的參數模式 877 01:13:59,800 --> 01:14:01,930 開始與下列序列之一。 878 01:14:01,930 --> 01:14:06,480 所以,R,打開文本文件進行讀取。這就是我們想要做的。 879 01:14:08,930 --> 01:14:13,210 對於閱讀,我要存儲。 880 01:14:13,210 --> 01:14:18,720 這件事是怎麼回事,是一個FILE *。現在我想要做的是什麼呢? 881 01:14:18,720 --> 01:14:21,200 給了我第二次​​。 882 01:14:28,140 --> 01:14:30,430 好吧。現在我想要做的是什麼呢? 883 01:14:30,430 --> 01:14:32,940 [學生]檢查它是否為NULL。 >> [鮑登]是啊。 884 01:14:32,940 --> 01:14:38,690 任何時候你打開一個文件時,請確保你能夠成功打開它。 885 01:14:58,930 --> 01:15:10,460 >> 現在我想做的事,termios的東西,我想先讀我的當前設置 886 01:15:10,460 --> 01:15:14,050 並保存到的東西,那麼我想改變我的設置 887 01:15:14,050 --> 01:15:19,420 扔掉我鍵入任何字符, 888 01:15:19,420 --> 01:15:22,520 然後我想更新這些設置。 889 01:15:22,520 --> 01:15:27,250 然後在程序結束時,我想改回我原來的設置。 890 01:15:27,250 --> 01:15:32,080 結構類型termios的,我會想這些。 891 01:15:32,080 --> 01:15:35,600 第一個是是我的current_settings, 892 01:15:35,600 --> 01:15:42,010 然後,他們將是我的hacker_settings。 893 01:15:42,010 --> 01:15:48,070 首先,我要保存我的當前設置, 894 01:15:48,070 --> 01:15:53,790 然後我會要更新hacker_settings, 895 01:15:53,790 --> 01:16:01,570 然後結束時,我的計劃,我想恢復到當前設置。 896 01:16:01,570 --> 01:16:08,660 所以保存當前設置的方式工作,我們的人termios的。 897 01:16:08,660 --> 01:16:15,810 我們看到,我們有這樣的詮釋tcsetattr,詮釋tcgetattr。 898 01:16:15,810 --> 01:16:22,960 我通過一個termios結構由它的指針。 899 01:16:22,960 --> 01:16:30,640 這看起來是 - 我已經忘記了調用該函數。 900 01:16:30,640 --> 01:16:34,930 複製和粘貼。 901 01:16:39,150 --> 01:16:45,500 因此,tcgetattr,然後我保存的信息,我想通過在結構中​​, 902 01:16:45,500 --> 01:16:49,650 這是怎麼回事是current_settings, 903 01:16:49,650 --> 01:16:59,120 而第一個參數是文件描述符的事情,我要保存的屬性。 904 01:16:59,120 --> 01:17:04,360 任何時候你打開一個文件的文件描述符是,它得到一個文件描述符。 905 01:17:04,360 --> 01:17:14,560 當我FOPEN的argv [1],它得到了你所引用的文件描述符 906 01:17:14,560 --> 01:17:16,730 每當你要讀取或寫入到它。 907 01:17:16,730 --> 01:17:19,220 這不是我想在這裡使用的文件描述符。 908 01:17:19,220 --> 01:17:21,940 默認情況下,你有三個文件描述符, 909 01:17:21,940 --> 01:17:24,310 這是標準輸入,標準輸出和標準錯誤。 910 01:17:24,310 --> 01:17:29,960 默認情況下,我認為它的標準是0,標準輸出為1,標準誤差為2。 911 01:17:29,960 --> 01:17:33,980 那麼,我要更改的設置嗎? 912 01:17:33,980 --> 01:17:37,370 我想改變的設置,每當我打了一個字符, 913 01:17:37,370 --> 01:17:41,590 我希望它拋出的字符,而不是打印到屏幕上。 914 01:17:41,590 --> 01:17:45,960 流 - 標準,標準輸出和標準錯誤 - 915 01:17:45,960 --> 01:17:52,050 響應的事情,當我在鍵盤上鍵入? >> [學生]標準英寸>>呀。 916 01:17:52,050 --> 01:17:56,450 所以我可以做0或者我可以做標準輸入。 917 01:17:56,450 --> 01:17:59,380 我得到了current_settings標準中。 918 01:17:59,380 --> 01:18:01,720 >> 現在,我想更新這些設置, 919 01:18:01,720 --> 01:18:07,200 所以,我首先複製到hacker_settings我的current_settings的。 920 01:18:07,200 --> 01:18:10,430 結構如何工作,它只會複製。 921 01:18:10,430 --> 01:18:14,510 這會將所有的領域,如你所期望的。 922 01:18:14,510 --> 01:18:17,410 >> 現在,我要更新的一些字段。 923 01:18:17,410 --> 01:18:21,670 在termios的,你就必須讀了很多這方面 924 01:18:21,670 --> 01:18:24,110 只是看你要尋找的, 925 01:18:24,110 --> 01:18:28,210 但標誌,你會想看看有回音, 926 01:18:28,210 --> 01:18:33,110 所以echo回顯輸入的字符。 927 01:18:33,110 --> 01:18:37,710 首先,我想設置 - 從來就已經被遺忘的領域是什麼。 928 01:18:45,040 --> 01:18:47,900 這是結構看起來像什麼。 929 01:18:47,900 --> 01:18:51,060 所以輸入模式,我覺得我們要改變。 930 01:18:51,060 --> 01:18:54,210 我們來看看解決方案,以確保這正是我們想要改變。 931 01:19:04,060 --> 01:19:12,610 我們要改變lflag,以防止需要通過所有這些。 932 01:19:12,610 --> 01:19:14,670 我們要改變本地模式。 933 01:19:14,670 --> 01:19:17,710 你將不得不讀通過這整個事情了解的一切都屬於 934 01:19:17,710 --> 01:19:19,320 我們要改變。 935 01:19:19,320 --> 01:19:24,120 但是它裡面的本地模式,我們要去的地方,要改變這種狀況。 936 01:19:27,080 --> 01:19:33,110 因此,hacker_settings.cc_lmode是它叫什麼。 937 01:19:39,630 --> 01:19:43,020 c_lflag。 938 01:19:49,060 --> 01:19:52,280 這是我們進入按位運算符。 939 01:19:52,280 --> 01:19:54,860 我們種出來的時候,但我們會通過它真正的快速。 940 01:19:54,860 --> 01:19:56,600 這是我們進入按位運算符, 941 01:19:56,600 --> 01:19:59,950 在那裡我覺得我說的很久以前,每當你開始處理標誌, 942 01:19:59,950 --> 01:20:03,370 你將要使用按位運算符有很多。 943 01:20:03,370 --> 01:20:08,240 標誌中的每個位對應於某種行為。 944 01:20:08,240 --> 01:20:14,090 所以在這裡,這個標誌有一堆不同的東西,所有的人意味著不同的東西。 945 01:20:14,090 --> 01:20:18,690 但我想要做的是關閉位,對應於ECHO。 946 01:20:18,690 --> 01:20:25,440 因此,要打開關閉我做&=¬ECHO。 947 01:20:25,440 --> 01:20:30,110 其實,我認為這是如TECHO什麼。我只是要再次檢查。 948 01:20:30,110 --> 01:20:34,050 我可以termios的。這只是迴聲。 949 01:20:34,050 --> 01:20:38,440 ECHO將是一個單比特。 950 01:20:38,440 --> 01:20:44,230 ,ECHO將意味著所有位都設置為1,這意味著所有的標誌都設置為true 951 01:20:44,230 --> 01:20:47,140 除了的ECHO位。 952 01:20:47,140 --> 01:20:53,830 結束我的本地標誌,這意味著目前所有標誌設置為true, 953 01:20:53,830 --> 01:20:56,520 將仍然被設置為true。 954 01:20:56,520 --> 01:21:03,240 如果我的ECHO標誌設置為true,那麼這是必然的ECHO標誌設置為false。 955 01:21:03,240 --> 01:21:07,170 所以,這行代碼只是關閉ECHO標誌。 956 01:21:07,170 --> 01:21:16,270 行代碼,我就複製他們的利益的時間,然後加以解釋。 957 01:21:27,810 --> 01:21:30,180 在該解決方案中,他說0。 958 01:21:30,180 --> 01:21:33,880 明確地說,標準輸入,它可能會更好。 959 01:21:33,880 --> 01:21:42,100 >> 請注意,我也做ECHO ICANON。 960 01:21:42,100 --> 01:21:46,650 ICANON是指一些獨立的,這意味著典型的模式。 961 01:21:46,650 --> 01:21:50,280 典型模式是指的是當你鍵入的命令行, 962 01:21:50,280 --> 01:21:54,670 標準不處理任何事情,直到你擊中換行。 963 01:21:54,670 --> 01:21:58,230 所以當你的GetString,你鍵入了一堆東西,然後你打換行。 964 01:21:58,230 --> 01:22:00,590 這時候,它的發送到標準中。 965 01:22:00,590 --> 01:22:02,680 這是默認的。 966 01:22:02,680 --> 01:22:05,830 當我關閉典型模式,你按現在每一個字符 967 01:22:05,830 --> 01:22:10,910 是被處理,這通常是有種不好的,因為它是緩慢的處理這些事情, 968 01:22:10,910 --> 01:22:14,330 這就是為什麼它是很好的緩衝到整行。 969 01:22:14,330 --> 01:22:16,810 但我想每個字符處理 970 01:22:16,810 --> 01:22:18,810 因為我不希望它等待我打換行 971 01:22:18,810 --> 01:22:21,280 前處理所有的字符,我一直打字。 972 01:22:21,280 --> 01:22:24,760 關閉標準模式。 973 01:22:24,760 --> 01:22:31,320 這東西只是意味著當實際處理字符。 974 01:22:31,320 --> 01:22:35,830 這意味著,他們立即處理;盡快,因為我​​打字,處理它們。 975 01:22:35,830 --> 01:22:42,510 這是更新的功能,我的設置標準, 976 01:22:42,510 --> 01:22:45,480 和TCSA手段做是正確的。 977 01:22:45,480 --> 01:22:50,310 其他選項等待,,直到流上的一切,這是目前處理。 978 01:22:50,310 --> 01:22:52,030 這其實並不重要。 979 01:22:52,030 --> 01:22:56,920 現在改變我的設置,無論是目前在hacker_typer_settings的。 980 01:22:56,920 --> 01:23:02,210 我想我把它叫做hacker_settings,讓我們改變它。 981 01:23:09,610 --> 01:23:13,500 改變一切hacker_settings。 982 01:23:13,500 --> 01:23:16,870 >> 現在,在我們的計劃,我們將要恢復 983 01:23:16,870 --> 01:23:20,210 什麼是目前的normal_settings內, 984 01:23:20,210 --> 01:23:26,560 這是怎麼回事,只是看起來像及normal_settings。 985 01:23:26,560 --> 01:23:30,650 請注意,我並沒有改變任何,我normal_settings,因為最初得到它。 986 01:23:30,650 --> 01:23:34,520 然後就改回來,我通過他們在最後。 987 01:23:34,520 --> 01:23:38,390 這是更新。好吧。 988 01:23:38,390 --> 01:23:43,900 >> 內,在這裡我就解釋中的代碼的利益。 989 01:23:43,900 --> 01:23:46,350 這是沒有那麼多的代碼。 990 01:23:50,770 --> 01:24:03,750 我們看到,我們從文件中讀取一個字符。我們稱它f。 991 01:24:03,750 --> 01:24:07,850 現在,您可以男人fgetc函數,fgetc去上班 992 01:24:07,850 --> 01:24:11,910 只是它會返回你剛才讀的字符或EOF, 993 01:24:11,910 --> 01:24:15,680 其對應的端部的文件或一些錯誤發生。 994 01:24:15,680 --> 01:24:19,900 我們循環,繼續從文件中讀取一個字符, 995 01:24:19,900 --> 01:24:22,420 直到我們已經用完了要讀取的字符。 996 01:24:22,420 --> 01:24:26,650 而我們這樣做,我們等待的單個字符標準英寸 997 01:24:26,650 --> 01:24:29,090 每一次你在命令行中鍵入一些東西, 998 01:24:29,090 --> 01:24:32,820 閱讀一個字符從標準中。 999 01:24:32,820 --> 01:24:38,330 隨後的putchar只是打算把在這裡,我們讀到了從文件到標準輸出的字符。 1000 01:24:38,330 --> 01:24:42,890 男人的putchar,但它只是把輸出到標準輸出,它的打印字符。 1001 01:24:42,890 --> 01:24:51,600 你也可以做輸出(“%C”,C);同樣的想法。 1002 01:24:53,330 --> 01:24:56,670 這是怎麼回事,做大量的工作。 1003 01:24:56,670 --> 01:25:00,300 >> 我們想要做的最後一件事是只是FCLOSE我們的文件。 1004 01:25:00,300 --> 01:25:03,310 如果你不FCLOSE,這是一個內存洩漏。 1005 01:25:03,310 --> 01:25:06,680 我們要FCLOSE我們最初打開的文件,我認為這是它的。 1006 01:25:06,680 --> 01:25:13,810 如果我們達到這個目標,我已經有問題。 1007 01:25:13,810 --> 01:25:17,260 讓我們來看看。 1008 01:25:17,260 --> 01:25:19,960 那有什麼抱怨嗎? 1009 01:25:19,960 --> 01:25:30,220 預計'詮釋',但實參的類型結構_IO_FILE *“。 1010 01:25:36,850 --> 01:25:39,370 我們可以看到,如果這樣的作品。 1011 01:25:45,210 --> 01:25:53,540 只允許在C99。 Augh。好吧,讓hacker_typer。 1012 01:25:53,540 --> 01:25:57,760 現在,我們得到更多有用的描述。 1013 01:25:57,760 --> 01:25:59,900 因此,使用未聲明的標識符“normal_settings”。 1014 01:25:59,900 --> 01:26:04,170 我沒有把它normal_settings。我稱為它current_settings。 1015 01:26:04,170 --> 01:26:12,090 因此,讓我們改變這一切。 1016 01:26:17,920 --> 01:26:21,710 現在傳遞參數。 1017 01:26:26,290 --> 01:26:29,500 現在,我會讓0。 1018 01:26:29,500 --> 01:26:36,720 好吧。 / hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 我也並沒有明確的開始屏幕上。 1020 01:26:39,590 --> 01:26:42,960 但是你可以回頭看的最後一個問題集,就看你如何清除屏幕。 1021 01:26:42,960 --> 01:26:45,160 這就是打印一些字符 1022 01:26:45,160 --> 01:26:47,210 雖然這是做我想做的事情。 1023 01:26:47,210 --> 01:26:48,900 好吧。 1024 01:26:48,900 --> 01:26:55,280 思考為什麼這個需要,而不是標準輸入為0, 1025 01:26:55,280 --> 01:27:00,560 應#定義0, 1026 01:27:00,560 --> 01:27:03,890 這是抱怨 - 1027 01:27:13,150 --> 01:27:19,360 以前我說的文件描述符,但你也有你的FILE *, 1028 01:27:19,360 --> 01:27:23,210 一個文件描述符只是一個單一的整數, 1029 01:27:23,210 --> 01:27:26,970 而一個FILE *有一大堆的東西,與它相關聯的。 1030 01:27:26,970 --> 01:27:30,380 究其原因,我們需要說0,而不是標準輸入 1031 01:27:30,380 --> 01:27:37,480 的是,stdin是一個FILE *,它指向的東西被引用文件描述符0。 1032 01:27:37,480 --> 01:27:45,070 因此,即使在這裡,當我做FOPEN(ARGV [1],我得到一個FILE *。 1033 01:27:45,070 --> 01:27:51,180 但是,在該文件中*是對應於該文件的文件描述符的事情。 1034 01:27:51,180 --> 01:27:57,430 如果你看看在開放的手冊頁,所以我認為你必須做的人3個開放式的 - 都能跟得上 - 1035 01:27:57,430 --> 01:27:59,380 男子2個開放 - 是啊。 1036 01:27:59,380 --> 01:28:06,250 如果你看一下在頁面的開放,開放是像一個較低的水平FOPEN, 1037 01:28:06,250 --> 01:28:09,350 它返回的實際文件描述符。 1038 01:28:09,350 --> 01:28:12,050 的FOPEN做了一堆東西之上的開放, 1039 01:28:12,050 --> 01:28:17,640 而不是只是返回的文件描述符FILE *指針返回一個整 1040 01:28:17,640 --> 01:28:20,590 裡面,這是我們的小文件描述符。 1041 01:28:20,590 --> 01:28:25,020 所以標準是指FILE *的事情, 1042 01:28:25,020 --> 01:28:29,120 而0指的是剛才的文件描述標準本身。 1043 01:28:29,120 --> 01:28:32,160 >> 有問題嗎? 1044 01:28:32,160 --> 01:28:35,930 [笑]吹過。 1045 01:28:35,930 --> 01:28:39,140 好的。我們就大功告成了。 [笑] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]