[Powered by Google Translate] [CS50圖書館]
內特 - 哈迪森] [哈佛大學]
[這是CS50。 CS50.TV]
CS50庫是一個有用的工具，我們已經安裝在設備上
使您更輕鬆地編寫程序，提示用戶輸入。
在這段視頻中，我們將拉回來的窗簾，看看究竟是什麼在CS50庫。
>> 在C庫上的視頻，我們來談談如何＃include頭文件
你的源代碼庫中，
然後你鏈接的二進制庫文件中的鏈接階段
編譯過程。
頭文件指定的庫的接口。
也就是說，他們的所有細節，圖書館的資源供您使用，
像函數聲明，常量和數據類型。
二進制庫文件包含了執行的庫，
這是從庫的頭文件和庫的C源代碼文件編譯的。
>> 二進制庫文件看，因為它是，在二進制，是不是很有趣。
所以，讓我們來看看庫，而不是在頭文件。
在這種情況下，只有一個頭稱為cs50.h.的文件
我們已經安裝了它在用戶目錄
隨著其他系統庫的頭文件。
>> 你會注意到的第一件事情之一是，cs50.h＃包括從其他庫的頭文件 -
持股量，範圍，標準的布爾值，標準庫。
同樣，不重新發明輪子的原則，
我們已經建立了的CS0庫使用的工具，為我們提供。
>> 接下來的事情，你會看到在圖書館，我們定義一個新類型，叫做“string”。
這條線真的僅僅是創建一個別名為char *類型，
所以它不會奇蹟般地灌輸新的字符串類型與屬性
通常與其他語言的字符串對象，
如長度。
我們已經做到了這一點的原因是保護新的程序員的血淋淋的細節
的指針，直到他們準備好了。
>> 下一個部分的頭文件聲明的功能
，CS50庫的提供以及相關的文檔。
在這裡，請注意信息的詳細程度。
這是超級重要的，讓人們知道如何使用這些功能。
我們宣布，在功能來提示用戶並返回字符，雙打，花車，整數，
長期的渴望，和字符串，用我們自己的字符串類型。
信息隱藏的原則，
我們已經把我們定義在一個單獨的C語言實現文件 - cs50.c -
在用戶的源代碼目錄。
我們已經提供了該文件，你可以看一看，
從中汲取教訓，並重新編譯它，如果你想在不同的機器上，
即使我們認為這是更好的工作設備上的這個類。
無論如何，讓我們來看看它現在。
>> 的的功能GETCHAR，GetDouble，GetFloat，調用getInt，GetLongLong
全部建成的GetString函數。
事實證明，基本上都遵循相同的模式。
他們使用一個while循環來提示用戶輸入的一行。
他們返回一個特殊的值，如果用戶輸入一個空行。
他們試圖解析用戶的輸入，作為適當的類型，
無論是一個字符，雙，花車等。
然後他們返回的結果，如果輸入成功解析
或者它們重新提示用戶。
>> 在較高的水平，這裡沒有什麼真正棘手的。
你可能會寫自己在過去類似的結構化的代碼。
也許最神秘的前瞻性部分是sscanf的調用，分析用戶的輸入。
sscanf函數的輸入格式轉換系列的一部分。
住在標準io.h，它的工作是解析一個C字符串，
根據一個特定的格式，存儲在變量中的解析結果
所提供的主叫方。
由於輸入格式轉換功能是非常有用的，廣泛使用的功能
不超直觀的第一，
我們就去了如何sscanf的作品。
>> sscanf的是一個char *的第​​一個參數 - 一個指向字符的指針。
對於機能得以正常工作，
字符應該是一個C字符串的第一個字符，
空\ 0字符終止。
這是要分析的字符串
到sscanf函數的第二個參數是一個格式字符串，
通常通過在一個字符串常量，
，你可能會看到一個這樣的字符串時，使用printf之前。
格式字符串中的百分號表示轉換符。
該字符緊跟一個百分號，
表示，我們希望sscanf的轉換為C型。
在調用getInt，你看，有一個％d和％C。
這意味著，sscanf的將嘗試一個十進制整數 - ％ - 和一個char - ％C。
對於每一個轉換中指定的格式字符串，
sscanf的預計，相應的參數後，在其參數列表。
這個參數必須指向一個相應類型的位置
要在其中存儲的轉換的結果。
>> 典型的方法，這樣做是在棧上創建一個變量前sscanf的調用
對於每一個項目，你要解析的字符串
然後使用地址操作符 - 符號 - 通過指針
這些變量的sscanf的調用。
你可以看到，在調用getInt，我們正是這樣做的。
前sscanf的調用，我們稱為n聲明一個int和一個char調用C堆棧上的，
我們sscanf的調用指針傳遞給他們。
把這些變量在棧上優於使用空間分配
的堆用malloc，避免malloc調用的開銷，因為你，
你不必擔心內存洩漏。
沒有前綴一個百分號字符不提示轉換。
相反，他們只需要添加的格式規範。
>> 例如，如果格式字符串在調用getInt％d代替，
sscanf的尋找字母a，後面跟著一個int，
，雖然它試圖將其轉換為int，它不會做任何事情的一個。
唯一的例外是空白。
格式字符串中的空格字符匹配任何數量的空白 -
甚至都沒有。
所以，這就是為什麼註解中提到的可能與領先的和/或尾隨的空白。
所以，在這一點上它看起來像我們sscanf的調用嘗試將其解析用戶輸入的字符串
通過檢查可能的前導空格，
其次是一個int值將被轉換並存儲在int變量n
一定量的空白，後面的字符
存儲在char變量c。
>> 的返回值呢？
sscanf的解析輸入線從開始到結束，
停止當它到達末尾時，或當一個字符在輸入
不匹配的格式字符，或當它不能轉換。
它的返回值是用來挑選時停止。
如果它停止了，因為它已經達到結束的輸入字符串的
之前，作出任何轉換之前，不匹配的格式字符串的一部分，
特殊常量EOF返回。
否則，它返回成功轉換的數量，
這可能是0，1或2，因為我們已經要求兩個轉換。
在我們的例子中，我們要確保用戶輸入一個int，並僅使用一個int。
>> 所以，我們希望sscanf的返回1。知道為什麼嗎？
如果sscanf函數返回0，則沒有轉換，
所以用戶鍵入的輸入開始時的int以外的東西。
如果sscanf的返回2，然後用戶沒有正確地鍵入它在在開始的輸入，
但他們在一些非空白字符，然後鍵入後
因為％c轉換成功了。
哇，這是一個相當冗長的解釋為一個函數調用。
無論如何，如果你想sscanf的和它的兄弟姐妹的更多信息，
檢查手冊頁，谷歌，或兩者。
有很多的格式字符串選項，
而這些可以為您節省大量的手工勞動時，試圖解析字符串C.
>> 在圖書館看的是最後一個函數GetString的。
事實證明，GetString的是一個棘手的功能，正確寫，
即使它看起來像一個簡單的，共同的任務。
為什麼會出現這樣的情況呢？
好吧，讓我們想想我們要如何來存儲線，用戶鍵入的
由於字符串是一個字符序列，
我們可能要存儲在一個數組在堆棧上，
但我們需要知道過了多久數組是要當我們聲明。
同樣，如果我們想要把它的堆，
我們需要通過對malloc我們要保留的字節數，
但這是不可能的。
我們不知道用戶輸入多少字符
之前，用戶實際上並鍵入它們。
>> 這個問題是只保留一大塊的空間，比方說，一個天真的解決方案
在一個塊的1000的用戶的輸入的字符，
假設用戶將永遠不會輸入一個字符串，它長。
這是一個壞主意，原因有兩個。
首先，假設，用戶通常不鍵入字符串中的那麼長，
你可能會浪費大量的內存。
在現代化的機器，這可能不是一個問題，如果你這樣做
在一個或兩個分離的情況下，
但是，如果你在一個循環中用戶的輸入，存儲供以後使用，
您可以快速地吸了一噸的內存。
此外，如果你寫的是一個較小的計算機程序 -
在內存有限的設備，如智能手機或別的東西 -
該解決方案將導致問題的速度快了很多。
第二，更嚴重的不這樣做的原因是，它讓你的程序脆弱
什麼所謂的緩衝區溢出攻擊。
在編程中，緩衝器是用來臨時存儲輸入或輸出數據的存儲器，
在這種情況下，這是我們1000字符塊。
過去的塊數據被寫入時發生緩衝區溢出。
>> 例如，如果一個用戶實際上在超過1000個字符類型。
你可能已經經歷過這樣的意外編程時數組。
如果你有10個整數的數組，沒有什麼可以阻止你試圖讀取或寫入
15日的詮釋。
有任何編譯器警告或錯誤。
該計劃只是失誤直行和訪問內存
如認為第15的int，這樣就可以覆蓋其他變量。
在最壞的情況下，可以覆蓋一些程序的內部
控制機制，從而導致你的程序執行不同的指令
比您預期。
>> 現在，它是不是共同做這個意外，
但是，這是一個相當普遍的技術壞人破壞程序
在其他人的電腦上，並把惡意代碼。
因此，我們不能只用我們的天真的解決方案。
我們需要一種方法來防止我們的計劃是脆弱的
一個緩衝區溢出攻擊。
要做到這一點，我們需要確保增長，因為我們閱讀我們的緩衝區
更多的來自用戶的輸入。
該如何解決呢？我們使用堆分配的緩衝區。
因為我們可以改變它的大小調整realloc函數，
而我們跟踪的兩個數字 - 在緩衝區中的下一個空槽的索引
和緩衝區的長度或容量。
我們讀到chars中從用戶1在一個時間使用fgetc函數。
fgetc函數需要的參數 - STDIN - 是一個參考的標準輸入字符串，
預連接的輸入信道，用於傳輸用戶的輸入，這是一個
從終端到該程​​序。
>> 每當用戶鍵入一個新的角色，我們要檢查一下，如果索引
下一個空閒槽加1是大於緩衝區的容量。
+1，因為如果下一個可用的索引為5，
然後我們緩衝區的長度必須是6感謝0索引。
如果我們已經用完了空間，在緩衝區中，然後我們嘗試調整它的大小，
一倍，使我們的次數減少，我們調整
如果用戶是在一個很長的字符串輸入。
如果字符串中已經得到了太長時間，如果我們運行的堆內存，
我們釋放我們的緩衝區，並返回null。
>> 最後，我們追加字符的緩衝區。
一旦用戶點擊進入或返回，標誌著一個新的生產線，
或特殊字符 - 控制D - 信號輸入，
我們做一個檢查，看看如果用戶輸入的任何所有。
如果沒有，則返回null。
否則，因為我們的緩衝區可能是超出我們所需要的，
在最壞的情況下，它幾乎兩倍大，因為我們需要
因為我們每年翻一番的時間調整，
我們的字符串，只是使用的空間量，我們需要一個新的副本。
我們增加了一個額外的1 malloc調用，
有特殊的NULL終止符的空間 ​​- 在“\ 0”，
我們添加一旦我們在其餘的字符複製到字符串，
使用strncpy而不是strcpy
因此，我們可以指定要複製我們到底有多少個字符。
STRCPY複製，直到它擊中了\ 0。
然後，我們幫助我們緩衝的副本，並返回給調用者。
>> 誰知道這樣一個看似簡單的功能，可以這麼複雜嗎？
現在你知道什麼進入CS50庫。
>> 我的名字是Nate哈迪森，這是CS50。
[CS50.TV]