DAVID Malan: Được rồi, chào đón trở lại. Đây là CS50. Đây là khởi đầu của tuần bảy. Vì vậy, nó được một thời gian, vì vậy tôi nghĩ chúng tôi có một tour du lịch cơn lốc của nơi mà chúng tôi rời đi và nơi chúng tôi bây giờ đi. Vì vậy, điều này ở đây có thể có gây ra một số lo lắng lúc đầu. Nhưng hy vọng, bạn đang bắt đầu thích nghi với những gì điều này biểu thị ở đây - ngôi sao đại diện cho một con trỏ, đó là chỉ là những gì, trong nhiều điều kiện hơn của giáo dân? Vì vậy, nó là một địa chỉ. Vì vậy, nó là địa chỉ của một cái gì đó trong bộ nhớ. Và chúng tôi bắt đầu bóc lớp một vài tuần trước đây, những thứ như GetString và các chức năng khác như tất cả các thời gian này đã được trở về địa chỉ của sự vật trong bộ nhớ, như các địa chỉ của ký tự đầu tiên trong một số thứ tự. Vì vậy, chúng tôi cũng giới thiệu valgrind, mà bạn sẽ bắt đầu sử dụng cho vấn đề này thiết lập, đặc biệt là cho các tiếp theo vấn đề thiết lập là tốt. Và valgrind làm những gì cho chúng ta? Nó sẽ kiểm tra xem có rò rỉ bộ nhớ, và nó cũng kiểm tra tình trạng lạm dụng bộ nhớ. Nó có thể, với một số xác suất, nếu phát hiện mã của bạn sẽ chạm vào bộ nhớ nó chỉ đơn giản là không nên. Vì vậy, không nhất thiết phải là một rò rỉ, nhưng nếu bạn vượt ra ngoài ranh giới của một số mảng, và bạn thực sự chạy valgrind và gây ra hành vi đó trong khi valgrind đang chạy trong chương trình của bạn chạy bên trong của nó, bạn sẽ nhận được tin nhắn như thế này - "không hợp lệ viết của kích thước 4 ", mà, nhớ lại một vài tuần trước có nghĩa là tôi đã vô tình giống như trên một int quá xa vượt ra ngoài ranh giới của một mảng. Và vì vậy kích thước 4 có nghĩa là ở đây kích thước đó int cụ thể. Vì vậy hãy bảo đảm trong thực tế là đầu ra valgrind của, định dạng của nó, chỉ là tàn bạo. Nó thực sự khó để nhìn thấy thông qua sự lộn xộn những thông tin thú vị. Vì vậy, những gì chúng tôi đã làm ở đây chỉ là trích đoạn một số các cặp vợ chồng của hơn dòng thú vị. Nhưng nhận ra rằng 80% của valgrind đầu ra là có được một chút của một mất tập trung. Chỉ cần tìm kiếm các mẫu như thế này - không hợp lệ rồi, không hợp lệ đọc, 40 byte và một số số khối chắc chắn bị mất, các từ khóa như thế. Và những gì hy vọng bạn sẽ thấy một số loại dấu vết của những gì các chức năng sai lầm là thực sự nhập Trong trường hợp này đây, trong những dòng mã của tôi là lỗi rõ ràng? 26 trong một tập tin gọi là memory.c, đó là ví dụ chúng tôi đã chơi với vào thời điểm đó. Vì vậy, nó có lẽ không phải trong malloc. Nó có thể là trong mã của tôi để thay thế. Vì vậy, chúng ta sẽ thấy điều này một lần nữa và một lần nữa trước khi dài. Vì vậy, scanf, điều này đã đưa ra trong một vài hình thức cho đến nay. Chúng ta đã thấy sscanf một thời gian ngắn. Đó là một cái gì đó một số bạn chui vào trong của bạn chuẩn bị cho các bài kiểm tra. Và scanf thực sự là những gì CS50 thư viện đã được sử dụng bên dưới mui xe một thời gian khá để để có được đầu vào từ người sử dụng. Ví dụ, nếu tôi di chuyển qua các CS50 thiết bị ở đây, hãy để tôi mở ra một Ví dụ hôm nay đó được gọi là scanf-0.c Và đó là siêu đơn giản. Nó chỉ là một vài dòng mã. Nhưng nó thể hiện thực sự như thế nào getInt đã làm việc tất cả thời gian này. Trong chương trình này đây, trong dòng 16 , Thông báo rằng tôi tuyên bố một int. Vì vậy, không có con trỏ, không có gì huyền diệu có, chỉ là một int. Sau đó trong dòng 17, tôi nhắc nhở người người sử dụng đối với một số, xin vui lòng. Sau đó, vào cuối năm 18, tôi sử dụng scanf đây. Và tôi đã chỉ định, giống như printf, mà tôi hy vọng báo unquote phần trăm tôi. Vì vậy, phần trăm tôi, tất nhiên, biểu thị một int. Nhưng hãy chú ý những gì các thứ hai đối số là scanf. Làm thế nào bạn sẽ mô tả thứ hai tham số sau dấu phẩy? Đó là những gì? Đó là địa chỉ của x. Vì vậy, điều này rất hữu ích vì bằng cách cung cấp scanf với địa chỉ của x, những gì hiện mà trao quyền cho chức năng đó để làm gì? Không chỉ đến đó, nhưng cũng làm những gì? Thực hiện thay đổi nó. Bởi vì bạn có thể đến đó, đó là loại như một bản đồ đến một vị trí trong bộ nhớ. Và miễn là bạn cung cấp scanf, hoặc bất kỳ chức năng với một bản đồ như vậy, mà chức năng có thể đến đó, và không chỉ nhìn vào giá trị, nhưng nó cũng có thể thay đổi giá trị đó, đó là hữu ích nếu mục đích trong cuộc sống của scanf là quét đầu vào từ người sử dụng, đặc biệt từ bàn phím. Và f biểu thị định dạng, giống như printf, f biểu thị một định dạng chuỗi mà bạn muốn in. Vì vậy, trong ngắn hạn, dòng 18 này chỉ đơn giản nói, cố gắng đọc một int từ của người sử dụng bàn phím và lưu trữ nó bên trong của x, tại bất cứ điều gì xảy ra với địa chỉ x sống tại. Và sau đó cuối cùng, dòng 19 chỉ nói, cảm ơn cho int, trong trường hợp này. Vì vậy, hãy để tôi đi trước và thực hiện điều này. Vì vậy, hãy scanf 0. Hãy để tôi đi trước và zoom in Tôi sẽ đi và chạy với chấm giảm scanf 0. Số, xin vui lòng? 50. Cảm ơn cho 50. Vì vậy, nó khá đơn giản. Bây giờ những gì là nó không làm? Nó không phải làm một bó toàn bộ kiểm tra lỗi. Ví dụ, nếu tôi không hợp tác, và tôi không nhập vào một số, nhưng thay vào đó tôi viết một cái gì đó như "xin chào" đó chỉ là một chuyện lạ. Và như vậy một trong những điều các CS50 thư viện đã làm cho chúng tôi một số thời gian là reprompting mà và reprompting. Thử lại cụm từ thu hồi là trong cs50.c, và đó là lý do mà trong getInt thư viện CS50 thực sự là một toàn bộ loạt các hàng dài, bởi vì chúng ta kiểm tra cho các công cụ ngu ngốc như thế này. Đã không cung cấp cho người sử dụng chúng tôi, trên thực tế, một int? Anh ấy hoặc cô ấy cho chúng ta một cái gì đó như một chữ cái? Nếu như vậy, chúng tôi muốn phát hiện đó và hét vào mặt họ. Nhưng những thứ có được thú vị hơn trong ví dụ tiếp theo này. Nếu tôi đi đến scanf-1.c, là những gì mà một điều đó là thay đổi cơ bản trong ví dụ này tiếp theo? Tôi đang sử dụng char *, tất nhiên, thay vì int. Vì vậy, đây là thú vị, bởi vì char * nhớ lại, thực sự chỉ là điều tương tự như chuỗi. Vì vậy, nó cảm thấy như có lẽ đây là một siêu thực hiện đơn giản của GetString. Nhưng tôi đã bóc vỏ trở lại lớp của thư viện CS50, vì vậy tôi gọi char * này ngay bây giờ. Vì vậy, chúng ta hãy xem ở đâu, nếu bất cứ nơi nào, chúng ta đi sai. Line 17 - Tôi lại nói, xin vui lòng cho tôi một cái gì đó, trong trường hợp này, một chuỗi. Và sau đó trong dòng tiếp theo, tôi gọi scanf, một lần nữa, cho nó một mã định dạng, nhưng lần này phần trăm s. Và sau đó thời gian này, tôi cho nó bộ đệm. Bây giờ nhận thấy, tôi không sử dụng các ký hiệu. Nhưng tại sao là có thể OK đây? Bởi vì là những gì bộ đệm đã? Nó đã là một con trỏ. Nó đã là một địa chỉ. Và cho phép của từ này "nhầm lẫn" cho tôi chỉ cần gọi nó s, ví dụ, cho đơn giản. Nhưng tôi đã gọi nó là đệm bởi vì trong Nhìn chung, trong lập trình, nếu bạn có một đoạn bộ nhớ, đó là một chuỗi thực sự chỉ là, bạn có thể gọi nó là một bộ đệm. Đó là một nơi để lưu trữ thông tin. Tương tự như những thứ như YouTube, khi họ đang đệm, có thể nói, đó chỉ có nghĩa là nó tải về các bit từ internet và lưu trữ chúng trong một mảng địa phương, một đoạn địa phương của bộ nhớ để bạn có thể xem nó sau này mà không nó bỏ qua hoặc treo trên bạn trong khi chơi lại. Vì vậy, có một vấn đề ở đây mặc dù, bởi vì tôi đang nói với scanf, mong đợi một chuỗi từ người sử dụng. Đây là địa chỉ của một đoạn bộ nhớ. Đặt rằng chuỗi đó. Tại sao là ràng buộc cho chúng tôi gặp khó khăn, mặc dù? Đó là những gì? Tôi có được phép truy cập một phần của bộ nhớ? Bạn biết đấy, tôi không biết. Vì đã đệm được khởi tạo để bất cứ điều gì? Không thực sự. Và vì vậy đó là những gì chúng tôi đã gọi một giá trị rác, mà không phải là một từ chính thức. Nó chỉ có nghĩa là chúng tôi không có ý tưởng những gì bit là bên trong của bốn byte Tôi đã được phân bổ như đệm. Tôi đã không gọi malloc. Tôi đã chắc chắn không gọi là GetString. Vì vậy, ai biết điều gì là thực sự bên trong bộ đệm? Nhưng nói scanf một cách mù quáng, đến đó và đặt bất cứ điều gì người dùng gõ. Vì vậy, những gì có thể gây ra trong mã của chúng tôi nếu chúng tôi chạy nó? Có thể là một segfault. Có lẽ không, nhưng có thể là một segfault. Và tôi nói có lẽ không phải vì đôi khi bạn làm gì, đôi khi bạn không có được một segfault. Đôi khi bạn chỉ nhận được may mắn, nhưng nó dù sao sẽ một lỗi trong chương trình của chúng tôi. Vì vậy, hãy để tôi đi trước và biên dịch này. Tôi sẽ làm điều đó một cách trường học cũ. Vì vậy, kêu vang dấu gạch ngang 0, scanf-1, scanf-1.c, Enter. Rất tiếc, trường học quá cũ. Chúng ta hãy xem. Tôi đã đi đâu? Oh, char * đệm. Oh, cảm ơn bạn - Tiết kiệm, OK - trường rất cũ. Được rồi, được một lúc. Vì vậy, tôi đã chỉ cần lưu lại các tập tin sau khi làm cho rằng tạm thời thay đổi một thời điểm trước đây. Và bây giờ tôi đã biên dịch nó tay với Clang. Và bây giờ tôi sẽ đi trước và chạy scanf-1, Enter. Chuỗi xin. Tôi sẽ gõ "hello". Và bây giờ, đây là nơi mà, thẳng thắn, printf có thể là một chút khó chịu. Nó không thực sự đi vào segfault trong trường hợp này. Printf là một chút đặc biệt vì nó rất siêu thường được sử dụng về cơ bản printf đang làm chúng tôi ủng hộ và thực hiện, đó không phải là một con trỏ hợp lệ. Hãy để tôi mang nó theo mình chỉ cần in trong ngoặc vô giá trị, thậm chí mặc dù nó không nhất thiết những gì chính chúng ta mong đợi. Vì vậy, chúng ta có thể không thực sự dễ dàng tạo ra một segfault với điều này, nhưng rõ ràng điều này không phải là hành vi của tôi muốn. Vì vậy, các giải pháp đơn giản là những gì? Vâng, trong scanf-2, hãy để tôi đề nghị thay vì thực sự chỉ phân bổ một char *, hãy để tôi được một chút thông minh hơn về này, và để cho tôi phân bổ đệm như là một chuỗi 16 ký tự. Vì vậy, tôi có thể làm điều này trong một vài cách. Tôi hoàn toàn có thể sử dụng malloc. Nhưng tôi có thể quay trở lại tuần hai khi Tôi cần một đống ký tự. Đó chỉ là một mảng. Vì vậy, hãy để tôi thay vì xác định lại đệm là một mảng 16 ký tự. Và bây giờ, khi tôi vượt qua bộ đệm trong - và điều này là một cái gì đó chúng tôi đã không nói về trong tuần hai - nhưng bạn có thể điều trị một mảng như mặc dù nó là một địa chỉ. Về mặt kỹ thuật, như chúng ta đã thấy, họ một chút khác nhau. Nhưng scanf sẽ không nhớ nếu bạn vượt qua nó tên của một mảng, bởi vì những gì Kêu vang sẽ làm cho chúng ta về cơ bản là xử lý tên của mảng đó là địa chỉ của đoạn 16 byte. Vì vậy, điều này là tốt. Điều này có nghĩa là bây giờ mà tôi có thể hy vọng làm như sau. Hãy để tôi thu nhỏ cho một thời điểm và làm cho scanf-2, biên soạn OK. Bây giờ chúng tôi không có dấu gạch chéo scanf-2. Chuỗi xin. "Xin chào." Và nó dường như làm việc thời gian này. Nhưng ai đó có thể đề xuất một kịch bản trong đó nó có thể không còn hoạt động? Yeah? Một cái gì đó dài hơn 16 ký tự. Và thực sự, chúng ta có thể một chút chính xác hơn. Một cái gì đó dài hơn 15 ký tự, bởi vì thực sự chúng ta cần phải ghi nhớ rằng chúng ta cần có dấu gạch chéo ngược không ngầm ở cuối chuỗi, đó là một sang một bên scanf sẽ thường chăm sóc cho chúng tôi. Vì vậy, hãy để tôi làm một cái gì đó như - đôi khi chúng ta chỉ có thể để nó như thế. OK, vì vậy chúng tôi đã gây ra tại lỗi phân khúc của chúng tôi. Tại sao? Bởi vì tôi đã gõ đến hơn 15 ký tự, và vì vậy chúng tôi đã thực sự bộ nhớ xúc động mà tôi thực sự không nên có. Vì vậy, những gì thực sự là giải pháp ở đây? Vâng, nếu chúng ta cần một chuỗi dài hơn? Vâng, chúng tôi có thể làm cho nó 32 byte. Vâng, những gì nếu đó là không đủ dài? Làm thế nào về 64 byte? Nếu đó là không đủ dài? Làm thế nào về 128 hoặc 200 byte? Điều gì thực sự là giải pháp ở đây trường hợp tổng quát, nếu chúng ta không biết tiến những gì người dùng sẽ gõ? Nó chỉ là loại một nỗi đau lớn trong ass, phải trung thực, đó là lý do CS50 thư viện có một vài chục dòng mã thực hiện chung GetString chuỗi trong một cách mà chúng tôi làm không phải biết trước những gì các người sử dụng sẽ gõ. Đặc biệt, nếu bạn nhìn lại cs50.c từ cách đây hai tuần, bạn sẽ thấy GetString mà thực sự không không sử dụng scanf theo cách này. Thay vào đó, nó đọc một ký tự tại một thời điểm. Bởi vì một trong những điều tốt đẹp về đọc một ký tự là chúng ta có thể đảm bảo chính mình để luôn luôn có ít nhất một ký tự. Tôi chỉ có thể tuyên bố một char, và sau đó đi các bước thực sự em bé chỉ đọc một ký tự trong một thời gian từ bàn phím. Và sau đó, những gì bạn sẽ thấy GetString hiện là mỗi lần nó chạy ra khỏi, nói, 16 byte bộ nhớ, nó sử dụng malloc, hoặc một người anh em họ của nó, để cấp phát bộ nhớ hơn, sao chép cũ nhớ vào mới, và sau đó bò cùng, nhận được một ký tự tại một thời gian, và khi nó chạy ra khỏi đó đoạn bộ nhớ, ném nó đi, gầu ngoạm một phần lớn của bộ nhớ, bản sao cũ vào mới, và lặp đi lặp lại. Và nó thực sự là một nỗi đau thực sự thực hiện một cái gì đó đơn giản như nhận được thông tin từ một người sử dụng. Vì vậy, bạn có thể sử dụng scanf. Bạn có thể sử dụng chức năng tương tự khác. Và rất nhiều sách giáo khoa và trực tuyến ví dụ làm, nhưng tất cả đều dễ bị tổn thương với các vấn đề như thế này. Và cuối cùng, bị một segfault là loại gây phiền nhiễu. Nó không tốt cho người sử dụng. Nhưng trong trường hợp xấu nhất, những gì hiện nó về cơ bản đặt của bạn đang có nguy cơ? Một số loại tấn công, có khả năng. Chúng tôi đã nói về một cuộc tấn công như vậy - tràn stack. Nhưng nói chung, nếu bạn được phép tràn bộ đệm, như chúng tôi đã làm một vài tuần trước đây, chỉ với văn bản hơn "hello" trên ngăn xếp, bạn thực sự có thể đi qua, có khả năng, một máy tính, hoặc ít nhất là có được ít dữ liệu không thuộc về bạn. Vì vậy, trong ngắn hạn, đây là lý do tại sao chúng tôi có những bánh xe đào tạo. Nhưng bây giờ, chúng ta bắt đầu đưa họ ra, như các chương trình của chúng tôi không còn cần, nhất thiết phải, đầu vào từ người sử dụng. Nhưng trong trường hợp của vấn đề thiết lập sáu, đầu vào của bạn sẽ đến từ một lớn tập tin từ điển với 150 số lẻ ngàn chữ. Vì vậy, bạn sẽ không phải lo lắng về đầu vào tùy ý của người dùng. Chúng tôi sẽ cung cấp cho bạn một số giả định về tập tin đó. Bất kỳ câu hỏi về con trỏ hoặc scanf hoặc người sử dụng đầu vào nói chung? Được rồi, do đó, một cái nhìn nhanh chóng sau đó tại một theo sau chủ đề từ hai tuần trước. Và đó là khái niệm về một cấu trúc. Không phải là - khái niệm này của một cấu trúc, đó là những gì? Điều gì đã làm cấu trúc làm cho chúng ta? Xác định - xin lỗi? Xác định một kiểu biến. Vì vậy, sắp xếp của. Chúng tôi đang thực sự kết hợp hai chủ đề. Vì vậy, với typedef, nhớ lại rằng chúng ta có thể khai báo một kiểu riêng của chúng tôi, như một từ đồng nghĩa, như chuỗi cho char *. Nhưng sử dụng typedef và cấu trúc, chúng ta có thể tạo ra sự cấu trúc dữ liệu của chúng ta. Ví dụ, nếu tôi quay trở lại vào gedit đây chỉ là một thời điểm, và tôi đi trước và làm điều gì đó như thế, hãy để tôi tiết kiệm này, chúng ta hãy nói, structs.c tạm thời, tôi chỉ cần đi đi trước và bao gồm standardio.h, int chính hiệu. Và sau đó trong đây, giả sử tôi muốn viết một chương trình mà các cửa hàng nhiều sinh viên đến từ nhiều nhà ở, ví dụ. Vì vậy, nó giống như một registrarial cơ sở dữ liệu của một số loại. Vì vậy, nếu tôi cần tên một sinh viên, tôi có thể làm một cái gì đó như char tên *, và tôi sẽ làm một cái gì đó như - trên thực tế, chúng ta hãy sử dụng thư viện CS50 chỉ một chút thời gian để thực hiện điều này chút đơn giản, vì vậy chúng tôi có thể vay những hàng chục dòng mã. Và chúng ta chỉ là giữ nó đơn giản. Chúng tôi sẽ giữ nó chuỗi, và bây giờ GetString. Vì vậy, tôi khẳng định bây giờ mà tôi đã được lưu trữ tên của một số sinh viên, và nhà một số sinh viên, chỉ đơn giản là sử dụng các biến như chúng tôi đã làm và trong một tuần. Nhưng giả sử bây giờ tôi muốn hỗ trợ nhiều sinh viên. Được rồi, bản năng của tôi là làm chuỗi name2, được GetString, chuỗi House2 được GetString. Và sau đó sinh viên thứ ba của chúng tôi, chúng ta hãy làm NAME3 GetString. Được rồi, vì vậy đây là hy vọng nổi bật bạn là ngu ngốc, bởi vì quá trình này là thực sự không bao giờ sẽ kết thúc, và nó chỉ cần đi để làm cho mã của tôi trông tệ hơn và tồi tệ hơn và tồi tệ hơn. Nhưng chúng tôi giải quyết này trong quá hai tuần. Giải pháp tương đối sạch sẽ của chúng tôi là gì khi chúng tôi đã có nhiều biến của kiểu dữ liệu được tất cả các liên quan, nhưng chúng tôi không muốn lộn xộn tồi tệ này các biến có tên tương tự? Chúng tôi đã làm gì để thay thế? Vì vậy, tôi nghĩ rằng tôi nghe một vài nơi. Chúng tôi đã có một mảng. Nếu bạn muốn có nhiều trường hợp của một cái gì đó, tại sao chúng ta không làm sạch tất cả điều này và chỉ nói, cho tôi mảng gọi tên? Và bây giờ, chúng ta hãy cứng mã 3. Và sau đó cung cấp cho tôi một mảng khác được gọi là nhà, và cho tôi cho bây giờ đang khó khăn 3. Và tôi đã ồ ạt làm sạch các gây rối mà tôi vừa tạo ra. Bây giờ, tôi vẫn còn cứng mã hoá 3, nhưng thậm chí 3 động có thể đến từ các người sử dụng, hoặc argv, hoặc tương tự. Vì vậy, đây là đã sạch hơn. Nhưng những gì khó chịu về điều này có nghĩa là bây giờ, mặc dù một tên là bằng cách nào đó về cơ bản liên quan đến nhà của học sinh - đó là một sinh viên mà tôi thực sự muốn đại diện cho - Bây giờ tôi có hai mảng mà song song trong ý nghĩa rằng họ là cùng kích thước, tên và khung 0 có lẽ là bản đồ đến nhà khung 0, và tên khung 1 bản đồ nhà ở khung 1. Nói cách khác, sinh viên sống trong ngôi nhà, và sinh viên khác cuộc sống trong căn nhà khác. Nhưng chắc chắn điều này có thể thực hiện thậm chí sạch hơn. Vâng, nó có thể, trong thực tế. Và để cho tôi đi trước và mở structs.h lên, và bạn sẽ thấy ý tưởng này đây. Chú ý rằng tôi đã sử dụng typedef, như bạn ám chỉ một khoảnh khắc trước tuyên bố của chúng tôi kiểu dữ liệu riêng. Nhưng tôi cũng sử dụng từ khóa khác này được gọi là cấu trúc mang đến cho tôi một mới cấu trúc dữ liệu. Và cấu trúc dữ liệu này, tôi khẳng định sẽ có hai điều bên trong nó - một chuỗi gọi tên, và một chuỗi được gọi là nhà. Và tên tôi sẽ cung cấp cho cấu trúc dữ liệu này sẽ được gọi là sinh viên. Tôi có thể gọi nó là bất cứ điều gì tôi muốn, nhưng điều này làm cho ngữ nghĩa cảm nhận với tôi trong tâm trí của tôi. Vì vậy, bây giờ, nếu tôi mở ra một phiên bản tốt hơn của chương trình tôi bắt đầu viết có, hãy để tôi di chuyển đến đầu trang. Và có dòng một số chi tiết của mã ở đây, nhưng hãy để tôi tập trung cho thời điểm trên một. Tôi đã tuyên bố một hằng số gọi là sinh viên và cứng mã hoá 3 cho giờ. Nhưng bây giờ, chú ý cách sạch mã của tôi bắt đầu để có được. Trong dòng 22, tôi tuyên bố mảng của học sinh. Và nhận thấy rằng sinh viên là rõ ràng bây giờ là một kiểu dữ liệu. Bởi vì ở trên cùng của tập tin này, thông báo Tôi đã bao gồm tập tin tiêu đề mà tôi kéo lên chỉ là một thời điểm trước đây. Và rằng tập tin tiêu đề khá đơn giản có định nghĩa này của một học sinh. Vì vậy, bây giờ, tôi đã tạo ra dữ liệu riêng của tôi loại mà các tác giả của C năm trước đã không nghĩ đến trước. Nhưng không có vấn đề. Tôi có thể làm cho bản thân mình. Vì vậy, đây là một mảng gọi là sinh viên, mỗi thành viên có là một cấu trúc sinh viên. Và tôi muốn ba của những trong mảng. Và bây giờ, những gì hiện phần còn lại của chương trình này làm gì? Tôi cần một chút gì đó tùy ý. Vì vậy, từ trực tuyến 24 trở đi, Tôi lặp lại 0-3. Sau đó tôi yêu cầu người dùng tên của học sinh. Và sau đó tôi sử dụng GetString như trước. Sau đó, tôi yêu cầu nhà của học sinh, và tôi sử dụng GetString như trước. Nhưng thông báo - một chút mới mảnh cú pháp - Tôi vẫn có thể chỉ cho học sinh thứ i, nhưng làm thế nào để có được các dữ liệu cụ thể lĩnh vực bên trong các cấu trúc? Tốt, những gì là rõ ràng là đoạn mới của cú pháp? Nó chỉ là dấu chấm. Chúng tôi đã không thực sự thấy trước đây. Bạn đã nhìn thấy nó trong pset năm nếu bạn đã lặn trong đã có file bitmap. Nhưng dấu chấm chỉ có nghĩa là bên trong này cấu trúc hoặc nhiều lĩnh vực, cho dấu chấm tên, hoặc cho tôi chấm nhà. Điều đó có nghĩa đi bên trong các cấu trúc và nhận được những lĩnh vực cụ thể. Những gì còn lại của chương trình này làm gì? Nó không phải là tất cả những gì gợi cảm. Chú ý rằng tôi lặp 0-3 một lần nữa, và tôi chỉ đơn giản là tạo ra một tiếng Anh cụm từ như vậy và như vậy là trong đó và một ngôi nhà như vậy, đi qua trong dấu chấm tên từ học sinh thứ i và họ nhà là tốt. Và sau đó cuối cùng, bây giờ chúng tôi sẽ bắt đầu để có được hậu môn về điều này, bây giờ mà chúng tôi quen thuộc với những gì malloc và các chức năng khác đã được làm tất cả những thời gian này. Tại sao tôi phải để giải phóng cả hai tên và ngôi nhà, mặc dù tôi không gọi malloc? GetString đã làm. Và đó là bí mật nhỏ bẩn cho vài tuần, nhưng có GetString bị rò rỉ bộ nhớ trên tất cả các đặt tất cả các học kỳ cho đến nay. Và valgrand sẽ cuối cùng tiết lộ này cho chúng tôi. Nhưng nó không phải là một vấn đề lớn, bởi vì tôi biết rằng tôi chỉ đơn giản là có thể giải phóng các tên và ngôi nhà, mặc dù về mặt kỹ thuật, để được siêu, siêu an toàn, tôi sẽ có làm một số kiểm tra lỗi ở đây. Được bản năng của bạn nói cho bạn những gì? Tôi cần được kiểm tra để làm gì trước khi tôi giải phóng là những gì một chuỗi, hay còn gọi mà một char *? Tôi thực sự cần được kiểm tra nếu học sinh khung tôi chấm tên không vô giá trị như nhau. Sau đó nó sẽ được OK để đi trước và miễn phí con trỏ đó, và cùng hay khác một là tốt. Nếu học sinh khung tôi chấm nhà không phải là bằng vô giá trị, điều này bây giờ sẽ bảo vệ đối với trường hợp góc trong đó GetString trả về một cái gì đó như vô giá trị. Và chúng ta đã thấy một thời điểm trước đây, sẽ printf bảo vệ chúng ta lên đây bằng cách nói null, mà là sẽ xem xét lạ. Nhưng ít nhất nó sẽ không segfault, như chúng ta đã thấy. Vâng, hãy để tôi làm một việc khác ở đây. cấu trúc-0 là loại một chương trình ngu ngốc bởi vì tôi nhập tất cả các dữ liệu này, và sau đó nó bị mất một khi chương trình kết thúc. Nhưng hãy để tôi đi trước và làm điều này. Hãy để tôi làm cho các thiết bị đầu cuối cửa sổ lớn hơn một chút. Hãy để tôi làm cho cấu trúc-1, là một phiên bản mới này. Tôi sẽ phóng to một chút. Và bây giờ cho phép tôi chạy dot cắt giảm cấu trúc-1. Tên học sinh - David Mather, chúng ta hãy làm Rob Kirkland, chúng ta hãy làm Lauren Leverett. Điều thú vị bây giờ là thông báo - và tôi chỉ biết điều này vì Tôi đã viết chương trình - có một tập tin bây giờ hiện tại của tôi thư mục gọi là students.csv. Một số bạn có thể đã thấy những trong thế giới thực. Một tập tin CSV là những gì? Bằng dấu phẩy giá trị. Đó là loại giống như một người đàn ông của người nghèo phiên bản của một tập tin Excel. Đó là một bảng các hàng và cột bạn có thể mở trong một chương trình như Excel, hoặc số trên máy Mac. Và nếu tôi mở tập tin này đây trên gedit, thông báo - và con số này không có. Đó chỉ là gedit nói tôi số dòng. Thông báo trên dòng đầu tiên của này tập tin là David và Mather. Dòng tiếp theo là Rob dấu phẩy Kirkland. Và dòng thứ ba là Lauren Leverett dấu phẩy. Vì vậy, những gì tôi đã tạo ra? Bây giờ tôi đã viết một chương trình C hiệu quả có thể tạo ra các bảng tính có thể được mở trong một chương trình như Excel. Không phải tất cả mà hấp dẫn một bộ dữ liệu, nhưng nếu bạn có khối lớn hơn nhiều dữ liệu mà bạn thực sự muốn thao tác và làm cho đồ thị của và thích, đây có lẽ là một cách để tạo ra dữ liệu đó. Hơn nữa, CSVs thực sự siêu chung chỉ để lưu trữ dữ liệu đơn giản - Yahoo Tài chính, ví dụ, nếu bạn nhận được giá cổ phiếu thông qua cái gọi là của họ API, các dịch vụ miễn phí cho phép bạn có được hiện tại cổ phiếu up-to-the-ngày báo giá cho các công ty, họ cung cấp cho các dữ liệu trở lại trong siêu định dạng CSV đơn giản. Vì vậy, làm thế nào chúng tôi làm điều đó? Cũng nhận thấy, hầu hết các chương trình của này gần như giống nhau. Nhưng nhận thấy ở đây, chứ không phải in các sinh viên ra ngoài, trên đường 35 trở đi, tôi cho rằng tôi đang tiết kiệm sinh viên vào đĩa, do đó tiết kiệm một tập tin. Vì vậy, nhận thấy tôi đang tuyên bố một FILE * - bây giờ, đây là loại một sự bất thường trong C. Vì lý do gì, tập tin là tất cả các mũ, mà không giống như hầu hết các loại dữ liệu khác trong C. Tuy nhiên, đây là một built-in kiểu dữ liệu, FILE *. Và tôi tuyên bố một con trỏ đến một tập tin, là làm thế nào bạn có thể nghĩ rằng. fopen có nghĩa là tập tin mở. Tập tin làm những gì bạn muốn mở? Tôi muốn mở một tập tin mà tôi sẽ tùy tiện gọi students.csv. Tôi có thể gọi đó là bất cứ điều gì tôi muốn. Và sau đó có nhiều phán đoán. Những gì hiện các số thứ hai để fopen có thể nghĩa là gì? Phải, w cho viết, có thể là r để đọc. Có một cho nối thêm nếu bạn muốn thêm hàng và không ghi đè lên toàn bộ sự việc. Nhưng tôi chỉ muốn tạo ra tập tin này một lần, vì vậy tôi sẽ sử dụng trích dẫn unquote w. Và tôi biết rằng chỉ từ khi đọc các tài liệu, hoặc các trang người đàn ông. Nếu tập tin không phải là null - nói cách khác, nếu không có gì đã xảy ra ở đó - hãy để tôi lặp qua sinh viên 0-3. Và bây giờ nhận thấy có điều gì đó bao giờ nên hơi khác nhau về dòng 41 đây. Nó không phải là printf. Đó là fprintf cho tập tin printf. Vì vậy, nó sẽ ghi vào tập tin. Tập tin đó? Một con trỏ mà bạn chỉ định như là đối số đầu tiên. Sau đó, chúng tôi chỉ định một chuỗi định dạng. Sau đó, chúng tôi xác định những chuỗi chúng ta muốn plug in cho tỷ lệ đầu tiên, và sau đó một biến hoặc s phần trăm giây. Sau đó chúng tôi đóng tập tin với fclose. Hơn tôi miễn phí bộ nhớ như trước đây, mặc dù Tôi nên đi trở lại và thêm một số kiểm tra cho null. Và đó là nó. fopen, fprintf, fclose mang lại cho tôi khả năng tạo ra tập tin văn bản. Bây giờ, bạn sẽ thấy trong vấn đề thiết lập năm, trong đó bao gồm hình ảnh, bạn sẽ được sử dụng tập tin nhị phân để thay thế. Nhưng về cơ bản, ý tưởng là như nhau, mặc dù các chức năng bạn sẽ thấy có một chút khác nhau. Vì vậy, du lịch cơn lốc, nhưng bạn sẽ nhận được tất cả các quá quen thuộc với các tập tin I/O-- đầu vào và đầu ra - với pset năm. Và bất kỳ câu hỏi về vấn đề cơ bản ban đầu đây? Yeah? Nếu bạn cố gắng để giải phóng một giá trị null? Tôi tin rằng, nếu miễn phí đã nhận được một ít sử dụng, bạn có thể có khả năng segfault. Đi qua nó vô giá trị là xấu bởi vì tôi không tin miễn phí phiền để kiểm tra cho bạn, bởi vì nó có khả năng sẽ là một sự lãng phí thời gian cho nó để làm cho bản thân tất cả mọi người trên thế giới. Tốt câu hỏi, mặc dù. Được rồi, vì vậy loại này được chúng ta đến một chủ đề thú vị. Chủ đề của bộ vấn đề năm là pháp y. Ít nhất đó là một phần của bộ vấn đề. Pháp y thường dùng để chỉ phục hồi các thông tin có thể có hoặc có thể không đã bị xóa cố ý. Và vì vậy tôi nghĩ rằng tôi muốn cung cấp cho bạn một cách nhanh chóng hương vị của những gì thực sự đang diễn ra trên tất cả các thời gian này bên dưới mui xe của máy tính của bạn. Ví dụ, nếu bạn có bên trong của bạn máy tính xách tay hoặc máy tính để bàn của bạn một ổ cứng, nó hoặc là một cơ khí thiết bị thực sự quay - có những vòng tròn được gọi là đĩa cứng mà nhìn khá giống như những gì tôi chỉ có trên màn hình ở đây, mặc dù đây là trường ngày càng cũ. Đây là một ba-và-một-nửa-inch ổ cứng. Và ba và một nửa inch dùng của với những điều khi bạn cài đặt nó trong một máy tính. Nhiều người trong số các bạn trong máy tính xách tay của bạn bây giờ có ổ đĩa cứng SSD, hoặc ổ SSD, mà không có bộ phận chuyển động. Họ giống như bộ nhớ RAM và ít như các thiết bị cơ khí. Tuy nhiên, ý tưởng này vẫn như nhau, chắc chắn có liên quan cho vấn đề thiết lập năm. Và nếu bạn nghĩ về hiện tại một ổ đĩa cứng đại diện là một vòng tròn, mà Tôi sẽ vẽ như thế này đây. Khi bạn tạo một tập tin trên máy tính của bạn, cho dù đó là một ổ SSD, hoặc trong trường hợp này, một ổ đĩa cứng trường cũ, tập tin đó bao gồm nhiều bit. Hãy nói rằng đó là này 0 và 1, một bó toàn bộ các số 0 và 1. Vì vậy, đây là toàn bộ ổ đĩa cứng của tôi. Điều này rõ ràng là một tập tin khá lớn. Và nó được sử dụng các số 0 và 1 ở đó phần của đĩa vật lý. Vâng, đó là phần vật lý là gì? Vâng, nó quay ra rằng trên một ổ đĩa cứng, ít nhất thuộc loại này, có các hạt từ tính nhỏ bé. Và họ chủ yếu có ở phía bắc và cực nam cho họ, do đó nếu bạn biến một trong những hạt từ tính Bằng cách này, bạn có thể nói rằng đó là đại diện cho một 1. Và nếu nó lộn ngược về phía nam tới phía bắc, bạn có thể nói rằng đó là đại diện cho một 0. Vì vậy, trong thế giới vật chất thực tế, đó là làm thế nào bạn có thể đại diện cho một cái gì đó trong trạng thái nhị phân 0 và 1. Vì vậy, đó là tất cả một tập tin. Có một bó toàn bộ các từ hạt có cách này hay của họ Bằng cách này, các mô hình tạo của 0 và 1. Nhưng nó quay ra khi bạn lưu một tập tin, một số thông tin được lưu riêng. Vì vậy, đây là một bảng nhỏ, một thư mục, do đó, để nói chuyện. Và tôi sẽ gọi tên cột này, và Tôi sẽ gọi vị trí cột này. Và tôi sẽ nói, giả sử đây là hồ sơ của tôi. Resume.doc tôi được lưu trữ tại vị trí, chúng ta hãy nói 123. Tôi luôn luôn đi cho số đó. Nhưng nó đủ để nói rằng giống như trong bộ nhớ RAM, bạn có thể mất một ổ đĩa cứng đó là một GB hoặc 200 GB hoặc một terabyte, và bạn có thể số tất cả các byte. Bạn có thể đếm tất cả các khối của 8 bit. Vì vậy, chúng tôi sẽ nói rằng điều này là vị trí 123. Vì vậy, thư mục bên trong này điều hành của tôi hệ thống nhớ rằng tôi sơ yếu lý lịch là ở vị trí 123. Nhưng nó được thú vị khi bạn xóa một tập tin. Vì vậy, ví dụ - và may mắn thay, hầu hết trên thế giới có bị bắt vào này - những gì sẽ xảy ra khi bạn kéo một tập tin vào hệ điều hành Mac Thùng rác của bạn hoặc Windows Recycle Bin? Mục đích của việc đó là những gì? Đó rõ ràng là để thoát khỏi các tập tin, nhưng những gì hiện các hành động kéo và rơi vào Thùng rác hoặc bạn của bạn Recycle Bin làm trên một máy tính? Hoàn toàn không có gì, thực sự. Nó giống như một thư mục. Đó là một thư mục đặc biệt, để đảm bảo. Nhưng nó thực sự xóa các tập tin? Vâng, không có, bởi vì một số bạn có thể đã được như thế, oh damn, bạn đã làm không có nghĩa là để làm điều đó. Vì vậy, bạn nhấn đúp chuột vào Thùng rác hoặc thùng rác. Bạn đã chọc xung quanh và bạn đã phục hồi các tập tin chỉ bằng cách kéo nó ra khỏi đó. Vì vậy, rõ ràng, nó không nhất thiết xóa nó. OK, bạn thông minh hơn. Bạn có biết rằng chỉ cần kéo nó vào trong Thùng rác Recycle Bin hoặc không có nghĩa là bạn đang đổ vào thùng rác. Vì vậy, bạn đi đến trình đơn, và bạn nói Thùng rác có sản phẩm nào hoặc Empty Recycle Bin. Sau đó điều gì sẽ xảy ra? Yeah, vì vậy nó sẽ bị xóa nhiều hơn như vậy. Nhưng tất cả những gì xảy ra là điều này. Máy tính quên nơi resume.doc là. Nhưng những gì đã không thay đổi rõ ràng trong hình ảnh? Các bit, các số 0 và số 1 mà tôi khẳng định là trên trang web của một số khía cạnh vật lý của phần cứng. Họ vẫn còn đó. Nó chỉ là máy tính có quên những gì họ đang có. Vì vậy, nó về cơ bản giải phóng của tập tin bit để họ có thể được tái sử dụng. Nhưng không cho đến khi bạn tạo ra các tập tin nhiều hơn, và nhiều tập tin, và nhiều tập tin sẽ xác suất, những số 0 và 1, những hạt từ tính, được tái sử dụng, ngược hoặc bên phải lên, cho các file khác, 0 và 1. Vì vậy, bạn có cửa sổ này thời gian. Và nó không phải của dự đoán chiều dài, thực sự. Nó phụ thuộc vào kích thước của đĩa cứng của bạn ổ đĩa và bao nhiêu dữ liệu mà bạn có và nhanh như thế nào bạn làm cho những người mới. Nhưng có cửa sổ này thời gian trong mà tập tin đó vẫn còn hoàn toàn thu hồi. Vì vậy, nếu bạn đã bao giờ sử dụng các chương trình như McAfee hoặc Norton để cố gắng phục hồi dữ liệu, tất cả họ đang làm là cố gắng phục hồi này được gọi là thư mục tìm ra nơi tập tin của bạn được. Và đôi khi Norton và sẽ nói, tập tin là 93% thu hồi. Vâng, điều đó không có nghĩa là gì? Điều đó chỉ có nghĩa là một số file khác tình cờ đã kết thúc bằng cách sử dụng, nói, các bit ra của tập tin ban đầu của bạn. Vì vậy, những gì đang thực sự tham gia trong việc khôi phục dữ liệu? Vâng, nếu bạn không có một cái gì đó như Norton cài đặt sẵn trên máy tính của bạn, tốt nhất bạn đôi khi có thể làm là nhìn tại toàn bộ ổ đĩa cứng tìm kiếm mô hình của các bit. Và một trong những chủ đề của bộ vấn đề năm là bạn sẽ tìm kiếm tương đương với một ổ đĩa cứng, một pháp y hình ảnh của một thẻ flash nhỏ gọn từ một máy ảnh kỹ thuật số, tìm kiếm các số 0 và số 1 mà thông thường, với cao xác suất, đại diện cho bắt đầu của một hình ảnh JPEG. Và các bạn có thể khôi phục lại những hình ảnh bằng cách giả sử, nếu tôi thấy mô hình này bit trên hình ảnh pháp y, với xác suất cao, đánh dấu khởi đầu của một JPEG. Và nếu tôi thấy mô hình tương tự một lần nữa, mà có lẽ là điểm bắt đầu của khác JPEG, và một JPEG, và một JPEG. Và điều này là thường làm thế nào phục hồi dữ liệu sẽ làm việc. Mặc dù những gì tốt đẹp về hình ảnh JPEG là các định dạng tập tin chính nó là hơi phức tạp, đầu mỗi như vậy tập tin thực sự mang tính chất tương đối và đơn giản, như bạn sẽ thấy, nếu bạn đã không đã. Vì vậy, chúng ta hãy xem xét kỹ hơn bên dưới mui xe là chính xác những gì đang được xảy ra, và những gì các số 0 và 1 là, để cung cấp cho bạn nhiều hơn một chút bối cảnh thách thức đặc biệt này. [VIDEO xem lại] -Trong trường hợp máy tính của bạn lưu trữ tất của dữ liệu vĩnh viễn của nó. Để làm điều đó, các dữ liệu đi từ bộ nhớ RAM cùng với các tín hiệu phần mềm cho ổ cứng như thế nào để lưu trữ dữ liệu đó. Các mạch ổ cứng dịch những tín hiệu vào điện áp biến động. Này, đến lượt nó, điều khiển của ổ đĩa cứng bộ phận chuyển động, một số trong số ít bộ phận chuyển động còn lại trong máy tính hiện đại. Một số của các tín hiệu điều khiển động cơ mà quay đĩa cứng kim loại tráng. Dữ liệu của bạn là thực sự được lưu trữ trên những đĩa cứng. Các tín hiệu khác di chuyển đầu đọc / ghi đầu đọc hoặc ghi dữ liệu trên đĩa cứng. Máy móc này chính xác như vậy mà một con người tóc thậm chí không thể vượt qua giữa người đứng đầu và đĩa cứng quay. Tuy nhiên, tất cả hoạt động ở tốc độ tuyệt vời. [END xem video] DAVID Malan: Phóng to một chút sâu hơn tại những gì thực sự trên những đĩa cứng. [VIDEO xem lại] -Chúng ta hãy nhìn vào những gì chúng tôi chỉ thấy trong chuyển động chậm. Khi một xung ngắn gọn về điện gửi đến các đầu đọc / ghi, nếu làm bật trên một điện nhỏ cho một phần nhỏ của một giây. Nam châm tạo ra một lĩnh vực, trong đó thay đổi tính phân cực của một nhỏ bé, nhỏ bé phần của các hạt kim loại áo mỗi bề mặt đĩa. Một loạt mô hình của những nhỏ, khu vực tính lên trên đĩa đại diện cho một chút thời gian dữ liệu trong các số nhị phân hệ thống được sử dụng bởi máy tính. Bây giờ, nếu hiện tại được gửi một cách thông qua việc đọc / ghi đầu, khu vực này bị phân cực theo một hướng. Nếu hiện tại được gửi trong hướng ngược lại, phân cực đảo ngược. Làm thế nào bạn nhận được dữ liệu từ đĩa cứng? Chỉ cần đảo ngược quá trình này. Vì vậy, các hạt trên đĩa mà có được hiện tại trong đọc / ghi đầu di chuyển. Đặt cùng hàng triệu những đoạn từ hóa, và bạn đã có một tập tin. Bây giờ, các mảnh của một tập tin duy nhất có thể được rải rác trên một ổ đĩa của tất cả đĩa cứng, giống như sự lộn xộn các giấy tờ trên bàn làm việc của bạn. Vì vậy, một tập tin thêm đặc biệt theo dõi nơi tất cả mọi thứ. Anh không muốn bạn có một cái gì đó như thế? [END xem video] DAVID Malan: OK, có thể là không. Vì vậy, bao nhiêu người trong các bạn lớn lên với những? OK, vì vậy nó càng ít tay mỗi năm. Nhưng tôi rất vui vì bạn ít nhất quen thuộc với họ, bởi vì điều này và của chính chúng ta giới thiệu cuốn sách, thật đáng buồn, đang chết rất chậm cái chết ở đây quen thuộc. Nhưng đây là những gì tôi, ít nhất, trở lại trong học cao, sử dụng được sử dụng để sao lưu. Và nó là tuyệt vời, bởi vì bạn có thể lưu trữ 1,4 MB trên đĩa đặc biệt này. Và đây là phiên bản mật độ cao, như được chỉ ra bởi HD, trong đó có có nghĩa là trước khi video HD hiện nay. Mật độ tiêu chuẩn là 800 kilobyte. Và trước đó, đã có Đĩa 400 kilobyte. Và trước đó, đã có 5 và 1/4 đĩa inch, mà đã thực sự mềm, và một chút rộng hơn và cao hơn hơn những điều này ở đây. Nhưng bạn có thể nhìn thấy cái gọi là khía cạnh mềm của các ổ đĩa. Và chức năng, họ đang thực sự khá giống với ổ đĩa cứng tại ít nhất là loại này. Một lần nữa, ổ SSD trong máy tính mới hơn làm việc một chút khác nhau. Nhưng nếu bạn di chuyển mà tab kim loại nhỏ, bạn thực sự có thể nhìn thấy một cookie nhỏ, hoặc platter. Nó không phải là kim loại như thế này. Điều này thực sự là một số rẻ hơn nhựa nguyên liệu. Và bạn có thể loại lung nó. Và bạn đã trully chỉ xóa khỏi một số số bit hoặc các hạt từ tính từ đĩa này. Vì vậy, may mắn thay, không có gì trên đó. Nếu điều đó là trong cách - và bao gồm mắt và những người hàng xóm của bạn của bạn - bạn có thể chỉ cần loại kéo này toàn bộ vỏ ra như thế. Nhưng có một chút mùa xuân, vì vậy hãy nhận thức được rằng với đôi mắt của bạn. Vì vậy, bây giờ bạn có thực sự là một đĩa mềm. Và những gì đáng chú ý về điều này là trong nhiều như đây là một đại diện quy mô nhỏ của một lớn hơn ổ cứng, những điều này là siêu, siêu đơn giản. Nếu bạn pinch dưới cùng của nó, bây giờ mà rằng điều kim loại là giảm, và vỏ họ mở cửa, tất cả có là hai mảnh cảm thấy và đĩa mềm được gọi là với một miếng kim loại ở bên trong. Và có đi một nửa nội dung đĩa của tôi. Thêm một chiếc nữa một nửa trong số họ. Nhưng đó là tất cả những gì đã được quay bên trong máy tính của bạn trong trước đây. Và một lần nữa, để đưa điều này vào quan điểm, làm thế nào lớn là hầu hết các bạn ổ đĩa cứng những ngày này? 500 GB, một terabyte, có thể trong một máy tính để bàn, 2 terabyte, 3 terabyte, 4 terabyte, phải không? Đây là một trong megabyte, cho hay phải mất, mà thậm chí không thể phù hợp với một MP3 điển hình nữa những ngày này, hoặc một số tập tin âm nhạc tương tự. Vì vậy, một chút quà lưu niệm cho bạn ngày hôm nay, và cũng để giúp bối cảnh những gì chúng tôi sẽ được tham gia cho các cấp bây giờ trong vấn đề thiết lập năm. Vì vậy, những người đang có của bạn để giữ. Vì vậy, hãy để tôi chuyển đến nơi sẽ được dành pset tiếp theo là tốt. Vì vậy, bây giờ chúng tôi đã thiết lập trang này để - oh, một vài thông báo một cách nhanh chóng. Thứ sáu này, nếu bạn muốn tham gia CS50 ăn trưa, đi đến nơi bình thường, cs50.net/rsvp. Và dự án cuối cùng - để mỗi giáo trình, chúng tôi đã đăng đặc điểm kỹ thuật dự án cuối cùng đã. Nhận ra rằng đó không có nghĩa là đó là do đặc biệt sớm. Được đăng, thực sự, chỉ để có được các bạn suy nghĩ về nó. Và thực sự, một siêu đáng kể tỷ lệ phần trăm của bạn sẽ được giải quyết dự án cuối cùng về tài liệu mà chúng thậm chí còn không nhận được để trong lớp, nhưng sẽ là vào đầu tuần tới. Thông báo, mặc dù, rằng các spec kêu gọi một vài thành phần khác nhau của dự án cuối cùng. Đầu tiên, trong một vài tuần, là một trước khi đề nghị, một email khá giản dị để TF của bạn để nói cho anh ta hoặc những gì bạn đang suy nghĩ về dự án của bạn, với không cam kết. Đề nghị sẽ được cụ thể của bạn cam kết, nói rằng, ở đây, đây là những gì Tôi muốn làm cho dự án của tôi. Bạn nghĩ gì? Quá lớn? Quá nhỏ? Là nó dễ quản lý? Và bạn thấy spec cho biết thêm chi tiết. Vài tuần sau đó là tình trạng báo cáo, mà là một tương tự email thường để TF của bạn để nói như thế nào xa phía sau bạn đang ở cuối cùng của bạn thực hiện của dự án, tiếp theo các CS50 Hackathon mà tất cả mọi người là mời, đó sẽ là một sự kiện từ 20:00 vào một buổi tối cho đến 07:00 AM sáng hôm sau. Pizza, như tôi có thể đã được đề cập trong tuần bằng không, wil được phục vụ tại 9:00, Thực phẩm Trung Quốc lúc 1:00 AM. Và nếu bạn vẫn còn tỉnh táo vào 5:00, chúng tôi sẽ đưa bạn đến IHOP cho bữa ăn sáng. Vì vậy, các Hackathon là một trong những hơn kinh nghiệm đáng nhớ trong lớp. Sau đó thực hiện là do, và sau đó Hội chợ gay cấn CS50. Thêm chi tiết về tất cả các trong những tuần tới. Nhưng chúng ta hãy quay trở lại một cái gì đó trường học cũ - một lần nữa, một mảng. Vì vậy, một mảng đã được tốt đẹp, bởi vì nó giải quyết các vấn đề như chúng ta đã thấy chỉ là một thời điểm trước đây với các cấu trúc sinh viên nhận được một trong số ít kiểm soát nếu chúng ta muốn có một sinh viên, sinh viên hai, sinh ba, sinh viên chấm chấm chấm, một số tùy ý của học sinh. Vì vậy, mảng, một vài tuần trước, nhào trong và giải quyết tất cả các vấn đề của chúng ta về không biết trước bao nhiêu thứ của một số loại mà chúng ta muốn. Và chúng tôi đã nhìn thấy rằng cấu trúc có thể giúp chúng tôi tổ chức thêm mã của chúng tôi và giữ biến khái niệm tương tự, như một tên và một ngôi nhà, cùng nhau, để chúng ta có thể đối xử với họ như một thực thể, trong trong đó có phần nhỏ hơn. Nhưng mảng có một số nhược điểm. Một số nhược điểm là gì chúng tôi đã gặp phải với mảng cho đến nay? Đó là những gì? Kích thước cố định - vì vậy mặc dù em có thể có thể cấp phát bộ nhớ cho một mảng, một khi bạn biết có bao nhiêu sinh viên bạn có, bao nhiêu ký tự mà bạn có từ người sử dụng, một khi bạn đã phân bổ mảng, bạn đã loại sơn mình vào một góc. Bởi vì bạn không thể chèn các phần tử mới vào giữa một mảng. Bạn không thể chèn các yếu tố khác ở phần cuối của một mảng. Thực sự, bạn phải nghỉ mát để tạo ra một toàn bộ mảng mới, như chúng ta đã thảo luận, sao chép cũ thành mới. Và một lần nữa, đó là nhức đầu GetString giao dịch với bạn. Nhưng một lần nữa, bạn có thể thậm chí không chèn một cái gì đó vào giữa mảng nếu tỷ lệ không hoàn toàn đầy. Ví dụ, nếu mảng này đây kích thước Sáu chỉ có năm điều trong nó, tốt, bạn có thể chỉ là chiến thuật một cái gì đó vào cuối cùng. Nhưng nếu bạn muốn chèn một cái gì đó vào giữa mảng, mặc dù nó có thể có năm trong số sáu thứ trong nó? Vâng, những gì chúng tôi đã làm khi chúng ta đã có tất cả của những người tình nguyện của chúng tôi trên sân khấu trong tuần qua? Nếu chúng ta muốn đặt một người nào đó ở đây, hoặc những người này như thế nào để di chuyển này cách, hoặc những người này như thế nào để di chuyển này cách, và trở nên đắt đỏ. Việc chuyển dịch của người bên trong của một mảng kết thúc thêm lên và chi phí chúng tôi thời gian, do đó rất nhiều n bình phương của chúng tôi lần chạy như sắp xếp chèn, cho Ví dụ, trong trường hợp xấu nhất. Vì vậy, mảng là rất lớn, nhưng bạn phải biết trước lớn như thế nào bạn muốn họ. Vì vậy, OK, đây là một giải pháp. Nếu tôi không biết trước bao nhiêu sinh viên tôi có thể có, và tôi biết một lần Tôi quyết định, tuy nhiên, tôi bị mắc kẹt với nhiều sinh viên, tại sao không tôi chỉ luôn luôn phân bổ gấp đôi không gian như tôi có thể nghĩ rằng tôi cần? Là không phải là một giải pháp hợp lý? Thực tế, tôi không nghĩ rằng chúng tôi sẽ cần nhiều hơn 50 khe cắm trong một mảng cho một lớp học cỡ trung bình, vì vậy hãy chỉ làm tròn. Tôi sẽ làm cho 100 khe trong mảng của tôi, chỉ cần để chúng tôi chắc chắn có thể nhận được số lượng sinh viên tôi mong đợi để có trong một số lớp học vừa. Vì vậy, tại sao không chỉ làm tròn và phân bổ bộ nhớ hơn, thông thường, một mảng hơn bạn nghĩ rằng bạn thậm chí có thể cần? Pushback đơn giản này là những gì ý tưởng đó? Bạn chỉ lãng phí bộ nhớ. Nghĩa là tất cả các chương trình bạn viết sau đó là có thể sử dụng hai lần như nhiều bộ nhớ như bạn thực sự cần. Và rằng chỉ cần không cảm thấy giống như một đặc biệt là giải pháp thanh lịch. Hơn nữa, nó chỉ làm giảm xác suất của một vấn đề. Nếu bạn xảy ra để có một khóa học phổ biến một học kỳ và bạn có 101 sinh viên, chương trình của bạn vẫn còn về cơ bản phải đối mặt với cùng một vấn đề. Vì vậy, may mắn thay, có một giải pháp để quảng cáo này tất cả các vấn đề của chúng tôi trong các hình thức cấu trúc dữ liệu mà phức tạp hơn so với những người chúng ta đã thấy cho đến nay. Này, tôi khẳng định, là một danh sách liên kết. Đây là một danh sách các số - 9, 17, 22, 26, và 34 - đã được liên kết với nhau bằng cách về những gì tôi đã rút ra như mũi tên. Nói cách khác, nếu tôi muốn đại diện cho một mảng, tôi có thể làm một cái gì đó như thế này. Và tôi sẽ đặt này trên trên không chỉ trong một thời điểm. Tôi có thể làm - xin chào, tất cả các bên phải. Đứng. Máy tính mới đây, rõ ràng - Được rồi. Vì vậy, nếu tôi có những con số trong mảng - 9, 17, 22, 26, 24 - không nhất thiết phải mở rộng quy mô. Được rồi, vì vậy đây là mảng của tôi - oh my god. Được rồi, vì vậy đây là mảng của tôi. Oh my god. [Cười] DAVID Malan: Giả vờ. Đó là quá nhiều nỗ lực để quay trở lại và khắc phục điều đó, vì vậy - 26. Vì vậy, chúng ta có mảng này 9, 17, 22, 26, và 34. Đối với những người bạn sẽ nhìn thấy sai lầm đáng xấu hổ tôi chỉ cần thực hiện, có nó được. Vì vậy, tôi cho rằng đây là một giải pháp rất hiệu quả. Tôi đã được phân bổ như nhiều số nguyên như Tôi cần - một, hai, ba, bốn, năm, hoặc sáu - và tôi đã sau đó lưu trữ những con số bên trong của mảng này. Nhưng giả sử, sau đó, tôi muốn chèn một giá trị như số 8? Tốt, nơi nào nó đi? Giả sử tôi muốn chèn một số như 20. Tốt, nơi nào nó đi? Ở nơi nào đó ở giữa, hoặc số 35 đã đi một nơi nào đó ở cuối. Nhưng tôi là tất cả ra khỏi không gian. Và do đó, đây là một thách thức cơ bản của mảng mà là giải pháp. Tôi tuyên bố một thời điểm trước đây, GetString giải quyết vấn đề này. Nếu bạn muốn chèn một số thứ sáu vào mảng này, những gì là ít nhất một giải pháp bạn có thể rơi trở lại cho chắc chắn, giống như chúng ta làm với GetString? Đó là những gì? Tốt, làm cho nó lớn hơn được nói dễ hơn làm. Chúng ta không thể nhất thiết phải làm cho mảng lớn hơn, nhưng những gì chúng tôi có thể làm gì? Thực hiện một mảng mới đó là lớn hơn, kích thước 6, hoặc có kích thước 10, nếu chúng ta muốn để có được trước mọi thứ, và sau đó sao chép mảng cũ sang mới, và sau đó giải phóng mảng cũ. Nhưng thời gian hoạt động là những gì tại của quá trình đó? Đó là O lớn của n, bởi vì việc sao chép là sẽ chi phí bạn một số đơn vị thời gian, vì vậy không nên lý tưởng nếu chúng ta phải cấp phát một mảng mới, mà là có tiêu thụ gấp đôi bộ nhớ tạm thời. Sao chép cũ thành mới - Ý tôi là, nó chỉ là một nhức đầu, mà được, một lần nữa, lý do tại sao chúng tôi đã viết GetString cho bạn. Vì vậy, những gì chúng tôi có thể làm gì để thay thế? Vâng, nếu cấu trúc dữ liệu của chúng tôi thực sự có những khoảng trống trong nó? Giả sử tôi thư giãn mục tiêu của tôi có khối tiếp giáp của bộ nhớ, nơi 9 là ngay bên cạnh 17, đó là ngay bên cạnh 22, và như vậy. Và cho rằng số 9 có thể được ở đây trong Bộ nhớ RAM, và 17 có thể được ở đây trong bộ nhớ RAM, và 22 có thể được ở đây trong bộ nhớ RAM. Nói cách khác, tôi không cần họ thậm chí sao lưu để sao nữa. Tôi chỉ có bằng cách nào đó luồn kim qua từng con số, hoặc mỗi các nút này, như chúng tôi sẽ gọi hình chữ nhật như tôi đã rút ra cho họ, để nhớ làm thế nào để có được đến cuối cùng nút như vậy từ đầu tiên. Vì vậy, những gì là lập trình xây dựng chúng tôi đã nhìn thấy thời gian gần đây mà tôi có thể thực hiện chủ đề đó, hoặc rút ra ở đây, mà tôi có thể thực hiện những mũi tên? Con trỏ như vậy, phải không? Nếu tôi phân bổ không chỉ là một int, nhưng một nút - và nút, tôi chỉ có nghĩa là container. Và trực quan, tôi có nghĩa là một hình chữ nhật. Vì vậy, một nút rõ ràng cần chứa hai giá trị - int riêng của mình, và sau đó, như ngụ ý của nửa dưới của hình chữ nhật, đủ không gian cho một int. Vì vậy chỉ cần suy nghĩ trước đây, lớn như thế nào là nút này, điều này chứa trong câu hỏi? Bao nhiêu byte cho int? Có lẽ là 4, nếu nó giống như bình thường. Và sau đó bao nhiêu byte cho con trỏ? 4. Vì vậy, bình chứa, hoặc nút này, là sẽ là một cấu trúc 8-byte. Oh, và đó là một trùng hợp ngẫu nhiên hạnh phúc chúng tôi chỉ giới thiệu khái niệm này một cấu trúc, hoặc một cấu trúc C. Vì vậy, tôi cho rằng tôi muốn có một bước hướng này phức tạp hơn thực hiện một danh sách các số, một danh sách liên kết các con số, tôi cần phải làm một suy nghĩ nhiều hơn một chút lên phía trước và tuyên bố không chỉ là một int, nhưng một cấu trúc mà tôi sẽ gọi, thông thường đây, nút. Chúng ta có thể gọi nó là bất cứ điều gì chúng ta muốn, nhưng nút là có được chuyên đề trong rất nhiều trong những điều chúng tôi bắt đầu xem xét ngay bây giờ. Bên trong của nút đó là một n int. Và sau đó cú pháp này, một chút lạ ở cái nhìn đầu tiên - struct node * tiếp theo. Cũng những bức tranh, đó là những gì? Đó là nửa dưới của hình chữ nhật mà chúng ta đã thấy chỉ là một thời điểm trước đây. Nhưng tại sao tôi nói rằng cấu trúc nút * như trái ngược với chỉ nút *? Bởi vì nếu con trỏ đang trỏ tại nút khác, nó chỉ là địa chỉ của một nút. Đó là phù hợp với những gì chúng tôi đã thảo luận về con trỏ cho đến nay. Nhưng tại sao, nếu tôi khẳng định cấu trúc này là gọi là nút, tôi có thể nói cấu trúc nút trong đây? Chính xác. Đó là sắp xếp của một thực tế ngu ngốc của C. Typedef, có thể nói, có không xảy ra. C là siêu đen. Nó đọc trên mã của bạn để phía dưới, từ trái sang phải. Và đến khi nó chạm dấu chấm phẩy mà trên dòng dưới cùng, đoán những gì không tồn tại như một kiểu dữ liệu? Nút, nút unquote giá. Nhưng vì nhiều tiết tuyên bố tôi đã làm trên dòng đầu tiên - nút typedef struct - bởi vì đó đến đầu tiên, trước khi dấu ngoặc nhọn, đó là loại giống như trước giáo dục kêu vang đó, bạn biết những gì, cho tôi một cấu trúc gọi là nút cấu trúc. Thành thật mà nói, tôi không thích những thứ gọi cấu trúc nút, cấu trúc nút tất cả trong mã của tôi. Nhưng tôi sẽ chỉ sử dụng nó một lần, chỉ cần bên trong, để tôi có thể có hiệu quả tạo ra một loại tài liệu tham khảo thông tư, không một con trỏ đến bản thân mình cho mỗi gia nhập, nhưng một con trỏ đến một của một loại giống hệt nhau. Vì vậy, nó chỉ ra rằng trên một cấu trúc dữ liệu như thế này, có một vài hoạt động đó có thể là quan tâm đến chúng tôi. Chúng tôi có thể muốn chèn vào một danh sách như thế này. Chúng tôi có thể muốn xóa từ một danh sách như thế này. Chúng tôi có thể muốn tìm kiếm danh sách cho một giá trị, hay rộng hơn, đi qua. Và đi qua chỉ là một cách ưa thích của nói rằng bắt đầu ở bên trái và di chuyển tất cả các đường bên phải. Và thông báo, ngay cả với điều này hơn một chút cấu trúc dữ liệu phức tạp, chúng ta hãy tôi đề nghị rằng chúng ta có thể vay một số những ý tưởng của hai tuần qua và thực hiện một chức năng được gọi là tìm kiếm như thế này. Nó sẽ trở lại đúng hay sai, cho thấy, có hoặc không, n là trong danh sách. Số thứ hai của nó là một con trỏ vào danh sách riêng của mình, do đó, một con trỏ đến một nút. Tất cả tôi sẽ để sau đó làm là khai báo một biến tạm thời. Chúng tôi sẽ gọi nó là ptr theo quy ước, cho con trỏ. Và tôi chỉ định nó bằng đầu danh sách. Và bây giờ thông báo các vòng lặp while. Vì vậy, miễn là con trỏ là không bình đẳng thành vô giá trị, tôi sẽ kiểm tra. Là con trỏ mũi tên n bằng n được thông qua vào? Và chờ một phút - mới mảnh cú pháp. Mũi tên là tất cả những gì của một bất ngờ? Yeah? Chính xác. Vì vậy, trong khi một vài phút trước đây, chúng tôi sử dụng các ký hiệu dấu chấm để truy cập vào một cái gì đó bên trong một cấu trúc, nếu biến bạn đã không phải là cấu trúc chính nó, nhưng một con trỏ đến một cấu trúc, may mắn thay, một phần của cú pháp cuối cùng có ý nghĩa trực quan. Mũi tên có nghĩa là theo con trỏ, như mũi tên của chúng tôi thường có nghĩa là những bức tranh, và đi tại trường dữ liệu bên trong. Vì vậy, mũi tên là điều tương tự như dấu chấm, nhưng bạn sử dụng nó khi bạn có một con trỏ. Vì vậy, tóm lại là sau đó, nếu lĩnh vực n bên trong các cấu trúc được gọi là con trỏ bằng bằng n, trả lại sự thật. Nếu không, dòng này đây - con trỏ bằng con trỏ tới. Vì vậy, những gì đang thực hiện, thông báo, là nếu tôi hiện đang chỉ vào các cấu trúc chứa 9 và 9 không phải là số Tôi đang tìm - cho rằng tôi đang tìm cho n bằng 50 - Tôi sẽ cập nhật con trỏ tạm thời của tôi không chỉ vào nút này nữa, nhưng con trỏ mũi tên bên cạnh, mà là sẽ đưa tôi lên đây. Bây giờ, tôi nhận ra là một cơn lốc giới thiệu. Thứ tư, chúng tôi thực sự sẽ làm điều này với một số người và với một số chi tiết mã ở một tốc độ chậm hơn. Nhưng nhận ra, bây giờ chúng tôi đang làm cho dữ liệu của chúng tôi cấu trúc phức tạp hơn để chúng tôi các thuật toán có thể nhận được hiệu quả hơn, mà sẽ là điều kiện tiên quyết cho pset sáu, khi chúng ta nạp vào, một lần nữa, những 150.000 từ, nhưng cần phải làm như vậy hiệu quả, và lý tưởng, tạo ra một chương trình chạy cho người dùng của chúng tôi không trong tuyến tính, không trong n bình phương, nhưng trong thời gian liên tục, trong lý tưởng. Chúng ta sẽ thấy bạn vào thứ tư. Loa: Tại CS50 tiếp theo, David quên trường hợp cơ sở của mình. DAVID Malan: Và đó là cách bạn gửi tin nhắn văn bản với C. Cái gì - [CÁC VĂN BẢN THÔNG ĐIỆP THÔNG BÁO SOUNDS]