[Powered by Google Translate] [Tuần 4] [David J. Malan] [Đại học Harvard] [Đây là CS50.] [CS50.TV] Được rồi, đây là CS50, và điều này là sự bắt đầu của tuần thứ 4, và đây là một trong các thuật toán phân loại chậm nhất có thể. Đó một lần mà chúng tôi chỉ xem đó? Đó là bong bóng sắp xếp, để lớn O (n ^ 2) + tổng hợp, và thực sự chúng tôi không phải là những người duy nhất trong thế giới này dường như biết bong bóng sắp xếp thời gian chạy của nó. Thật vậy, đây là một cuộc phỏng vấn với Eric Schmidt của Google và cựu Thượng nghị sĩ Barack Obama chỉ là một vài năm trước đây. Bây giờ, Thượng nghị sĩ, bạn ở đây tại Google, và tôi thích nghĩ của nhiệm kỳ tổng thống là một cuộc phỏng vấn việc làm. Bây giờ, thật khó để có được một công việc như là chủ tịch, và bạn đang trải qua sự khắc nghiệt. Nó cũng khó để có được một công việc tại Google. Chúng tôi có thắc mắc, và chúng tôi yêu cầu ứng viên câu hỏi, và điều này là từ Larry Schwimmer. Các bạn nghĩ rằng tôi đang đùa? Nó ở ngay đây. Cách hiệu quả nhất để sắp xếp một triệu số nguyên 32-bit là gì? [Cười] Well- Tôi xin lỗi >> Không, không, không, không. Tôi nghĩ rằng các loại bong bóng sẽ là con đường sai để đi. Thôi nào, người đã nói với anh như thế? Tuần trước, nhớ lại chúng tôi đã nghỉ một từ mã, ít nhất là trong một ngày, và bắt đầu tập trung vào một số ý tưởng cấp độ cao hơn và giải quyết vấn đề nói chung trong bối cảnh tìm kiếm và phân loại, và chúng tôi giới thiệu một cái gì đó mà chúng tôi không tát tên này vào tuần trước, nhưng tiệm cận ký hiệu, Big O, Omega Big, và đôi khi Theta Big ký hiệu, và những đơn giản chỉ là cách mô tả thời gian chạy của thuật toán, phải mất bao nhiêu thời gian cho một thuật toán để chạy. Và bạn có thể nhớ lại rằng bạn nói chuyện về thời gian hoạt động về kích thước của các đầu vào, mà chúng ta thường gọi là n, bất cứ vấn đề có thể, trong đó n là số lượng người trong phòng, số lượng các trang trong một cuốn sách điện thoại, và chúng tôi bắt đầu viết những điều trên như O (n ^ 2) hoặc O (n) hoặc O (n log n), và ngay cả khi tính toán không làm việc khá hoàn hảo và nó đã được n ² - n / 2 hoặc một cái gì đó như thế chúng tôi thay vì chỉ ném đi một số các điều khoản cấp thấp hơn, và động cơ là chúng ta thực sự muốn có một sắp xếp cách khách quan đánh giá việc thực hiện các chương trình, hoạt động của các thuật toán vào cuối ngày không có gì để làm, ví dụ, với tốc độ của máy tính của bạn ngày hôm nay. Ví dụ, nếu bạn thực hiện loại bong bóng, hoặc bạn thực hiện hợp nhất phân loại hoặc lựa chọn sắp xếp trên máy tính ngày nay, 2 GHz máy tính, và bạn chạy nó, và phải mất một số giây, trong năm tới có GHz 3 hoặc 4 GHz máy tính, và sau đó bạn có thể cho rằng "Wow, thuật toán của tôi bây giờ là nhanh gấp hai lần ", trong khi thực tế rõ ràng là không phải như vậy. Nó chỉ là phần cứng đã nhận được nhanh hơn, nhưng máy tính của bạn không và vì vậy chúng tôi thực sự muốn vứt bỏ những thứ như bội số của 2 hoặc bội số của 3 khi nói đến mô tả nhanh như thế nào hoặc làm thế nào chậm thuật toán là thực sự chỉ tập trung n hoặc một số yếu tố của, một số quyền lực hiện như trong trường hợp của các loại so với tuần trước. Và nhớ lại rằng với sự giúp đỡ của loại hợp nhất chúng tôi đã có thể làm tốt hơn rất nhiều hơn loại bong bóng và sắp xếp lựa chọn và thậm chí chèn loại. Chúng tôi đã xuống đến n log n, và một lần nữa, nhớ lại rằng log n thường dùng để chỉ một cái gì đó mà phát triển chậm hơn sau đó n, vì vậy n log n vậy, đến nay là tốt bởi vì nó là ít hơn n ². Nhưng để đạt được n đăng nhập n với loại hợp nhất mầm mống cơ bản của một ý tưởng mà chúng tôi đã tận dụng được những gì rằng chúng ta cũng thừa hưởng trở lại trong tuần 0? Làm thế nào chúng ta giải quyết các vấn đề sắp xếp khéo léo với merge loại? Cái nhìn sâu sắc quan trọng là gì, có lẽ? Bất cứ ai ở tất cả. Được rồi, chúng ta hãy lùi lại một bước. Mô tả hợp nhất sắp xếp theo cách của bạn. Làm thế nào nó hoạt động? Được rồi, chúng tôi sẽ chèo trở lại 0 tuần. Được rồi, yeah. [Không nghe được học sinh] Được rồi, tốt, vì vậy chúng tôi chia các mảng của các con số thành 2 mảnh. Chúng tôi sắp xếp những mảnh, và sau đó chúng tôi kết hợp chúng, và chúng tôi đã nhìn thấy ý tưởng này trước khi tham gia một vấn đề lớn này và cắt nó ra thành một vấn đề đó là lớn hay lớn này. Nhớ lại những ví dụ cuốn sách điện thoại. Nhớ lại những thuật toán tự đếm từ vài tuần trước đây, sort hợp nhất tóm tắt của thành viên này giả ở đây. Khi bạn đang đưa ra n phần tử, đầu tiên là kiểm tra sanity. Nếu n <2 sau đó không làm bất cứ điều gì ở tất cả bởi vì nếu n <2 sau đó n rõ ràng là 0 hoặc 1, và vì vậy nếu nó là 0 hoặc 1 không có gì để sắp xếp. Bạn đang làm. Danh sách của bạn đã được trivially sắp xếp. Nhưng nếu không nếu bạn đã có 2 hoặc nhiều hơn các yếu tố đi trước và chia chúng thành 2 nửa, trái và phải. Sắp xếp của những người nửa, và sau đó hợp nhất các nửa sắp xếp. Nhưng vấn đề ở đây là ở cái nhìn đầu tiên này cảm thấy như chúng tôi đang punting. Đây là một định nghĩa vòng tròn trong đó nếu tôi đã hỏi bạn sắp xếp các yếu tố n và bạn đang nói với tôi "Được rồi, tốt, chúng tôi sẽ sắp xếp những yếu tố n / 2 và những n / 2", sau đó câu hỏi tiếp theo của tôi là có được "Được rồi, làm thế nào để sắp xếp n / 2 phần tử?" Tuy nhiên, vì cấu trúc của chương trình này, bởi vì có trường hợp này cơ sở, có thể nói, trường hợp đặc biệt này nói rằng nếu n là > Sara, tất cả các quyền. Kelly. >> Kelly và? Willy. >> Willy, Sara, Kelly, và Willy. Ngay bây giờ tôi đã được hỏi những câu hỏi của một ai đó bao nhiêu người trên sân khấu này, và tôi không có ý tưởng. Đây là một danh sách rất dài, và do đó, thay vì tôi sẽ làm điều này lừa. Tôi sẽ yêu cầu người bên cạnh tôi để làm hầu hết công việc, và khi cô ấy được thực hiện làm hầu hết công việc Tôi sẽ làm số tiền ít nhất có thể làm việc và chỉ cần thêm 1 bất cứ câu trả lời của cô, vì vậy ở đây chúng tôi đi. Tôi đã yêu bao nhiêu người trên sân khấu. Có bao nhiêu người trên sân khấu để bên trái của bạn? Bên trái của tôi >> Được rồi, nhưng không ăn gian. Đó là tốt, đó là chính xác, nhưng nếu chúng ta muốn tiếp tục logic này chúng ta hãy giả sử rằng bạn tương tự như muốn punt vấn đề này để bên trái của bạn, chứ không phải là câu trả lời trực tiếp đi trước và chỉ cần vượt qua các buck. Oh, có bao nhiêu người bên trái của tôi? Có bao nhiêu người bên trái? 1. [Cười] Được rồi, do đó, 0, vì vậy những gì bây giờ Willy đã làm là bạn đã quay trở lại câu trả lời của bạn hướng này nói rằng 0. Bây giờ, những gì bạn nên làm gì? >> 1. Được rồi, do đó, bạn là số 1, vì vậy bạn nói, "Được rồi, tôi sẽ thêm 1 để bất cứ điều gì Willy đếm được ", vì vậy 1 + 0. Bây giờ bạn đã 1 do đó, câu trả lời của bạn bên phải bây giờ là 1. >> Và tôi sẽ là 2. Tốt, do đó, bạn đang dùng các câu trả lời trước của 1, thêm số tiền tối thiểu của công việc bạn muốn làm, mà là +1. Bây giờ bạn có 2, và sau đó bạn đưa cho tôi mà giá trị? 3, tôi có nghĩa là, xin lỗi, 2. Tốt. Vâng, chúng tôi đã có 0 bên trái. Sau đó, chúng tôi đã có 1, và sau đó chúng tôi thêm 2, và bây giờ bạn đang trao cho tôi số 2, và vì vậy tôi đang nói, okay, +1, 3. Có thực sự 3 người đứng cạnh tôi trên sân khấu này, vì vậy chúng tôi có thể đã rõ ràng làm điều này rất tuyến tính, rất nhiều trong thời trang rõ ràng, nhưng những gì chúng tôi đã thực sự làm? Chúng tôi đã là một vấn đề có kích thước 3 ban đầu. Sau đó chúng tôi đã phá vỡ nó xuống thành một vấn đề về kích thước 2, sau đó là một vấn đề có kích thước 1, và cuối cùng trường hợp cơ sở thật sự, oh, không có ai ở đó, điểm mà tại đó Willy trở lại có hiệu quả một câu trả lời cứng mã hóa một vài lần, và một trong những thứ hai sau đó đã được sôi nổi, sôi nổi, sôi nổi, và sau đó thêm này thêm một 1 chúng tôi đã thực hiện ý tưởng này cơ bản của đệ quy. Bây giờ, trong trường hợp này, nó không thực sự giải quyết một vấn đề bất kỳ hiệu quả hơn sau đó chúng tôi đã nhìn thấy cho đến nay. Nhưng hãy nghĩ về các thuật toán chúng tôi đã thực hiện trên sân khấu vậy, đến nay. Chúng tôi đã có 8 miếng giấy lên bảng, trên video khi Sean đang tìm kiếm cho số 7, và ông đã làm những gì thực sự làm? À, anh ấy đã không làm bất kỳ loại phân chia và chinh phục. Ông đã không làm bất kỳ loại đệ quy. Thay vì ông đã làm điều này thuật toán tuyến tính. Nhưng khi chúng tôi giới thiệu ý tưởng của các số được sắp xếp trên sân khấu sống tuần trước sau đó chúng tôi đã có bản năng đi đến giữa, tại thời điểm đó, chúng tôi đã có một danh sách nhỏ hơn kích thước 4 hoặc danh sách khác của kích thước 4, và sau đó chúng tôi đã có cùng một vấn đề chính xác, vì vậy chúng tôi lặp đi lặp lại, lặp đi lặp lại, lặp đi lặp lại. Nói cách khác, chúng tôi recursed. Cảm ơn bạn rất nhiều đến 3 tình nguyện viên của chúng tôi ở đây để chứng minh đệ quy với chúng tôi. Hãy xem nếu chúng ta không thể thực hiện điều này cụ thể hơn một chút, việc giải quyết một vấn đề mà một lần nữa chúng ta có thể làm được khá dễ dàng, nhưng chúng tôi sẽ sử dụng nó như là một bước để thực hiện ý tưởng này cơ bản. Nếu tôi muốn để tính toán tổng của một loạt các con số, Ví dụ, nếu bạn vượt qua trong số 3, Tôi muốn cung cấp cho bạn giá trị của sigma 3, như vậy tổng của 3 + 2 + 1 + 0. Tôi muốn nhận được câu trả lời 6, do đó, chúng tôi sẽ thực hiện chức năng này sigma, chức năng này tổng kết , một lần nữa, có trong đầu vào, và sau đó trả về tổng kết của con số tất cả các cách xuống 0. Chúng ta có thể làm điều này khá đơn giản, phải không? Chúng ta có thể làm điều này với một số loại cấu trúc vòng lặp, vì vậy hãy để tôi đi trước và điều này bắt đầu. Bao gồm stdio.h. Hãy để tôi nhận được bản thân mình vào chính để làm việc ở đây. Hãy lưu là sigma.c. Sau đó, tôi sẽ đi ở đây, và tôi sẽ khai báo một n int, và tôi sẽ làm như sau trong khi người sử dụng không hợp tác. Trong khi người sử dụng đã không cho tôi một số dương hãy để tôi đi trước và nhắc nhở họ cho n = getInt, và để cho tôi cung cấp cho họ một số hướng dẫn như những gì để làm, để printf ("Tích cực số nguyên"). Chỉ cần một cái gì đó tương đối đơn giản như thế này để theo thời gian, chúng tôi nhấn dòng 14 bây giờ chúng ta có một số nguyên dương có lẽ trong n. Bây giờ chúng ta hãy làm một cái gì đó với nó. Hãy để tôi đi trước và tính toán tổng kết, vì vậy int sum = sigma (n). Sigma chỉ là tổng kết, vì vậy tôi chỉ viết nó trong cách fancier. Chúng tôi sẽ chỉ gọi nó là sigma có. Đó là số tiền, và bây giờ tôi sẽ in ra kết quả, printf ("tổng hợp là% d \ n", tổng hợp). Và sau đó tôi sẽ trở về 0 cho các biện pháp tốt. Chúng tôi đã làm tất cả mọi thứ mà chương trình này đòi hỏi ngoại trừ phần thú vị, đó là thực sự thực hiện chức năng sigma. Hãy để tôi đi xuống đây vào phía dưới, và để cho tôi tuyên bố chức năng sigma. Nó có để có một biến kiểu số nguyên, và những gì loại dữ liệu nào tôi muốn trở lại có lẽ là từ sigma? Int, bởi vì tôi muốn nó để phù hợp với mong đợi của tôi trên dòng 15. Tại đây, hãy để tôi đi trước và thực hiện điều này một cách khá đơn giản. Chúng ta hãy đi trước và nói int sum = 0, và bây giờ tôi sẽ đi một chút cho vòng lặp ở đây đó là sẽ nói một cái gì đó như thế này, for (int i = 0; I <= số; i + +) tổng + = i. Và sau đó tôi sẽ trả lại số tiền. Tôi đã có thể thực hiện điều này trong bất kỳ số cách khác nhau. Tôi đã có thể sử dụng một vòng lặp while. Tôi có thể bỏ qua bằng cách sử dụng các biến số tiền nếu tôi thực sự muốn, nhưng trong ngắn hạn, chúng tôi chỉ có một chức năng mà nếu tôi không goof tuyên bố số tiền là 0. Sau đó, nó lặp từ 0 lên thông qua số lượng, và mỗi lần lặp, nó cho biết thêm rằng giá trị hiện tại tổng hợp và sau đó trả về tổng hợp. Bây giờ, có một tối ưu hóa nhẹ ở đây. Đây có lẽ là một bước lãng phí, nhưng để được nó. Đó là tốt cho bây giờ. Chúng tôi ít nhất là kỹ lưỡng và sẽ 0 tất cả các cách trên lên. Không phải rất khó khăn và khá đơn giản, nhưng nó quay ra rằng với chức năng sigma chúng tôi có cơ hội như nhau như chúng ta đã ở đây trên sân khấu. Trên sân khấu, chúng tôi chỉ đếm được có bao nhiêu người bên cạnh tôi, nhưng thay vào đó nếu chúng ta muốn đếm số 3 + 2 + 1 trên xuống đến 0, chúng ta có thể tương tự như punt đến một chức năng mà tôi thay vào đó sẽ mô tả như là đệ quy. Ở đây, chúng ta hãy làm một sự tỉnh táo nhanh chóng kiểm tra và chắc chắn rằng tôi đã không goof. Tôi biết có ít nhất một điều trong chương trình này mà tôi đã làm sai. Khi tôi nhấn vào tôi để có được bất kỳ loại la tôi? Những gì tôi sẽ hét lên vào khoảng? Yeah, tôi quên các mẫu thử nghiệm, do đó, tôi đang sử dụng một chức năng được gọi là sigma on line 15, nhưng nó không được khai báo cho đến dòng 22, vì vậy tôi tốt nhất chủ động đi lên và tuyên bố một mẫu thử nghiệm, và tôi sẽ nói int sigma (int number), và đó là nó. Nó được thực hiện ở phía dưới. Hoặc một cách khác tôi có thể giải quyết vấn đề này, Tôi có thể di chuyển các chức năng trên đó, mà không phải là xấu, nhưng ít nhất là khi chương trình của bạn bắt đầu để có được lâu dài, thẳng thắn, Tôi nghĩ rằng có một số giá trị luôn luôn có chính ở đầu để bạn đọc có thể mở các tập tin và sau đó ngay lập tức nhìn thấy những gì chương trình được thực hiện mà không cần phải tìm kiếm thông qua nó tìm kiếm cho rằng chức năng chính. Hãy đi xuống vào cửa sổ thiết bị đầu cuối của tôi ở đây, hãy thử làm sigma làm cho sigma, và tôi hơi say lên ở đây quá. Implicit tuyên bố getInt chức năng có nghĩa là tôi đã quên làm những gì khác? [Không nghe được học sinh] Tốt, như vậy rõ ràng là một sai lầm phổ biến, vì vậy chúng ta hãy đặt này lên đây, cs50.h, và bây giờ hãy quay trở lại cửa sổ thiết bị đầu cuối của tôi. Tôi sẽ xóa màn hình, và tôi sẽ chạy lại làm cho sigma. Nó dường như đã biên soạn. Hãy để tôi bây giờ chạy sigma. Tôi sẽ nhập vào số 3, và tôi đã nhận được 6, do đó, không phải là một kiểm tra nghiêm ngặt, nhưng ít nhất có vẻ như được làm việc ở cái nhìn đầu tiên, nhưng bây giờ hãy rip nó ngoài, và chúng ta hãy thực sự tận dụng ý tưởng của đệ quy, một lần nữa, trong một bối cảnh rất đơn giản vì vậy mà trong một thời gian vài tuần khi chúng tôi bắt đầu khám phá fancier cấu trúc dữ liệu cho các mảng chúng ta có một công cụ trong bộ công cụ nào đó để thao tác các cấu trúc dữ liệu như chúng ta sẽ thấy. Đây là phương pháp lặp đi lặp lại, cách tiếp cận dựa trên vòng lặp. Hãy để tôi thay vì bây giờ làm điều này. Hãy để tôi thay vì nói rằng tổng của số lượng xuống 0 thực sự là điều tương tự như số + sigma (số 1). Nói cách khác, giống như trên sân khấu tôi punted mỗi người bên cạnh tôi, và họ lần lượt giữ punting cho đến khi chúng tôi cuối cùng đã chạm đáy tại Willy, người đã phải trả lại một câu trả lời cứng mã hóa như 0. Ở đây bây giờ chúng ta đang tương tự như punting sigma chức năng giống như ban đầu được gọi là, nhưng cái nhìn sâu sắc quan trọng ở đây rằng chúng tôi không gọi sigma giống nhau. Chúng tôi không đi qua trong n. Rõ ràng chúng ta đang đi qua trong số 1, do đó, một vấn đề hơi nhỏ hơn, nhỏ hơn một chút vấn đề. Thật không may, điều này không phải là một giải pháp được nêu ra, và trước khi chúng tôi sửa chữa những gì có thể nhảy ra khỏi rõ ràng tại một số các bạn hãy để tôi đi trước và chạy lại làm. Nó dường như biên dịch được không. Hãy để tôi chạy lại sigma với 6. Whoops, tôi chạy lại sigma với 6. Chúng tôi đã nhìn thấy điều này trước khi, mặc dù thời gian vô tình cuối cùng là tốt. Tại sao tôi nhận được lỗi phân khúc này khó hiểu? Yeah. [Không nghe được học sinh] Không có trường hợp cơ sở, và đặc biệt hơn, những gì có thể xảy ra? Đây là một triệu chứng của những hành vi nào? Nói nó to hơn một chút. [Không nghe được học sinh] Đây là một vòng lặp vô hạn có hiệu quả, và vấn đề với các vòng lặp vô hạn khi chúng liên quan đến đệ quy trong trường hợp này, một chức năng gọi điện thoại, điều gì sẽ xảy ra mỗi khi bạn gọi một chức năng? Vâng, nghĩ lại làm thế nào chúng ta đặt ra bộ nhớ trong một máy tính. Chúng tôi nói rằng có đoạn bộ nhớ này được gọi là ngăn xếp ở phía dưới cùng, và mỗi khi bạn gọi một chức năng nhiều hơn một chút bộ nhớ được đặt trên stack này được gọi là có chứa các biến địa phương hoặc các thông số của chức năng đó, vì vậy nếu sigma gọi sigma cuộc gọi sigma gọi sigma  gọi sigma kết thúc câu chuyện này? Vâng, nó cuối cùng đã vượt tổng số tiền bộ nhớ mà bạn có sẵn cho máy tính của bạn. Bạn tràn ngập các phân khúc mà bạn đang nghĩ ở bên trong, và bạn nhận được lỗi phân khúc này, lõi bán phá giá, và những gì core dumped có nghĩa là bây giờ tôi có một tập tin lõi mà là một tập tin có chứa số không và những người thân mà thực sự trong tương lai sẽ được chẩn đoán hữu ích. Nếu nó không rõ ràng cho bạn nơi lỗi của bạn là bạn thực sự có thể làm một chút phân tích pháp y, do đó, để nói chuyện, trên tập tin dump cốt lõi này, một lần nữa, chỉ là một bó toàn bộ số không và những người thân mà về cơ bản đại diện cho trạng thái của chương trình của bạn trong bộ nhớ thời điểm này, nó đã bị rơi theo cách này. Việc sửa chữa ở đây là chúng tôi có thể không chỉ một cách mù quáng trở lại sigma, số + sigma của một vấn đề nhỏ hơn một chút. Chúng tôi cần phải có một số loại trường hợp cơ sở ở đây, và trường hợp cơ sở những gì có thể được? [Không nghe được học sinh] Được rồi, miễn là số là dương chúng tôi thực sự nên trở về này, hay nói một cách khác, nếu số là, nói, <= 0 bạn biết gì, tôi sẽ đi trước và trở về 0, giống như Willy đã làm, và khác, tôi sẽ đi trước và trở về điều này, vì vậy nó không phải là ngắn hơn nhiều so với phiên bản lặp đi lặp lại mà chúng tôi whipped lên đầu tiên sử dụng một vòng lặp for, nhưng nhận thấy rằng có loại này sang trọng với nó. Thay vì trả lại một số số lượng và thực hiện tất cả những điều này toán học và thêm với các biến địa phương Thay vào đó, bạn đang nói "Được rồi, nếu điều này là một vấn đề dễ dàng siêu, như số là <0, cho tôi ngay lập tức trở về 0. " Chúng tôi sẽ không bận tâm hỗ trợ số âm, vì vậy tôi sẽ cứng mã giá trị 0. Nhưng nếu không, để thực hiện ý tưởng tổng hợp tất cả những con số này lại với nhau bạn có hiệu quả có thể ăn một miếng nhỏ trong số các vấn đề, giống như chúng tôi đã làm ở đây trên sân khấu, sau đó punt phần còn lại của vấn đề cho người kế tiếp, nhưng trong trường hợp này người tiếp theo là chính mình. Đây là một chức năng giống nhau được đặt tên. Chỉ cần vượt qua một vấn đề nhỏ hơn và nhỏ hơn và nhỏ hơn mỗi lần, và mặc dù chúng ta không có những điều khá chính thức hóa trong mã ở đây điều này là chính xác những gì đang diễn ra trong tuần 0 với các cuốn sách điện thoại. Điều này là chính xác những gì đang diễn ra trong tuần qua với Sean và với các cuộc biểu tình của chúng tôi tìm kiếm các số. Đó là một vấn đề và chia nó một lần nữa và một lần nữa. Nói cách khác, có một cách dịch thuật này xây dựng thế giới thực, xây dựng này mức độ cao hơn phân chia và chinh phục và làm một cái gì đó một lần nữa và một lần nữa trong mã, vì vậy đây là một cái gì đó chúng ta sẽ thấy một lần nữa theo thời gian. Bây giờ, khi một sang một bên, nếu bạn mới để đệ quy, bạn nên ít nhất là hiểu bây giờ lý do tại sao điều này là buồn cười. Tôi sẽ đi đến google.com, và tôi sẽ tìm kiếm một số mẹo và thủ thuật về đệ quy, nhập. Hãy nói với người bên cạnh bạn nếu chúng không được cười ngay bây giờ. Ý của bạn là đệ quy? Ý của bạn là-ah, có chúng tôi đi. Được rồi, bây giờ đó là phần còn lại của tất cả mọi người. Một quả trứng Phục Sinh ít nhúng một nơi nào đó trong Google. Là một sang một bên, một trong các liên kết mà chúng tôi đặt trên trang web của khóa học cho ngày hôm nay chỉ là lưới này của các thuật toán phân loại khác nhau, một số trong đó chúng ta nhìn vào tuần trước, nhưng những gì tốt đẹp về quán tưởng này như bạn cố gắng để bọc tâm trí của bạn xung quanh những điều khác nhau liên quan đến các thuật toán biết rằng bạn có thể rất dễ dàng bây giờ bắt đầu với các loại khác nhau của các yếu tố đầu vào. Tất cả các yếu tố đầu vào đảo ngược, các yếu tố đầu vào chủ yếu là sắp xếp, các yếu tố đầu vào ngẫu nhiên và vv. Như bạn cố gắng, một lần nữa, phân biệt những điều này trong tâm trí của bạn nhận ra rằng URL này trên trang web của khóa học trên trang bài giảng có thể giúp bạn lý do thông qua một số những người. Hôm nay chúng ta cuối cùng cũng có được để giải quyết vấn đề này từ khi trở lại, đó là chức năng này trao đổi đã không làm việc, và vấn đề cơ bản này trao đổi chức năng là gì, mục tiêu trong số đó là, một lần nữa, để trao đổi một giá trị ở đây và ở đây như vậy mà điều này xảy ra? Điều này đã không thực sự làm việc. Tại sao? Yeah. [Không nghe được học sinh] Chính xác, lời giải thích cho bugginess này chỉ đơn giản là bởi vì khi bạn gọi chức năng trong C và những chức năng đối số, như a và b ở đây, bạn đang đi qua các bản sao của bất cứ điều gì giá trị mà bạn đang cung cấp cho chức năng đó. Bạn không cung cấp các giá trị ban đầu, vì vậy chúng ta đã thấy điều này trong bối cảnh của buggyc buggy3.c, nhìn một chút gì đó như thế này. Nhớ lại rằng chúng tôi đã có x và y khởi tạo 1 và 2, tương ứng. Chúng tôi sau đó in ra những gì họ được. Sau đó tôi tuyên bố rằng tôi đã trao đổi chúng bằng cách gọi điện thoại trao đổi của x, y. Nhưng vấn đề là các trao đổi làm việc, nhưng chỉ trong phạm vi trao đổi chức năng của chính nó. Ngay khi chúng tôi nhấn đường 40 những giá trị trao đổi đã được vứt bỏ, và như vậy không có gì trong chính chức năng ban đầu đã thực sự thay đổi ở tất cả, vì vậy nếu bạn nghĩ rằng sau đó là những gì này trông giống như trong bộ nhớ của chúng tôi nếu điều này phía bên tay trái của hội đồng quản trị đại diện cho- và tôi sẽ làm tốt nhất của tôi cho mọi người xem này nếu điều này phía bên tay trái của hội đồng quản trị đại diện, nói, bộ nhớ RAM của bạn, và ngăn xếp là sẽ phát triển lên theo cách này, và chúng tôi gọi một chức năng như chính, và chính có 2 biến địa phương, x và y, hãy mô tả những người như x ở đây, và chúng ta hãy mô tả những như y, và chúng ta hãy đặt trong các giá trị 1 và 2, do đó, ở đây là chính, và khi chính các cuộc gọi chức năng hoán đổi hệ điều hành cung cấp cho các chức năng hoán đổi swath riêng của mình bộ nhớ trên stack, khung hình riêng của mình trên stack, do đó, để nói chuyện. Nó cũng phân bổ 32 bit cho các ints. Nó xảy ra để gọi a, b, nhưng đó là hoàn toàn tùy ý. Nó có thể gọi họ bất cứ điều gì nó muốn, nhưng điều gì sẽ xảy ra khi chính cuộc gọi trao đổi là phải mất 1, đặt một bản sao ở đó, đặt một bản sao ở đó. Hiện có 1 biến địa phương khác trong trao đổi, mặc dù, được gọi là >> Tmp những gì. Tmp, vì vậy hãy để tôi cung cấp cho bản thân mình khác 32 bit ở đây, và tôi đã làm gì trong chức năng này? Tôi nói int tmp được, do đó, có 1, vì vậy tôi đã làm điều này khi chúng tôi đã chơi gần với ví dụ này. Sau đó, một được b, do đó, b là 2, vì vậy bây giờ trở thành 2, và bây giờ b được temp, vì vậy temp là 1, vì vậy bây giờ b trở thành này. Đó là tuyệt vời. Nó làm việc. Nhưng sau đó, ngay sau khi trở về chức năng trao đổi của bộ nhớ một cách hiệu quả biến mất để nó có thể được tái sử dụng một số chức năng khác trong tương lai, và chính rõ ràng là hoàn toàn không thay đổi. Chúng tôi cần một cách cơ bản giải quyết vấn đề này, và hôm nay chúng tôi cuối cùng sẽ có một cách để làm điều này, theo đó chúng tôi có thể giới thiệu một cái gì đó được gọi là một con trỏ. Nó chỉ ra rằng chúng ta có thể giải quyết vấn đề này không phải bằng cách đi qua trong bản sao của x và y nhưng thay vì đi qua trong những gì bạn nghĩ, chức năng trao đổi? Yeah, những gì về địa chỉ? Chúng tôi đã không thực sự nói về các địa chỉ chi tiết hơn, nhưng nếu bảng đen đại diện cho bộ nhớ máy tính của tôi chúng tôi chắc chắn có thể bắt đầu đánh số các byte trong bộ nhớ RAM của tôi và nói rằng đây là # 1 byte, byte # 2, # 3 byte, byte # 4, byte # ... 2 tỷ đồng nếu tôi có 2 GB RAM, vì vậy chúng tôi chắc chắn có thể đưa ra một số đề án đánh số tùy ý cho tất cả các byte cá nhân trong bộ nhớ máy tính của tôi. Điều gì sẽ xảy ra nếu thay vì khi tôi gọi hoán đổi chứ không phải vượt qua trong bản sao của x và y tại sao tôi không thay vì vượt qua trong địa chỉ của x ở đây, địa chỉ của y ở đây, chủ yếu là địa chỉ bưu điện của x và y bởi vì sau đó trao đổi, nếu anh ta thông báo của địa chỉ trong bộ nhớ của x và y, sau đó trao đổi, nếu chúng ta đào tạo anh ta một chút, ông có thể có khả năng lái xe đến địa chỉ đó, có thể nói, x, và thay đổi số ở đó, sau đó lái xe đến địa chỉ của y, thay đổi số ở đó, ngay cả khi không thực sự nhận được bản sao của những giá trị bản thân mình, do đó, mặc dù chúng tôi đã nói về điều này như là chính của bộ nhớ và trao đổi như là bộ nhớ mạnh mẽ và nguy hiểm của C là bất kỳ chức năng có thể chạm vào bộ nhớ bất cứ nơi nào trong máy tính, và điều này là mạnh mẽ mà bạn có thể làm những điều rất lạ mắt với các chương trình máy tính trong C. Điều này rất nguy hiểm bởi vì bạn cũng có thể vít lên rất dễ dàng. Trong thực tế, một trong những cách phổ biến nhất cho các chương trình trong những ngày này được khai thác vẫn còn là một lập trình viên không nhận ra rằng người đó cho phép dữ liệu được viết ở một vị trí trong bộ nhớ mà không được dự định. Ví dụ, anh ta hoặc cô ta khai báo một mảng có kích thước là 10 nhưng sau đó vô tình cố gắng để đưa 11 byte vào mảng đó của bộ nhớ, và bạn bắt đầu chạm vào các bộ phận của bộ nhớ không còn giá trị. Chỉ cần theo ngữ cảnh này, một số bạn có thể biết rằng phần mềm thường yêu cầu bạn nhập số hoặc các phím đăng ký, Photoshop và Word và các chương trình như thế này. Có tồn tại các vết nứt, như một số bạn biết, trực tuyến, nơi bạn có thể chạy một chương trình nhỏ, và thì đấy, không có yêu cầu nhiều hơn cho một số serial. Làm thế nào là làm việc? Trong nhiều trường hợp những điều này chỉ đơn giản là việc tìm kiếm trong các máy tính các phân đoạn trong văn bản số không thực tế và những người thân của máy tính là chức năng nơi mà số serial được yêu cầu, và bạn ghi đè lên không gian đó, hoặc trong khi chương trình đang chạy bạn có thể tìm ra mà chính là thực sự được lưu trữ sử dụng cái gì được gọi là một trình gỡ lỗi, và bạn có thể crack phần mềm như vậy. Điều này không phải là để nói rằng đây là mục tiêu của chúng tôi trong vài ngày tới, nhưng nó có rất thực tế hậu quả. Một trong đó xảy ra liên quan đến hành vi trộm cắp của phần mềm, nhưng cũng có sự thỏa hiệp của toàn bộ máy. Trong thực tế, khi các trang web những ngày này đang khai thác và bị xâm nhập và dữ liệu bị rò rỉ và mật khẩu bị đánh cắp điều này rất thường xuyên liên quan đến quản lý yếu kém của bộ nhớ của một người, hoặc, trong trường hợp của cơ sở dữ liệu, không để dự đoán đối lập đầu vào, do đó, thêm vào đó trong những tuần tới, nhưng bây giờ chỉ cần một sneak xem trước của các loại thiệt hại mà bạn có thể làm bằng cách không hoàn toàn hiểu những thứ như thế nào làm việc bên dưới mui xe. Hãy đi về sự hiểu biết lý do tại sao điều này bị phá vỡ với một công cụ mà sẽ trở thành nhiều hơn và hữu ích hơn như các chương trình của chúng tôi có được phức tạp hơn. Như vậy đến nay, khi bạn đã có một lỗi trong chương trình của bạn Anh đã đi như thế nào về gỡ lỗi nó? Kỹ thuật của bạn đang làm gì vậy, đến nay, cho dù được giảng dạy bởi TF của bạn hay chỉ là tự học? [Sinh viên] printf. Printf, do đó, printf có thể là bạn của bạn ở chỗ nếu bạn muốn xem những gì đang xảy ra bên trong của chương trình của bạn bạn chỉ cần đặt printf đây, printf, printf. Sau đó, bạn chạy nó, và bạn nhận được một bó toàn bộ công cụ trên màn hình mà bạn có thể sử dụng để sau đó suy luận những gì đang thực sự xảy ra sai trong chương trình của bạn. Printf có xu hướng là một điều rất mạnh mẽ, nhưng đó là một quá trình rất hướng dẫn sử dụng. Bạn có phải đặt một printf ở đây, một printf đây, và nếu bạn đặt nó bên trong một vòng lặp, bạn có thể nhận được 100 dòng sản lượng mà sau đó bạn phải sift thông qua. Đó không phải là một cơ chế rất thân thiện với người sử dụng tương tác cho các chương trình gỡ lỗi, nhưng may mắn tồn tại lựa chọn thay thế. Có một chương trình, ví dụ, được gọi là GDB, GNU Debugger, mà là một phức tạp chút trong cách bạn sử dụng nó. Đó là một chút phức tạp, nhưng thẳng thắn, đây là một trong những điều mà nếu bạn đặt trong tuần này và tiếp theo thêm giờ để hiểu một cái gì đó giống như GDB nó sẽ giúp bạn tiết kiệm có thể hàng chục giờ trong thời gian dài, do đó, với điều đó, hãy để tôi cung cấp cho bạn một lời trêu ghẹo của điều này làm việc như thế nào. Tôi trong cửa sổ thiết bị đầu cuối của tôi. Hãy để tôi đi trước và biên dịch chương trình này, buggy3. Nó đã được cập nhật. Hãy để tôi chạy nó giống như chúng ta đã làm một trở lại trong khi, và thực sự, nó bị hỏng. Nhưng tại sao điều này? Có lẽ tôi hơi say lên chức năng trao đổi. Có lẽ đó là a và b. Tôi không hoàn toàn di chuyển chúng xung quanh một cách chính xác. Hãy để tôi đi trước và làm điều này. Thay vì chỉ cần chạy buggy3 cho tôi thay vì chạy GDB chương trình, và tôi sẽ nói cho nó để chạy buggy3, và tôi sẽ bao gồm một số dòng lệnh-tui, và chúng tôi sẽ đặt điều này trong các vấn đề trong tương lai tại spec để nhắc nhở. Và giờ đây, giao diện màu đen và trắng xuất hiện đó, một lần nữa, là một chút áp đảo lúc đầu vì có tất cả những điều này thông tin bảo hành ở đây, nhưng ít nhất có một cái gì đó quen thuộc. Ở phía trên cùng của cửa sổ là mã thực tế của tôi, và nếu tôi di chuyển lên đây cho tôi di chuyển đến phần trên của tập tin của tôi, và quả thật, có buggy3.c, và thông báo ở phía dưới cùng của cửa sổ này Tôi có nhắc nhở này GDB. Điều này không giống như bình thường John Harvard dấu nhắc của tôi. Đây là một nhắc nhở sẽ cho phép tôi để kiểm soát GDB. GDB là một trình gỡ lỗi. Trình gỡ lỗi là một chương trình cho phép bạn đi bộ qua thực hiện các chương trình của bạn dòng từng dòng, trên đường đi làm bất cứ điều gì bạn muốn chương trình, thậm chí còn gọi chức năng, hoặc tìm kiếm, quan trọng hơn, tại các giá trị khác nhau của biến. Hãy cho đi trước và làm điều này. Tôi sẽ đi trước và gõ vào chạy tại dấu nhắc GDB của, do đó, lưu ý ở phía dưới bên trái của màn hình tôi đã đánh máy chạy, và tôi đã nhấn Enter, và điều đó đã làm gì? Nó nghĩa là chạy chương trình của tôi, nhưng tôi đã không thực sự nhìn thấy nhiều ở đây bởi vì tôi đã không thực sự nói với các trình gỡ lỗi tạm dừng tại một thời điểm cụ thể trong thời gian. Chỉ cần đánh chạy chạy chương trình. Tôi không thực sự nhìn thấy bất cứ điều gì. Tôi không thể thao tác nó. Thay vào đó, hãy để tôi làm việc này. Tại dấu nhắc GDB cho tôi thay vì gõ break, nhập. Đó không phải là những gì tôi có nghĩa là để loại. Hãy thay vì gõ nghỉ chính. Nói cách khác, tôi muốn thiết lập một cái gì đó được gọi là một breakpoint, được đặt tên bởi vì nó sẽ phá vỡ hoặc tạm dừng thực hiện các chương trình của bạn tại nơi cụ thể. Chính là tên của chức năng của tôi. Chú ý rằng GDB là khá thông minh. Nó đã tìm ra rằng chính xảy ra để bắt đầu khoảng dòng 18 của buggy3.c, và sau đó nhận thấy đây ở trên cùng bên trái b + là ngay bên cạnh dòng 18. Điều đó nhắc nhở tôi rằng tôi đã thiết lập một breakpoint tại dòng 18. Lần này khi tôi gõ chạy, tôi sẽ chạy chương trình của tôi lên cho đến khi nó chạm breakpoint đó, do đó, chương trình sẽ tạm dừng cho tôi ở dòng 18. Ở đây chúng tôi đi, chạy. Không có gì dường như đã xảy ra, nhưng thông báo ở phía dưới trái bắt đầu chương trình, buggy3, breakpoint 1 trong chính tại buggy3.c dòng 18. Những gì tôi có thể làm bây giờ? Thông báo tôi có thể bắt đầu gõ những thứ như in, không printf, in x, và bây giờ đó là lạ. $ 1 chỉ là một sự tò mò, như chúng ta sẽ thấy mỗi khi bạn in một cái gì đó bạn sẽ có được một giá trị mới. Đó là để bạn có thể tham khảo lại giá trị trước đó chỉ trong trường hợp, nhưng bây giờ những gì in nói với tôi là giá trị của x vào thời điểm này trong câu chuyện rõ ràng là 134.514.032. Gì? Ở đâu mà ngay cả đến từ đâu? [Không nghe được học sinh] Thật vậy, đây là những gì chúng ta sẽ gọi một giá trị rác, và chúng tôi đã không nói chuyện về việc này chưa, nhưng lý do mà bạn khởi tạo các biến rõ ràng là để họ có một số giá trị mà bạn muốn họ có. Tuy nhiên, sản lượng đánh bắt được nhớ lại rằng bạn có thể khai báo các biến như tôi đã làm một chút thời gian trước đây trong ví dụ sigma của tôi mà không thực sự đem lại cho họ một giá trị. Nhớ lại những gì tôi đã làm ở đây trong sigma. Tôi tuyên bố n, nhưng những gì giá trị tôi đã cung cấp cho nó? Không, bởi vì tôi biết rằng trong vài dòng tiếp theo GetInt sẽ chăm sóc của vấn đề của việc đưa một giá trị bên trong của n. Nhưng vào thời điểm này trong câu chuyện của dòng 11 và dòng 12 và dòng 13 và dòng 14 trong suốt những một vài dòng giá trị của n là gì? Trong C, bạn chỉ không biết. Đó là nói chung một số giá trị rác, một số số hoàn toàn ngẫu nhiên còn lại chủ yếu từ một số chức năng trước đây đã được chạy, để chương trình của bạn chạy nhớ lại rằng chức năng được chức năng, chức năng, chức năng. Tất cả những khung hình có được đặt vào bộ nhớ, sau đó những người trở về chức năng, và cũng giống như tôi đã đề nghị với tẩy bộ nhớ của họ được tái sử dụng cuối cùng. Vâng, nó chỉ như vậy sẽ xảy ra rằng điều này biến x trong chương trình này dường như đã có một số giá trị rác như 134514032 từ một số chức năng trước đây, không phải một mà tôi đã viết. Nó có thể là một cái gì đó mà đi kèm hiệu quả với hệ điều hành, một số chức năng bên dưới mui xe. Được rồi, đó là tốt, nhưng chúng ta hãy tiến đến dòng kế tiếp. Nếu tôi gõ "tiếp theo" tại dấu nhắc GDB của tôi và tôi nhấn Enter, nhận thấy rằng làm nổi bật di chuyển xuống dòng 19, nhưng ngụ ý hợp lý là dòng 18 đã hoàn tất thi công, vì vậy nếu tôi lại gõ "in x" Bây giờ tôi sẽ thấy 1, và quả thật, tôi làm. Một lần nữa, những thứ là một cách để GDB nhắc nhở bạn lịch sử của bản in mà bạn đã thực hiện. Bây giờ để tôi đi trước và in ra y, và quả thật, y là một số giá trị điên như, nhưng không có vấn đề lớn bởi vì trong dòng 19, chúng tôi đang về để gán cho nó giá trị 2, vì vậy hãy để tôi gõ "bên cạnh" một lần nữa. Và bây giờ chúng tôi đang ở trên dòng printf. Hãy để tôi làm x in. Hãy để tôi làm y in. Thẳng thắn mà nói, tôi nhận được một chút mệt mỏi in ấn này. Hãy để tôi thay vì gõ "hiển thị x" và "hiển thị y" và bây giờ mỗi khi tôi gõ lệnh trong tương lai Tôi sẽ được nhắc nhở về những gì x và y, những gì x và y, x và y là những gì. Tôi cũng có thể, như là một loại, bên cạnh "người dân địa phương biết." Thông tin là một lệnh đặc biệt. Người dân địa phương có nghĩa là nó cho thấy tôi các biến địa phương. Chỉ trong trường hợp tôi quên hoặc đây là một chức năng phức tạp điên mà tôi hoặc người khác đã viết người dân địa phương thông tin sẽ cho bạn biết tất cả các biến địa phương bên trong chức năng địa phương này là gì mà bạn có thể quan tâm đến nếu bạn muốn poke xung quanh. Bây giờ, printf về để thực hiện, vì vậy hãy để tôi đi trước và chỉ cần gõ "tiếp theo." Bởi vì chúng ta đang ở trong môi trường này, chúng tôi đang không thực sự nhìn thấy nó thực hiện xuống ở đây, nhưng nhận thấy nó nhận được một chút đã bị đọc sai ở đây. Nhưng hãy chú ý trọng các màn hình có, vì vậy nó không phải là một chương trình hoàn hảo ở đây, nhưng đó là ổn bởi vì tôi luôn luôn có thể poke xung quanh sử dụng in nếu tôi muốn. Hãy để tôi gõ tiếp theo một lần nữa, và bây giờ đây là phần thú vị. Tại thời điểm này trong câu chuyện y là 2, và x là 1, như đề xuất ở đây, và một lần nữa, lý do này được tự động hiển thị giờ là bởi vì tôi đã sử dụng lệnh hiển thị x và màn hình hiển thị y, do đó, thời điểm tôi gõ tiếp theo trong lý thuyết x và y sẽ trở nên đổi chỗ. Bây giờ, chúng ta đã biết điều đó sẽ không phải là trường hợp, nhưng chúng ta sẽ thấy trong một thời điểm như thế nào chúng tôi có thể lặn sâu hơn để tìm ra lý do tại sao đó là sự thật. Tiếp theo, và không may, y vẫn còn 2 và x vẫn còn 1, và tôi có thể xác nhận càng nhiều. In x, y in. Thật vậy, không có trao đổi đã thực sự xảy ra, vì vậy hãy bắt đầu điều này hơn. Rõ ràng hoán đổi là bị hỏng. Hãy thay vì gõ "chạy" một lần nữa. Hãy để tôi nói có, tôi muốn khởi động lại nó từ đầu, nhập. Bây giờ tôi trở lên ở dòng 18. Bây giờ nhận thấy x và y là các giá trị rác một lần nữa. Tiếp theo, tiếp theo, tiếp theo, tiếp theo. Nếu tôi nhận được chán, tôi cũng có thể chỉ cần gõ n tiếp theo. Bạn có thể viết tắt trình tự ngắn nhất có thể của các nhân vật. Swap bây giờ bị hỏng. Hãy lặn trong, do đó, thay vì gõ tiếp theo, bây giờ tôi sẽ gõ bước vì vậy mà tôi đang bước vào bên trong của chức năng này vì vậy mà tôi có thể đi bộ qua nó, do đó, tôi nhấn bước và sau đó nhập vào. Chú ý rằng nhảy làm nổi bật xuống thấp trong chương trình của tôi đến dòng 36. Bây giờ các biến địa phương là gì? Thông tin người dân địa phương. Không có gì chỉ được nêu ra bởi vì chúng tôi đã không nhận được dòng đó, do đó, chúng ta hãy đi trước và nói "bên cạnh". Bây giờ chúng ta dường như có tmp tmp in,. Garbage giá trị, phải không? Tôi nghĩ vậy. Làm thế nào về in, in b, 1 và 2? Trong một khoảnh khắc, ngay sau khi tôi gõ tiếp theo nữa tmp là sẽ mất giá trị là 1, hy vọng, vì tmp sẽ được gán giá trị của một. Bây giờ chúng ta hãy làm in, in b, nhưng bây giờ in tmp, và nó thực sự 1. Hãy để tôi làm gì tiếp theo. Hãy để tôi làm gì tiếp theo. Tôi đã hoàn thành các chức năng trao đổi. Tôi vẫn còn bên trong của nó ở đường 40, vì vậy hãy để tôi in một, in b, và tôi không quan tâm những gì tmp. Có vẻ như trao đổi là chính xác khi nói đến để trao đổi a và b. Nhưng nếu tôi gõ tiếp theo, tôi nhảy trở lại dòng 25, và dĩ nhiên, nếu tôi gõ trong x và y in họ vẫn không thay đổi, vì vậy chúng tôi đã không cố định được vấn đề. Nhưng chẩn đoán bây giờ có lẽ với chương trình này GDB chúng tôi đã ít nhất nhận được một bước gần hơn để hiểu những gì đang xảy ra sai mà không cần phải xả rác mã của chúng tôi bằng cách đặt một printf ở đây, printf, printf đây và sau đó chạy nó một lần nữa và một lần nữa cố gắng tìm ra những gì đang xảy ra sai. Tôi sẽ đi trước và bỏ điều này hoàn toàn bỏ thuốc lá. Nó sẽ sau đó nói, "Thoát không?" Vâng. Bây giờ tôi đang trở lại tại dấu nhắc bình thường của tôi, và tôi đang thực hiện bằng cách sử dụng GDB. Một sang một bên, bạn không cần phải sử dụng-tui cờ. Trong thực tế, nếu bạn bỏ qua nó, bạn sẽ có được bản chất nửa dưới của màn hình. Nếu tôi sau đó gõ nghỉ chính và sau đó chạy Tôi vẫn có thể chạy chương trình của tôi, nhưng những gì nó sẽ làm là textually chỉ cần cho tôi một dòng tại một thời điểm hiện nay. Tui qua, giao diện người dùng văn bản, chỉ cho bạn thấy nhiều chương trình cùng một lúc, mà có lẽ là một chút dễ dàng hơn khái niệm. Nhưng thực sự, tôi chỉ có thể làm gì tiếp theo, tiếp theo, tiếp theo, và tôi sẽ nhìn thấy một dòng tại một thời điểm, và nếu tôi thực sự muốn xem những gì đang xảy ra Tôi có thể loại danh sách và nhìn thấy một bó toàn bộ các đường lân cận. Có một video mà chúng tôi đã hỏi bạn xem vấn đề đặt ra 3 trong đó Nate bao gồm một số những phức tạp của GDB, và đây là một cách trung thực, những điều đó, một số tỷ lệ phần trăm không tầm thường của bạn sẽ không bao giờ chạm vào GDB, và điều đó sẽ là một điều xấu vì nghĩa là bạn sẽ kết thúc dành nhiều thời gian vào cuối học kỳ này đuổi xuống lỗi sau đó bạn sẽ nếu bạn đặt trong nửa giờ / giờ trong tuần này và học tập tiếp theo để có được thoải mái với GDB. Printf là bạn của bạn. GDB nên bây giờ là bạn của bạn. Bất kỳ câu hỏi trên GDB? Và đây là danh sách của một số các lệnh công cụ mạnh mẽ và hữu ích nhất. Yeah. >> Bạn có thể in một chuỗi? Bạn có thể in một chuỗi? Chắc chắn rồi. Nó không phải chỉ là các số nguyên. Nếu một biến s là một chuỗi chỉ cần gõ vào s in. Nó sẽ cho bạn những gì mà biến chuỗi. [Không nghe được học sinh] Nó sẽ cho bạn địa chỉ và bản thân chuỗi. Nó sẽ cho bạn cả. Và một điều cuối cùng, chỉ vì đây là tốt để biết quá. Truy ngược và khung hình, hãy để tôi nhảy vào một lần cuối cùng này, chương trình giống hệt với GDB. Hãy để tôi đi trước và chạy các phiên bản giao diện người dùng văn bản, phá vỡ chính. Hãy để tôi đi trước và chạy một lần nữa. Tôi ở đây. Bây giờ hãy để tôi đi tiếp theo, tiếp theo, tiếp theo, tiếp theo, tiếp theo, bước, bước vào. Và bây giờ giả sử tôi bây giờ trong trao đổi cố ý, nhưng tôi như "Damn, giá trị của x là gì?" Tôi không thể làm x nữa. Tôi không thể làm y bởi vì họ đang không ở trong phạm vi. Chúng không phải là trong bối cảnh, nhưng không có vấn đề. Tôi có thể gõ backtrace. Điều đó cho thấy tôi tất cả các chức năng đã thực hiện đến thời điểm này. Chú ý rằng một trong những ngày phía dưới, chính, đường dây với chính trên dưới cùng của hình ảnh của chúng tôi ở đây. Thực tế rằng trao đổi ở trên nó dòng với trao đổi ở trên nó trong bộ nhớ ở đây, và nếu tôi muốn để lại cho chính tạm thời tôi có thể nói "khung". Những gì số? Chính là khung # 1. Tôi sẽ đi trước và nói "frame 1". Bây giờ tôi đang trở lại trong chính, và tôi có thể in x, và tôi có thể in y, nhưng tôi không thể in a hoặc b. Nhưng tôi có thể nếu tôi nói, "Được rồi, chờ một phút là trao đổi?" Hãy để tôi đi trước và nói "khung 0." Bây giờ tôi trở lại nơi mà tôi muốn, và như một sang một bên, có lệnh khác quá, giống như nếu bạn đang thực sự nhận được đánh máy chán tiếp theo, tiếp theo, tiếp theo, tiếp theo, bạn thường có thể nói những điều như "tới 10", và điều đó sẽ bước qua 10 dòng tiếp theo. Bạn cũng có thể viết "tiếp tục" khi bạn thực sự nhận được chán với việc đẩy mạnh thông qua nó. Tiếp tục chạy chương trình của bạn mà không bị gián đoạn cho đến khi nó chạm khác breakpoint, cho dù trong một vòng lặp hoặc giảm xuống trong chương trình của bạn. Trong trường hợp này, chúng tôi tiếp tục đến cùng, và chương trình đã thoát bình thường. Đây là một cách ưa thích, quá trình kém. Chỉ cần chương trình của bạn đã thoát bình thường. Thêm vào đó trong đoạn video và trong gỡ lỗi các phiên tới. Đó là rất nhiều. Chúng ta hãy nghỉ 5-phút của chúng tôi ở đây, và chúng tôi sẽ trở lại với cấu trúc và các tập tin. Nếu bạn đã tụt dốc vào pset tuần này đã bạn sẽ biết rằng chúng tôi sử dụng trong mã phân phối, mã nguồn mà chúng tôi cung cấp cho bạn như là một điểm khởi đầu, một số kỹ thuật mới. Đặc biệt, chúng tôi giới thiệu từ khoá này mới được gọi là cấu trúc, cấu trúc, để chúng tôi có thể tạo ra các biến tùy chỉnh của các loại. Chúng tôi cũng giới thiệu khái niệm về tập tin tập tin đầu vào và đầu ra I / O,, và điều này là để chúng ta có thể lưu trạng thái của hội đồng quản trị Scramble của bạn vào một tập tin trên đĩa để các nghiên cứu sinh giảng dạy và tôi có thể hiểu những gì đang xảy ra bên trong của chương trình của bạn mà không cần phải tự chơi hàng chục trò chơi của Scramble. Chúng ta có thể làm điều này automatedly hơn. Ý tưởng này của một cấu trúc giải quyết một vấn đề khá hấp dẫn. Giả sử chúng ta muốn thực hiện một số chương trình bằng cách nào đó theo dõi những thông tin về học sinh, và sinh viên có thể có, ví dụ, một ID, một tên và một ngôi nhà tại một nơi như Harvard, do đó, đây là 3 mẩu thông tin chúng tôi muốn giữ cho xung quanh, vì vậy hãy để tôi đi trước và bắt đầu viết một chương trình nhỏ ở đây, bao gồm stdio.h. Hãy để tôi làm bao gồm cs50.h. Và sau đó bắt đầu chức năng chính của tôi. Tôi sẽ không bận tâm với bất kỳ đối số dòng lệnh, và ở đây tôi muốn có một sinh viên, do đó, tôi sẽ nói một học sinh có tên, vì vậy tôi sẽ nói "tên chuỗi". Sau đó, tôi sẽ nói một học sinh cũng có một ID, id để int, và một học sinh có một căn nhà, vì vậy tôi cũng sẽ nói "chuỗi nhà". Sau đó, tôi sẽ đặt hàng những một chút sạch hơn như thế này. Được rồi, bây giờ tôi có 3 biến để đại diện cho một học sinh, do đó, "một học sinh." Và bây giờ tôi muốn để cư các giá trị, vì vậy hãy để tôi đi trước và nói một cái gì đó như "Id = 123". Tên là sẽ nhận được David. Hãy nói rằng ngôi nhà là sẽ nhận được Mather, và sau đó tôi sẽ làm một cái gì đó tùy ý giống như printf ("% s, có ID là% d, sống trong% s. Và bây giờ, tôi làm những gì muốn cắm ở đây, sau khi một khác? Tên, id, house, trở về 0. Được rồi, trừ khi tôi hơi say lên một nơi nào đó ở đây Tôi nghĩ rằng chúng tôi có một chương trình khá tốt mà các cửa hàng một học sinh. Tất nhiên, đây không phải là tất cả những gì thú vị. Điều gì sẽ xảy ra nếu tôi muốn có 2 học sinh? Đó là không có vấn đề lớn. Tôi có thể hỗ trợ 2 người. Hãy để tôi đi trước và làm nổi bật này và đi xuống đây, và tôi có thể nói "id = 456" cho một người nào đó giống như Rob người sống trong Kirkland. Được rồi, chờ đợi, nhưng tôi không thể gọi những điều tương tự, và có vẻ như tôi sẽ phải để sao chép, vì vậy hãy để tôi nói rằng đây sẽ là David biến, và để cho tôi có được một số bản sao của các Rob. Chúng tôi sẽ gọi những Rob nhưng điều này sẽ không làm việc bây giờ bởi vì tôi đã chờ đợi, chúng ta hãy thay đổi tôi id1, name1 và house1. Rob sẽ là 2, 2. Tôi đã có để thay đổi điều này đây, ở đây, ở đây, ở đây, ở đây, ở đây. Chờ đợi, những gì về Tommy? Hãy làm điều này một lần nữa. Rõ ràng là nếu bạn vẫn còn nghĩ đây là một cách tốt để làm điều này, nó không phải, để sao chép / dán xấu. Nhưng chúng ta giải quyết điều này một tuần trước đây. Giải pháp của chúng tôi là gì khi chúng tôi muốn có nhiều trường hợp của cùng một kiểu dữ liệu? [Sinh viên] Một mảng. Một mảng, vì vậy hãy để tôi cố gắng làm sạch này lên. Hãy để tôi làm cho một số phòng cho bản thân mình ở đầu trang, và để cho tôi thay vì làm điều này ở đây. Chúng tôi sẽ gọi những người này, và thay vào đó tôi sẽ nói "id int," và tôi sẽ hỗ trợ 3 của chúng tôi bây giờ. Tôi sẽ nói "tên chuỗi," và tôi sẽ hỗ trợ 3 của chúng tôi, và sau đó tôi sẽ nói "nhà chuỗi," và tôi sẽ hỗ trợ 3 của chúng tôi. Bây giờ ở đây thay vì David nhận được các biến riêng của địa phương của mình chúng ta có thể thoát khỏi những. Mà cảm thấy tốt mà chúng ta đang lau chùi này. Sau đó tôi có thể nói rằng David sẽ là [0] và tên [0] và nhà [0]. Và sau đó Rob chúng tôi tương tự như vậy có thể tiết kiệm này. Chúng ta hãy đặt này xuống đây, vì vậy anh sẽ tự ý id [1]. Ông ấy sẽ có tên [1], và sau đó cuối cùng, nhà [1]. Vẫn còn một chút buồn tẻ, và bây giờ tôi có con số này ra, do đó, chúng ta hãy nói rằng "tên [0], id [0], nhà [0], và chúng ta hãy pluralize này. Id, id, id. Và một lần nữa, tôi đang làm nó, vì vậy một lần nữa, tôi đã viện đến sao chép / dán lại, do đó, tỷ lệ cược là có một giải pháp khác ở đây. Tôi có lẽ có thể làm sạch này lên cao hơn nữa với một vòng lặp hoặc một cái gì đó như thế, do đó, trong ngắn hạn, đó là tốt hơn một chút, nhưng vẫn cảm thấy như Tôi đang phải dùng đến sao chép / dán, nhưng ngay cả điều này, tôi yêu cầu bồi thường, không thực sự về cơ bản là giải pháp đúng vì bạn nếu đôi khi chúng ta quyết định những gì biết không? Chúng tôi thực sự nên đã được lưu trữ các địa chỉ email cho David và Rob và tất cả mọi người khác trong chương trình này. Chúng ta cũng nên lưu số điện thoại. Chúng ta cũng nên lưu trữ các số liên lạc khẩn cấp. Chúng tôi có tất cả các mảnh dữ liệu mà chúng tôi muốn để lưu trữ, vậy làm thế nào để bạn đi về làm điều đó? Bạn khai báo một mảng ở đầu trang, và sau đó bạn tự thêm một địa chỉ email [0], địa chỉ email [1] David và Rob và vv. Nhưng có thực sự chỉ là một giả định cơ bản thiết kế này Tôi đang sử dụng hệ thống vinh dự để biết rằng [I] trong mỗi của các mảng nhiều chỉ để xảy ra để chỉ cùng một người, [0] trong id là số 123, và tôi sẽ cho rằng tên [0] là cùng một người tên và nhà [0] là cùng một người nhà và vv cho tất cả các mảng khác nhau mà tôi tạo ra. Nhưng hãy chú ý rằng không có mối liên kết cơ bản trong số những 3 mẩu thông tin, tên, id và ngôi nhà, mặc dù đơn vị chúng tôi đang cố gắng để mô hình trong chương trình này không phải là mảng. Mảng là một cách như vậy chương trình để làm điều này. Những gì chúng tôi thực sự muốn mô hình trong chương trình của chúng tôi là một người như David, một người như Rob bên trong đó hoặc đóng gói là một cái tên và ID và một ngôi nhà. Bằng cách nào đó chúng ta có thể bày tỏ ý tưởng này đóng gói theo đó một người có một ID, một cái tên và một ngôi nhà và không phải nghỉ mát để hack thực sự này nhờ đó chúng ta chỉ tin tưởng rằng một cái gì đó khung đề cập đến các thực thể của con người tương tự trong mỗi của các mảng khác nhau? Chúng tôi thực sự có thể làm điều này. Hãy để tôi đi trên chính cho bây giờ, và cho tôi tạo kiểu dữ liệu của tôi thực sự là lần đầu tiên. Chúng tôi sử dụng kỹ thuật này trong Scramble, nhưng ở đây tôi sẽ đi trước và tạo ra một kiểu dữ liệu, và bạn biết không, tôi cũng sẽ gọi nó là sinh viên hoặc người, và tôi sẽ sử dụng typedef cho định nghĩa một kiểu. Tôi sẽ nói rằng đây là một cấu trúc, và sau đó cấu trúc này sẽ là kiểu của học sinh, chúng tôi sẽ nói, mặc dù nó là một ít ngày bây giờ cho tôi. Chúng tôi sẽ nói "int id." Chúng tôi sẽ nói "tên chuỗi." Sau đó, chúng tôi sẽ nói "chuỗi nhà," vì vậy bây giờ vào cuối những vài dòng mã Tôi vừa dạy kêu vang rằng có tồn tại một kiểu dữ liệu bên cạnh ints, bên cạnh chuỗi, bên cạnh việc tăng gấp đôi, bên cạnh nổi. Tính đến thời điểm này trong 11 dòng thời gian, bây giờ có một kiểu dữ liệu mới gọi là sinh viên, và bây giờ tôi có thể khai báo một biến của học sinh ở bất cứ nơi nào tôi muốn, vì vậy hãy để tôi di chuyển xuống cho người dân. Bây giờ tôi có thể nhận được thoát khỏi điều này, và tôi có thể trở lại David ở đây, và cho David, tôi thực sự có thể nói rằng David, nghĩa là chúng tôi có thể đặt tên biến sau khi bản thân mình, là có được kiểu của học sinh. Điều này có thể trông hơi kì lạ một chút, nhưng điều này không phải là tất cả những gì khác nhau tuyên bố một cái gì đó như là một int hoặc một chuỗi hoặc một phao. Nó chỉ như vậy sẽ xảy ra để được gọi là sinh viên bây giờ, và nếu tôi muốn đặt một cái gì đó bên trong của cấu trúc này Tôi bây giờ có sử dụng một đoạn mới của cú pháp, nhưng nó khá đơn giản, david.id = 123, david.name = "David" ở thủ đô D, và david.house = "Mather," và bây giờ tôi có thể nhận được thoát khỏi công cụ này ở đây. Thông báo bây giờ chúng tôi đã thiết kế lại chương trình của chúng tôi trong một cách thực sự tốt hơn nhiều trong chương trình của chúng tôi phản ánh thế giới thực. Có một khái niệm thực tế của một người hoặc một học sinh. Ở đây chúng tôi có một phiên bản C của một người hoặc cụ thể hơn là một học sinh. Bên trong của người đó là những đặc điểm này có liên quan, ID, tên và ngôi nhà, do đó, Rob cơ bản trở thành điều tương tự ở đây, cho nên sinh viên cướp, và bây giờ rob.id = 456, rob.name = "Rob". Thực tế là biến được gọi là Rob là loại vô nghĩa. Chúng ta có thể gọi nó là x hoặc y hoặc z. Chúng tôi chỉ đặt tên cho nó là Rob được ngữ nghĩa phù hợp, nhưng thực sự tên là bên trong của bản thân mà lĩnh vực, vậy bây giờ tôi có này. Điều này cũng không cảm thấy như thiết kế tốt nhất mà tôi đã cứng mã hoá David. Tôi đã cứng mã hoá Rob. Và tôi vẫn phải nghỉ mát một số bản sao và dán mỗi khi tôi muốn biến mới. Hơn nữa, dường như tôi phải cung cấp cho mỗi của các biến này một tên, mặc dù tôi rất muốn mô tả các biến  hơn tổng quát như sinh viên. Bây giờ chúng ta có thể hợp nhất các ý tưởng đã được làm việc tốt cho chúng tôi và thay vì nói, "Anh biết không, cho tôi một sinh viên gọi là biến, và để cho nó có được kích thước 3 ", vì vậy bây giờ tôi có thể tinh chỉnh này hơn nữa, thoát khỏi David tay tuyên bố, và tôi thay vì có thể nói một cái gì đó giống như sinh viên [0] ở đây. Sau đó tôi có thể nói sinh viên [0] ở đây, sinh viên [0] ở đây, và vân vân, và tôi có thể đi xung quanh và làm sạch mà cho Rob. Tôi cũng có thể đi về thể bổ sung thêm một vòng lặp và sử dụng GetString và getInt để thực sự có được những giá trị từ người sử dụng. Tôi có thể đi về việc thêm một hằng số vì đây là nói chung là xấu thực hành cứng mã một số số tùy ý như 3 ngay tại đây và sau đó chỉ cần nhớ rằng bạn phải dồn không quá 3 học sinh ở trong đó. Nó có lẽ sẽ tốt hơn để sử dụng # xác định ở trên cùng của tập tin của tôi và các yếu tố mà ra, do đó, thực sự, hãy để tôi đi trước và tổng quát này. Hãy để tôi mở ra một ví dụ đó là trong ngày hôm nay ví dụ trước, structs1. Đây là một chương trình hoàn chỉnh hơn sử dụng # xác định đây và nói rằng chúng ta sẽ có 3 sinh viên theo mặc định. Ở đây tôi tuyên bố một giá trị lớp học của học sinh, do đó, một lớp học của sinh viên, và bây giờ tôi đang sử dụng một vòng lặp chỉ để làm cho đoạn code một chút thanh lịch hơn, cư trú trong lớp học với đầu vào của người dùng, do đó, lặp từ i = 0 trên cho học sinh, mà là 3. Và sau đó tôi nhắc nhở người dùng trong phiên bản này  ID của học sinh là gì, và tôi nhận được nó với getInt. Tên của học sinh là gì, và sau đó tôi nhận được nó với GetString. Nhà của học sinh là gì? Tôi nhận được nó với GetString. Và sau đó ở dưới cùng ở đây, tôi quyết định thay đổi làm thế nào tôi in này ra và thực sự sử dụng một vòng lặp, và tôi ai in? Theo những nhận xét tôi in bất cứ ai trong Mather, và đó là nó để Rob và Tommy và vv thực sự của Tommy Mather. Tommy và David sẽ được in trong trường hợp này, nhưng làm thế nào là làm việc này? Chúng tôi đã không nhìn thấy chức năng này trước đây, nhưng có nhiều phán đoán điều này không. So sánh hai xâu. Đó là một chút không rõ ràng làm thế nào nó so sánh chuỗi bởi vì nó chỉ ra nếu nó trả về 0 có nghĩa là các chuỗi bằng nhau. Nếu nó trả về một -1 có nghĩa là một đến theo thứ tự bảng chữ cái trước kia, và nếu nó trả về +1 mà có nghĩa là từ khác đi kèm theo bảng chữ cái trước kia, và bạn có thể xem trực tuyến hoặc tại trang người đàn ông để xem chính xác đó là cách, nhưng tất cả những điều này hiện đang làm là nó nói nếu [i]. nhà bằng "Mather" sau đó đi trước và in ra như vậy và như vậy là trong Mather. Nhưng đây là một cái gì đó chúng tôi đã không nhìn thấy trước, và chúng tôi sẽ trở lại này. Tôi không nhớ bao giờ phải làm điều này trong bất kỳ chương trình của tôi. Free là dường như đề cập đến bộ nhớ, giải phóng bộ nhớ, nhưng nhớ những gì tôi dường như giải phóng trong vòng lặp này ở dưới cùng của chương trình này? Dường như tôi đang giải phóng tên của một người và nhà của một người, nhưng tại sao vậy? Hóa ra tất cả những tuần lễ mà bạn đã sử dụng GetString chúng tôi đã loại được giới thiệu một lỗi vào mỗi một trong các chương trình của bạn. GetString cấp phát bộ nhớ thiết kế để nó có thể quay trở lại một chuỗi, như David, Rob, và sau đó bạn có thể làm bất cứ điều gì bạn muốn với chuỗi trong chương trình của bạn bởi vì chúng tôi đã dành bộ nhớ cho bạn. Vấn đề là tất cả thời gian này, mỗi khi bạn gọi getString chúng tôi, các tác giả của GetString, đã được yêu cầu hệ điều hành để cung cấp cho chúng tôi một chút RAM cho chuỗi này. Hãy cho chúng tôi một chút bộ nhớ RAM cho chuỗi này tiếp theo. Hãy cho chúng tôi RAM một số chi tiết cho chuỗi này tiếp theo. Những gì bạn, lập trình, chưa bao giờ được làm cho chúng tôi mà quay trở lại bộ nhớ, do đó, cho tất cả những vài tuần của các chương trình bạn đã viết đã có những gì được gọi là một bước nhảy vọt nhớ, theo đó họ tiếp tục sử dụng nhiều hơn và nhiều hơn nữa bộ nhớ mỗi khi bạn gọi GetString, và đó là tiền phạt. Chúng tôi cố tình làm điều đó trong những tuần đầu tiên vì nó không phải là thú vị có phải lo lắng về chuỗi là đến từ đâu. Tất cả những gì bạn muốn là từ Rob trở lại khi người dùng nhập vào. Nhưng di chuyển về phía trước chúng ta bây giờ phải bắt đầu phức tạp hơn về điều này. Bất cứ lúc nào chúng ta cấp phát bộ nhớ tốt hơn hết chúng ta cuối cùng đã đưa nó trở lại. Nếu không, trong thế giới thực trên máy Mac hoặc máy PC của bạn, bạn có thể có đôi khi kinh nghiệm triệu chứng máy tính của bạn được mài dừng lại cuối cùng hoặc quả bóng bãi biển quay ngu ngốc chỉ là chiếm của máy tính toàn bộ sự chú ý và bạn không thể làm việc. Điều đó có thể được giải thích bằng bất kỳ số lượng lỗi, nhưng trong số những lỗi có thể xảy ra điều được gọi là rò rỉ bộ nhớ, theo đó một người đã viết rằng phần của phần mềm bạn đang sử dụng không nhớ bộ nhớ miễn phí mà người đó yêu cầu hệ điều hành cho, không sử dụng GetString, bởi vì đó là một điều CS50, nhưng bằng cách sử dụng các chức năng tương tự yêu cầu hệ điều hành cho bộ nhớ. Nếu bạn hoặc họ vít lên và không bao giờ thực sự trở lại là bộ nhớ một triệu chứng có thể là một chương trình chậm và làm chậm và làm chậm trừ khi bạn nhớ để gọi miễn phí. Chúng tôi sẽ trở lại khi nào và tại sao bạn sẽ gọi miễn phí, nhưng chúng ta hãy chỉ cho biện pháp tốt và cố gắng chạy chương trình này cụ thể. Này được gọi là structs1, nhập. Hãy để tôi đi trước và chạy structs1, 123, David Mather, 456, Rob Kirkland, 789, Tommy Mather, và chúng ta thấy David trong Mather, Tommy trong Mather. Đây chỉ là một ít kiểm tra sanity rằng chương trình đang hoạt động. Bây giờ, thật không may, chương trình này là một chút bực bội trong đó Tôi đã làm tất cả những công việc, tôi đã gõ trong 9 dây khác nhau, nhấn Enter, nói với người trong Mather, nhưng rõ ràng là tôi biết ai đứng ở Mather đã vì tôi đã gõ nó. Nó sẽ là ít nhất là tốt đẹp nếu chương trình này là giống như một cơ sở dữ liệu và nó thực sự nhớ những gì tôi đã gõ vào vì vậy tôi không bao giờ phải nhập vào các hồ sơ học sinh. Có lẽ nó giống như một hệ thống registrarial. Chúng tôi có thể làm điều này bằng cách sử dụng kỹ thuật này được gọi là tập tin tập tin đầu vào và đầu ra I / O,, một cách rất chung chung nói rằng bất cứ lúc nào bạn muốn đọc các tập tin hoặc viết các tập tin bạn có thể làm điều này với một tập hợp các chức năng. Hãy để tôi đi trước và mở structs2.c ví dụ này, đó là gần như giống hệt nhau, nhưng chúng ta hãy xem những gì nó bây giờ không. Ở phía trên của tập tin tôi khai báo một lớp học của học sinh. Tôi sau đó cư các lớp học với đầu vào của người dùng, do đó, những dòng mã được chính xác như trước đây. Sau đó, nếu tôi di chuyển xuống đây tôi in tất cả mọi người là trong Mather tùy tiện như trước đây, nhưng đây là một tính năng mới thú vị. Các dòng mã mới, và họ giới thiệu cái gì ở đây, FILE, tất cả các mũ, và nó có * ở đây là tốt. Hãy để tôi di chuyển này ở đây, a * ở đây cũng. Chức năng này chúng tôi đã không nhìn thấy trước, fopen, nhưng nó có nghĩa là tập tin mở, do đó, chúng ta hãy lướt qua những, và điều này là một cái gì đó chúng tôi sẽ trở lại trong psets trong tương lai, nhưng dòng này ở đây về cơ bản sẽ mở ra một tập tin cơ sở dữ liệu, và nó cụ thể mở nó trong một cách mà nó có thể làm những gì với nó? [Không nghe được học sinh] Đúng, vì vậy "w" chỉ có nghĩa là nó nói với hệ điều hành mở tập tin này trong một cách mà tôi có thể viết thư cho nó. Tôi không muốn đọc nó. Tôi không muốn chỉ cần nhìn vào nó. Tôi muốn thay đổi nó và thêm công cụ có khả năng cho nó, và các tập tin sẽ được gọi là cơ sở dữ liệu. Điều này có thể được gọi là bất cứ điều gì. Điều này có thể database.txt. Điều này có thể là db. Điều này có thể là một từ như foo, nhưng tôi tự ý chọn để đặt tên cho tập tin cơ sở dữ liệu. Đây là một kiểm tra sanity ít rằng chúng tôi sẽ trở lại rất chi tiết theo thời gian, nếu fp, cho con trỏ tập tin, không bằng NULL có nghĩa là tất cả là tốt. Long câu chuyện ngắn, các chức năng như fopen đôi khi thất bại. Có lẽ các tập tin không tồn tại. Có lẽ bạn đang trên không gian đĩa. Có lẽ bạn không có sự cho phép vào thư mục đó, vì vậy nếu fopen trả về một cái gì đó vô giá trị xấu xảy ra. Ngược lại, nếu fopen không trả lại null tất cả là tốt và tôi có thể bắt đầu bằng văn bản cho tập tin này. Đây là một thủ thuật mới. Đây là một vòng lặp cho iterating trên mỗi sinh viên của tôi, và điều này có vẻ rất giống với những gì chúng tôi đã làm trước đó, nhưng chức năng này là một người anh em họ của printf gọi là fprintf cho tập tin printf, và nhận thấy nó khác nhau chỉ trong 2 cách. Một, nó bắt đầu với f thay vì của p, nhưng sau đó số đầu tiên của nó là rõ ràng những gì? [Sinh viên] File. Đó là một tập tin. Điều này được gọi là fp, mà cuối cùng chúng ta sẽ tách một con trỏ tập tin là những gì, nhưng bây giờ fp chỉ đơn giản là đại diện cho các tập tin mà tôi đã mở, fprintf đây nói in ID của người dùng này vào tập tin, không phải màn hình. In tên của người dùng vào tập tin, không màn hình, nhà cho các tập tin, không màn hình, và sau đó xuống đây, rõ ràng, đóng tập tin, và sau đó xuống ở đây miễn phí bộ nhớ. Sự khác biệt duy nhất giữa 2 phiên bản này và phiên bản 1 là sự ra đời của fopen và FILE này với * và khái niệm này fprintf, do đó, chúng ta hãy xem kết quả cuối cùng là những gì. Hãy để tôi đi vào cửa sổ thiết bị đầu cuối của tôi. Hãy để tôi chạy structs2, nhập. Hình như tất cả là tốt. Hãy chạy lại structs2. 123, David Mather, 456, Rob Kirkland, 789, Tommy Mather, nhập vào. Hình như nó cư xử như nhau, nhưng nếu tôi làm ls nhận thấy tập tin là trong số tất cả các mã của tôi, cơ sở dữ liệu, do đó, chúng ta hãy mở rằng, gedit cơ sở dữ liệu, và nhìn vào lúc đó. Đây không phải là gợi cảm nhất của các định dạng tập tin. Nó thực sự là một phần của dòng dữ liệu trên mỗi dòng mỗi dòng, nhưng những người bạn của những người sử dụng Excel hoặc CSV file, giá trị cách nhau bằng dấu phẩy, Tôi chắc chắn có thể đã sử dụng fprintf để thay vào đó có thể làm một cái gì đó như thế này vì vậy mà tôi thực sự có thể tạo ra tương đương với một tập tin Excel bằng cách tách biệt bằng dấu phẩy, không chỉ mới dòng. Trong trường hợp này nếu tôi thay vì sử dụng dấu phẩy thay vì dòng mới Tôi thật sự có thể mở tập tin cơ sở dữ liệu trong Excel nếu tôi thay vì làm cho nó trông như thế này. Trong ngắn hạn, bây giờ chúng ta có sức mạnh để viết các tập tin bây giờ chúng ta có thể bắt đầu dữ liệu bền bỉ, giữ nó trên đĩa để chúng tôi có thể giữ thông tin xung quanh một lần nữa và một lần nữa. Chú ý một vài thứ khác mà bây giờ một chút quen thuộc hơn. Ở phía trên của tập tin này C, chúng tôi có một typedef bởi vì chúng tôi muốn tạo ra một kiểu dữ liệu đại diện cho một từ, do đó, loại này được gọi là từ, và bên trong của cấu trúc này đó là một chút fancier. Tại sao là một từ của mảng rõ ràng? Một từ chỉ trực giác là gì? Đây là một mảng các ký tự. Đó là một chuỗi các ký tự trở lại trở lại trở lại. Thư trong tất cả các mũ sẽ xảy ra là chúng tôi tự ý nói chiều dài tối đa bất kỳ từ nào trong từ điển mà chúng tôi đang sử dụng cho Scramble. Tại sao tôi có một 1? Các ký tự null. Nhớ lại khi chúng tôi đã làm ví dụ Bananagrams chúng tôi cần một giá trị đặc biệt ở cuối từ để theo dõi mà những từ thực sự kết thúc, và như vấn đề thiết lập các đặc điểm kỹ thuật nói ở đây chúng tôi đang liên kết với một từ cho trước một giá trị boolean, một lá cờ, vậy để nói chuyện, đúng hay sai. Bạn đã tìm thấy từ này rồi, vì chúng ta nhận ra chúng tôi thực sự cần một cách ghi nhớ không chỉ những gì một từ trong Scramble nhưng có hay không bạn, con người đã tìm thấy nó do đó nếu bạn không tìm thấy từ "" bạn có thể không chỉ cần gõ, nhập, nhập vào,, nhập và nhận được 3 điểm, 3 điểm, 3 điểm, 3 điểm. Chúng tôi muốn để có thể vào danh sách đen từ đó bằng cách thiết lập một bool đúng nếu bạn đã tìm thấy nó, và vì vậy đó là lý do tại sao chúng tôi đóng gói nó trong cấu trúc này. Bây giờ, xuống đây Scramble này struct khác được gọi là từ điển. Vắng mặt ở đây là từ typedef bởi vì trong trường hợp này chúng tôi cần để đóng gói các ý tưởng của một từ điển, và một từ điển chứa một bó toàn bộ từ, như ngụ ý của mảng này, và bao nhiêu của những từ nào? Vâng, kích thước biến này được gọi là bất cứ điều gì. Nhưng chúng ta chỉ cần một từ điển. Chúng ta không cần một kiểu dữ liệu được gọi là từ điển. Chúng tôi chỉ cần một trong số họ, do đó, nó quay ra trong C rằng nếu bạn không nói typedef, bạn chỉ cần nói struct, sau đó bên trong các dấu ngoặc nhọn bạn đặt biến của bạn, sau đó bạn đặt tên. Này được tuyên bố một biến từ điển được gọi là trông như thế này. Ngược lại, những dòng này được tạo ra từ một cấu trúc dữ liệu có thể tái sử dụng được gọi là bạn có thể tạo nhiều bản sao của, giống như chúng ta đã tạo ra nhiều bản sao của các học sinh. Điều này không gì cuối cùng cho phép chúng ta làm? Hãy để tôi đi trở lại, hãy nói, một ví dụ đơn giản từ thời đơn giản, và cho tôi mở ra, hãy nói, compare1.c. Vấn đề ở đây ở bàn tay là để thực sự vỏ trở lại lớp một chuỗi và bắt đầu dùng những bánh xe đào tạo bởi vì nó chỉ ra rằng một chuỗi thời gian này như chúng tôi đã hứa trong 1 tuần thực sự chỉ là một biệt danh, một từ đồng nghĩa từ thư viện CS50 cho một cái gì đó có vẻ nhiều hơn một chút khó hiểu, char *, và chúng tôi đã nhìn thấy ngôi sao này trước khi. Chúng tôi nhìn thấy nó trong bối cảnh của các tập tin. Bây giờ chúng ta hãy xem lý do tại sao chúng tôi đã ẩn chi tiết này một thời gian. Đây là một tập tin gọi compare1.c, và nó dường như yêu cầu người dùng cho 2 dây, s và t, và sau đó nó sẽ cố gắng để so sánh những chuỗi bình đẳng trong line 26, và nếu chúng bằng nó nói, "Bạn gõ cùng một điều," và nếu họ không bằng nó nói, "Bạn gõ những thứ khác nhau." Hãy để tôi đi trước và chạy chương trình này. Hãy để tôi đi vào thư mục mã nguồn của tôi, làm cho một compare1. Nó được biên dịch okay. Hãy để tôi chạy compare1. Tôi sẽ phóng to, nhập. Nói điều gì đó. HELLO. Tôi sẽ nói điều gì đó một lần nữa. HELLO. Tôi chắc chắn không gõ những thứ khác nhau. Hãy để tôi thử này một lần nữa. BYE BYE. Chắc chắn không phải khác nhau, do đó, những gì đang xảy ra ở đây? Vâng, những gì là thực sự đang được so sánh trong line 26? [Không nghe được học sinh] Có, do đó nó chỉ ra rằng một chuỗi, kiểu dữ liệu, là một lời nói dối trắng. Một chuỗi là một char *, nhưng một char * là những gì? A * char, như họ nói, là một con trỏ, và một con trỏ là có hiệu quả một địa chỉ, một vị trí tổng hợp trong bộ nhớ, và nếu bạn xảy ra đã gõ vào một từ như Hello, nhớ lại từ các cuộc thảo luận qua các chuỗi điều này giống như từ HELLO. Hãy nhớ rằng một từ như Hello có thể được đại diện như là một mảng của các nhân vật như thế này và sau đó với một nhân vật đặc biệt ở cuối được gọi là các ký tự null, như là \. Điều gì thực sự là một chuỗi? Chú ý rằng điều này là nhiều khối của bộ nhớ, và trong thực tế, kết thúc của nó chỉ được biết đến khi bạn xem xét thông qua toàn bộ chuỗi tìm kiếm các ký tự null đặc biệt. Nhưng nếu điều này là một đoạn bộ nhớ từ bộ nhớ của máy tính của tôi, chúng ta hãy tự ý nói rằng chuỗi này chỉ có may mắn, và nó đã được đặt ở đầu của bộ nhớ RAM của máy tính của tôi. Đây là 0 byte, 1, 2, 3, 4, 5, 6 ... Khi tôi nói điều gì đó như GetString và tôi làm string s = GetString những gì thực sự được quay trở lại? Đối với những tuần lễ vừa qua, những gì đang thực sự được lưu trữ trong s không phải là chuỗi này mỗi se, nhưng trong trường hợp này những gì đang được lưu trữ số 0 bởi vì những gì GetString thực hiện là nó không thể chất trả về một chuỗi. Mà thậm chí không thực sự có ý nghĩa khái niệm. Những gì nó trả về là một số. Con số này là địa chỉ của Hello trong bộ nhớ, string s sau đó, nếu chúng ta vỏ trở lại lớp này, chuỗi không thực sự tồn tại. Nó chỉ là một đơn giản hóa trong thư viện CS50. Điều này thực sự là một cái gì đó gọi là char *. Char có ý nghĩa bởi vì một từ là những gì, như Hello? Vâng, đó là một loạt các ký tự, một loạt các ký tự. Char * có nghĩa là địa chỉ của một nhân vật, do đó, nó trả về một chuỗi có ý nghĩa gì? Một cách đơn giản, đẹp trả lại một chuỗi chứ không phải là cố gắng tìm ra làm thế nào tôi trở về 5 hoặc 6 byte khác nhau hãy để tôi quay trở lại địa chỉ trong đó byte? Người đầu tiên. Nói cách khác, hãy để tôi cung cấp cho bạn địa chỉ của một nhân vật trong bộ nhớ. Đó là những gì char * đại diện cho địa chỉ của một nhân vật duy nhất trong bộ nhớ. Gọi đó là biến s. Cửa hàng ở địa chỉ cụ thể, mà tôi tự ý nói là 0, chỉ để giữ cho mọi thứ đơn giản, nhưng trong thực tế nó thường là một số lớn hơn. Chờ một phút. Nếu bạn chỉ cho tôi địa chỉ của ký tự đầu tiên, làm thế nào để tôi biết những gì địa chỉ của nhân vật thứ hai, thứ ba, thứ tư và thứ năm? [Không nghe được học sinh] Bạn chỉ biết nơi kết thúc của chuỗi là bằng cách lừa này tiện dụng, vì vậy khi bạn sử dụng một cái gì đó giống như printf printf nghĩa là mất như là đối số của nó, nhớ lại rằng chúng tôi sử dụng giữ chỗ này% s, và sau đó bạn vượt qua trong biến lưu trữ một chuỗi. Những gì bạn đang thực sự đi qua là địa chỉ của ký tự đầu tiên của chuỗi đó. Printf sau đó sử dụng một vòng lặp hoặc một vòng lặp trong khi khi nhận được địa chỉ đó, ví dụ, 0, do đó, hãy để tôi làm điều này ngay bây giờ, printf ("% s \ n", s); Khi tôi gọi printf ("% s \ n", s); những gì tôi đang thực sự cung cấp printf với là địa chỉ của ký tự đầu tiên trong s, mà trong trường hợp này tùy ý là H. Làm thế nào để printf biết chính xác những gì hiển thị trên màn hình? Người thực hiện printf thực hiện một vòng lặp trong khi một vòng lặp for nói rằng nhân vật này bằng các ký tự null đặc biệt? Nếu không, in nó. Làm thế nào về một trong những điều này? Nếu không in, in, in ấn, in nó. Ồ, cái này là đặc biệt. Ngừng in ấn và trả lại cho người sử dụng. Và đó là nghĩa là tất cả những gì đang xảy ra bên dưới mui xe, và đó là rất nhiều để tiêu hóa trong ngày đầu tiên của một lớp, nhưng bây giờ nó thực sự là khối xây dựng sự hiểu biết tất cả mọi thứ đã xảy ra bên trong bộ nhớ máy tính của chúng tôi, và cuối cùng chúng tôi sẽ trêu chọc này ngoài với một chút giúp đỡ từ một trong những bạn bè của chúng tôi tại Stanford. Giáo sư Nick Parlante tại Stanford đã làm điều này chuỗi video tuyệt vời từ tất cả các loại ngôn ngữ khác nhau mà giới thiệu Binky nhân vật này Claymation ít. Giọng nói bạn đang về để nghe chỉ trong một sneak xem trước vài thứ hai là của một giáo sư Đại học Stanford, và bạn đang nhận được chỉ có 5 hoặc 6 giây của quyền này bây giờ, nhưng đây là lưu ý mà chúng ta sẽ kết thúc ngày hôm nay và bắt đầu vào thứ tư. Tôi cung cấp cho bạn Fun Pointer với Binky, xem trước. [♪ Âm nhạc ♪] [Giáo sư Parlante] Hey, Binky. Thức dậy. Đó là thời gian cho vui con trỏ. [Binky] đó là gì? Tìm hiểu về con trỏ? Oh, goody! Chúng ta sẽ thấy bạn hôm thứ Tư. [CS50.TV]