[Powered by Google Translate] [Tuần 4, Tiếp tục]
[David J. Malan - Đại học Harvard
[Đây là CS50. - CS50.TV]
>> Đây là CS50, và đây là kết thúc của tuần thứ 4.
Vì vậy, một số tin tốt và một số tin tức xấu.
Không có bài giảng Thứ hai, không có vấn đề thiết lập tuần tới. [Sinh viên cổ vũ]
Bạn sẽ không thích nơi này là đi.
Nhưng chúng ta không có điều này thay vì thứ tư tới,
và đó cũng là mỗi bài giảng giáo trình 1 thứ Sáu vào thứ sáu tới để chúng tôi có thể ở lại theo dõi.
Nhưng tất cả mọi thứ sẽ được quay như thường lệ, do đó, không phải lo lắng.
>> Và đối với bài kiểm tra 0 những gì chúng tôi sẽ làm đến cuối tuần
được đăng bài trên cs50.net trang chủ của khóa học một lời giải thích
bạn cần phải có những gì sắp xếp của những kỳ vọng khi nói đến các bài kiểm tra đầu tiên.
Nói chung, nó sẽ có nhiều lựa chọn, đúng-sai, câu trả lời ngắn gọn, các vấn đề mã hóa ngắn.
Bạn sẽ không được dự kiến ​​sẽ thực hiện tương đương
một vấn đề mà bạn sẽ thấy trên pset một, mà bạn có một máy tính
một trình gỡ lỗi và như thế, nhưng sẽ có một vấn đề nhỏ mã hóa.
>> Và quả thực, hướng dẫn tốt nhất để có được một cảm giác về những gì CS50 câu đố giống như
là đi đến cs50.net, đi đến liên kết Quizzes,
và bạn có thể nhìn thấy trong nhiều năm qua giá trị của các câu đố.
Chỉ cần nhận ra rằng chương trình giảng dạy đã không luôn luôn như vậy trong những năm qua.
Đôi khi chúng ta thêm, đôi khi trừ đi,
vì vậy nếu bạn nhìn thấy một số chủ đề trên một tuổi những câu đố
rằng bạn không có ý tưởng những gì nó nói về, nó hoặc là chúng tôi đã bao gồm nó
hoặc là chúng tôi không bao gồm nó.
Tuy nhiên, trong các hình thức đánh giá, chủ nhật tuần này, Thứ hai, và thứ ba
cũng như một khóa học toàn phiên xem xét vào đêm chủ nhật -
thời gian và địa điểm sẽ được công bố trên trang chủ của khóa học -
tất cả các bạn có một cơ hội để xem xét với các nghiên cứu sinh giảng dạy của khóa học
tài liệu cho năm nay, trong phần và như là một lớp học đầy đủ,
và những người sẽ được quay như bình thường là tốt.
>> Được rồi. Vì vậy, không có thêm ado, một bình luận về thông qua / không và thêm / thả.
Bạn có thể đã nhìn thấy ghi chú của tôi đêm qua, và điều này là thực sự chỉ là một số bảo đảm bổ sung
rằng nếu bạn là một trong những người đặc biệt ít thoải mái hoặc một nơi nào đó ở giữa
và bạn đang cảm thấy chỉ cần một chút trên đầu của bạn,
nhận ra đó thực sự là hoàn toàn bình thường, và có một cấu trúc hỗ trợ phong phú tại chỗ,
một trong số đó giờ hành chính là có ý định cải thiện hơn một đêm cuối cùng của tôi email,
và nhận ra quá mà một tùy chọn như vượt qua / không cho một lớp học như thế này
thực sự có ý nghĩa như một cơ chế để giúp bạn bắt tắt của một khóa học như thế này,
để một lần nữa nếu bạn đang chi tiêu những người 10, 15, 20 giờ
chỉ cần cố gắng để có được một số pset để làm việc và bạn biết bạn 90-95% số đường có
nhưng bạn không thể tìm thấy một số lỗi damn, vượt qua một / không mô hình đó là sắp xếp của không sao.
>> Ý tưởng là với cơ chế đó, sau đó bạn có thể đi tập trung trên psets khác của bạn
hoặc ngủ hoặc bất cứ điều gì nó là bạn muốn tập trung vào.
Vì vậy, nhận ra rằng bạn có cho đến thứ ba này tới kỹ thuật thứ hai 5,
nhưng đó là một kỳ nghỉ, vì vậy thứ ba này tới - để chuyển đổi từ đường chuyền / không được phân loại hoặc ngược lại.
Và nếu bạn thực sự trên các vách và đang nghĩ đến việc bỏ hoàn toàn,
xin vui lòng bắt tôi sau khi bài giảng hoặc thả cho tôi một lưu ý.
Chúng tôi rất muốn ít nhất là trò chuyện trước khi bạn đặt giá thầu lời nói sáo rỗng.
Được rồi. Vì vậy, chúng tôi bắt đầu tham gia các bánh xe đào tạo ra thời gian qua.
Đặc biệt, chúng tôi tập trung vào chuỗi.
String là một cái gì đó là tuyên bố trong thư viện CS50,
đặc biệt trong tập tin đó được gọi là cs50.h mà chúng ta sẽ bắt đầu nhìn vào tuần này và tiếp theo.
Nhưng chuỗi thực sự chỉ là một đơn giản hóa một cái gì đó
đó là một chút hơn arcanely mô tả như là char *.
Char chúng ta đã quen thuộc với. Nó chỉ là một nhân vật duy nhất.
Nhưng * thứ hai biểu thị những gì? >> [Sinh viên] Một con trỏ.
Một con trỏ. Và một con trỏ là những gì? >> [Sinh viên] Một địa chỉ.
>> Nó giống như một địa chỉ, một vị trí trong bộ nhớ.
Một địa chỉ hoặc vị trí bộ nhớ hoặc là gì?
Một lần nữa, tất cả chúng ta có máy tính xách tay với một buổi biểu diễn hoặc 2 GB RAM nhiều khả năng những ngày này,
và điều đó có nghĩa là bạn có một tỷ hoặc 2 tỷ byte giá trị của bộ nhớ.
Và nó không thực sự có vấn đề gì về thể chất có vẻ như,
nhưng trên đức tin mà bạn có thể đếm tất cả các byte cá nhân máy tính xách tay của bạn có -
điều này là byte 0, đây là 1 byte, đây là byte 2 tỷ -
và đó là chính xác những gì một máy tính nào.
Khi bạn phân bổ không gian cho một nhân vật duy nhất, ví dụ,
rõ ràng là nó phải sống ở một nơi nào đó trong bộ nhớ của máy tính của bạn,
và có lẽ đó là số byte 12.345,
và đó là một nơi nào đó ở đây trong bộ nhớ máy tính của bạn.
Và địa chỉ của nhân vật đó là 12345.
>> Bây giờ, trong tuần 0 thông qua vậy, đến nay, chúng tôi đã không thực sự quan tâm
nơi mà trong những điều bộ nhớ được lưu trữ bởi vì chúng ta thường sử dụng các biểu tượng,
biến, và mảng để thực sự có được dữ liệu của chúng tôi.
Nhưng vào thứ hai và hơn cả ngày hôm nay, bạn sẽ có
tất cả các khả năng biểu cảm hơn với các chương trình bằng văn bản
để thực sự thao tác bộ nhớ của máy vi tính tuy nhiên bạn thấy phù hợp,
cho cả hai mục đích tốt và xấu,
lỗi là một kết quả rất phổ biến vào thời điểm này trong việc học những thứ này.
Tuy nhiên, những gì thực sự có ý nghĩa là một char *?
Hãy cho đi trước trở lại và chúng tôi sẽ trở lại Binky như đã hứa hôm nay.
Chúng ta hãy đi vào một ví dụ đơn giản ở đây.
Hãy để tôi lưu tập tin này là compare.c, và hãy để tôi chỉ nhận được một số mẫu mã ở đây
trên bao gồm stdio.h, hãy để tôi cũng có thể cung cấp cho bản thân mình bao gồm cs50.h. Tôi sẽ phóng to lên đó.
Hãy để tôi bắt đầu viết int main, main (void), và bây giờ tôi muốn làm một cái gì đó như thế này:
printf ("Hãy cho tôi một chuỗi:") và sau đó tôi sẽ sử dụng chuỗi s được getString
để có được một chuỗi từ người dùng, sau đó tôi sẽ yêu cầu người dùng cho một số khác.
("Hãy cho tôi một chuỗi:") và tôi sẽ yêu cầu họ thông qua getString để có được điều đó.
Tôi sẽ gọi nó t vì t đi kèm sau và là một tên tốt đẹp cho một chuỗi nếu nó là khá chung chung.
Vì vậy, GetString, và bây giờ tôi chỉ muốn làm một kiểm tra sự tỉnh táo và tôi sẽ nói
if (s == t) sau đó tôi là chỉ cần nói cho người dùng printf ("Bạn gõ những điều tương tự \ n");
khác tôi sẽ in ra một cái gì đó như thế ("Bạn gõ một cái gì đó khác nhau \ n!")
hoặc bất cứ câu sẽ được. Vì vậy, một cái gì đó như thế.
Sau đó, như thường lệ, tôi sẽ trở về 0 mà chỉ có nghĩa rằng không có gì xấu xảy ra,
và tôi sẽ đi trước và biên dịch và chạy chương trình này.
>> Tuy nhiên, hôm chúng tôi chạy chương trình này,
và thực sự đã nói rằng Hello là không Hello và GOODBYE là không GOODBYE.
Các hành vi chúng ta nhìn thấy nhiều hơn một chút như thế này.
Hãy để tôi đi vào thư mục nguồn của tôi, zoom ở đây, và chúng ta hãy làm làm so sánh.
Tổng hợp okay. Cho phép tôi chạy so sánh. Hãy cho tôi một chuỗi: HELLO.
Hãy cho tôi một chuỗi: HELLO.
Bạn đã gõ một cái gì đó khác nhau!
Vâng, hãy để tôi thử một cái gì đó đơn giản như 50, 50. Bạn đã gõ một cái gì đó khác nhau!
hi, hi. Vì vậy, rõ ràng, một cái gì đó đang xảy ra ở đây.
Tuy nhiên, lời giải thích cho lý do tại sao là gì?
Rõ ràng, dòng 12 là hoàn toàn rối loạn chức năng.
Vấn đề cơ bản ở đây là gì? Yeah. >> [Sinh viên] so sánh các địa chỉ.
Yeah, chính xác. Nó thực sự so sánh các địa chỉ
trong đó Hello Hello được lưu trữ.
Nó không phải so sánh các chữ cái Hello một lần nữa và một lần nữa,
bởi vì những gì đang thực sự xảy ra, tất cả thời gian này, chúng tôi đã được sử dụng GetString -
Bảng đen Đây lại là bộ nhớ máy tính của chúng tôi,
và chúng ta hãy nói rằng tôi gọi GetString sau khi khai báo một biến s.
Bộ nhớ của tôi trông như thế nào?
Hãy tự ý nói đó là trông như thế này. Đó là một hình vuông.
Và khá nhiều bất kỳ thời gian tôi đã rút ra một mảnh bộ nhớ trên màn hình
nếu nó là 32 bit đã vẽ hình vuông như thế này bởi vì thực sự trong thiết bị,
một con trỏ, một địa chỉ, là 32 bit. Nó giống như một int.
Điều đó có thể khác nhau dựa trên hệ thống máy tính.
Những người bạn của những người quen quen với thực tế rằng Mac hoặc máy PC của bạn là 64 bit,
mà thực sự biểu thị rằng máy tính của bạn bằng cách sử dụng 64-bit con trỏ,
Địa chỉ 64-bit, và trong số những mặt tích cực đó là máy tính của bạn
có thể có bộ nhớ RAM nhiều hơn xưa đã.
Long câu chuyện ngắn, trở lại trong ngày khi máy tính chỉ được sử dụng 32 bit
để đại diện cho địa chỉ, số lượng lớn nhất của byte, bạn có thể đại diện cho
trong trường hợp đó là những gì nếu bạn có 32 bit?
Vì vậy, 4 tỷ đồng, đúng, bởi vì 2 đến số 32 là 4 tỷ đồng.
Con số này đã được tái diễn trong khóa học.
>> Vì vậy, nếu bạn chỉ có 32 bit, số lượng cao nhất bạn có thể đếm đến khoảng 4 tỷ đồng.
Nhưng đó là một hạn chế cơ bản của máy tính cho đến khi một vài năm trước đây
bởi vì nếu bạn chỉ có thể tính là cao là 4 tỷ đồng,
nó không quan trọng nếu bạn mua 8 GB RAM hoặc thậm chí 5 GB RAM;
bạn không thể đếm là cao, do đó, nó là vô ích.
Bạn chỉ có thể truy cập vào 3 hoặc 4 GB đầu tiên của bộ nhớ máy tính của bạn.
Đó là ít hơn của một vấn đề bây giờ, và bạn có thể mua MacBook Pros và Dells
với 8 GB RAM hoặc nhiều hơn những ngày này.
Nhưng nếu tôi phân bổ khá đơn giản trong chương trình này một con trỏ, một con trỏ được gọi là s,
nó có thể trông như thế này trên màn hình vì thực sự chúng ta cần phải vỏ trở lại lớp này.
Tôi tiếp tục chuỗi nói, nhưng thứ Hai, chuỗi thực sự là char *,
địa chỉ của một số nhân vật.
Vì vậy, hãy đi mà bánh xe đào tạo ra mặc dù chúng ta sẽ tiếp tục sử dụng GetString cho bây giờ.
Vì vậy, tôi đã khai báo, và đây là một đoạn bộ nhớ, 32 bit.
Gì ở đây trong bộ nhớ mặc định? >> [Không nghe được sinh viên phản ứng]
Đó là những gì? >> [Sinh viên] Garbage. >> Xe rác. Chính xác.
Nếu bạn lập trình viên không đặt một giá trị trong một biến, ai biết nó là gì?
Đôi khi bạn nhận được may mắn và nó là 0, là loại một giá trị mặc định tốt đẹp, sạch sẽ,
nhưng như chúng ta đã thấy Thứ hai, đôi khi nó là hoàn toàn vô nghia,
một số tích cực hay tiêu cực thực sự lớn số đó đến từ đâu?
Yeah. >> [Sinh viên] chức năng trước khi. >> Yeah.
>> Thường thì các chức năng đã được gọi trước đó vì nhớ,
như bạn gọi chức năng trong bộ nhớ, họ mất nhiều không gian hơn và nhiều hơn nữa từ dưới lên,
và ngay sau khi trở về chức năng, bộ nhớ mà được tái sử dụng
bởi các chàng tiếp theo đó được gọi là, những người đang sử dụng lát cùng một bộ nhớ của bạn.
Và nếu bạn đã rác bên trái có giá trị trước đó,
chúng ta có thể nhầm lẫn s là có một số giá trị khi thực sự chúng tôi đã không đặt bất cứ điều gì có.
Vì vậy, bộ nhớ RAM của chúng tôi tại thời điểm này trông như thế này.
Bây giờ ở phía bên tay phải của dòng 7, chúng tôi đang gọi điện thoại GetString,
mà chúng tôi đã làm bây giờ trong nhiều tuần, nhưng những gì được getString thực sự làm?
GetString được viết bởi các nhân viên CS50 là một chút thông minh
rằng ngay sau khi người dùng bắt đầu các phím gõ và số truy cập Nhập
GetString con số bao nhiêu tổ hợp phím đã bị người dùng,
bao nhiêu nhân vật cần phải phân bổ cho bộ nhớ RAM.
Và nơi RAM mà đến từ những người hiểu biết?
Đó là một nơi nào đó trong máy tính của bạn 2 GB hoặc whatnot bộ nhớ.
Nhưng chúng ta hãy giả sử rằng máy tính tìm thấy không gian cho từ Hello ngay tại đây.
Từ tôi đã nhập là H-E-L-L-O.
Và nếu chúng ta rút ra điều này như là một chuỗi ký tự, chúng ta có thể rút ra nó như thế này.
Nhưng tôi cần phải làm thêm 1 điều. Những gì thuộc về vào cuối của bất kỳ chuỗi trong C?
Các ký tự null, mà chúng tôi viết là \ 0.
Đó là kỹ thuật số 0, nhưng các dấu gạch chéo ngược làm cho tất cả các rõ ràng hơn
rằng điều này có nghĩa là số 0, số nguyên 0;
nó không phải, cho 0 dụ quote-unquote, mà bạn có thể gõ vào bàn phím.
Vì vậy, đây là HELLO.
>> Và chúng tôi đã nói vào hôm thứ Hai rằng một chức năng như GetString
thực sự là trả lại tất cả những tuần lễ?
Nó không phải trả lại một chuỗi cho mỗi gia nhập, vì điều đó không thực sự có ý nghĩa
vì chuỗi không tồn tại. Họ sắp xếp của một sự bịa đặt trong thư viện CS50.
Điều gì thực sự là một chuỗi, kỹ thuật hơn? >> [Sinh viên] Đó là ký tự đầu tiên.
Chính xác. Nó khá đơn giản chỉ là địa chỉ của ký tự đầu tiên mà người dùng gõ vào.
Vì vậy, nếu từ ngữ của tôi Hello kết thúc nó tại 123 số byte và sau đó tại số byte 124,
125, 126, và vân vân, nếu tôi chỉ số byte của tôi từ 0 trở lên,
những gì thực sự GetString đang quay trở lại có nghĩa là số 123 số.
Vì vậy, những gì được đặt vào s là số 123 số, không phải H với doanh nghiệp, không phải là từ HELLO,
khá đơn giản địa chỉ mà tôi có thể tìm thấy những chữ cái đầu tiên của Hello.
Nhưng điều đó không có vẻ như đủ. Tôi hỏi bạn cho một chuỗi, không phải là một nhân vật.
Vì vậy, làm thế nào để chúng ta hoặc máy tính biết rằng ello loại đi cùng với H?
Các loại thỏa thuận mà chúng ta có là gì? Yeah.
[Sinh viên] Nó giữ nói cho chính nó để tìm các ký tự một số chi tiết. >> Chính xác.
>> Có quy ước của con người-máy tính, theo đó khi bạn đang đối phó với chuỗi,
nếu không được biết đến tại sao char, bạn chỉ cần có để tìm ra
nơi kết thúc của tất cả các chuỗi trong cuộc sống là thực sự chỉ iterating trên nó với một vòng lặp for,
một vòng lặp trong khi, bất cứ điều gì, để khi bạn tìm thấy những kết thúc của chuỗi
bây giờ bạn có thể suy ra từ đó, oh, toàn bộ từ HELLO.
Những người bạn có kinh nghiệm lập trình trước có thể biết trong Java
bạn chỉ có thể gọi chiều dài và các ngôn ngữ khác, bạn có thể gọi chiều dài hoặc tương tự.
Đó là bởi vì trong rất nhiều ngôn ngữ, đặc biệt là điều được gọi là ngôn ngữ hướng đối tượng,
chiều dài của một cái gì đó là loại bên trong đóng gói các mảnh dữ liệu chính nó,
nhiều như chúng tôi ID đóng gói và tên, nhà bên trong của một sinh viên vào hôm thứ Hai.
Tuy nhiên, C là mức độ thấp hơn nhiều. Không có đối tượng hoặc các lớp học, nếu bạn đã nghe những điều khoản trước khi.
Tất cả bạn phải thực sự là địa chỉ bộ nhớ.
Vì vậy, đây là loại theo cách cũ thời đại diện cho cấu trúc dữ liệu thú vị.
Bạn có một giá trị bắt đầu giống như địa chỉ của ký tự đầu tiên
và sau đó chỉ cần một số quy ước tùy ý mà tất cả mọi người đồng ý làm theo.
Vì vậy, làm thế nào là chuỗi dài thực hiện, chúng tôi đề xuất?
Strlen, strlen, mà một số bạn đã sử dụng một vài lần. Nó khá đơn giản, phải không?
Nó giống như 2 dòng mã.
Đó là khá nhiều một vòng lặp của một số loại, có thể với một biến địa phương bổ sung.
Nhưng strlen chỉ để có một con trỏ và sau đó bắt đầu tìm kiếm cho \ 0.
>> Và ngay sau khi nó tìm thấy nó, nó có thể trả lại tổng số bước thực hiện trong chuỗi đó.
Vì vậy, chúng ta có thể suy ra từ những gì diễn ra tiếp theo.
Giả sử sau đó tôi tuyên bố t như tôi đã làm trong dòng 10.
Đây là một số giá trị rác. Ai biết tại đầu tiên?
Tuy nhiên, ở phía bên tay phải của dòng 10 tôi gọi getString một lần nữa.
Ai biết nơi này kết thúc?
Hãy tùy tiện nói rằng hệ điều hành tìm thấy chỗ cho nó theo cách trên đây.
Tôi xảy ra tình cờ gõ H-E-L-L-O một lần nữa,
và như vậy chúng ta có thể rút ra cùng một loại hình ảnh.
Tuy nhiên, thực tế là tôi đã vẽ lại hình ảnh này là có chủ ý
bởi vì đó là khác nhau hơn so với một trong những điều này.
Vì vậy, đây có thể là vị trí 456, 457, và vv.
Vì vậy, những gì được đặt dấu hỏi một lần?
Trong trường hợp này là 456.
Chúng tôi đang chọn những con số tùy tiện bởi vì thực sự sau ngày hôm nay
chúng tôi sẽ không quan tâm quá nhiều về những gì các địa chỉ của bất cứ điều gì.
Tất cả những gì chúng tôi quan tâm là chúng ta có thể tìm ra địa chỉ của một số phần dữ liệu như Hello.
>> Vì vậy, thực sự những gì hầu hết mọi người làm trong lĩnh vực khoa học máy tính khi nói về các địa chỉ bộ nhớ
và nói chuyện về con trỏ đặc biệt,
chứ không phải bận tâm để tìm ra 123 - những người quan tâm công cụ này thực sự là,
chúng tôi chỉ biết rằng đó là tại một số địa chỉ số
chúng ta đơn giản hóa trên thế giới và chỉ nói rằng s chỉ nhân vật đó
và t chỉ nhân vật đó.
Và thực tế là nó là một mũi tên khá cố ý
vì nghĩa đen tại s chỉ vào H và t chỉ tại H khác
bởi vì lúc cuối ngày, không có vấn đề gì địa chỉ là,
nhưng nó không thành vấn đề mà chúng ta có khả năng để thể hiện rằng địa chỉ với một số đoạn mã.
Chúng tôi đã không thực sự thao tác các địa chỉ này chỉ được nêu ra
do đó, chúng ta sẽ thấy chúng ta có thể xen vào và sắp xếp làm việc với con trỏ,
nhưng bây giờ trong dòng 12 nghĩa là những giá trị chúng ta so sánh
theo câu chuyện này trong dòng 12?
Chúng tôi đang nói là 123 bằng bằng 456? Và đó chắc chắn không phải là trường hợp.
Và ngay cả khái niệm, con trỏ này chắc chắn là không giống như thế này
bởi vì bạn được gọi là getString hai lần, và GetString không cố gắng để được siêu thông minh,
nó không cố gắng để nhận ra, oh, bạn đã gõ Hello 5 phút trước;
hãy để tôi cung cấp cho bạn con trỏ giống như tôi đã cho bạn,
nó chỉ cấp phát một đoạn mới của bộ nhớ mỗi khi bạn gọi nó.
>> Vì vậy, làm thế nào để chúng ta khắc phục vấn đề này?
Nếu cấp độ cao hơn, tôi muốn so sánh chuỗi Hello Hello -
Tôi không quan tâm về con trỏ làm thế nào để tôi đi về trả lời câu hỏi,
người dùng đã gõ điều tương tự? Những gì cần thiết ở đây? Yeah.
[Sinh viên] Sử dụng một chức năng. >> Tôi có thể sử dụng một chức năng ra khỏi hộp.
Tôi có thể sử dụng một chức năng được gọi là strcmp, s-t-r-c-m-p,
chỉ là phiên bản rút gọn của chuỗi so sánh.
Và nếu chúng ta đi vào, ví dụ, so sánh 2, là một trong số các tài liệu phát hiện nay,
Tôi làm chính xác điều đó.
Tôi giữ tất cả mọi thứ khác tương tự từ dòng 1 xuống 26 hoặc,
và bây giờ nhận thấy điều này một phần đã thay đổi chỉ là một chút.
Hãy bỏ qua dòng 28 cho một thời điểm và chỉ tập trung vào một trong những điều này.
Chúng tôi thứ hai cần nói rằng so sánh str?
Nó xử lý các quá trình của 2 con trỏ, s và t trong trường hợp này,
loại gần như đặt ngón tay của mình vào 2 chữ cái,
và những gì nó phải làm một cái gì đó giống như một vòng lặp trong khi một vòng lặp for,
và nó nói là những giống nhau? Nếu vậy, nó di chuyển các ngón tay hoặc con trỏ về phía trước.
Là những giống nhau, giống nhau, này, cùng
những giống nhau, những giống nhau? Và ooh, tôi đang ở phần cuối của chuỗi ở cả hai s và t.
Tôi đã không tìm thấy bất kỳ mâu thuẫn nào. Có, những chuỗi này đều giống nhau.
Và những gì str so sánh trở lại nếu 2 chuỗi đều giống nhau, rõ ràng? Zero.
Vì vậy, 0 là tốt trong trường hợp này bởi vì nếu nó trả về -1 hoặc +1,
điều đó có nghĩa là đó là chỉ xảy ra cho đến trước khi t theo thứ tự abc hoặc sau khi t.
Và tại sao mà có thể hữu ích để có một chức năng mà sẽ cho bạn biết chuỗi đến trước khi
hoặc sau khi trong một từ điển?
[Sinh viên] Tìm kiếm. >> Tìm kiếm và phân loại.
>> Vì vậy, bạn có thể làm những việc như tìm kiếm nhị phân hoặc phân loại bong bóng hoặc hợp nhất các loại
, nơi bạn có để so sánh mọi thứ.
Như vậy đến nay, chúng tôi đã loại cắt giảm một số góc và chỉ nói chuyện về phân loại
trong bối cảnh các con số bởi vì nó đẹp và dễ dàng để nói về,
nhưng bạn chắc chắn có thể so sánh chuỗi, táo và chuối,
bởi vì nếu táo được biết đến trước khi chuối, tương tự như vậy,
bạn có thể di chuyển các chuỗi xung quanh trong bộ nhớ giống như Rob đã làm với loại hợp nhất trong đoạn video
và chúng tôi đã làm ở đây trên sân khấu với sắp xếp lựa chọn, sắp xếp chèn và sắp xếp bong bóng.
Vì vậy, nơi khác chúng ta có thể thực hiện việc này? Hãy thử điều này.
Hãy loại quên bài học đó cho một thời điểm và thử ngay bây giờ và sao chép 1.c làm như sau.
Ở dòng 21 tôi đang nói một cái gì đó in,
sau đó tôi nhận được một chuỗi từ người dùng,
sau đó tôi đang kiểm tra này.
Chúng tôi đã không thực sự nhận được vào thói quen này, nhưng Bây giờ chúng ta hãy làm điều này.
Hãy thực sự bóc lớp này. Đây thực sự là char *. Anh chàng này thực sự là char *.
Vì vậy, nó có ý nghĩa gì để được kiểm tra nếu == NULL?
Nó chỉ ra rằng khi bạn gọi một chức năng giống như GetString
hoặc nói chung chỉ cần hỏi một máy tính để cung cấp cho bạn một số bộ nhớ,
một cái gì đó có thể đi sai.
Bạn có thể là điên và yêu cầu máy tính cho một terabyte bộ nhớ
bằng cách yêu cầu hàng nghìn tỷ byte của bộ nhớ mà chỉ cần không tồn tại trong máy tính,
nhưng chức năng GetString và cần một số cách la hét vào bạn
nếu bạn đã yêu cầu quá nhiều.
Và cách GetString thực hiện điều này là nếu bạn đã yêu cầu nhiều bộ nhớ hơn
hơn có sẵn trong máy tính, ngay cả khi đó là siêu, siêu xác suất thấp
bởi vì không ai trong chúng ta sẽ gõ một nghìn tỷ nhân vật và sau đó nhấn Enter,
nhưng xác suất thấp mặc dù nó có thể được, tôi vẫn muốn kiểm tra cho nó chỉ trong trường hợp,
và giá trị đặc biệt mà trở về GetString, câu trả lời, và các chức năng khác
nếu một cái gì đó đã đi sai là NULL trong tất cả các mũ.
>> Và những gì là NULL? NULL chỉ để xảy ra để đại diện cho một con trỏ. Đó là bộ nhớ địa chỉ 0.
Thế giới đã quyết định tùy tiện, nếu điều này là bộ nhớ máy tính của tôi - bạn biết những gì?
chúng ta sẽ ăn cắp chỉ 1 byte bộ nhớ của mỗi máy tính, và điều này là vị trí 0.
Chúng tôi sẽ để cho nó một biệt hiệu của NULL, và chúng tôi sẽ hứa hẹn
rằng chúng ta sẽ không bao giờ thực sự đưa dữ liệu thực sự có
bởi vì chúng ta chỉ cần tùy tiện cần một giá trị đặc biệt, 0, NULL aka,
để chúng tôi có thể hét lên với người sử dụng nếu có điều gì sai.
Nếu không, bạn có thể không biết không 0 có nghĩa là đặt một cái gì đó ở đây
hoặc có nghĩa là một cái gì đó đã đi sai?
Chúng tôi có cho tất cả đồng ý rằng không có gì có nghĩa là NULL được trả lại,
không có địa chỉ thực tế được trả lại.
Bây giờ, ở đây tôi chỉ áp dụng quy ước của con người của tôi của tôi trở về 1 từ chính
nếu có điều gì sai.
Đó là bởi vì ước trở lại chính là để trở về 0 nếu tốt,
1 hoặc một số giá trị khác nếu xấu.
Nhưng GetString và chức năng bất kỳ mà đề lại nhớ NULL nếu một cái gì đó xấu đi.
>> Okay. Vì vậy, thật không may, 27 dòng, siêu đơn giản, mặc dù nó là, hoàn toàn không để sao chép các chuỗi.
Tại sao? Chúng ta có thể thấy điều này như sau.
Tôi có khiếu nại trong dòng 27 được thực hiện một bản sao của s và gọi đó là t.
Vì vậy, tôi không yêu cầu người sử dụng cho 2 dây thời gian này, Tôi chỉ nói giá trị trong s
cần được đặt trong t là tốt.
Vì vậy, bây giờ chỉ để chứng minh bị hỏng này, trong dòng 29 trở đi những gì tôi làm?
Trước tiên, tôi kiểm tra nếu chiều dài của t là lớn hơn 0.
Có một số chuỗi có. Người dùng gõ một cái gì đó.
Dòng 32 làm, rõ ràng là gì?
[Không nghe được sinh viên phản ứng] >> phải. Loại có thể suy ra từ những gì tôi nói nó đang làm.
Nhưng về mặt kỹ thuật, điều này đang làm gì? t [0] đại diện cho những gì?
[Sinh viên] Các ký tự 0. >> [Malan] Các ký tự 0.
Hoặc, giống như con người, ký tự đầu tiên trong t, bất kể đó là, H có thể trong trường hợp này.
Và toupper những gì nó nói. Nó tận dụng các ký tự 0 t và nó thay đổi nó.
Vì vậy, điều này có nghĩa là các ký tự 0 của t, làm cho nó thành chữ hoa,
và đặt nó trở lại trong cùng một vị trí.
Vì vậy, nếu tôi gõ hello bằng chữ thường, điều này sẽ thay đổi h chữ thường để một H. vốn
Nhưng vấn đề là trong các dòng 35 và 36 những gì tôi sắp làm là in ra cho chúng ta s và t.
Và linh cảm của bạn là gì?
Những gì tôi thực sự sẽ để xem nếu tôi gõ trong hello tất cả bằng chữ thường?
Những gì đang xảy ra để có được in? >> [Không nghe được sinh viên phản ứng] >> đó là gì?
[Sinh viên] Big H và phần còn lại nhỏ. >> H lớn và phần còn lại nhỏ mà, t?
[Sinh viên] Cả hai. >> Cả hai. Chính xác. Vì vậy, chúng ta hãy xem những gì đang xảy ra ở đây.
>> Hãy để tôi đi trước và biên dịch này. Đây là copy1, do đó hãy copy1. Được rồi.
Zoom in Hãy để tôi đi trước và chạy copy1, Enter, Nói gì: hello bằng chữ thường.
Hoa sao chép, nhưng nó dường như hoa cũng,
bởi vì những gì xảy ra trong câu chuyện này?
Trong dòng 27, tôi không thực sự có vẻ được sao chép chuỗi,
nhưng ngay cả khi bạn có thể trực giác hy vọng rằng phải là trường hợp,
nếu bạn nghĩ về hình ảnh này, những gì thực sự tôi đã thực hiện?
Một nửa của hình ảnh là như nhau.
Vì vậy, chúng ta hãy quay trở lại trong thời gian để t không tồn tại được nêu ra trong câu chuyện.
S có thể tồn tại trong câu chuyện, nhưng chúng ta hãy thành chữ thường thời gian này.
Vì vậy, hãy để tôi sửa chữa những gì tôi thực sự đánh máy.
Trong trường hợp này ở đây, chúng ta có h-e-l-l-o.
Chúng tôi sẽ vẽ nó như là một chuỗi các ký tự, đặt đường phân cách của tôi ở đây và \ của tôi 0.
Vì vậy, đây là nơi chúng tôi là ngay khi dòng 1 thông qua 24-ish, cho hay phải mất, đã thực hiện.
Đây là hình ảnh bộ nhớ của tôi.
Khi tôi nhận được dòng 27, những gì sẽ xảy ra?
Giống như trước đây, tôi nhận được một con trỏ, mà tôi sẽ vẽ như hình vuông này.
Nó được gọi là t. Và giá trị của nó theo mặc định là gì? Ai biết được? Một số giá trị rác.
>> Vì vậy, tôi sẽ trừu tượng mà là một dấu hỏi.
Và ngay sau khi phía bên tay phải của dòng 27 thực hiện, tôi, những gì tôi đặt bên trong của t?
Cùng một điều đó là trong s.
Vì vậy, nếu chúng ta cho một thời điểm loại bỏ trừu tượng mũi tên này và chúng tôi nói,
oh, đây là địa chỉ tải bộ nhớ 123, khi bạn nói t được s, dấu chấm phẩy,
bạn nghĩa đen đặt 123 ở đây.
Bây giờ nếu chúng ta loại đơn giản hóa thế giới của chúng ta một lần nữa với hình ảnh,
những gì bạn đã thực sự làm được chỉ cần thêm một mũi tên để thế giới của bạn
chỉ từ t cùng một chuỗi chính xác.
Vì vậy, khi ở dòng 31 và 32, tôi thực sự đi về việc thay đổi t [0],
t là [0] dường như đồng nghĩa với bây giờ? s [0]
Vì vậy, đó là tất cả những gì đang xảy ra.
Và mặc dù loại này cảm thấy một chút cấp thấp và phức tạp
và loại này cảm thấy như có lẽ trực giác này nên đã chỉ làm việc
Tôi đã thực hiện bản sao của mọi thứ và nó chỉ làm việc -
nếu bạn thực sự suy nghĩ về những gì một chuỗi thực sự là, đó là một *.
Vâng, đó là những gì? Đó là địa chỉ của một số nhân vật.
Sau đó, có lẽ nó có ý nghĩa hơn khi bạn cố gắng để làm một cái gì đó
siêu dường như đơn giản như thế này, tất cả các bạn đang làm là sao chép một địa chỉ bộ nhớ.
Bạn không thực sự làm bất cứ điều gì với chuỗi chính nó.
Vì vậy, ngay cả khi bạn không có ý tưởng làm thế nào bạn sẽ giải quyết vấn đề này trong mã,
cao cấp, khái niệm, chúng ta làm những gì cần phải làm để làm cho ta bản sao có dấu sao y bản chính của s, rõ ràng?
Yeah. >> [Sinh viên] Cung cấp cho nó một vị trí mới? >> Chính xác.
>> Chúng ta cần để cung cấp cho một vị trí thương hiệu mới.
Chúng tôi cần phải bằng cách nào đó tạo ra một thế giới mà chúng tôi nhận được một đoạn mới của bộ nhớ,
mà chỉ vì lợi ích của sự rõ ràng, tôi sẽ vẽ ngay bên dưới một trong những điều này, nhưng nó không cần phải có mặt ở đó.
Nhưng nó cần phải có cùng kích thước, vì vậy tôi sẽ vẽ những đường thẳng đứng ở cùng một chỗ.
Đó là tốt nếu điều này là tất cả các rác thải ban đầu. Ai biết được những gì đã có?
Tuy nhiên, bước 1 là sẽ có được cho tôi như là bộ nhớ nhiều như tôi cần
để phù hợp với một bản sao của hello, sau đó tìm ra làm thế nào để sao chép các h đây, e đây,
l và vv.
Nhưng điều này nên đã cảm thấy một chút rõ ràng ngay cả khi một số chi tiết vẫn còn trừu tượng.
Để sao chép chuỗi này vào điều này, nó chỉ là một cho vòng lặp hoặc một vòng lặp trong khi
hoặc một cái gì đó mà bạn đã trở nên quen thuộc hơn.
Vì vậy, hãy thử này. Hãy để tôi đi vào copy2.c.
Trong copy2.c chúng tôi đã gần như cùng một chương trình ngoại trừ dòng 27.
Có vẻ một chút phức tạp, nhưng nếu chúng ta phá vỡ nó xuống mảnh của mảnh,
phía bên tay trái là như nhau.
Char * t tạo ra điều này trong bộ nhớ, mặc dù với một dấu hỏi
bởi vì chúng tôi không có ý tưởng những gì đang có theo mặc định.
Về phía bên phải bây giờ chúng tôi đang giới thiệu một chức năng mới, malloc,
cho bộ nhớ phân bổ, đưa cho tôi bộ nhớ,
và nó dường như có nhiều đối số, có bao nhiêu những thứ bên trong dấu ngoặc đơn?
Tôi nghe nói murmurings 1 và 2, nhưng nó chỉ là 1.
Có không có dấu phẩy, có nghĩa là chỉ có 1 điều bên trong dấu ngoặc đơn.
Mặc dù có dấu ngoặc đơn khác, hãy để tôi làm nổi bật
những gì bên trong dấu ngoặc đơn ngoài cùng, và nó biểu hiện này:
(Strlen (s) + 1) * sizeof (char).
Vì vậy, nếu chúng ta thực sự nghĩ rằng điều này thông qua, điều này được nói cho tôi chiều dài của s.
Tại sao tôi, mặc dù, thêm 1 vào chiều dài? >> [Không nghe được sinh viên phản ứng]
Chính xác. Chúng tôi cần không gian cho anh chàng này ở đuôi, nhân vật thứ sáu mà không có ý nghĩa tiếng Anh
nhưng không có ý nghĩa đặc biệt của chương trình.
>> Vì vậy, chúng ta cần một + 1 cho rằng bởi vì strlen trả về kỳ vọng của con người có chiều dài,
chào hay 5, không cung cấp cho bạn thêm các ký tự null.
Vì vậy, tôi tự thêm điều này với + 1.
Và sau đó, * kích thước của (char), chúng tôi đã không nhìn thấy điều này trước khi.
Đây không phải là kỹ thuật một chức năng.
Đó là một từ khóa đặc biệt chỉ cho bạn biết những gì kích thước của một số loại dữ liệu trên một máy tính
bởi vì trong thực tế, một số người trong chúng ta có máy tính 32-bit.
Tôi có một máy tính khá cũ ở nhà, và nó chỉ sử dụng 32 bit để đại diện cho con trỏ.
Và như vậy nếu tôi đã làm kích thước của một kiểu dữ liệu, nó có thể là 32 bit.
Nhưng nếu tôi đang sử dụng máy tính mới ưa thích của tôi, tôi có thể nhận được lại một giá trị 64 bit
cho một cái gì đó giống như một địa chỉ.
Vì vậy, trong trường hợp này, chỉ để được siêu an toàn, chúng tôi không đi đến một cái gì đó cứng mã như
tốt, kích thước của một char theo những gì chúng tôi đã nói cho đến nay là gì?
Chúng tôi đã khá nhiều nói bằng lời nói rằng đó là 1 byte, và đó là khá nhiều đúng trên bảng.
Nhưng một lần nữa, giả định có xu hướng là xấu.
Họ dẫn đến phần mềm lỗi nếu mọi người sử dụng phần mềm của bạn theo những cách bạn không có ý.
Vì vậy, hãy trừu tượng này đi và chỉ dẫn chung nói
Tôi cần điều này khối nhiều bộ nhớ
và mỗi đoạn bộ nhớ cần được tương đương với kích thước của một nhân vật,
mà là trong thực tế, bằng 1 trong trường hợp này, nhưng đó là một cách chung chung hơn viết nó.
Vì vậy, nếu từ đó là chào, bao nhiêu byte malloc dường như phân bổ lời chào?
[Sinh viên] Sáu. >> Six. Chính xác như nhiều như chúng tôi có dấu hỏi trên màn hình.
Và sau đó hãy đoán dựa trên sự hiểu biết của bạn GetString
malloc những gì có thể quay trở lại? >> [Sinh viên] Một địa chỉ.
Một địa chỉ của những gì? Của đoạn đầu tiên của bộ nhớ.
>> Chúng tôi không có ý tưởng những gì đang có bởi vì một số chức năng khác
có thể đã được sử dụng trước đó là bộ nhớ này.
Nhưng malloc, như GetString, trả về địa chỉ của byte đầu tiên của bộ nhớ
rằng nó đã dành cho bạn.
Tuy nhiên, những gì nó không làm là điền vào chỗ trống này với một ký tự null dấu gạch chéo ngược
bởi vì nó quay ra bạn có thể sử dụng malloc để cấp phát bất cứ điều gì: ints, chuỗi, mảng,
phao, cấu trúc sinh viên.
Bạn có thể sử dụng malloc hoàn toàn tổng quát.
Nó không quan tâm hoặc cần phải biết những gì bạn đang cấp phát bộ nhớ cho.
Vì vậy, nó sẽ là táo bạo cho malloc để đặt một 0 \
ở phần cuối của mỗi đoạn bộ nhớ nó đem lại cho bạn
bởi vì đây \ 0 điều chỉ là một quy ước cho các chuỗi.
Nó không được sử dụng cho ints, nó không được sử dụng cho nổi, nó không được sử dụng cho sinh viên.
Và vì vậy Gotcha với malloc là gánh nặng là hoàn toàn vào bạn lập trình viên
nhớ bao nhiêu byte bạn được giao và không bao giờ sử dụng một vòng lặp for
hoặc một vòng lặp while và đi qua ranh giới của đoạn bộ nhớ bạn đã được.
Nói cách khác, ngay sau khi bạn cấp phát bộ nhớ,
bạn không thể yêu cầu hệ điều hành, oh, bằng cách này, làm thế nào lớn của một đoạn bộ nhớ này?
Nó hoàn toàn vào bạn để nhớ nếu bạn cần giá trị đó.
>> Vì vậy, chúng ta hãy xem làm thế nào tôi tiếp tục sử dụng bộ nhớ này.
Trong dòng 28 và 29 lý do tại sao tôi làm điều này?
Chỉ cần tổng kiểm tra sự tỉnh táo.
Chỉ trong trường hợp một cái gì đó đã đi sai, tôi yêu cầu cho một số số tiền điên của bộ nhớ
hoặc tôi đã quá nhiều thứ đang chạy trên máy tính mà chỉ là không đủ bộ nhớ,
một cái gì đó như thế, tôi ít nhất là muốn để kiểm tra null.
Trong thực tế, hầu hết các máy tính sẽ cung cấp cho bạn ảo tưởng rằng mọi chương trình
có thể sử dụng toàn bộ bộ nhớ RAM của bạn,
nhưng ngay cả như vậy, nếu người sử dụng các loại trong một số chuỗi dài điên có thể bởi vì họ là một kẻ xấu
và họ đang thực sự cố gắng để sụp đổ chương trình hoặc hack của bạn vào đó,
bạn muốn ít nhất là kiểm tra giá trị trả về của malloc và liệu nó có bằng null.
Và nếu có, chúng ta hãy bỏ thuốc lá ngay bây giờ bởi vì tôi không biết phải làm gì trong trường hợp đó.
Làm thế nào để sao chép chuỗi? Có một số cách để làm điều này.
Có str sao chép các chức năng trong C, nhưng đó là siêu đơn giản cho chúng ta để làm điều này theo cách cũ.
>> Trước tiên hãy để tôi tìm ra chiều dài của s.
Tôi đã có thể đặt điều này trong vòng lặp, nhưng thay vào đó tôi chỉ cần đặt nó ra đây cho rõ ràng.
Vì vậy, n tại lưu trữ độ dài của chuỗi ban đầu, rõ ràng là 5.
Sau đó, trong vòng lặp cho tôi, tôi lặp lại từ 0 đến n,
và mỗi lần lặp Tôi đang đặt s [i] bên trong của t [i].
Vì vậy, đó là những gì tôi ngụ ý với 2 ngón tay chỉ vào các dây trước khi.
Vì đây cho vòng lặp như thế này, tôi sẽ được sao chép h vào đây,
e vào đây, tôi vào đây vì đây là s, đây là t.
Và sau đó cuối cùng, trong dòng 35 lý do tại sao tôi làm điều này?
Tôi cần phải làm cho chắc chắn rằng tôi kết thúc chuỗi t.
Và tôi đã làm nó theo cách này để được siêu rõ ràng.
Nhưng đề xuất, một ai đó, nếu bạn có thể, một cách khác nhau để làm điều này.
Tôi không thực sự cần dòng 35. Có một cách khác để làm điều này.
Yeah. >> [Không nghe được sinh viên phản ứng] >> Nói cho nó to hơn.
[Sinh viên] Nhỏ hơn hoặc bằng. >> Chính xác.
Chúng tôi chỉ có thể nói nhỏ hơn hoặc bằng n, mà nói chung đã xấu
bởi vì hầu như luôn luôn khi chúng tôi đi lên bằng những điều chúng ta đang đếm
chúng tôi đi 1 bước quá xa.
Nhưng hãy nhớ, chúng tôi phân bổ bao nhiêu byte?
Chúng tôi phân bổ strlen của s, do đó, 5 + 1 cho tổng cộng 6.
Vì vậy, trong trường hợp này, chúng ta có thể làm một cái gì đó như thế này
để chúng tôi đang sao chép không chỉ hello mà còn 0 \ ở cuối.
Ngoài ra, chúng tôi có thể sử dụng một chức năng gọi là str bản sao, strcpy,
nhưng điều đó sẽ không được vui vẻ gần như là nhiều.
Nhưng đó là tất cả nó bên dưới mui xe.
Sau đó, cuối cùng, chúng tôi làm điều tương tự như trước đây.
Tôi tận t và sau đó tôi cho rằng ban đầu trông như thế này và bản sao trông như thế.
Vì vậy, chúng ta hãy thử điều này ngay bây giờ. Hãy để tôi đi ở đây. Hãy copy2. Chúng tôi sẽ phóng to, thu nhỏ và chạy copy2.
Tôi sẽ gõ trong hello bằng chữ thường, và thực sự tôi có được chữ thường chào như bản gốc
nhưng vốn Xin chào cho bản sao.
Nhưng tôi không thực hiện chỉ được nêu ra. Tôi cần phải làm 1 điều cuối cùng ở đây.
46 và 47 rõ ràng là giải phóng bộ nhớ, nhưng điều đó không thực sự có nghĩa?
Tôi đang làm gì, bạn có nghĩ rằng, bằng cách gọi dòng 46 và dòng 47?
Tác động gì có? Yeah.
[Không nghe được sinh viên phản ứng] >> Chính xác.
>> Bạn chỉ cần nói với hệ điều hành, hey, cảm ơn cho bộ nhớ này.
Bây giờ bạn có thể sử dụng nó cho người khác.
Và đây là một ví dụ hoàn hảo của các giá trị rác.
Tôi đã chỉ sử dụng bộ nhớ này để viết xuống những từ hello tại 2 địa điểm,
đây, ở đây, ở đây, và ở đây.
Vì vậy, đây là h-e-l-l-o-\ 0.
Nhưng sau đó tôi gọi là dòng 46 và dòng 47, và bạn biết điều gì sẽ xảy ra trong điều khoản của hình ảnh?
Trên thực tế, chờ đợi, bức tranh này là cũ.
Một khi chúng ta thực hiện các bản sao, anh chàng này thực sự là chỉ ở đây,
vì vậy chúng ta hãy loại bỏ những con số và chỉ cần tóm tắt đi như mũi tên của chúng tôi một lần nữa.
Điều gì sẽ xảy ra trong bức tranh này khi tôi gọi miễn phí?
[Sinh viên không nghe được đáp ứng] >> Không, ngay cả.
Nếu tôi gọi miễn phí trên s và t - loại một câu hỏi trick - hình này không thay đổi ở tất cả các
bởi vì gọi điện thoại và gọi t chỉ cần nói với hệ điều hành,
hey, bạn có thể sử dụng bộ nhớ một lần nữa, nhưng nó không thay đổi điều này để null
hoặc một số ký tự đặc biệt, nó không thay đổi điều này,
nó không thay đổi h hoặc e hoặc l l hoặc o trong hoặc nơi để bất cứ điều gì khác.
Trong điều kiện của hình ảnh, ngay sau khi bạn gọi miễn phí, không có gì thay đổi.
Và đây là nguồn gốc của giá trị rác bởi vì nếu tôi sau đó trong chương trình này
yêu cầu hệ điều hành cho bộ nhớ nhiều hơn với GetString hoặc malloc hoặc một cái gì đó như là
và hệ điều hành nói, chắc chắn, tôi có 12 byte bộ nhớ chỉ được giải phóng,
sử dụng chúng, bạn sẽ được giao?
Bạn sẽ được giao cho một đoạn bộ nhớ mà chúng ta thường sẽ vẽ
với dấu hỏi, nhưng những dấu hỏi là gì?
Chúng xảy ra là h-e-l-l-o, h-e-l-l-o.
Đây là những giá trị rác mới của chúng tôi ngay khi bạn giải phóng bộ nhớ rằng.
>> Có một ý nghĩa thực tế ở đây quá.
Điều này xảy ra với bộ nhớ RAM, nhưng máy tính của bạn
thực sự làm điều tương tự với đĩa.
Chúng tôi sẽ nói về điều này đặc biệt với một tập hợp các vấn đề trong tương lai tập trung vào pháp y.
Nhưng những gì thực sự xảy ra nếu bạn có một số tập tin tài chính nhạy cảm trên máy tính để bàn của bạn
hoặc một số JPEG sơ sài và kéo nó vào thùng rác của bạn,
điều gì sẽ xảy ra khi bạn kéo nó vào thùng rác hoặc thùng rác?
Bạn biết những gì tôi đã nói về. [Cười]
Điều gì sẽ xảy ra khi bạn đã kéo mà bằng chứng vào thùng rác hoặc thùng rác của bạn có thể?
[Không nghe được sinh viên phản ứng]
Tốt, vì vậy cẩn thận. Điều gì sẽ xảy ra khi bạn làm điều đó?
Câu trả lời ngắn gọn là không có gì, phải không?
Sketchy hoặc tập tin nhạy cảm vẫn chỉ ngồi đó một nơi nào đó trong ổ cứng của bạn.
Hầu hết chúng ta ít nhất đã học được cách cứng mà bạn cần để trống thùng rác của bạn
hoặc thùng rác của bạn để thực sự xóa các tập tin.
Và quả thực, khi bạn kích chuột phải hoặc Kiểm soát nhấp chuột vào thùng rác của bạn có thể
hoặc chọn File, Empty Trash hoặc bất cứ điều gì
và bạn thực sự sạch thùng rác hoặc thùng rác, những gì thực sự xảy ra sau đó với hình ảnh này?
Không có gì. Vì vậy, không có gì thực sự xảy ra trên đĩa.
>> Và nếu chúng ta chỉ tạm thời lạc đề và viết sẽ chỉ cần sử dụng sau này.
Vì vậy, bây giờ câu chuyện đang thay đổi từ RAM, đó là nơi mà các chương trình tồn tại
trong khi bạn đang chạy chúng vào đĩa, đó là nơi mà chúng được lưu trữ lâu dài
ngay cả khi cúp điện, cho bây giờ - và chúng tôi sẽ trở lại vấn đề này trong tương lai -
chúng ta hãy giả vờ rằng điều này đại diện cho các bên trong ổ đĩa cứng của máy tính của bạn
bởi vì trở lại trong ngày, họ sử dụng là các ổ đĩa tròn, giống như đĩa mềm.
Vì vậy, nếu bạn có một số tập tin Excel nhạy cảm, nó có thể mất đến đoạn bộ nhớ này
trên đĩa cứng của máy tính của bạn, và tôi là chỉ cần vẽ cùng 1s tùy ý và số 0.
Khi bạn kéo thả các tập tin như thế để thùng rác của bạn hoặc có thể tái chế bin,
nghĩa là không có gì xảy ra bởi vì Apple và Microsoft đã quyết định
thùng rác và thùng rác thực sự chỉ là một trình giữ chỗ tạm thời.
Có lẽ cuối cùng hệ điều hành sẽ sản phẩm nào đó cho bạn, nhưng thông thường, nó không làm bất cứ điều gì,
ít nhất là cho đến khi bạn thực sự thấp trên không gian.
>> Tuy nhiên, khi bạn đi vào thùng rác hoặc thùng rác trống rỗng,
tương tự như vậy, không có gì xảy ra với hình ảnh này.
Tất cả điều đó xảy ra ở những nơi khác trên máy tính của bạn, có một số loại bảng.
Đó là loại giống như một cheat sheet nhỏ mà nói rằng, hãy nói, resume.doc,
do đó, hồ sơ của bạn trong một tập tin Word của Microsoft được sử dụng để sống ở vị trí 123 trên đĩa cứng của bạn,
không phải trong bộ nhớ và không có trong bộ nhớ RAM, nhưng trên đĩa cứng của bạn,
và JPEG sơ sài của bạn cuộc sống tại 456, và Excel tập tin của bạn sống tại 789 hoặc bất cứ nơi nào.
Khi bạn xóa các tập tin bằng cách thực sự dọn sạch thùng rác hoặc thùng rác,
hình này không thay đổi. 0 và 1 trên ổ đĩa cứng của bạn không đi bất cứ nơi nào.
Tuy nhiên, bảng này, cơ sở dữ liệu này của các loại, không thay đổi.
Khi bạn xóa hồ sơ của bạn, nó là như tập tin bị xóa theo một nghĩa nào,
nhưng tất cả các máy tính không được quên điều mà sống trên ổ đĩa cứng của bạn.
0 và 1 mà soạn hồ sơ của bạn hoặc bất kỳ của những tập tin khác vẫn còn nguyên vẹn.
>> Vì vậy, nếu bạn đã làm điều này vô tình, vẫn có một xác suất khác không
mà bạn có thể phục hồi dữ liệu của bạn bằng cách sử dụng Norton Utilities hoặc một số phần mềm thương mại
mà mục đích trong cuộc sống là tìm thấy 0 và 1 đã loại bị mồ côi,
quên ở đây nhưng lại ở đây, để bạn có thể nhận được dữ liệu của bạn trở lại.
Hoặc các nhà điều tra pháp y với cảnh sát hay FBI thực sự sẽ có một ổ cứng
và thực sự cho các mẫu của số 0 và 1 mà trông giống như hình ảnh JPEG, trông giống như các tập tin Excel,
và khôi phục lại chúng theo cách đó ngay cả khi máy tính đã quên chúng ở đó.
Vì vậy, cách duy nhất để thực sự xóa dữ liệu, như chúng ta sẽ thảo luận trong tương lai,
là để cọ rửa hoặc lau tập tin hoặc đĩa cứng bằng cách -
Bạn có thể không thực sự có được loại bỏ của 0 và 1
bởi vì nếu bạn muốn bắt đầu với một ổ đĩa cứng gigabyte
và bạn muốn kết thúc với một ổ cứng megabyte nếu bạn thường xuyên được xóa,
nghĩa đen, 0 và 1.
Vì vậy, những gì bạn sẽ làm gì nếu bạn thực sự muốn bao gồm các bản nhạc của bạn
và vấn đề cơ bản là vẫn còn 0 và 1 trên đĩa?
Tôi nhìn thấy một người nào đó gesticulating rằng bạn có thể chất sẽ phá vỡ các thiết bị. Điều đó sẽ làm việc.
[Cười] Nhưng nếu đó là loại của một giải pháp đắt tiền, những gì sẽ là hợp lý hơn?
Yeah. >> [Sinh viên] Ghi đè lên chúng. >> Ghi đè lên chúng với những gì? >> [Sinh viên] Các dữ liệu khác.
Các dữ liệu khác. Bạn chỉ có thể ghi đè lên đĩa cứng của bạn với số 0 hoặc 1 hoặc tất cả các số 0, tất cả 1s.
>> Và đó là thực sự những gì một số phần mềm không.
Bạn có thể mua phần mềm hoặc thậm chí có được phần mềm miễn phí,
và thậm chí được xây dựng trong hệ điều hành Mac OS những ngày này, ít như vậy trong Windows,
là khả năng xóa an toàn.
Trên thực tế, nếu bạn muốn tất cả nhà chạy ngày hôm nay nếu bạn có một máy Mac và làm điều này,
nếu bạn đã có một số công cụ trong thùng rác của bạn có thể, bạn có thể làm Secure Empty Trash,
mà không chính xác điều đó.
Thay vì chỉ xóa các tập tin ở đây, nó không xóa ở đây 0 và 1,
đúng hơn, nó chỉ thay đổi tất cả, ví dụ, số 0 và dấu chấm, dấu chấm, dấu chấm.
Vì vậy, một psets tương lai của bạn sẽ thực sự là cố ý phục hồi dữ liệu -
các bức ảnh mà chúng tôi đã lấy của người, địa điểm, và những thứ trong khuôn viên trường
mà chúng ta sẽ làm cho một hình ảnh pháp y của thẻ nhớ máy ảnh kỹ thuật số,
đó là cùng một ý tưởng chính xác - và bạn sẽ có được thử thách để thực sự tìm thấy
các mô hình đại diện cho hình ảnh JPEG trên ổ đĩa cứng của bạn,
giống như là cựu sinh viên có email, tôi đọc một vài tuần trước
để khôi phục lại hình ảnh của em gái mình.
Tại sao chúng ta không mất một break 5-phút ở đây, và chúng tôi sẽ tập hợp lại với nhiều bộ nhớ.
Vì vậy, đây là nơi mà mọi thứ có được một chút tâm-uốn, nhưng đây là một bước rất mạnh mẽ
để hiểu được điều này tất cả các chi tiết.
Đây là một chương trình được gọi là pointers.c.
Nó là một trong những mẫu mã ngày nay.
Chú ý rằng trong vài dòng đầu tiên, từ 19 đến 22, tất cả những gì chúng ta đang làm là một cái gì đó giống như GetString
và trả về một địa chỉ, lưu trữ nó trong s.
Từ nay trở đi cho pset thậm chí 3 nếu bạn muốn nhưng pset 4 và
nơi bạn có thể bắt đầu để có những bánh xe đào tạo ra mình,
không có lý do để giả vờ rằng chuỗi tồn tại nữa.
Đó chắc chắn không sao chỉ cần bắt đầu nói char *.
>> Một sang một bên, trong các tài liệu tham khảo trực tuyến và trong cuốn sách, bạn thường có thể nhìn thấy ngôi sao bên cạnh các biến.
Bạn thậm chí có thể nhìn thấy không gian xung quanh cả hai mặt của nó.
Tất cả những người có chức năng chính xác.
Bây giờ, mặc dù, chúng tôi sẽ chuẩn hóa trên phương pháp tiếp cận này để làm cho siêu rõ ràng
rằng * char là giống như nói rằng con trỏ ký tự.
Đó là các kiểu dữ liệu.
Và sau đó là tên của biến s trong trường hợp này.
Vì vậy, chúng tôi đã nhận được một chuỗi và chúng tôi đã gọi nó là s.
Và sau đó xuống đây nhận thấy rằng tôi đang làm thực sự là một chút thủ đoạn gian trá.
Điều này được gọi là con trỏ số học, được sắp xếp đơn giản siêu.
Nó chỉ có nghĩa là cộng và trừ các số cho con trỏ.
Nhưng điều này thực sự hoạt động.
Chương trình này dường như in nhân vật 1 chuỗi s trên mỗi dòng như vậy mà kết quả cuối cùng -
Để chúng tôi có thể làm hỏng nơi này là đi, làm cho con trỏ, chạy con trỏ, cho tôi phóng to.
Bây giờ hãy để tôi một cái gì đó giống như Hello và nhấn Enter
và nó in 1 ký tự trên mỗi dòng.
Cho đến một giây trước đó, chúng tôi đã có thể làm điều này bằng các ký hiệu khung hình vuông.
Chúng tôi muốn có một vòng lặp for và chúng tôi muốn làm printf của s [i] và chúng tôi muốn làm điều đó một lần nữa và một lần nữa và một lần nữa
với một n dấu gạch chéo ngược ở cuối mỗi dòng.
Tuy nhiên, chương trình này là khác nhau. Chương trình này được sử dụng, nghĩa là, số học.
Vì vậy, những gì đang xảy ra ở đây?
Trước hết, trước khi vòng lặp này thậm chí thực hiện, những gì, chỉ để được rõ ràng, là thực sự?
S là? >> [Sinh viên] Một địa chỉ. >> Một địa chỉ.
>> Và đó là, trong trường hợp của hello, địa chỉ của ký tự đầu tiên trong từ ngữ đó, mà là h.
Vì vậy, s, trong ví dụ này, địa chỉ của h.
Vì vậy, nó có nghĩa là để làm s + i?
Vâng, tôi bắt đầu từ 0 trong vòng lặp for. Chúng tôi đã thực hiện mà nhiều lần.
Tôi sẽ đi đến độ dài của chuỗi, rõ ràng.
Vì vậy, trên phiên đầu tiên của vòng lặp này, tôi rõ ràng là 0.
Vì vậy, biểu thức này được nói s + i - đúng hơn, s +0- rằng rõ ràng là chỉ s.
* Là những gì ở đây?
Bây giờ chúng ta đang sử dụng các ngôi sao trong một cách hơi khác nhau.
Hãy để tôi đi trước và thoát khỏi của t bởi vì chúng tôi đang thực hiện nói về t và các bản sao của s.
Bây giờ chúng tôi chỉ muốn kể một câu chuyện liên quan đến s.
Và như vậy tại thời điểm này, sau khi có kiểu chuỗi, thế giới của chúng ta trông khá giống như nó đã làm trước
chỉ với s lưu trữ các địa chỉ h và nói chung chỉ vào chuỗi hello.
Nếu tôi làm một dòng như * (s + i), chúng ta hãy cố gắng này ra.
Vì vậy, * (s + i). Hãy để tôi đơn giản hóa này bởi vì đây là 0, vì vậy đây là * (+0).
Vâng, chờ một phút. Đơn giản hóa hơn nữa. Đây là * (s).
Vâng, bây giờ ngoặc là ngu ngốc, vì vậy bây giờ chúng ta hãy chỉ làm * s.
Vì vậy, trong phiên đầu tiên của vòng lặp này, dòng đó sẽ được tô sáng, 26,
là khá nhiều tương đương với in ấn này.
Kiểu dữ liệu của s * là gì?
Trong bối cảnh này, bởi vì ngôi sao sẽ xảy ra là bên cạnh s,
nhưng cụ thể hơn, bởi vì chúng tôi không còn được tuyên bố,
chúng ta không tạo ra một biến nữa, không có đề cập đến char * line 26,
không có đề cập đến chuỗi từ khóa, chúng ta chỉ sử dụng một biến gọi là s,
nó quay ra ngôi sao có hơi khác nhau, và phải thừa nhận rằng, khó hiểu ý nghĩa.
* S ở đây có nghĩa là đi đến địa chỉ trong và in bất cứ điều gì là có.
Vì vậy, s là ở đây, * s là loại như Chutes and Ladders, theo các mũi tên - ở đây.
Vì vậy, đây là * s.
>> Vì vậy, những gì được in trên phiên đầu tiên của vòng lặp đó trong dòng 26?
Tôi in ra% c, đó là giữ chỗ cho một nhân vật,
sau đó \ n cho một dòng mới. * (S + i) nơi mà tôi có là 0 là chỉ này.
Vì vậy, những gì char để tôi đặt cho c%? H.
Trong phiên bản kế tiếp của vòng lặp - có thể bạn có thể nhìn thấy nơi này là đi -
lặp đi lặp lại tiếp theo tôi rõ ràng là 1, do đó, điều này có nghĩa là s +1,
và sau đó bây giờ tôi không cần dấu ngoặc đơn bởi vì bây giờ các ngôi sao cần phải nói
đi đến địa chỉ bộ nhớ s +1.
S là gì? Hãy quay trở lại trong thời gian và nói mũi tên này giờ không thực sự làm chúng tôi bất kỳ ân huệ.
Hãy cụ thể hơn nói rằng đó là lưu trữ 123 số
vì sự bắt đầu của chuỗi này hello, đây là địa chỉ 123, 124, và vv.
Vì vậy, trên lặp thứ hai khi tôi đang nói s 1, như nói 123 +1,
nếu không được biết đến là 124, vì vậy những gì char được in trên lặp thứ hai?
E ở địa chỉ bộ nhớ 124.
Sau đó + một lần nữa, 125, 126, 127, và vòng lặp này may mắn dừng lại trước khi chúng tôi nhận được ở đây
bởi vì tôi đang sử dụng strlen để làm cho chắc chắn rằng tôi không tính quá cao.
Vì vậy, đó cũng là nó.
Một lần nữa, điều này giống như chúng ta đã thực hiện một tuần trước đây.
Hãy để tôi viết nó trên hàng dưới đây mặc dù chúng ta không muốn làm cả hai.
Này giống hệt này.
>> Vì vậy, mặc dù s là một chuỗi, như chúng ta đã gọi nó cho tuần, s thực sự là một *.
Vì vậy, nếu chúng ta muốn được siêu hậu môn, nó thực sự thích hợp để viết các nhân vật cụ thể
tại vị trí thứ i bằng cách sử dụng các địa chỉ số và nhà điều hành ngôi sao này,
nhưng thẳng thắn, đây là sạch hơn rất nhiều. Vì vậy, điều này không phải là xấu.
Không có lý do gì để ngăn chặn dòng 27 ở đây, nhưng 26 là chức năng giống nhau,
và đó là chức năng tương tự cho chính xác những lý do mà chúng tôi đã thảo luận cho đến nay.
Và cuối cùng, 29 là chỉ thực hành tốt.
Gọi điện thoại miễn phí của s có nghĩa là bây giờ bạn đang đem lại cho trở lại bộ nhớ mà GetString cho bạn
vì một lần nữa, như tôi đã đề cập Thứ hai, GetString cho tuần
đã được giới thiệu một lỗi vào mã của bạn.
Mã của bạn cho tuần đã có rò rỉ bộ nhớ
nhờ đó mà bạn đã được yêu cầu GetString cho bộ nhớ, nhưng bạn đã không bao giờ được cho nó trở lại.
Và điều đó đã cố tình lựa chọn của chúng tôi sư phạm
bởi vì nó chỉ là quá nhiều để suy nghĩ về sớm.
Nhưng bây giờ chúng tôi cần đối xứng hơn.
Nếu bạn yêu cầu máy tính cho bộ nhớ, như là trường hợp cho GetString,
như là trường hợp rõ ràng cho malloc,
Bây giờ bạn phải cho 4 trở đi pset cũng miễn phí bất kỳ bộ nhớ như vậy.
Chú ý điều này là khác nhau từ nói n int.
Bạn không cần phải miễn phí này bởi vì bạn đã không gọi GetString
và bạn đã không gọi malloc.
>> Và thậm chí nếu bạn được gọi là getInt như chúng ta cuối cùng sẽ thấy,
GetInt không cấp phát bộ nhớ cho bạn bởi vì bạn thực sự có thể vượt qua khoảng số nguyên
và phao nổi và các ký tự chỉ là cách chúng tôi đã làm trong nhiều tuần.
Strings, mặc dù, là đặc biệt bởi vì thực sự họ là những nối của nhiều ký tự.
Vì vậy, chúng chỉ khác nhau từ các ký tự và phao nổi và ints và muốn.
Nhưng chúng tôi sẽ quay trở lại mà chẳng bao lâu.
Bất kỳ câu hỏi sau đó vào đầu con trỏ? Yeah.
[Câu hỏi sinh viên không nghe được]
Ah, câu hỏi rất tốt.
Một trong số ít những thứ C thực hiện cho bạn, đó là vị trí thuận tiện,
là nó ra cho bạn những gì kích thước của kiểu dữ liệu
và sau đó là loại nhân cho bạn.
Điều này là không thích hợp trong trường hợp của các ký tự bởi vì hầu như luôn luôn char là 1 byte,
do đó, điều này chỉ hoạt động.
Tuy nhiên, vì lợi ích của cuộc thảo luận, nếu bạn đã thực sự in số nguyên
và bạn đã cố gắng để in ra một số giá trị đã được chỉ vào một số nguyên,
bạn tương tự như vậy sẽ không cần phải làm + 4 * i chỉ vì một int là 4 byte.
Con trỏ số học có nghĩa là C và trình biên dịch làm tất cả những toán học cho bạn.
Tất cả những gì bạn phải quan tâm là kiểm loại của ý thức con người. Yeah.
[Sinh viên] Nếu bạn khai báo một chuỗi bên trong một vòng lặp for, bạn có để giải phóng nó sau này?
Tốt câu hỏi.
>> Nếu bạn tuyên bố bên trong chuỗi cho vòng lặp, bạn có cần để giải phóng nó sau này?
Bạn chỉ cần bộ nhớ miễn phí mà bạn phân bổ với GetString hoặc với malloc.
Vì vậy, nếu bạn chỉ cần nói một cái gì đó như thế - cho tôi đặt dấu ngoặc nhọn do đó, tất cả các mã có liên quan.
Nếu bạn đã làm một cái gì đó, mặc dù buggily, như thế này, char * t = s,
bạn không cần phải miễn phí t vì t không liên quan đến bất kỳ đề cập đến malloc hoặc GetString.
Nếu ngược lại, bạn đã làm điều này, GetString, sau đó có, bạn sẽ cần đến t miễn phí.
Và trên thực tế, cơ hội duy nhất của bạn để làm điều đó bây giờ là bên trong vòng lặp này, đối với cùng một vấn đề phạm vi
mà chúng tôi đã thảo luận trong quá khứ.
Nếu không, bạn sẽ được cấp phát bộ nhớ, cấp phát bộ nhớ, cấp phát bộ nhớ,
và ở phần cuối của chương trình bởi vì bạn đang ở bên ngoài vòng lặp,
t không tồn tại, nhưng bạn không bao giờ nói với hệ điều hành
mà bạn không cần phải có bộ nhớ nữa.
Không lâu sau, cho pset 4 hoặc 5 chúng tôi sẽ trang bị cho bạn với một chương trình được gọi là Valgrind,
đó là tinh thần tương tự GDB trong đó nó có phần nào của một giao diện phức tạp,
nhưng mục đích của nó trong cuộc sống là để giúp bạn.
Và Valgrind là một chương trình mà trong tương lai sẽ tìm kiếm các chương trình của bạn
tìm kiếm rò rỉ bộ nhớ, cho dù từ GetString hay malloc,
mà chúng ta sẽ bắt đầu sử dụng nhiều như chúng tôi dừng lại bằng cách sử dụng thư viện CS50 càng nhiều.
Chúng tôi cuối cùng đã có loại của từ vựng và sắp xếp các mô hình tinh thần trong lý thuyết
để giải quyết chương trình này bị hỏng.
>> Vì vậy, trong chương trình này bị hỏng, trao đổi hoạt động bên trong vùng trao đổi,
nhưng nó không bao giờ thực sự làm việc trong chính bởi vì chính thông qua tại x và y, thu hồi,
và những người đã được thông qua tại bởi các giá trị, do đó, để nói chuyện.
Bản sao của chúng đã được đưa ra để trao đổi.
Đến cuối vùng trao đổi, a và b đã thực sự được trao đổi,
nhưng tất nhiên x và y, như chúng ta đã thảo luận Thứ hai, đã không.
Vì vậy, tôi đề nghị màu xanh lá cây ở đây rằng điều này thực sự là giải pháp ở đây.
Và thực sự, hãy để tôi di chuyển sao của tôi chỉ để phù hợp
mặc dù, một lần nữa, chức năng này không quan trọng.
Trong những tuần trong tương lai, chúng tôi sẽ giải thích khi nào và lý do tại sao nó không thành vấn đề.
Vì vậy, màu xanh lá cây là một giải pháp.
Thẳng thắn mà nói, có vẻ một toàn bộ rất nhiều hỗn độn bởi vì tôi có tất cả những ngôi sao này.
Hãy để tôi chỉ ra một điều.
Dòng trên cùng ở đây, nơi nó nói int * a và int * b
về cơ bản là làm điều tương tự như nó luôn luôn có.
Nó được khai báo 2 đối số hoặc các thông số để trao đổi,
là người đầu tiên trong số đó là một con trỏ int được gọi là một
thứ hai trong số đó là một con trỏ int gọi là b.
Điều duy nhất mà mới vào thời điểm này là một thực tế rằng có một ngôi sao ở đó.
>> Điều đó có nghĩa là gì? Không phải là một int, b không phải là một int.
Là địa chỉ của một int và b là địa chỉ của một int khác nhau.
Ở đây, đây là nơi tôi thừa nhận C gây nhầm lẫn.
Bây giờ chúng tôi đang sử dụng một ngôi sao, nhưng nó có ý nghĩa khác nhau trong bối cảnh này.
Bởi vì chúng tôi không khai báo con trỏ như là chúng tôi đang ở đây,
ở đây chúng tôi đang dereferencing vật.
Vì vậy, về mặt kỹ thuật, ngôi sao trong bối cảnh này của dòng đầu tiên, thứ hai, và thứ ba bên trong vùng trao đổi
được các nhà điều hành dereference, mà chỉ có nghĩa là đi đến đó.
Vì vậy, chỉ cần ngón tay của tôi theo mũi tên để h,
* Một phương tiện đi đến địa chỉ đó và tìm tôi int đó là có.
* B có nghĩa là đi đến địa chỉ và vượt qua những gì đang có.
Vì vậy, hãy vẽ lại hình ảnh từ thứ hai bằng cách sử dụng một ngăn xếp của khung hình,
một trong những dưới cùng trong số đó là có được chính,
trên một trong những số đó là có được trao đổi,
do đó, giống như Thứ hai, thế giới của chúng ta trông như thế này.
Dưới đây là một đoạn bộ nhớ chính được sử dụng.
>> Nhớ lại từ thứ Hai rằng chương trình chỉ có 2 biến,
một gọi là x và một gọi là y, và tôi đã đặt các con số 1 và 2 có.
Bây giờ khi tôi gọi trao đổi như tôi đã làm ngày Thứ hai,
trước đây khi tôi sử dụng phiên bản màu đỏ của chương trình này, như thế này,
Tôi có 2 thông số, a và b, và những gì chúng tôi đã viết ở đây và ở đây?
Chỉ cần 1 và 2, nghĩa là bản sao của x và y.
Hôm nay chúng ta thay đổi điều đó.
Hôm nay thay vì đi qua trong ints a và b chúng ta sẽ phải vượt qua trong 2 địa chỉ.
Những địa chỉ xảy ra chỉ để ints, nhưng những địa chỉ không ints mình.
Họ là những địa chỉ. Nó giống như một địa chỉ bưu điện thay thế.
Vì vậy, bây giờ chúng ta cần phải chỉ cho bản thân mình một chi tiết nhỏ hơn trên màn hình.
Đây là bộ nhớ máy tính của tôi như nó được tất cả các ngày.
Bây giờ chúng ta cần một số đề án đánh số tùy ý.
Vì vậy, chúng ta hãy chỉ nói, chỉ tình cờ thấy rằng đây là địa chỉ bộ nhớ 123, 124.
Chúng ta hãy chỉ nói điều này là 125, 126, và vân vân, nhưng đó là hoàn toàn tùy ý.
Chúng ta chỉ cần một số đề án đánh số trong bộ nhớ của tôi.
Vì vậy, bây giờ khi tôi thực sự vượt qua trong x và y, tôi sẽ không để vượt qua trong x và y;
Tôi sẽ vượt qua trong địa chỉ bưu điện, có thể nói, của x và y
do đó những gì được lưu trữ ở đây và ở đây không phải là 1 và 2,
nhưng nếu bạn có thể xem văn bản nhỏ của tôi, những gì được thông qua tại đây và ở đây?
[Không nghe được sinh viên phản ứng] >> Chính xác. 123 được đặt ở đây và 124 được đặt ở đây.
>> Bây giờ, vì tôi đã sử dụng ngôi sao trong cách này, dòng đầu tiên lên đây ở đầu trang,
chương trình của tôi chỉ biết rằng 123 và 124, mặc dù họ rõ ràng là số nguyên
rằng bất kỳ con người có thể nhận thấy, họ nên được giải thích như là địa chỉ, địa chỉ số.
Họ không phải là trong và của chính ints, họ, địa chỉ,
và đó là bởi vì tôi đã đặt một cách rõ ràng ngôi sao ở đó.
Vì vậy, bây giờ trong dòng đầu tiên, thứ hai, thứ ba của tôi và mã thực tế những gì xảy ra ở đây?
Chúng ta hãy vẽ phần còn lại của hình ảnh.
Tmp là giống như nó là vào hôm thứ Hai. Không có gì đặc biệt về tmp.
Đó là chỉ là một 32 bit biến địa phương, và bên trong đó, tôi dường như lưu trữ các giá trị của một *.
Bây giờ, nếu tôi chỉ nói tmp = a, những gì tôi sẽ đặt ở đây? >> [Sinh viên] 123.
123. Nhưng đó không phải những gì tôi đang làm.
Tôi đang nói tmp = * a. Sao có nghĩa là đi đến đó.
Vì vậy, đây là một, 123. Làm thế nào để đi đến đó? Giả vờ như có một mũi tên.
Vâng, đó là, 1. Vì vậy, những gì được lưu trữ trong tmp, rõ ràng? Chỉ cần 1.
Vì vậy, nói cách khác, tmp * a, * là một phương tiện đi đến các địa chỉ hiện đang trong,
mà rõ ràng là 123.
>> Được rồi, ở đây chúng tôi đang ở vị trí 123, tôi thấy số 1,
vì vậy tôi sẽ đưa số 1.
Bây giờ tôi phải làm gì trong dòng 2, * a = * b?
Điều này là một chút liên quan bởi vì bây giờ là gì? Đó là 123.
Vì vậy, là ở đâu? Bên phải, nơi tôi đã được trước đó. Vì vậy, đi đến đó. Okay.
Bây giờ, cuối cùng, và sau đó cuối cùng này sẽ bắt đầu có ý nghĩa, hy vọng,
* B có nghĩa là những gì trong b? 124. Vì vậy, tôi cần phải đến đó, đó là 2.
Vì vậy, tôi phải làm gì đặt ở đâu?
2 đi vào đây vì * b đi vào * a. Vì vậy, tôi sẽ làm điều đó.
Và bạn đã có thể nhìn thấy, có lẽ, rằng chúng tôi gần gũi hơn nhiều
để giải quyết vấn đề này, ngu ngốc, đơn giản một cách chính xác cho lần đầu tiên
bởi vì bây giờ chúng tôi vẫn còn có một hồi ức của những gì x là,
chúng tôi có 2 bản, thừa nhận, y,
nhưng dòng 3 * b.
Vì vậy, đây là b. * B có nghĩa là đi đến đó. Vì vậy, nơi vị trí 124?
Đó là rõ ràng ở đây. Vì vậy, tôi phải làm gì đặt ở đây? Rõ ràng, tmp.
Vì vậy, bây giờ tôi làm điều này. Vì vậy, tôi có 1 ở đây và 2 ở đây.
Và bây giờ những gì về tất cả điều này, 123, 124, và 1?
Ngay sau khi trở về trao đổi, bộ nhớ này là tốt như bị mất
bởi vì ngay sau khi trở về trao đổi, hệ điều hành
là miễn phí để sử dụng bộ nhớ một lần nữa trong tương lai.
Chỉ chính của bộ nhớ ở dưới cùng của chồng này được gọi là gậy xung quanh.
>> Và vì vậy chúng tôi cuối cùng đã có bây giờ là một phiên bản làm việc.
Hãy để tôi đi thành swap.c, và chú ý những điều sau đây.
Ở phía trên của chương trình, tôi đã thay đổi nguyên mẫu của tôi để được int * a và int * b.
Vì vậy, điều duy nhất tôi thay đổi từ màu đỏ, mà là xấu, màu xanh lá cây, đó là tốt,
Tôi được thêm vào những ngôi sao này ngày hôm nay.
Nhưng sau đó xuống đây trong trao đổi bản thân tôi đã sao chép, dán những gì đã được chỉ trên slide.
Tôi có một ngôi sao ở đây, ngôi sao ở đây - đó phù hợp với các mẫu thử nghiệm -
và sau đó tất cả những điều này bây giờ có sao trừ tmp
bởi vì việc sử dụng một biến tạm thời, không có gì mới.
Tôi chỉ cần lưu trữ tạm thời cho một int.
Vì vậy, chúng ta không cần một ngôi sao.
Chúng ta chỉ cần ngôi sao để chúng tôi có thể vượt qua ranh giới tùy ý
giữa 2 khung hình trong bộ nhớ của máy tính của tôi.
Tuy nhiên, một điều cuối cùng có thay đổi, và bạn có thể đã thoáng thấy nó đã.
Gì khác dòng rõ ràng là khác nhau? >> [Sinh viên] & x.
>> Yeah, vì vậy 25 là dòng cuối cùng của mã tôi cần phải thay đổi để làm việc này.
Một tuần trước và ngay cả ngày thứ hai, dòng 25 trông như thế này, trao đổi x và y,
và điều này đã được chỉ bị hỏng bởi vì nếu bạn nói swap (x, y)
bạn đang đưa ra các bản sao của x và y để trao đổi, sau đó nó làm nhiệm vụ của nó,
nhưng bạn sẽ không bao giờ thực sự thay đổi x và y chính nó.
Vì vậy, ngay cả khi bạn đã không bao giờ nhìn thấy nhân vật này trước đây với các ký hiệu trong mã,
chỉ mất một đoán. Dấu và làm gì, rõ ràng không?
[Sinh viên] Đưa các địa chỉ. >> Đưa địa chỉ.
Vì vậy, các dấu "và" nói cho tôi địa chỉ của x.
Ai biết nó ở đâu? Nó sẽ xảy ra là 123. Tôi không quan tâm. Chỉ cần cho tôi địa chỉ của x.
& Y có nghĩa là cung cấp cho tôi địa chỉ của y.
Và tại thời điểm đó câu chuyện là hoàn toàn phù hợp với hình ảnh, chúng tôi đã thu hút một chút thời gian trước đây.
>> Vì vậy, tôi sẽ thừa nhận con trỏ, chắc chắn đối với tôi khi tôi lần đầu tiên bắt đầu công việc này,
chắc chắn là một trong những điều khó khăn nhất để bọc tâm trí của tôi xung quanh.
Nhưng nhận ra, đặc biệt là khi chúng tôi tiếp tục chơi với những thứ này,
nếu bạn phá vỡ nó xuống để những siêu sắp xếp đơn giản của trí tuệ uninteresting vấn đề
chỉ cần chuyển một số lượng xung quanh, câu trả lời cho rất nhiều nhầm lẫn với con trỏ
thực sự có thể được bắt nguồn từ những cơ chế rất cơ bản.
Dưới đây là một địa chỉ. Đến đó với ngôi sao.
Hoặc ngược lại, đây là một dấu "và". Tìm ra địa chỉ thực sự là.
Được rồi.
Vì vậy, nơi tất cả các bộ nhớ này đến từ đâu?
Chúng tôi đã vẽ bức tranh này một vài lần, và tôi tiếp tục hứa hẹn chúng tôi sẽ trở lại với nó,
nhưng ở đây là các đại diện của bộ nhớ máy tính của bạn
đó là một chút dán nhãn hơn so với bảng đen của chúng tôi ở đây là.
Đoạn văn bản ở đầu đại diện cho những gì liên quan đến chương trình của bạn?
[Không nghe được sinh viên phản ứng] >> Xin lỗi? Nói một lần nữa.
[Sinh viên] chương trình thực tế. >> Chương trình thực tế.
>> Vì vậy, các Clang 0 và 1 mà bạn đã biên soạn sau khi viết mã C và sau đó chạy
và tạo ra các kết thúc 0 và 1 cùng bị nhét trong bộ nhớ
bởi vì khi bạn nhấp đúp chuột vào một biểu tượng trên máy Mac hoặc máy PC của bạn
hoặc chạy một lệnh như Mario tại dấu nhắc của bạn, 0 và 1 của bạn từ đĩa
có được nạp vào bộ nhớ để các máy tính có thể thao tác chúng
và thực hiện chúng một cách nhanh chóng hơn.
Vì vậy, khởi tạo dữ liệu và dữ liệu chưa được khởi tạo, chúng tôi sẽ không nói nhiều về những người,
nhưng chỉ là những biến toàn cầu.
Khởi tạo có nghĩa là các biến toàn cầu mà bạn đã cho giá trị để;
uninitialized có nghĩa là các biến toàn cầu mà bạn đã chưa cung cấp cho các giá trị để.
Sau đó có các biến môi trường mà tôi hoàn toàn sẽ vẫy tay của tôi,
nhưng họ có và lưu trữ những thứ như tên người dùng của bạn
và các loại chi tiết mức độ thấp hơn.
Tuy nhiên, các mảnh juiciest bố trí bộ nhớ của bạn là điều này được gọi là stack và heap.
Ngăn xếp một lần nữa, để được rõ ràng, là bộ nhớ được sử dụng bất cứ khi nào chức năng này được gọi là,
bất cứ khi nào có các biến địa phương
và bất cứ khi nào có thông số đang được thông qua xung quanh.
Tất cả điều đó xảy ra trong ngăn xếp.
Đống, chúng tôi đã không nói chuyện, nhưng có nhiều phán đoán những người sử dụng các đống.
Chỉ cần một đoạn khác nhau của bộ nhớ.
Nó xảy ra được rút ra ở đây ở đầu trang, nhưng đó là một quy ước bằng hình ảnh tùy ý.
Ai rõ rệt đã được sử dụng bộ nhớ từ đống cho tuần?
Đó là kỹ thuật bạn nhưng gián tiếp. >> [Sinh viên] GetString.
GetString và malloc. Vì vậy, đây là sự khác biệt cơ bản.
>> Bạn có biết trong vài tuần qua rằng nếu bạn cần bộ nhớ, chỉ cần khai báo một biến.
Nếu bạn cần rất nhiều bộ nhớ, khai báo một mảng nằm ngay bên trong chức năng của bạn.
Nhưng vấn đề chúng tôi đã giữ phải đối mặt với là nếu bạn khai báo các biến cục bộ bên trong các chức năng,
ngay sau khi trở về chức năng, những gì xảy ra với bộ nhớ và các biến?
Chỉ cần sắp xếp của nó không còn là của bạn, phải không? Nó chỉ biến mất loại khái niệm.
Nó vẫn còn thể chất có, rõ ràng, nhưng nó không còn là quyền của bạn để sử dụng.
Điều này rõ ràng là có vấn đề nếu bạn muốn viết các chức năng trong cuộc sống
mà thực sự cấp phát bộ nhớ và không cho nó trở lại ngay lập tức.
Trường hợp tại điểm: GetString mục đích trong cuộc sống là không có ý tưởng trước
lớn như thế nào của một chuỗi tôi sẽ gõ vào bàn phím,
nhưng nó có để có thể cấp phát bộ nhớ để giữ David hoặc hello
hoặc toàn bộ một bài luận mà người sử dụng có thể đã gõ.
Vì vậy, GetString đã được sử dụng malloc.
Malloc do đó phải được sử dụng không phải ngăn xếp;
thay vào đó nó sử dụng điều này được gọi là đống.
Không có gì khác nhau về bộ nhớ. Nó không phải là nhanh hơn hoặc chậm hơn hoặc bất cứ điều gì như thế.
Nó chỉ là thể chất ở một vị trí khác nhau.
>> Tuy nhiên, quy tắc là bộ nhớ được cấp phát trên heap
sẽ không bao giờ được lấy đi từ bạn cho đến khi bạn gọi một đoán miễn phí.
Ngược lại, bất kỳ bộ nhớ, bạn yêu cầu trên các ngăn xếp bởi chỉ cần khai báo một mảng
hoặc khai báo một biến như chúng tôi đã làm trong nhiều tuần,
theo mặc định kết thúc trên stack.
Và rằng hoạt động 90% thời gian, nhưng vào những dịp hiếm
nơi bạn muốn cấp phát bộ nhớ và giữ nó xung quanh,
sau đó bạn cần phải sử dụng một chức năng giống như malloc.
Hay chúng ta đã sử dụng một chức năng như GetString, mà lần lượt sử dụng malloc.
Hãy xem nơi này có thể phá vỡ và sau đó mất một peek tại Binky.
Chúng tôi sẽ trở lại đó trong tương lai.
Dưới đây là một chương trình đơn giản siêu trong 2 dòng đầu tiên làm những gì?
Trong tiếng Anh, 2 dòng đầu tiên của mã gì bên trong của chính?
[Không nghe được sinh viên phản ứng]
Cẩn thận. Nó không cung cấp cho tôi địa chỉ của x hoặc y.
[Sinh viên] Cung cấp cho con trỏ để ints. >> Good. Hãy cho tôi 2 con trỏ đến số nguyên.
Nói cách khác, cho tôi 2 phần bộ nhớ mà tôi tiếp tục vẽ ngày hôm nay,
mặc dù tôi xóa nó bây giờ, như hình vuông.
Hãy cho tôi 2 phần bộ nhớ, một gọi là x, một gọi là y -
trước đó tôi gọi họ s và t và các loại mà đoạn bộ nhớ là những gì?
Nó sẽ lưu trữ một địa chỉ.
Đó là kiểu int *.
>> Vì vậy, các địa chỉ của một int cuối cùng sẽ sống trong x,
địa chỉ của một int cuối cùng sẽ sống trong y,
nhưng ban đầu, những gì bên trong của x và y? Ai biết được? Garbage giá trị.
Nó không có gì để làm với con trỏ.
Nếu chúng tôi không đặt một cái gì đó ở đó, những người hiểu biết những gì thực sự có?
Bây giờ, x. Điều gì sẽ xảy ra đây? Điều này là VN bây giờ bởi vì x là một con trỏ. Đây là một int *.
Vì vậy, điều đó có nghĩa là tôi có thể đặt trong x địa chỉ của một số đoạn bộ nhớ.
Malloc gì trở lại? Hoàn hảo, nó sẽ trả về địa chỉ,
địa chỉ của byte đầu tiên trong một đoạn toàn bộ bộ nhớ.
Bao nhiêu byte này dường như phân bổ, ví dụ, trong thiết bị?
Kích thước của một int là gì? 4.
Nếu bạn nghĩ rằng trở lại 1 tuần, nó không phải là siêu quan trọng để luôn luôn nhớ rằng,
nhưng trong trường hợp này đó là hữu ích để biết, 4 byte.
Vì vậy, đây là phân bổ trên 4 byte đống
và nó trở về địa chỉ của một trong những đầu tiên để tôi tùy tiện.
Bây giờ, x đang làm gì?
A * x = 42 là làm những gì?
Nếu vào thời điểm này trong câu chuyện, chúng tôi có x, trông như thế này với một số giá trị rác,
đây là bây giờ y với một số giá trị rác, bây giờ trong dòng 3, tôi đã được giao 4 byte.
Hình ảnh này về cơ bản trông như thế này.
Hoặc cụ thể hơn, nếu điều này là tùy ý địa chỉ 123, đây là câu chuyện của chúng tôi bây giờ trông giống như.
* X = 42 bây giờ có nghĩa là gì? Điều đó có nghĩa là đi đến số 123 địa chỉ và số 42 có.
Tôi không cần phải rút ra những dòng này bởi vì chúng ta không làm dây.
>> Tôi có nên viết nó như thế này, và chỉ vì lợi ích trình diễn của,
42 như một loại int của chiếm rất nhiều không gian, 4 byte.
Vì vậy, đó là những gì đang xảy ra ở đó, nhưng có một vấn đề.
* Y = 13. Điều gì sẽ xảy ra ở đây?
Vấn đề là * y trên thế giới đơn giản của chúng tôi chỉ có nghĩa là đi đến địa chỉ trong y.
Gì trong y? Đó là một số giá trị rác.
Vì vậy, chúng ta hãy giả định rằng giá trị rác là 5551212, một cái gì đó điên rồ như thế.
* Y có nghĩa là đi để giải quyết 5.551.212.
Điều đó giống như ở đây. Nó không tồn tại, ví dụ.
Vì vậy, * y được 13 có nghĩa là tôi đang cố gắng để vẽ 13 ở đây. Nó không tồn tại.
Tôi đã vượt quá phân đoạn của bảng đen. Tôi nhận được gì?
Đó là thông điệp bí ẩn phân khúc lỗi vì tôi đang cố gắng để đưa vào bộ nhớ
một giá trị như 13 tại một địa điểm không tồn tại.
Phần còn lại của chương trình có thể làm việc được, nhưng cho đến thời điểm đó nó không.
Vì vậy, chúng ta hãy cố gắng kể câu chuyện này.
Chúng tôi sẽ quay trở lại khi chúng tôi đã nói chuyện về hex.
Hãy quay trở lại này và kết luận với điều này được gọi là Binky,
thu hồi là một giáo sư Stanford ngồi ở nhà chơi với Claymation,
để kể câu chuyện chính xác của chương trình đó.
Nó chỉ khoảng 3 phút. Ở đây chúng tôi có Binky.
[Male loa trên video] Hey Binky, dậy đi. Đó là thời gian cho vui con trỏ.
[Binky] đó là gì? Tìm hiểu về con trỏ? Oh, goody!
[Nam loa] Vâng, để bắt đầu, tôi đoán chúng ta sẽ cần một vài con trỏ.
>> [Binky] Okay. Đoạn mã này cấp phát 2 con trỏ có thể trỏ đến số nguyên.
[Male loa] Okay. Vâng, tôi thấy 2 con trỏ, nhưng họ dường như không được trỏ đến bất cứ điều gì.
[Binky] Đó là đúng. Ban đầu, con trỏ không trỏ đến bất cứ điều gì.
Những điều họ chỉ được gọi là pointees, và thiết lập chúng là một bước riêng biệt.
[Nam loa] Oh, đúng, đúng. Tôi biết điều đó. Các pointees là riêng biệt.
Er, do đó, làm thế nào để bạn phân bổ một pointee?
[Binky] Okay. Mã này phân bổ một pointee số nguyên, và phần này đặt x để trỏ đến nó.
[Male loa] Hey, có vẻ tốt hơn.
Vì vậy, làm cho nó làm một cái gì đó. >> [Binky] Okay.
Tôi sẽ tới đích của con trỏ x để lưu trữ các số 42 được pointee của nó.
Cho trick này, tôi sẽ cần phải cây đũa thần của tôi dereferencing.
[Male loa] cây đũa thần của bạn dereferencing? Đó là tuyệt vời.
[Binky] Đây là những gì mã trông giống như. Tôi chỉ sẽ thiết lập số lượng và ... [Popping âm thanh]
[Male loa] nhìn, có nó đi.
Vì vậy, làm một dereference trên x sau mũi tên để truy cập pointee của nó,
trong trường hợp này để lưu trữ 42 trong đó.
Hey, hãy thử sử dụng nó để lưu trữ các số 13 thông qua con trỏ khác, y.
[Binky] Okay. Tôi sẽ chỉ đi qua đây y và con số 13 thiết lập
và sau đó lấy cây đũa phép của dereferencing và chỉ cần ... [Ù âm thanh] Whoa!
[Nam loa] Oh hey, mà không làm việc.
>> Nói, Binky, tôi không nghĩ rằng dereferencing y là một ý tưởng tốt
bởi vì thiết lập các pointee là một bước riêng biệt
và tôi không bao giờ nghĩ rằng chúng tôi đã làm nó.
[Binky] Hmm, điểm tốt.
[Male loa] Yeah. Chúng tôi phân bổ y con trỏ, nhưng chúng tôi không bao giờ thiết lập nó để trỏ đến một pointee.
[Binky] Hmm, rất giỏi quan sát.
[Nam loa] Hey, bạn đang tìm kiếm tốt, Binky.
Bạn có thể sửa chữa nó để y đến pointee giống như x? >> [Binky] Chắc chắn rồi.
Tôi sẽ sử dụng cây đũa thần của tôi giao con trỏ.
[] Loa nam là sẽ là một vấn đề như trước đây?
[Binky] Không, điều này không chạm vào các pointees.
Nó chỉ thay đổi một con trỏ để trỏ đến cùng một điều như là một. [Popping âm thanh]
[Male loa] Ồ, tôi nhìn thấy. Bây giờ y điểm đến cùng một nơi như x.
Vì vậy, chờ đợi. Bây giờ y được cố định. Nó có một pointee.
Vì vậy, bạn có thể thử cây đũa phép của dereferencing một lần nữa để gửi hơn 13.
[Binky] Uh, okay. Ở đây đi. [Popping âm thanh]
[Male loa] Hey, nhìn vào đó. Bây giờ dereferencing công trình về y.
Và bởi vì các con trỏ được chia sẻ là một trong những pointee, cả hai đều thấy số 13.
[Binky] Yeah, chia sẻ. Sao cũng được.
>> Vì vậy, chúng ta sẽ chuyển đổi địa điểm ngay bây giờ?
[Male loa] Oh nhìn, chúng tôi hết thời gian. >> [Binky] -
[Male loa] Chỉ cần nhớ 3 quy tắc con trỏ.
Number 1, cấu trúc cơ bản là bạn có một con trỏ và nó chỉ qua một pointee.
Nhưng con trỏ và pointee riêng biệt, và các lỗi phổ biến là để thiết lập một con trỏ
nhưng để quên để cho nó một pointee.
Số 2, con trỏ dereferencing bắt đầu từ con trỏ và sau mũi tên của nó trên
để truy cập pointee của nó.
Như chúng ta đều biết, điều này chỉ hoạt động nếu có pointee,
trong đó loại được trở lại để loại trừ số 1.
Số 3, con trỏ chuyển nhượng mất một con trỏ và thay đổi nó
để trỏ đến pointee giống như con trỏ khác.
Vì vậy, sau khi chuyển nhượng, 2 con trỏ sẽ trỏ đến cùng một pointee.
Đôi khi điều đó được gọi là chia sẻ.
>> Và đó là tất cả để có nó thực sự. Bye-bye.
Đây là Binky. Đây là CS50. Chúng ta sẽ thấy bạn vào tuần tới. [Vỗ tay]
>> [CS50.TV]