[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]