1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Phần 5 - thoải mái hơn] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Đại học Harvard] 3 00:00:04,690 --> 00:00:07,250 [Đây là CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Giống như tôi đã nói trong email của tôi, có rất nhiều điều bạn có thể sử dụng 5 00:00:14,250 --> 00:00:17,060 khác hơn so với các thiết bị để thực sự làm các bài tập. 6 00:00:17,060 --> 00:00:19,910 Chúng tôi đề nghị bạn làm điều đó trong thiết bị chỉ vì sau đó chúng ta có thể dễ dàng giúp bạn 7 00:00:19,910 --> 00:00:22,070 và chúng tôi biết làm thế nào tất cả mọi thứ sẽ làm việc. 8 00:00:22,070 --> 00:00:26,950 Tuy nhiên, như một ví dụ về nơi bạn có thể làm những điều nếu nói, bạn không có quyền truy cập 9 00:00:26,950 --> 00:00:31,570 một thiết bị hoặc bạn muốn làm việc trong tầng hầm của Trung tâm Khoa học - 10 00:00:31,570 --> 00:00:33,090 mà thực sự họ có thiết bị - 11 00:00:33,090 --> 00:00:35,150 nếu bạn muốn làm việc bất cứ nơi nào. 12 00:00:35,150 --> 00:00:42,370 Một ví dụ có bạn thấy / nghe nói của SSH? 13 00:00:44,380 --> 00:00:47,780 SSH là về cơ bản giống như kết nối đến một cái gì đó. 14 00:00:47,780 --> 00:00:51,340 Trên thực tế, ngay bây giờ tôi SSHed vào thiết bị. 15 00:00:51,340 --> 00:00:54,290 Tôi không bao giờ làm việc trực tiếp trong thiết bị. 16 00:00:55,930 --> 00:01:01,060 Đây là thiết bị, và nếu bạn nhìn xuống ở đây bạn thấy địa chỉ IP này. 17 00:01:01,060 --> 00:01:03,650 Tôi không bao giờ làm việc trong thiết bị chính nó; 18 00:01:03,650 --> 00:01:08,840 Tôi luôn luôn đi qua một cửa sổ / cửa sổ thiết bị đầu cuối iTerm2. 19 00:01:08,840 --> 00:01:15,910 Bạn có thể SSH đến địa chỉ IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Tôi nhớ rằng số lượng rất dễ dàng bởi vì nó là một mô hình tốt đẹp như vậy. 21 00:01:20,390 --> 00:01:24,920 Nhưng điều đó sẽ yêu cầu mật khẩu của tôi, và bây giờ tôi đang ở trong thiết bị. 22 00:01:24,920 --> 00:01:33,060 Về cơ bản, vào thời điểm này, nếu bạn đã mở ra một thiết bị đầu cuối bên trong của thiết bị chính nó, 23 00:01:33,060 --> 00:01:36,350 giao diện này, tuy nhiên bạn sẽ sử dụng nó, là chính xác giống 24 00:01:36,350 --> 00:01:40,010 như giao diện, tôi đang sử dụng ở đây nhưng bây giờ bạn đang SSHed. 25 00:01:42,240 --> 00:01:44,920 Bạn không cần phải SSH vào thiết bị. 26 00:01:44,920 --> 00:01:52,360 Một ví dụ về một nơi khác, bạn có thể SSH đến là tôi khá chắc chắn rằng bạn có theo mặc định - 27 00:01:52,360 --> 00:01:55,020 Oh. Lớn hơn. 28 00:01:55,020 --> 00:02:01,130 Tất cả các bạn cần phải có tài khoản FAS mặc định trên các máy chủ của FAS. 29 00:02:01,130 --> 00:02:06,840 Đối với tôi, tôi sẽ SSH đến rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 Nó sẽ hỏi bạn là lần đầu tiên, và bạn nói có. 31 00:02:11,610 --> 00:02:15,840 Mật khẩu của tôi là chỉ cần đi để được mật khẩu của tôi FAS. 32 00:02:15,840 --> 00:02:22,650 Và vì vậy bây giờ, tôi đang SSHed đến các máy chủ tốt đẹp, và tôi có thể làm bất cứ điều gì tôi muốn ở đây. 33 00:02:22,650 --> 00:02:28,560 Rất nhiều các lớp học bạn có thể mất, như 124, sẽ có bạn tải lên các công cụ ở đây 34 00:02:28,560 --> 00:02:30,950 để thực sự gửi bộ vấn đề của bạn. 35 00:02:30,950 --> 00:02:34,100 Nhưng nói bạn không có quyền truy cập vào thiết bị của bạn. 36 00:02:34,100 --> 00:02:37,910 Sau đó, bạn có thể làm điều gì đó, giống như ở đây, nó sẽ nói - 37 00:02:37,910 --> 00:02:42,160 Đây chỉ là phần câu hỏi của chúng tôi. 38 00:02:42,160 --> 00:02:45,070 Nó sẽ yêu cầu bạn làm điều này trong thiết bị. 39 00:02:45,070 --> 00:02:47,790 Thay vào đó tôi sẽ chỉ làm điều đó trên máy chủ. 40 00:02:47,790 --> 00:02:50,560 Tôi sẽ phải giải nén mà. 41 00:02:50,560 --> 00:02:55,670 Vấn đề là có được rằng bạn đang sử dụng bằng cách sử dụng một cái gì đó như gedit 42 00:02:55,670 --> 00:02:58,160 hoặc bất cứ điều gì bên trong của thiết bị. 43 00:02:58,160 --> 00:03:01,830 Bạn sẽ không phải có mà trên máy chủ FAS. 44 00:03:01,830 --> 00:03:04,110 Đó là tất cả chỉ là giao diện này văn bản. 45 00:03:04,110 --> 00:03:09,180 Vì vậy, bạn có thể hoặc là một, cố gắng tìm hiểu một trình soạn thảo văn bản mà không có. 46 00:03:09,180 --> 00:03:12,130 Họ có Nano. 47 00:03:12,130 --> 00:03:14,990 Nano thường là khá dễ dàng để sử dụng. 48 00:03:14,990 --> 00:03:19,470 Bạn có thể sử dụng mũi tên của bạn và gõ bình thường. 49 00:03:19,470 --> 00:03:21,250 Vì vậy, đó không phải là khó. 50 00:03:21,250 --> 00:03:24,720 Nếu bạn muốn nhận được thực sự ưa thích, bạn có thể sử dụng Emacs, 51 00:03:24,720 --> 00:03:29,850 mà tôi có lẽ không nên đã mở ra bởi vì tôi thậm chí không biết làm thế nào để đóng Emacs. 52 00:03:29,850 --> 00:03:32,760 Kiểm soát X, Control C? Yeah. 53 00:03:32,760 --> 00:03:35,310 Hoặc bạn có thể sử dụng Vim, đó là những gì tôi sử dụng. 54 00:03:35,310 --> 00:03:37,800 Và do đó, những lựa chọn của bạn. 55 00:03:37,800 --> 00:03:43,830 Nếu bạn không muốn làm điều đó, bạn cũng có thể, nếu bạn nhìn vào manual.cs50.net - 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Trên một máy tính, bạn có thể SSH bằng cách sử dụng PuTTY, 58 00:03:49,920 --> 00:03:51,940 mà bạn sẽ phải tải về một cách riêng biệt. 59 00:03:51,940 --> 00:03:55,460 Trên máy Mac, bạn có thể chỉ bằng cách đầu cuối sử dụng mặc định hoặc bạn có thể tải về iTerm2, 60 00:03:55,460 --> 00:03:58,490 mà là giống như một Terminal tốt đẹp ưa thích,. 61 00:03:58,490 --> 00:04:03,780 Nếu bạn đi đến manual.cs50.net, bạn sẽ thấy một liên kết để Notepad + +, 62 00:04:03,780 --> 00:04:07,120 mà là những gì bạn có thể sử dụng trên một máy tính. 63 00:04:07,120 --> 00:04:13,340 Nó cho phép bạn SFTP từ Notepad + +, đó là cơ bản SSH. 64 00:04:13,340 --> 00:04:17,750 Điều này sẽ cho phép bạn làm là chỉnh sửa các tập tin của bạn tại địa phương, 65 00:04:17,750 --> 00:04:20,670 và sau đó bất cứ khi nào bạn muốn lưu chúng, nó sẽ tiết kiệm nice.fas 66 00:04:20,670 --> 00:04:23,670 sau đó bạn có thể chạy chúng. 67 00:04:23,670 --> 00:04:26,880 Và tương đương trên máy Mac sẽ được TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Vì vậy, nó cho phép bạn làm điều tương tự. 69 00:04:28,760 --> 00:04:32,800 Nó cho phép bạn chỉnh sửa các tập tin địa phương và lưu chúng vào nice.fas, 70 00:04:32,800 --> 00:04:35,730 sau đó bạn có thể chạy chúng. 71 00:04:35,730 --> 00:04:40,400 Vì vậy, nếu bạn đang bị mắc kẹt mà không có một thiết bị, bạn có các tùy chọn 72 00:04:40,400 --> 00:04:44,230 vẫn còn làm bộ vấn đề của bạn. 73 00:04:44,230 --> 00:04:48,250 Một vấn đề là có được rằng bạn sẽ không có thư viện CS50 74 00:04:48,250 --> 00:04:51,580 vì nice.fas không theo mặc định có điều đó. 75 00:04:51,580 --> 00:04:55,970 Bạn có thể tải về thư viện CS50 - 76 00:04:55,970 --> 00:04:58,470 Tôi không nghĩ rằng tôi cần phải có vào thời điểm này. 77 00:04:58,470 --> 00:05:03,270 Bạn có thể tải về các thư viện CS50 và sao chép nó để nice.fas, 78 00:05:03,270 --> 00:05:07,450 Tôi nghĩ rằng vào thời điểm này, chúng tôi không sử dụng nó nữa nào. 79 00:05:07,450 --> 00:05:12,720 Hoặc nếu chúng ta làm, bạn có thể cho thời gian được thay thế nó với 80 00:05:12,720 --> 00:05:18,480 triển khai thực hiện các chức năng trong thư viện CS50 anyway. 81 00:05:18,480 --> 00:05:21,370 Vì vậy, đó không phải là rằng có rất nhiều hạn chế. 82 00:05:21,370 --> 00:05:23,710 Và đó là điều đó. 83 00:05:26,460 --> 00:05:29,820 >> Tôi sẽ quay lại vào thiết bị ngay bây giờ, chúng tôi sẽ làm tất cả mọi thứ trong thiết bị. 84 00:05:29,820 --> 00:05:37,510 Nhìn vào phần câu hỏi của chúng tôi, ngay từ đầu, như tôi đã nói trong email của tôi, 85 00:05:37,510 --> 00:05:43,620 chúng ta phải nói về con đường ngắn bạn đã dự để xem. 86 00:05:43,620 --> 00:05:51,980 Chúng tôi có chuyển hướng & Ống và ba câu hỏi này. 87 00:05:51,980 --> 00:05:56,070 >> Để dòng làm chức năng như printf viết theo mặc định? 88 00:05:56,070 --> 00:05:59,130 Vì vậy, dòng suối. Một dòng suối là gì? 89 00:06:06,520 --> 00:06:15,100 Dòng A là cơ bản giống như nó chỉ là một số 90 00:06:15,100 --> 00:06:21,450 Nó thậm chí không một nguồn 1 và 0. 91 00:06:21,450 --> 00:06:24,920 Các dòng nó yêu cầu ở đây là tiêu chuẩn ra. 92 00:06:24,920 --> 00:06:27,250 Và do đó, tiêu chuẩn ra là một dòng suối mà khi bạn viết thư cho nó, 93 00:06:27,250 --> 00:06:30,940 nó xuất hiện trên màn hình. 94 00:06:30,940 --> 00:06:36,860 Tiêu chuẩn ra, theo dòng suối, nó có nghĩa là bạn chỉ cần viết 1 và số 0 cho nó, 95 00:06:36,860 --> 00:06:40,220 và đầu kia của ra tiêu chuẩn chỉ cần đọc từ dòng suối đó. 96 00:06:40,220 --> 00:06:43,540 Nó chỉ là một chuỗi của 1 và 0. 97 00:06:43,540 --> 00:06:45,570 Bạn có thể viết dòng suối hoặc bạn có thể đọc từ các dòng suối 98 00:06:45,570 --> 00:06:47,950 tùy thuộc vào dòng thực sự là. 99 00:06:47,950 --> 00:06:52,800 Hai dòng mặc định khác là tiêu chuẩn trong lỗi tiêu chuẩn. 100 00:06:52,800 --> 00:06:57,540 Tiêu chuẩn trong bất cứ khi nào bạn GetString, nó chờ đợi cho bạn các công cụ đầu vào. 101 00:06:57,540 --> 00:07:01,570 Vì vậy, nó chờ đợi cho bạn, nó thực sự chờ đợi vào tiêu chuẩn trong, 102 00:07:01,570 --> 00:07:04,880 mà thực sự là những gì bạn nhận được khi bạn gõ vào bàn phím. 103 00:07:04,880 --> 00:07:07,530 Bạn gõ vào tiêu chuẩn. 104 00:07:07,530 --> 00:07:10,050 Lỗi tiêu chuẩn về cơ bản là tương đương với tiêu chuẩn ra, 105 00:07:10,050 --> 00:07:13,280 nhưng đó là chuyên ngành trong đó khi bạn in ra lỗi tiêu chuẩn, 106 00:07:13,280 --> 00:07:16,770 bạn đang nghĩ đến chỉ in thông báo lỗi đó 107 00:07:16,770 --> 00:07:20,200 để bạn có thể phân biệt giữa các tin nhắn thường xuyên in ra màn hình 108 00:07:20,200 --> 00:07:24,560 so với thông báo lỗi tùy thuộc vào việc họ đã đi ra tiêu chuẩn hay sai số chuẩn. 109 00:07:24,560 --> 00:07:28,660 Các tập tin quá. 110 00:07:28,660 --> 00:07:32,440 Ra tiêu chuẩn, tiêu chuẩn, và lỗi tiêu chuẩn chỉ là dòng đặc biệt, 111 00:07:32,440 --> 00:07:36,810 nhưng thực sự tập tin bất kỳ, khi bạn mở một tập tin, nó sẽ trở thành một dòng các byte 112 00:07:36,810 --> 00:07:40,740 nơi mà bạn chỉ có thể đọc từ dòng suối chảy. 113 00:07:40,740 --> 00:07:47,770 Bạn, cho hầu hết các phần, chỉ có thể nghĩ về một tập tin như một dòng các byte. 114 00:07:47,770 --> 00:07:51,190 Vì vậy, những gì dòng họ viết theo mặc định? Tiêu chuẩn ra ngoài. 115 00:07:51,190 --> 00:07:56,980 >> Sự khác biệt giữa> và >> là gì? 116 00:07:58,140 --> 00:08:03,710 Có ai xem video trước? Okay. 117 00:08:03,710 --> 00:08:10,960 > Sẽ là làm thế nào bạn chuyển hướng vào các tập tin, 118 00:08:10,960 --> 00:08:15,240 và >> cũng sẽ chuyển hướng đầu ra vào các tập tin, 119 00:08:15,240 --> 00:08:17,820 nhưng nó thay vì để phụ thêm vào tập tin. 120 00:08:17,820 --> 00:08:23,430 Ví dụ, hãy nói rằng tôi xảy ra để có dict ngay tại đây, 121 00:08:23,430 --> 00:08:27,020 và các công cụ duy nhất bên trong của dict là con mèo, con mèo, con chó, con chó, cá. 122 00:08:27,020 --> 00:08:31,530 Một lệnh mà bạn có tại các dòng lệnh là con mèo, 123 00:08:31,530 --> 00:08:34,539 mà chỉ là sẽ in trong một tập tin. 124 00:08:34,539 --> 00:08:40,679 Vì vậy, khi tôi nói dict con mèo, nó sẽ in con mèo, con mèo, con chó, con chó, cá. Đó là con mèo tất cả. 125 00:08:40,679 --> 00:08:46,280 Điều đó có nghĩa rằng nó được in tiêu chuẩn ra con mèo, con mèo, con chó, con chó, cá. 126 00:08:46,280 --> 00:08:53,240 Nếu tôi thay vì muốn chuyển hướng vào một tập tin, tôi có thể sử dụng> và chuyển hướng nó vào tập tin bất cứ điều gì. 127 00:08:53,240 --> 00:08:56,460 Tôi sẽ gọi các tập tin tập tin. 128 00:08:56,460 --> 00:09:00,320 Vì vậy, bây giờ nếu tôi ls, tôi sẽ thấy tôi có một tập tin mới được gọi là tập tin. 129 00:09:00,320 --> 00:09:05,700 Và nếu tôi mở nó lên, nó sẽ có chính xác những gì con mèo đặt tại dòng lệnh. 130 00:09:05,700 --> 00:09:11,040 Vì vậy, bây giờ nếu tôi làm điều đó một lần nữa, sau đó nó sẽ chuyển hướng đầu ra vào một tập tin, 131 00:09:11,040 --> 00:09:13,930 và tôi sẽ có cùng một điều chính xác. 132 00:09:13,930 --> 00:09:17,910 Vì vậy, về mặt kỹ thuật, nó hoàn toàn overrode những gì chúng ta có. 133 00:09:17,910 --> 00:09:22,970 Và chúng ta sẽ thấy nếu tôi thay đổi dict, tôi đã diễn ra chó. 134 00:09:22,970 --> 00:09:29,980 Bây giờ nếu chúng ta mèo dict vào tập tin một lần nữa, chúng ta sẽ có phiên bản mới với loại bỏ con chó. 135 00:09:29,980 --> 00:09:32,400 Vì vậy, nó hoàn toàn sẽ ghi đè nó. 136 00:09:32,400 --> 00:09:36,640 Thay vào đó, nếu chúng ta sử dụng >>, nó sẽ nối thêm tập tin. 137 00:09:36,640 --> 00:09:40,860 Bây giờ, mở tập tin, chúng ta thấy chúng ta có cùng một điều in hai lần 138 00:09:40,860 --> 00:09:44,920 bởi vì nó đã có một lần, sau đó chúng tôi nối với bản gốc. 139 00:09:44,920 --> 00:09:48,130 Vì vậy, đó là những gì> và >>. 140 00:09:48,130 --> 00:09:50,580 Có một trong những tiếp theo yêu cầu - Nó không hỏi về nó. 141 00:09:50,580 --> 00:09:59,050 >> Một trong những khác mà chúng ta có là <, mà nếu chuyển hướng ra tiêu chuẩn, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Hãy xem nếu chúng ta có một ví dụ. 144 00:10:14,750 --> 00:10:16,930 Tôi có thể viết một thực sự nhanh chóng. 145 00:10:17,870 --> 00:10:25,700 Chúng ta hãy bất kỳ tập tin, hello.c. 146 00:10:56,060 --> 00:10:59,070 Tương đối đơn giản tập tin. 147 00:10:59,070 --> 00:11:03,570 Tôi chỉ nhận được một chuỗi và sau đó in ra "Hello" chuỗi tôi chỉ cần nhập vào bất cứ điều gì là. 148 00:11:03,570 --> 00:11:07,990 Vì vậy, hãy chào và sau đó / hello. 149 00:11:07,990 --> 00:11:10,720 Bây giờ nó khiến tôi nhập vào một cái gì đó, 150 00:11:10,720 --> 00:11:15,070 có nghĩa là nó chờ đợi vào những thứ được đưa vào tiêu chuẩn. 151 00:11:15,070 --> 00:11:20,450 Vì vậy, nhập bất cứ điều gì tôi muốn vào tiêu chuẩn. Chúng tôi chỉ cần đi để cất tiếng chào Rob! 152 00:11:20,450 --> 00:11:23,310 Sau đó, nó in tiêu chuẩn ra Xin chào, Rob! 153 00:11:23,310 --> 00:11:28,860 Nếu tôi làm / hello. Và sau đó chuyển hướng, 154 00:11:30,740 --> 00:11:34,310 bây giờ bạn chỉ có thể chuyển hướng từ một tập tin. 155 00:11:34,310 --> 00:11:41,720 Vì vậy, nếu tôi đặt trong một số tập tin, txt, và tôi đặt Rob, 156 00:11:41,720 --> 00:11:52,300 nếu tôi chạy chào và sau đó chuyển hướng file txt vào / hello, nó sẽ nói Xin chào, Rob! ngay lập tức. 157 00:11:52,300 --> 00:11:57,160 Khi lần đầu tiên được GetString và chờ đợi vào tiêu chuẩn trong, 158 00:11:57,160 --> 00:12:01,730 tiêu chuẩn trong không còn chờ đợi trên bàn phím cho các dữ liệu để nhập vào. 159 00:12:01,730 --> 00:12:05,980 Thay vào đó, chúng tôi đã chuyển hướng tiêu chuẩn để đọc từ file txt. 160 00:12:05,980 --> 00:12:10,290 Và do đó, nó sẽ đọc từ txt tập tin, mà chỉ là Rob dòng, 161 00:12:10,290 --> 00:12:13,380 và sau đó nó sẽ in Xin chào, Rob! 162 00:12:13,380 --> 00:12:18,180 Và nếu tôi muốn, tôi cũng có thể làm. / Hello 00:12:21,500 và sau đó là tiêu chuẩn ra rằng đó là in ấn, mà là Hello, Rob, 164 00:12:21,500 --> 00:12:24,700 Tôi có thể chuyển hướng vào một tập tin riêng của mình. 165 00:12:24,700 --> 00:12:29,790 Tôi sẽ chỉ gọi các tập tin hello - không, tôi sẽ không, bởi vì đó là thực thi - txt2. 166 00:12:29,790 --> 00:12:40,150 Bây giờ, txt2 là sẽ có đầu ra của / hello 00:12:43,520 >> Câu hỏi? 168 00:12:45,900 --> 00:12:49,090 >> Okay. Vì vậy, sau đó ở đây chúng tôi có đường ống. 169 00:12:49,090 --> 00:12:53,510 Đường ống là đơn vị cuối cùng của chuyển hướng. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Tôi đoán thêm một đơn vị chuyển hướng là nếu thay vì> bạn làm 2> 171 00:12:58,750 --> 00:13:01,070 chuyển hướng lỗi tiêu chuẩn. 172 00:13:01,070 --> 00:13:06,280 Vì vậy, nếu một cái gì đó đã đi sai số chuẩn, nó sẽ không có được đặt thành txt2. 173 00:13:06,280 --> 00:13:12,480 Nhưng hãy chú ý nếu tôi làm 2>, sau đó nó vẫn còn in Xin chào, Rob! vào dòng lệnh 174 00:13:12,480 --> 00:13:18,600 bởi vì tôi chỉ chuyển hướng lỗi tiêu chuẩn, tôi không chuyển hướng tiêu chuẩn. 175 00:13:18,600 --> 00:13:22,210 Ra lỗi tiêu chuẩn và tiêu chuẩn khác nhau. 176 00:13:24,210 --> 00:13:27,080 Nếu bạn muốn thực sự viết ra lỗi tiêu chuẩn, 177 00:13:27,080 --> 00:13:35,080 sau đó tôi có thể thay đổi điều này fprintf thiết bị lỗi chuẩn. 178 00:13:35,080 --> 00:13:37,850 Vì vậy, printf, theo mặc định, bản in để ra tiêu chuẩn. 179 00:13:37,850 --> 00:13:41,720 Nếu tôi muốn in ra lỗi tiêu chuẩn bằng tay, sau đó tôi phải sử dụng fprintf 180 00:13:41,720 --> 00:13:45,010 và chỉ định những gì tôi muốn in. 181 00:13:45,010 --> 00:13:49,720 Nếu thay vào đó tôi đã làm thiết bị xuất chuẩn fprintf, thì đó là về cơ bản tương đương với printf. 182 00:13:49,720 --> 00:13:55,530 Nhưng fprintf lỗi tiêu chuẩn. 183 00:13:57,790 --> 00:14:03,650 Vì vậy, bây giờ, nếu tôi chuyển hướng vào txt2, Xin chào, Rob! vẫn nhận được in tại dòng lệnh 184 00:14:03,650 --> 00:14:08,270 kể từ khi nó nhận được in ra lỗi tiêu chuẩn và tôi chỉ chuyển hướng tiêu chuẩn. 185 00:14:08,270 --> 00:14:16,420 Nếu bây giờ tôi chuyển hướng lỗi tiêu chuẩn, bây giờ nó không được in, và txt2 là có được Xin chào, Rob! 186 00:14:16,420 --> 00:14:21,910 Vì vậy, bây giờ, bạn có thể in lỗi thực tế của bạn ra lỗi tiêu chuẩn 187 00:14:21,910 --> 00:14:24,720 và in các thông điệp thường xuyên của bạn để ra tiêu chuẩn. 188 00:14:24,720 --> 00:14:31,420 Và do đó, khi bạn chạy chương trình của bạn, bạn có thể chạy nó như là / hello. Loại này với 2> 189 00:14:31,420 --> 00:14:33,800 để chương trình của bạn sẽ chạy bình thường, 190 00:14:33,800 --> 00:14:38,400 nhưng bất kỳ thông báo lỗi mà bạn nhận được bạn có thể kiểm tra sau này trong nhật ký lỗi của bạn, 191 00:14:38,400 --> 00:14:44,500 để sai sót, và sau đó nhìn sau và tập tin lỗi của bạn sẽ có bất kỳ lỗi nào xảy ra. 192 00:14:45,200 --> 00:14:47,540 >> Câu hỏi? 193 00:14:47,540 --> 00:14:58,070 >> Người cuối cùng là đường ống, mà bạn có thể nghĩ là các tiêu chuẩn của một lệnh 194 00:14:58,070 --> 00:15:01,210 và làm cho nó trở thành tiêu chuẩn trong các lệnh tiếp theo. 195 00:15:01,210 --> 00:15:05,570 Một ví dụ ở đây là tiếng vang là một dòng lệnh điều 196 00:15:05,570 --> 00:15:11,840 là chỉ cần đi để echo bất cứ điều gì tôi đặt như là đối số của nó. Tôi sẽ không đặt dấu ngoặc kép. 197 00:15:11,840 --> 00:15:16,150 Echo blah, blah, blah là chỉ cần đi in blah, blah, blah. 198 00:15:16,150 --> 00:15:20,600 Trước đây, khi tôi nói rằng tôi đã phải đặt Rob vào một tập tin txt 199 00:15:20,600 --> 00:15:28,830 bởi vì tôi chỉ có thể chuyển hướng các file txt, thay vào đó, / Tôi echo Rob 200 00:15:28,830 --> 00:15:35,520 và sau đó ống vào / hello, đó cũng sẽ làm cùng một loại điều. 201 00:15:35,520 --> 00:15:39,160 Điều này đang ra của lệnh này, echo Rob, 202 00:15:39,160 --> 00:15:43,610 và sử dụng nó như là đầu vào cho / hello. 203 00:15:44,790 --> 00:15:49,560 Bạn có thể nghĩ về nó như chuyển hướng đầu tiên vang Rob vào một tập tin 204 00:15:49,560 --> 00:15:54,160 và sau đó nhập vào / hello tập tin đó đã được đưa ra cả. 205 00:15:54,160 --> 00:15:57,850 Nhưng phải mất các tập tin tạm thời của hình ảnh. 206 00:16:01,890 --> 00:16:04,460 >> Câu hỏi về điều đó? 207 00:16:04,460 --> 00:16:07,150 >> Câu hỏi tiếp theo sẽ liên quan đến điều này. 208 00:16:07,150 --> 00:16:15,310 Đường ống dẫn bạn có thể sử dụng để tìm số lượng các tên duy nhất trong một tập tin gọi là names.txt? 209 00:16:15,310 --> 00:16:24,160 Các lệnh chúng ta sẽ muốn sử dụng ở đây là duy nhất, do đó, uniq, và sau đó wc. 210 00:16:24,160 --> 00:16:28,840 Bạn có thể làm uniq người đàn ông để thực sự nhìn vào những gì mà thực hiện, 211 00:16:28,840 --> 00:16:34,840 và nó chỉ sẽ lọc các dòng kề nhau tương ứng từ đầu vào. 212 00:16:34,840 --> 00:16:40,690 Và người đàn ông wc là sẽ in từ, dòng mới, và số byte cho mỗi tập tin. 213 00:16:40,690 --> 00:16:43,760 Và cuối cùng chúng ta sẽ muốn sử dụng là sắp xếp, 214 00:16:43,760 --> 00:16:47,410 đó là sẽ chỉ cần sắp xếp các dòng file txt. 215 00:16:47,410 --> 00:16:58,080 Nếu tôi làm cho một số tập tin txt, names.txt, và đó là Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 những gì tôi muốn làm ở đây là tìm số lượng các tên duy nhất trong tập tin này. 217 00:17:03,910 --> 00:17:08,750 Vì vậy, câu trả lời nên được? >> [Sinh viên] 4. >> Yeah. 218 00:17:08,750 --> 00:17:13,780 Nó nên được 4 kể từ Rob, Tommy, Joseph, RJ là tên chỉ có duy nhất trong tập tin này. 219 00:17:13,780 --> 00:17:20,180 Bước đầu tiên, nếu tôi chỉ làm số lượng từ trên names.txt, 220 00:17:20,180 --> 00:17:24,290 điều này thực sự nói cho tôi tất cả mọi thứ. 221 00:17:24,290 --> 00:17:32,560 Điều này thực sự in ấn - Hãy xem, người đàn ông wc - dòng mới, từ, và đếm byte. 222 00:17:32,560 --> 00:17:38,270 Nếu tôi chỉ quan tâm về dòng, sau đó tôi chỉ có thể làm names.txt wc-l. 223 00:17:41,730 --> 00:17:44,300 Vì vậy, đó là bước 1. 224 00:17:44,300 --> 00:17:50,510 Nhưng tôi không muốn wc-l names.txt vì names.txt chỉ chứa tất cả các tên, 225 00:17:50,510 --> 00:17:54,170 và tôi muốn lọc ra bất kỳ những người không phải duy nhất. 226 00:17:54,170 --> 00:18:01,200 Vì vậy, nếu tôi làm uniq names.txt, điều đó không hoàn toàn cho tôi những gì tôi muốn 227 00:18:01,200 --> 00:18:03,760 bởi vì tên nhân đôi vẫn còn ở đó. 228 00:18:03,760 --> 00:18:07,690 Tại sao vậy? Tại sao uniq không làm những gì tôi muốn? 229 00:18:07,690 --> 00:18:10,500 [Sinh viên] Bản sao không phải là không nghe được] >> Yeah. 230 00:18:10,500 --> 00:18:16,370 Ghi trang người đàn ông cho uniq nói dòng phù hợp với bộ lọc liền kề. 231 00:18:16,370 --> 00:18:19,680 Chúng không phải là lân cận, do đó, nó sẽ không lọc chúng. 232 00:18:19,680 --> 00:18:31,100 Nếu tôi sắp xếp chúng đầu tiên, sắp xếp names.txt sẽ đặt tất cả các dòng trùng lặp với nhau. 233 00:18:31,100 --> 00:18:34,450 Vì vậy, bây giờ loại names.txt là. 234 00:18:34,450 --> 00:18:40,550 Tôi sẽ muốn sử dụng như là đầu vào uniq, | uniq. 235 00:18:40,550 --> 00:18:43,390 Điều đó mang lại cho tôi Joseph, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 và tôi muốn sử dụng như là đầu vào wc-l, 237 00:18:49,260 --> 00:18:52,740 đó là sẽ cung cấp cho tôi 4. 238 00:18:52,740 --> 00:18:56,930 Như nó nói ở đây, bạn có thể sử dụng những đường ống dẫn? 239 00:18:56,930 --> 00:19:01,390 Bạn có thể làm rất nhiều thứ như bằng cách sử dụng một loạt các lệnh 240 00:19:01,390 --> 00:19:05,130 nơi bạn sử dụng đầu ra của một lệnh như là đầu vào cho lệnh tiếp theo. 241 00:19:05,130 --> 00:19:08,780 Bạn có thể làm rất nhiều thứ, rất nhiều thứ thông minh. 242 00:19:08,780 --> 00:19:11,440 >> Câu hỏi? 243 00:19:12,910 --> 00:19:14,600 Okay. 244 00:19:14,600 --> 00:19:17,880 Đó là nó cho các đường ống và chuyển hướng. 245 00:19:18,370 --> 00:19:24,090 >> Bây giờ chúng ta đi vào những thứ thực tế, các công cụ mã hóa. 246 00:19:24,090 --> 00:19:29,100 Bên trong của PDF này, bạn sẽ thấy lệnh này, 247 00:19:29,100 --> 00:19:32,950 và bạn sẽ muốn chạy lệnh này trong thiết bị của bạn. 248 00:19:36,240 --> 00:19:42,250 wget là lệnh chỉ nhận được một cái gì đó từ Internet, về cơ bản, 249 00:19:42,250 --> 00:19:45,180 wget và URL này. 250 00:19:45,180 --> 00:19:49,110 Nếu bạn đã đi đến URL này trong trình duyệt của bạn, nó sẽ tải về tập tin đó. 251 00:19:49,110 --> 00:19:52,510 Tôi chỉ cần nhấp vào nó, do đó, nó tải về các tập tin cho tôi. 252 00:19:52,510 --> 00:19:55,650 Nhưng viết wget điều mà bên trong của các thiết bị đầu cuối 253 00:19:55,650 --> 00:19:58,620 là chỉ cần đi để tải nó vào thiết bị đầu cuối của bạn. 254 00:19:58,620 --> 00:20:02,750 Tôi có section5.zip, và bạn sẽ muốn giải nén section5.zip, 255 00:20:02,750 --> 00:20:06,520 đó là sẽ cung cấp cho bạn một thư mục gọi là section5, 256 00:20:06,520 --> 00:20:11,550 đó là sẽ có tất cả các tập tin chúng ta sẽ được sử dụng ngày hôm nay bên trong của nó. 257 00:20:33,380 --> 00:20:37,710 Như tên tập tin của các chương trình này cho thấy, họ là một lỗi bit, 258 00:20:37,710 --> 00:20:40,990 Nhiệm vụ của bạn là để tìm ra lý do tại sao bằng cách sử dụng gdb. 259 00:20:40,990 --> 00:20:44,560 Tất cả mọi người có họ tải về / biết làm thế nào để có được họ tải về 260 00:20:44,560 --> 00:20:47,480 vào thiết bị của họ? Okay. 261 00:20:47,480 --> 00:20:56,400 >> Chạy ./buggy1, nó sẽ nói lỗi Segmentation (core dumped), 262 00:20:56,400 --> 00:21:00,500 bất cứ lúc nào bạn nhận được một segfault, đó là một điều xấu. 263 00:21:00,500 --> 00:21:03,810 Trong trường hợp nào để bạn có được một segfault? 264 00:21:03,810 --> 00:21:08,210 [Sinh viên] dereferencing một con trỏ null. >> Yeah. Vì vậy, đó là một ví dụ. 265 00:21:08,210 --> 00:21:11,580 Dereferencing một con trỏ null bạn sẽ nhận được một segfault. 266 00:21:11,580 --> 00:21:16,720 Gì một segfault có nghĩa là bạn đang chạm vào bộ nhớ, bạn không nên chạm vào. 267 00:21:16,720 --> 00:21:21,350 Vì vậy, dereferencing một con trỏ null được chạm vào địa chỉ 0, 268 00:21:21,350 --> 00:21:28,060 và về cơ bản, tất cả các máy tính ngày nay nói rằng địa chỉ 0 là bộ nhớ bạn không nên chạm vào. 269 00:21:28,060 --> 00:21:31,920 Vì vậy, đó là lý do tại sao dereferencing kết quả một con trỏ null trong một segfault. 270 00:21:31,920 --> 00:21:37,210 Khi bạn xảy ra để không khởi tạo một con trỏ, sau đó nó có một giá trị rác, 271 00:21:37,210 --> 00:21:41,520 và do đó, khi bạn cố gắng để tới đích của nó, trong khả năng tất cả các bạn đang chạm vào bộ nhớ 272 00:21:41,520 --> 00:21:43,540 đó là trong giữa hư không. 273 00:21:43,540 --> 00:21:45,650 Nếu bạn xảy ra để có được may mắn và giá trị rác 274 00:21:45,650 --> 00:21:48,440 xảy ra để trỏ đến một nơi nào đó trên stack hoặc một cái gì đó, 275 00:21:48,440 --> 00:21:50,820 sau đó khi bạn dereference con trỏ mà bạn đã không được khởi tạo, 276 00:21:50,820 --> 00:21:52,730 không có gì sẽ đi sai. 277 00:21:52,730 --> 00:21:55,480 Nhưng nếu nó chỉ đến, nói, một nơi nào đó giữa stack và heap, 278 00:21:55,480 --> 00:21:59,850 hoặc nó chỉ chỉ để một nơi nào đó đã không được sử dụng bởi chương trình của bạn, 279 00:21:59,850 --> 00:22:02,240 sau đó bạn đang chạm vào bộ nhớ bạn không nên chạm vào và bạn segfault. 280 00:22:02,240 --> 00:22:06,370 Khi bạn viết một hàm đệ quy và nó recurses quá nhiều lần 281 00:22:06,370 --> 00:22:08,720 và ngăn xếp của bạn trở nên quá lớn và va chạm ngăn xếp vào những điều 282 00:22:08,720 --> 00:22:12,270 rằng nó không nên va chạm với, bạn đang chạm vào bộ nhớ, bạn không nên chạm vào, 283 00:22:12,270 --> 00:22:14,810 vì vậy bạn segfault. 284 00:22:14,810 --> 00:22:17,010 Đó là những gì một segfault. 285 00:22:17,010 --> 00:22:21,810 >> Đó cũng là lý do tương tự nếu bạn có một chuỗi như thế - 286 00:22:21,810 --> 00:22:23,930 chúng ta hãy quay trở lại với các chương trình trước. 287 00:22:23,930 --> 00:22:28,530 Trong hello.c-Tôi chỉ cần đi để làm một cái gì đó khác. 288 00:22:28,530 --> 00:22:33,770 char * s = "hello thế giới"; 289 00:22:33,770 --> 00:22:42,310 Nếu tôi sử dụng * s = một cái gì đó hoặc s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 do đó hãy hello, / hello, tại sao mà segfault? 291 00:22:48,410 --> 00:22:51,250 Tại sao điều này segfault? 292 00:22:55,660 --> 00:22:57,890 Những gì bạn sẽ mong đợi xảy ra? 293 00:22:57,890 --> 00:23:06,640 Nếu tôi đã làm printf ("% s \ n", s); những gì bạn mong chờ để được in? 294 00:23:06,640 --> 00:23:09,930 [Sinh viên] X hello. >> Yeah. 295 00:23:09,930 --> 00:23:15,140 Vấn đề là khi bạn khai báo một chuỗi như thế này, 296 00:23:15,140 --> 00:23:18,190 s là một con trỏ sẽ đi trên stack, 297 00:23:18,190 --> 00:23:25,880 và những gì s được trỏ đến chuỗi này được chứa trong bộ nhớ chỉ đọc. 298 00:23:25,880 --> 00:23:30,560 Vì vậy, chỉ cần bộ nhớ chỉ đọc tên, bạn sẽ nhận được ý tưởng 299 00:23:30,560 --> 00:23:33,010 rằng nếu bạn cố gắng thay đổi những gì trong bộ nhớ chỉ đọc, 300 00:23:33,010 --> 00:23:36,670 bạn đang làm một cái gì đó bạn không nên làm với bộ nhớ và bạn segfault. 301 00:23:36,670 --> 00:23:45,360 Điều này thực sự là một sự khác biệt lớn giữa char * s và char s []. 302 00:23:45,360 --> 00:23:48,790 Vì vậy, char s [], chuỗi này sẽ được đưa vào ngăn xếp, 303 00:23:48,790 --> 00:23:53,960 và ngăn xếp không phải là chỉ đọc, có nghĩa rằng điều này nên làm việc hoàn toàn tốt đẹp. 304 00:23:55,500 --> 00:23:57,370 Và nó. 305 00:23:57,370 --> 00:24:06,250 Hãy nhớ rằng khi tôi làm char * s = "hello thế giới!", Chính nó là trên stack 306 00:24:06,250 --> 00:24:10,390 nhưng s điểm đến một nơi khác, và rằng ở một nơi khác sẽ xảy ra là chỉ đọc. 307 00:24:10,390 --> 00:24:15,640 Nhưng char s [] chỉ là một cái gì đó trên stack. 308 00:24:17,560 --> 00:24:21,760 Vì vậy, đó là một ví dụ về một segfault xảy ra. 309 00:24:21,760 --> 00:24:27,820 >> Chúng ta đã thấy mà ./buggy1 dẫn đến một segfault. 310 00:24:27,820 --> 00:24:31,810 Về lý thuyết, bạn không nên nhìn vào buggy1.c ngay lập tức. 311 00:24:31,810 --> 00:24:35,170 Thay vào đó, chúng ta sẽ nhìn vào nó thông qua gdb. 312 00:24:35,170 --> 00:24:37,750 Chú ý rằng khi bạn nhận được Segmentation fault (core dumped), 313 00:24:37,750 --> 00:24:40,850 bạn nhận được tập tin này trên cốt lõi ở đây được gọi là. 314 00:24:40,850 --> 00:24:45,200 Nếu chúng ta ls-l, chúng ta sẽ thấy cốt lõi mà thường là một tập tin khá lớn. 315 00:24:45,200 --> 00:24:51,580 Đây là số lượng byte của tập tin, do đó, nó có vẻ như nó là 250-kilobyte. 316 00:24:51,580 --> 00:24:56,120 Lý do cho điều này là những gì các bãi chứa lõi thực sự là 317 00:24:56,120 --> 00:25:01,410 là khi chương trình của bạn bị treo, nhà nước của bộ nhớ chương trình của bạn 318 00:25:01,410 --> 00:25:05,230 chỉ được sao chép và dán vào tập tin này. 319 00:25:05,230 --> 00:25:07,270 Nó được bán phá giá vào tập tin đó. 320 00:25:07,270 --> 00:25:13,060 Chương trình này, trong khi nó đã được chạy, xảy ra để có một cách sử dụng bộ nhớ của khoảng 250 kilobyte, 321 00:25:13,060 --> 00:25:17,040 và vì vậy đó là những gì đã đổ vào tập tin này. 322 00:25:17,040 --> 00:25:23,630 Bây giờ bạn có thể nhìn vào tập tin đó nếu chúng ta làm gdb buggy1 cốt lõi. 323 00:25:23,630 --> 00:25:30,130 Chúng tôi chỉ có thể làm gdb buggy1, và sẽ chỉ bắt đầu gdb thường xuyên, 324 00:25:30,130 --> 00:25:33,800 sử dụng buggy1 là tập tin đầu vào của nó. 325 00:25:33,800 --> 00:25:38,260 Nhưng nếu bạn làm gdb buggy1 cốt lõi, sau đó nó đặc biệt sẽ bắt đầu lên gdb 326 00:25:38,260 --> 00:25:40,330 bằng cách nhìn vào tập tin đó cốt lõi. 327 00:25:40,330 --> 00:25:45,560 Và bạn nói buggy1 gdb phương tiện biết rằng tập tin lõi đến từ chương trình buggy1. 328 00:25:45,560 --> 00:25:49,580 Vì vậy, gdb buggy1 cốt lõi là sẽ mang lại cho chúng tôi ngay lập tức 329 00:25:49,580 --> 00:25:52,060 nơi mà chương trình đã xảy ra chấm dứt. 330 00:25:57,720 --> 00:26:02,340 Chúng ta thấy ở đây Chương trình kết thúc với 11 tín hiệu, phân đoạn lỗi. 331 00:26:02,340 --> 00:26:10,110 Chúng tôi tình cờ thấy một dòng, lắp ráp, mà có lẽ không phải là rất hữu ích. 332 00:26:10,110 --> 00:26:15,360 Nhưng nếu bạn gõ bt hoặc backtrace, đó sẽ là chức năng 333 00:26:15,360 --> 00:26:19,430 cung cấp cho chúng tôi danh sách các khung stack hiện tại của chúng tôi. 334 00:26:19,430 --> 00:26:23,150 Vì vậy, backtrace Có vẻ như chúng ta chỉ có hai khung stack. 335 00:26:23,150 --> 00:26:26,310 Đầu tiên là ngăn xếp khung chính của chúng tôi, 336 00:26:26,310 --> 00:26:29,810 và thứ hai là khung stack cho chức năng này mà chúng tôi xảy ra được trong, 337 00:26:29,810 --> 00:26:34,440 mà hình như chúng ta chỉ có mã lắp ráp cho. 338 00:26:34,440 --> 00:26:38,050 Vì vậy, chúng ta hãy quay trở lại vào chức năng chính của chúng tôi, 339 00:26:38,050 --> 00:26:42,300 và để làm điều đó chúng ta có thể làm frame 1, và tôi nghĩ rằng chúng tôi cũng có thể làm, 340 00:26:42,300 --> 00:26:45,160 nhưng tôi gần như không bao giờ làm - hoặc lên. Yeah. 341 00:26:45,160 --> 00:26:50,710 Lên và xuống. Up mang đến cho bạn một khung ngăn xếp, xuống mang đến cho bạn một khung stack. 342 00:26:50,710 --> 00:26:53,240 Tôi có xu hướng không bao giờ sử dụng. 343 00:26:53,240 --> 00:26:59,120 Tôi chỉ nói cụ thể 1 frame, được đi đến khung có nhãn 1. 344 00:26:59,120 --> 00:27:01,750 Frame 1 là sẽ mang lại cho chúng tôi vào khung chính stack, 345 00:27:01,750 --> 00:27:05,570 và nó nói ngay tại đây các dòng mã chúng tôi xảy ra được. 346 00:27:05,570 --> 00:27:07,950 Nếu chúng ta muốn thêm một vài dòng mã, chúng ta có thể nói danh sách, 347 00:27:07,950 --> 00:27:11,280 và đó sẽ cung cấp cho chúng tôi tất cả các dòng của mã xung quanh nó. 348 00:27:11,280 --> 00:27:13,360 Dòng segfaulted tại 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 đá", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Nếu nó không phải là rõ ràng nhưng bạn có thể nhận được trực tiếp từ đây chỉ bằng cách suy nghĩ lý do tại sao nó segfaulted. 351 00:27:24,130 --> 00:27:28,800 Nhưng chúng tôi có thể mang nó một bước xa hơn và nói, "Tại sao argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Hãy in argv [1], và nó trông giống như 0x0 của nó, đó là con trỏ null. 353 00:27:38,830 --> 00:27:44,750 Chúng tôi đang strcmping CS50 đá và vô giá trị, và đó là sẽ segfault. 354 00:27:44,750 --> 00:27:48,280 Và tại sao argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Sinh viên] Bởi vì chúng tôi không cung cấp cho bất kỳ đối số dòng lệnh. 356 00:27:51,280 --> 00:27:53,390 Yeah. Chúng tôi không cung cấp cho bất kỳ đối số dòng lệnh. 357 00:27:53,390 --> 00:27:58,460 Vì vậy, ./buggy1 được chỉ sẽ có argv [0] là ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Nó sẽ không có một argv [1], vì vậy đó là sẽ segfault. 359 00:28:02,100 --> 00:28:07,450 Nhưng nếu thay vì đó, tôi làm chỉ CS50, nó sẽ nói Bạn nhận được một D 360 00:28:07,450 --> 00:28:09,950 bởi vì đó là những gì nó phải làm. 361 00:28:09,950 --> 00:28:15,240 Nhìn vào buggy1.c, đó là nghĩa vụ in "Bạn nhận được một D" - 362 00:28:15,240 --> 00:28:20,820 Nếu argv [1] không "CS50 đá", "Bạn nhận được một D", khác "Bạn nhận được một A!" 363 00:28:20,820 --> 00:28:25,660 Vì vậy, nếu chúng ta muốn một, chúng tôi cần điều này để so sánh là đúng, 364 00:28:25,660 --> 00:28:28,710 điều đó có nghĩa là nó so sánh là 0. 365 00:28:28,710 --> 00:28:31,100 Vì vậy, argv [1] cần phải được "CS50 đá". 366 00:28:31,100 --> 00:28:35,660 Nếu bạn muốn làm điều đó trên dòng lệnh, bạn cần phải sử dụng \ để thoát khỏi không gian. 367 00:28:35,660 --> 00:28:41,690 Vì vậy, CS50 \ đá và Bạn nhận được một A! 368 00:28:41,690 --> 00:28:44,060 Nếu bạn không làm dấu gạch chéo ngược, tại sao điều này không làm việc? 369 00:28:44,060 --> 00:28:47,190 [Sinh viên] Đây là hai đối số khác nhau. >> Yeah. 370 00:28:47,190 --> 00:28:52,540 Argv [1] là có được CS50, và argv [2] là có được đá. Okay. 371 00:28:52,540 --> 00:28:56,470 >> Bây giờ ./buggy2 sẽ segfault một lần nữa. 372 00:28:56,470 --> 00:29:01,880 Thay vì mở nó với các tập tin cốt lõi của nó, chúng tôi sẽ chỉ mở ra buggy2 trực tiếp, 373 00:29:01,880 --> 00:29:05,000 do đó, gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Bây giờ nếu chúng ta chỉ cần chạy chương trình của chúng tôi, sau đó nó sẽ nói Chương trình đã nhận được tín hiệu SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 đó là segfault tín hiệu, và đây là nơi mà nó đã xảy ra xảy ra. 376 00:29:15,530 --> 00:29:21,250 Nhìn vào backtrace của chúng tôi, chúng tôi thấy rằng chúng tôi đã trong oh_no chức năng, 377 00:29:21,250 --> 00:29:23,900 được gọi là dinky chức năng, được gọi là bởi binky chức năng, 378 00:29:23,900 --> 00:29:26,460 được gọi là chính. 379 00:29:26,460 --> 00:29:31,680 Chúng tôi cũng có thể nhìn thấy các đối số cho các chức năng này. 380 00:29:31,680 --> 00:29:34,680 Đối số để dinky và binky 1. 381 00:29:34,680 --> 00:29:44,390 Nếu chúng ta liệt kê các chức năng oh_no, chúng ta thấy rằng oh_no chỉ làm char ** s = NULL; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Tại sao mà có thất bại? 384 00:29:54,330 --> 00:29:58,380 [Sinh viên] Bạn có thể không tới đích của con trỏ null? >> Yeah. 385 00:29:58,380 --> 00:30:06,090 Đây chỉ là nói s là NULL, bất kể nếu điều đó xảy ra là một char **, 386 00:30:06,090 --> 00:30:12,070 đó, tùy thuộc vào cách bạn giải thích nó, nó có thể là một con trỏ đến một con trỏ đến một chuỗi 387 00:30:12,070 --> 00:30:15,550 hoặc một mảng của chuỗi. 388 00:30:15,550 --> 00:30:21,430 Đó là s là NULL, do đó * s dereferencing một con trỏ null, 389 00:30:21,430 --> 00:30:24,800 và do đó, điều này sẽ sụp đổ. 390 00:30:24,800 --> 00:30:27,540 Đây là một trong những cách nhanh nhất bạn có thể có thể segfault. 391 00:30:27,540 --> 00:30:31,300 Nó chỉ cần khai báo một con trỏ null, và ngay lập tức segfaulting. 392 00:30:31,300 --> 00:30:34,570 Đó là những gì oh_no làm. 393 00:30:34,570 --> 00:30:43,400 Nếu chúng ta đi lên một khung hình, sau đó chúng tôi đang đi để có được vào các chức năng mà được gọi là oh_no. 394 00:30:43,400 --> 00:30:44,830 Tôi cần để làm điều đó xuống. 395 00:30:44,830 --> 00:30:48,610 Nếu bạn không nhập một câu lệnh và bạn chỉ cần nhấn Enter lần nữa, 396 00:30:48,610 --> 00:30:52,350 nó sẽ chỉ lặp lại các lệnh trước đó mà bạn chạy. 397 00:30:52,350 --> 00:30:56,610 Chúng tôi đang trong frame 1. 398 00:30:56,610 --> 00:31:04,650 Liệt kê khung này, chúng ta thấy ở đây là chức năng của chúng tôi. 399 00:31:04,650 --> 00:31:08,520 Bạn có thể nhấn danh sách một lần nữa, hoặc bạn có thể làm danh sách 20 và nó sẽ liệt kê nhiều hơn. 400 00:31:08,520 --> 00:31:13,640 Dinky chức năng nói rằng nếu tôi là 1, sau đó đi đến chức năng oh_no, 401 00:31:13,640 --> 00:31:15,960 khác đi đến chức năng Slinky. 402 00:31:15,960 --> 00:31:18,700 Và chúng ta biết i là 1 bởi vì chúng tôi xảy ra để xem ở đây 403 00:31:18,700 --> 00:31:22,560 dinky đã được gọi với các đối số 1. 404 00:31:22,560 --> 00:31:27,560 Hoặc bạn chỉ có thể làm print i và nó sẽ nói i là 1. 405 00:31:27,560 --> 00:31:33,770 Chúng tôi đang trong dinky, và nếu chúng ta đi lên một khung, chúng ta biết chúng ta sẽ kết thúc trong binky. 406 00:31:33,770 --> 00:31:36,600 Up. Bây giờ chúng tôi đang trong binky. 407 00:31:36,600 --> 00:31:41,340 Danh sách chức năng này - danh sách từ trước khi một nửa cắt cho tôi đi - 408 00:31:41,340 --> 00:31:52,670 nó bắt đầu như thể tôi là 0, sau đó chúng ta sẽ gọi nó oh_no, khác gọi dinky. 409 00:31:52,670 --> 00:31:57,000 Chúng tôi biết tôi đã được 1, do đó nó được gọi là dinky. 410 00:31:57,000 --> 00:32:05,030 Và bây giờ chúng tôi đang trở lại trong chính, và chính là chỉ cần đi int i = rand () 3%; 411 00:32:05,030 --> 00:32:08,790 Đó chỉ là sẽ cung cấp cho bạn một số ngẫu nhiên đó là là 0, 1, hoặc 2. 412 00:32:08,790 --> 00:32:12,780 Nó sẽ gọi binky với con số đó, và nó sẽ trở về 0. 413 00:32:12,780 --> 00:32:16,700 Nhìn này, 414 00:32:16,700 --> 00:32:19,880 chỉ cần đi bộ qua các chương trình bằng tay mà không cần chạy nó ngay lập tức, 415 00:32:19,880 --> 00:32:25,400 bạn sẽ thiết lập một điểm break ở chính, có nghĩa là khi chúng ta chạy chương trình 416 00:32:25,400 --> 00:32:31,020 chương trình của bạn chạy cho đến khi nó chạm một điểm break. 417 00:32:31,020 --> 00:32:35,450 Vì vậy, chạy chương trình, nó sẽ chạy và sau đó nó sẽ được tung ra chức năng chính và ngừng chạy. 418 00:32:35,450 --> 00:32:44,700 Bây giờ chúng ta đang ở trong chính, và bước tiếp theo sẽ đưa chúng ta đến dòng tiếp theo của mã. 419 00:32:44,700 --> 00:32:47,050 Bạn có thể làm bước tiếp theo. 420 00:32:47,050 --> 00:32:51,800 Đánh tiếp theo, bây giờ tôi đã được thiết lập để rand ()% 3, vì vậy chúng ta có thể in giá trị của i, 421 00:32:51,800 --> 00:32:55,280 và nó sẽ nói i là 1. 422 00:32:55,280 --> 00:32:58,110 Bây giờ nó không thành vấn đề cho dù chúng tôi sử dụng tiếp theo hoặc bước. 423 00:32:58,110 --> 00:33:01,000 Tôi đoán nó quan trọng trước đó, nhưng chúng tôi muốn sử dụng tiếp theo. 424 00:33:01,000 --> 00:33:06,000 Nếu chúng ta sử dụng bước, chúng ta bước vào chức năng, nhiệm vụ, có nghĩa là nhìn vào điều thực tế 425 00:33:06,000 --> 00:33:07,940 đang xảy ra bên trong của binky. 426 00:33:07,940 --> 00:33:10,510 Nếu chúng ta sử dụng tiếp theo, sau đó nó có nghĩa là đi qua các chức năng 427 00:33:10,510 --> 00:33:14,070 và chỉ cần đi vào dòng tiếp theo của mã trong chức năng chính của chúng tôi. 428 00:33:14,070 --> 00:33:17,900 Ở ngay trên dòng này, tôi đã được ở nơi mà nó nói rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 nếu tôi đã làm bước, nó sẽ đi vào thực hiện của rand 430 00:33:21,320 --> 00:33:25,110 và nhìn vào những gì đang xảy ra ở đó, và tôi có thể bước qua chức năng rand. 431 00:33:25,110 --> 00:33:26,920 Nhưng tôi không quan tâm về các chức năng rand. 432 00:33:26,920 --> 00:33:30,190 Tôi chỉ muốn đi đến dòng tiếp theo của mã trong main, vì vậy tôi sử dụng tiếp theo. 433 00:33:30,190 --> 00:33:35,800 Nhưng bây giờ tôi quan tâm về các chức năng binky, vì vậy tôi muốn bước vào đó. 434 00:33:35,800 --> 00:33:37,730 Bây giờ tôi đang trong binky. 435 00:33:37,730 --> 00:33:42,040 Dòng đầu tiên của mã sẽ nói if (i == 0), tôi đi một bước, 436 00:33:42,040 --> 00:33:44,930 chúng ta thấy chúng ta kết thúc tại dinky. 437 00:33:44,930 --> 00:33:51,620 Nếu chúng ta điều danh sách, chúng tôi thấy rằng nó kiểm tra là i = 0. 438 00:33:51,620 --> 00:33:55,470 tôi không phải là bằng 0, do đó, nó đến điều kiện khác, 439 00:33:55,470 --> 00:33:59,540 đó là sẽ gọi dinky (i). 440 00:33:59,540 --> 00:34:04,030 Bạn có thể bị lẫn lộn. 441 00:34:04,030 --> 00:34:07,380 Nếu bạn chỉ cần nhìn vào những dòng trực tiếp, bạn có thể nghĩ rằng nếu (i == 0), 442 00:34:07,380 --> 00:34:10,800 okay, sau đó tôi đã tiến một bước và bây giờ tôi tại dinky (i), 443 00:34:10,800 --> 00:34:14,120 bạn có thể nghĩ rằng phải có nghĩa là i = 0 hoặc một cái gì đó. 444 00:34:14,120 --> 00:34:18,980 Nó chỉ có nghĩa là nó biết nó có thể dính trực tiếp đến dinky dòng (i). 445 00:34:18,980 --> 00:34:23,300 Bởi vì tôi không phải là 0, bước tiếp theo là sẽ không kết thúc tại người nào khác. 446 00:34:23,300 --> 00:34:26,239 Khác không phải là một dòng nó sẽ dừng lại ở. 447 00:34:26,239 --> 00:34:31,570 Nó chỉ là để đi đến dòng kế tiếp, nó thực sự có thể thực hiện, đó là dinky (i). 448 00:34:31,570 --> 00:34:36,090 Bước vào dinky (i), chúng ta thấy if (i == 1). 449 00:34:36,090 --> 00:34:42,670 Chúng tôi không biết i = 1, do đó, khi chúng ta bước, chúng ta biết chúng ta sẽ kết thúc trong oh_no 450 00:34:42,670 --> 00:34:46,489 bởi vì i = 1 gọi oh_no chức năng, mà bạn có thể bước vào, 451 00:34:46,489 --> 00:34:52,969 đó là sẽ thiết lập char ** s = NULL và ngay lập tức "bùng nổ". 452 00:34:54,270 --> 00:34:59,690 Và sau đó thực sự nhìn vào việc thực hiện các buggy2, 453 00:34:59,690 --> 00:35:04,590 này, tôi chỉ nhận được một số ngẫu nhiên - 0, 1, hoặc 2 - gọi binky, 454 00:35:04,590 --> 00:35:10,610 nếu tôi là 0 nó gọi oh_no, khác nó gọi dinky, mà đi kèm ở đây. 455 00:35:10,610 --> 00:35:18,100 Nếu tôi là 1, gọi oh_no, khác gọi Slinky, đến đây, 456 00:35:18,100 --> 00:35:20,460 nếu tôi là 2, gọi oh_no. 457 00:35:20,460 --> 00:35:24,720 Tôi thậm chí không nghĩ rằng có một cách - 458 00:35:24,720 --> 00:35:30,030 Có ai nhìn thấy một cách để làm cho một chương trình mà sẽ không segfault? 459 00:35:30,030 --> 00:35:37,530 Bởi vì trừ khi tôi đang thiếu một cái gì đó, nếu tôi là 0, bạn ngay lập tức sẽ segfault, 460 00:35:37,530 --> 00:35:41,250 khác bạn đi đến một chức năng mà nếu tôi là 1 bạn segfault, 461 00:35:41,250 --> 00:35:44,540 khác bạn đi đến một chức năng mà nếu tôi là 2 bạn segfault. 462 00:35:44,540 --> 00:35:46,810 Vì vậy, không có vấn đề gì bạn làm, bạn segfault. 463 00:35:46,810 --> 00:35:52,380 >> Tôi đoán một cách để sửa chữa nó sẽ là thay vì làm char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 bạn có thể malloc không gian cho chuỗi đó. 465 00:35:55,610 --> 00:36:04,230 Chúng tôi có thể làm malloc (sizeof) - sizeof những gì? 466 00:36:09,910 --> 00:36:15,190 [Sinh viên] (char) * 5? >> Điều này có vẻ phải không? 467 00:36:15,190 --> 00:36:21,060 Tôi giả định này sẽ làm việc nếu tôi thực sự chạy nó, nhưng nó không phải là những gì tôi đang tìm kiếm. 468 00:36:24,400 --> 00:36:32,940 Nhìn vào các loại s. Hãy thêm int *, do đó, int * x. 469 00:36:32,940 --> 00:36:35,600 Tôi sẽ làm malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Hoặc nếu tôi muốn có một mảng của 5, tôi sẽ làm (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Điều gì sẽ xảy ra nếu tôi có một ** int? 472 00:36:46,260 --> 00:36:49,140 Tôi sẽ malloc? 473 00:36:49,140 --> 00:36:53,510 [Sinh viên] Kích thước của con trỏ. >> Yeah. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 Cùng một điều ở đây. 475 00:36:56,960 --> 00:37:01,280 Tôi muốn (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 Điều này sẽ phân bổ không gian cho con trỏ trỏ "BOOM". 477 00:37:12,840 --> 00:37:15,330 Tôi không cần phải phân bổ không gian cho "BOOM" 478 00:37:15,330 --> 00:37:17,210 bởi vì điều này về cơ bản là tương đương với những gì tôi đã nói trước 479 00:37:17,210 --> 00:37:20,870 char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "Bùng nổ" đã tồn tại. Nó xảy ra tồn tại trong khu vực chỉ đọc của bộ nhớ. 481 00:37:27,950 --> 00:37:35,200 Nhưng nó đã tồn tại, có nghĩa là dòng mã này, nếu s là một char **, 482 00:37:35,200 --> 00:37:43,900 * s là một char * và bạn đang thiết lập này char * để trỏ đến "bùng nổ". 483 00:37:43,900 --> 00:37:50,040 Nếu tôi muốn sao chép "BOOM" vào s, sau đó tôi sẽ cần phải phân bổ không gian cho s. 484 00:37:55,170 --> 00:38:03,900 Tôi sẽ làm * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Tại sao 5? 486 00:38:06,210 --> 00:38:10,860 Tại sao không 4? Nó trông giống như "BOOM" là 4 ký tự. >> [Sinh viên] ký tự null. 487 00:38:10,860 --> 00:38:14,580 Yeah. Tất cả các chuỗi của bạn sẽ cần các ký tự null. 488 00:38:14,580 --> 00:38:23,590 Bây giờ tôi có thể làm một cái gì đó như strcat chức năng sao chép một chuỗi là gì? 489 00:38:23,590 --> 00:38:28,520 [Sinh viên] CPY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 người đàn ông strcpy. 491 00:38:36,120 --> 00:38:39,590 Vì vậy, strcpy hoặc strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy là một chút an toàn hơn kể từ khi bạn có thể xác định chính xác có bao nhiêu nhân vật, 493 00:38:43,410 --> 00:38:46,190 nhưng ở đây nó không quan trọng bởi vì chúng tôi biết. 494 00:38:46,190 --> 00:38:50,340 Vì vậy, strcpy và tìm trong các đối số. 495 00:38:50,340 --> 00:38:53,100 Đối số đầu tiên là điểm đến của chúng tôi. 496 00:38:53,100 --> 00:38:56,770 Số thứ hai là nguồn của chúng tôi. 497 00:38:56,770 --> 00:39:10,310 Chúng tôi sẽ sao chép vào * điểm đến của chúng tôi s con trỏ "BOOM". 498 00:39:10,310 --> 00:39:19,820 Tại sao bạn có thể muốn làm điều này với một strcpy thay vì chỉ là những gì chúng tôi đã có trước khi 499 00:39:19,820 --> 00:39:22,800 * s = "bùng nổ"? 500 00:39:22,800 --> 00:39:28,630 Có một lý do bạn có thể muốn làm điều này, nhưng lý do đó là những gì? 501 00:39:28,630 --> 00:39:31,940 [Sinh viên] Nếu bạn muốn thay đổi một cái gì đó trong "BOOM". >> Yeah. 502 00:39:31,940 --> 00:39:37,950 Bây giờ tôi có thể làm một cái gì đó như s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 vì s điểm vào đống và không gian trên heap là được trỏ đến 504 00:39:48,190 --> 00:39:52,320 là một con trỏ đến nhiều không gian hơn trên heap, được lưu trữ "BOOM". 505 00:39:52,320 --> 00:39:55,150 Vì vậy, bản sao của "BOOM" này đang được lưu trữ trong heap. 506 00:39:55,150 --> 00:39:58,780 Về mặt kỹ thuật có hai bản sao của "bùng nổ" trong chương trình của chúng tôi. 507 00:39:58,780 --> 00:40:03,500 Có một trong những đầu tiên đó chỉ là do hằng số này "BOOM" chuỗi, 508 00:40:03,500 --> 00:40:09,250 và bản sao thứ hai của "BOOM", strcpy tạo ra các bản sao của "bùng nổ". 509 00:40:09,250 --> 00:40:13,100 Tuy nhiên, các bản sao của "BOOM" được lưu trữ trên heap, và đống bạn đang miễn phí để thay đổi. 510 00:40:13,100 --> 00:40:17,250 Heap là không chỉ đọc, do đó có nghĩa là s [0] 511 00:40:17,250 --> 00:40:20,500 sẽ cho phép bạn thay đổi giá trị của "BOOM". 512 00:40:20,500 --> 00:40:23,130 Nó sẽ cho phép bạn thay đổi các ký tự. 513 00:40:23,130 --> 00:40:26,640 >> Câu hỏi? 514 00:40:27,740 --> 00:40:29,290 Okay. 515 00:40:29,290 --> 00:40:35,500 >> Chuyển sang buggy3, chúng ta hãy gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Chúng tôi chỉ cần chạy nó và chúng ta thấy chúng tôi có được một segfault. 517 00:40:39,840 --> 00:40:46,550 Nếu chúng ta backtrace, chỉ có hai chức năng. 518 00:40:46,550 --> 00:40:52,970 Nếu chúng ta đi vào chức năng chính của chúng tôi, chúng tôi thấy rằng chúng tôi segfaulted tại dòng này. 519 00:40:52,970 --> 00:41:00,180 Vì vậy, chỉ cần nhìn vào dòng này, for (int line = 0; fgets công cụ này không NULL không bằng nhau; 520 00:41:00,180 --> 00:41:03,770 dòng + +). 521 00:41:03,770 --> 00:41:08,010 Khung trước của chúng tôi được gọi là _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Bạn sẽ thấy rằng rất nhiều với tích hợp chức năng C, 523 00:41:10,720 --> 00:41:15,350 khi bạn nhận được segfault, sẽ có tên chức năng thực sự khó hiểu 524 00:41:15,350 --> 00:41:18,090 như thế này _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Nhưng điều đó đang xảy ra liên quan đến cuộc gọi này fgets. 526 00:41:21,770 --> 00:41:25,850 Một nơi nào đó bên trong ở đây, chúng tôi được segfaulting. 527 00:41:25,850 --> 00:41:30,340 Nếu chúng ta nhìn vào các đối số fgets, chúng ta có thể in đệm. 528 00:41:30,340 --> 00:41:41,180 Hãy in như là một - Ồ, không. 529 00:41:48,980 --> 00:41:51,900 In không phải là đi làm việc chính xác như tôi muốn nó. 530 00:41:55,460 --> 00:41:58,000 Chúng ta hãy nhìn vào chương trình thực tế. 531 00:42:02,200 --> 00:42:09,640 Đệm là một mảng ký tự. Đó là một mảng ký tự 128 ký tự. 532 00:42:09,640 --> 00:42:14,980 Vì vậy, khi tôi nói đệm in, nó sẽ in 128 ký tự, 533 00:42:14,980 --> 00:42:18,300 mà tôi đoán là gì được mong đợi. 534 00:42:18,300 --> 00:42:21,390 Những gì tôi đang tìm kiếm là in địa chỉ của bộ đệm, 535 00:42:21,390 --> 00:42:23,680 nhưng điều đó không thực sự cho tôi rất nhiều. 536 00:42:23,680 --> 00:42:30,770 Vì vậy, khi tôi xảy ra để nói lên ở đây x đệm, nó cho thấy tôi 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 , nếu bạn nhớ từ trước đó hoặc một số điểm, Oxbffff có xu hướng trở thành khu vực stack-ish. 538 00:42:38,690 --> 00:42:46,020 Ngăn xếp có xu hướng để bắt đầu một nơi nào đó dưới 0xc000. 539 00:42:46,020 --> 00:42:51,890 Chỉ cần nhìn thấy địa chỉ này, tôi biết rằng bộ đệm đang xảy ra trên stack. 540 00:42:51,890 --> 00:43:04,500 Khởi động lại chương trình của tôi, chạy, lên, đệm, chúng ta đã thấy là chuỗi các ký tự này 541 00:43:04,500 --> 00:43:06,530 có khá nhiều vô nghĩa. 542 00:43:06,530 --> 00:43:12,270 Sau đó, in tập tin, tập tin trông giống như những gì? 543 00:43:15,120 --> 00:43:17,310 [Sinh viên] Null. >> Yeah. 544 00:43:17,310 --> 00:43:22,610 Tập tin là một * FILE loại, do đó, nó là một con trỏ, 545 00:43:22,610 --> 00:43:26,610 và giá trị của con trỏ đó là null. 546 00:43:26,610 --> 00:43:33,240 Vì vậy, fgets sẽ cố gắng để đọc từ con trỏ đó một cách gián tiếp, 547 00:43:33,240 --> 00:43:37,320 nhưng để có thể truy cập vào con trỏ, nó phải tới đích của nó. 548 00:43:37,320 --> 00:43:40,550 Hoặc, để truy cập vào những gì nó nên được trỏ đến, nó dereferences nó. 549 00:43:40,550 --> 00:43:43,810 Vì vậy, nó dereferencing một con trỏ null và nó segfaults. 550 00:43:46,600 --> 00:43:48,730 Tôi đã có thể khởi động lại nó ở đó. 551 00:43:48,730 --> 00:43:52,170 Nếu chúng ta phá vỡ tại điểm chính của chúng tôi và chạy, 552 00:43:52,170 --> 00:43:57,320 dòng đầu tiên của mã là char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 Điều đó sẽ cho một gợi ý khá lớn là lý do tại sao chương trình này không thành công. 554 00:44:00,870 --> 00:44:06,080 Gõ tiếp theo mang lại cho tôi đến dòng kế tiếp, nơi tôi mở tập tin này, 555 00:44:06,080 --> 00:44:11,140 và sau đó tôi ngay lập tức nhận được vào đường dây của chúng tôi, một khi tôi nhấn tiếp theo, nó sẽ segfault. 556 00:44:11,140 --> 00:44:16,880 Có ai muốn ném ra một lý do tại sao chúng tôi có thể được segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Sinh viên] File không tồn tại. >> Yeah. 558 00:44:19,130 --> 00:44:22,250 Điều này được coi là một gợi ý 559 00:44:22,250 --> 00:44:29,570 rằng bất cứ khi nào bạn mở một tập tin, bạn cần kiểm tra rằng tập tin thực sự tồn tại. 560 00:44:29,570 --> 00:44:31,510 Vì vậy, ở đây, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Khi chúng tôi fopen tên tập tin để đọc, sau đó chúng tôi cần phải nói 562 00:44:34,700 --> 00:44:45,870 (file == NULL) và nói printf ("File không tồn tại!" 563 00:44:45,870 --> 00:44:56,340 hoặc tốt hơn nữa - filename); trả lại 1; 564 00:44:56,340 --> 00:45:00,300 Vì vậy, bây giờ chúng tôi kiểm tra để xem nếu nó là NULL 565 00:45:00,300 --> 00:45:03,930 trước khi thực sự tiếp tục và cố gắng để đọc từ tập tin đó. 566 00:45:03,930 --> 00:45:08,800 Chúng ta có thể làm lại nó chỉ để thấy rằng các công trình. 567 00:45:11,020 --> 00:45:14,970 Tôi có ý định để bao gồm một dòng mới. 568 00:45:21,090 --> 00:45:25,290 Vì vậy, bây giờ nonexistent.txt không tồn tại. 569 00:45:26,890 --> 00:45:30,040 Bạn nên luôn luôn kiểm tra cho các loại điều này. 570 00:45:30,040 --> 00:45:33,870 Bạn nên luôn luôn kiểm tra xem nếu fopen trả về NULL. 571 00:45:33,870 --> 00:45:38,170 Bạn nên luôn luôn kiểm tra để chắc chắn rằng malloc không trở về NULL, 572 00:45:38,170 --> 00:45:41,410 hoặc người nào khác bạn segfault. 573 00:45:42,200 --> 00:45:45,930 >> Bây giờ buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Chạy. Tôi đoán này được chờ đợi đầu vào hoặc Looping có thể vô hạn. 575 00:45:58,440 --> 00:46:01,870 Có, nó là vòng lặp vô hạn. 576 00:46:01,870 --> 00:46:05,560 Vì vậy, buggy4. Dường như chúng ta đang vô hạn vòng lặp. 577 00:46:05,560 --> 00:46:12,590 Chúng tôi có thể phá vỡ chính, chạy chương trình của chúng tôi. 578 00:46:12,590 --> 00:46:20,180 Gdb, miễn là chữ viết tắt mà bạn sử dụng là rõ ràng 579 00:46:20,180 --> 00:46:23,420 hoặc chữ viết tắt đặc biệt mà họ cung cấp cho bạn, 580 00:46:23,420 --> 00:46:29,020 sau đó bạn có thể sử dụng n để sử dụng thay vì phải gõ tiếp theo tất cả các cách. 581 00:46:29,020 --> 00:46:33,730 Và bây giờ tôi đã trúng n một lần, tôi chỉ có thể nhấn Enter để tiếp tục đi tiếp theo 582 00:46:33,730 --> 00:46:36,640 thay vì phải nhấn n Enter, n Enter, n Nhập. 583 00:46:36,640 --> 00:46:44,630 Có vẻ như tôi là trong một số loại cho vòng lặp đó là thiết lập mảng [i] đến 0. 584 00:46:44,630 --> 00:46:50,510 Có vẻ như tôi không bao giờ phá vỡ của vòng lặp for. 585 00:46:50,510 --> 00:46:54,780 Nếu tôi in tôi, vì vậy tôi là 2, sau đó tôi sẽ đi tiếp theo. 586 00:46:54,780 --> 00:46:59,250 Tôi sẽ in i, i là 3, sau đó tôi sẽ đi tiếp theo. 587 00:46:59,250 --> 00:47:05,360 Tôi sẽ in i và i là 3. Tiếp theo, in i, i là 4. 588 00:47:05,360 --> 00:47:14,520 Trên thực tế, in ấn sizeof (array), do đó, kích thước của mảng là 20. 589 00:47:16,310 --> 00:47:32,870 Nhưng có vẻ như có một số lệnh gdb đặc biệt để đi cho đến khi một cái gì đó sẽ xảy ra. 590 00:47:32,870 --> 00:47:37,620 Nó giống như thiết lập một điều kiện về giá trị của biến. Nhưng tôi không nhớ nó là gì. 591 00:47:37,620 --> 00:47:44,100 Vì vậy, nếu chúng ta tiếp tục đi - 592 00:47:44,100 --> 00:47:47,120 Bạn đang nói gì vậy? Những gì bạn đã mang đến? 593 00:47:47,120 --> 00:47:50,500 [Sinh viên] hiển thị tôi thêm - >> Vâng. Vì vậy, hiển thị tôi có thể giúp. 594 00:47:50,500 --> 00:47:54,530 Nếu chúng ta chỉ hiển thị i, nó sẽ đưa ra ở đây những gì giá trị của i là 595 00:47:54,530 --> 00:47:56,470 vì vậy tôi không phải in nó ra mỗi lần. 596 00:47:56,470 --> 00:48:02,930 Nếu chúng ta chỉ tiếp tục đi tiếp theo, chúng ta thấy 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. 597 00:48:02,930 --> 00:48:08,530 Một cái gì đó khủng khiếp sai, và tôi đang được đặt lại là 0. 598 00:48:13,330 --> 00:48:22,220 Nhìn vào buggy4.c, chúng ta thấy tất cả những điều đó xảy ra là int array [5]; 599 00:48:22,220 --> 00:48:26,200 (i = 0; i <= sizeof (array); i + +) 600 00:48:26,200 --> 00:48:28,550 mảng [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Gì chúng ta thấy đó là sai ở đây? 602 00:48:31,390 --> 00:48:39,480 Là một gợi ý, khi tôi đã làm gdb buggy4 - hãy phá vỡ chính, chạy - 603 00:48:39,480 --> 00:48:45,980 Tôi đã in sizeof (array) chỉ để xem những gì điều kiện là nơi cuối cùng tôi đã thoát ra khỏi. 604 00:48:47,690 --> 00:48:51,100 Tôi đang ở đâu? Tôi đã chạy? 605 00:48:51,100 --> 00:48:54,280 Tôi đã không tuyên bố. 606 00:48:54,280 --> 00:48:58,680 Vì vậy, in sizeof (array) và là 20, 607 00:48:58,680 --> 00:49:06,690 trong đó dự kiến ​​kể từ mảng của tôi là có kích thước 5 và nó gồm 5 số nguyên, 608 00:49:06,690 --> 00:49:12,410 do đó, toàn bộ điều nên được 5 * sizeof (int) byte, sizeof (int) có xu hướng là 4. 609 00:49:12,410 --> 00:49:14,780 Vì vậy, sizeof (array) là 20. 610 00:49:14,780 --> 00:49:17,420 Điều này nên được? 611 00:49:17,420 --> 00:49:21,720 [Sinh viên] Phân theo sizeof (int). >> Yeah, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Dường như vẫn còn có một vấn đề ở đây. Tôi nghĩ rằng điều này chỉ nên được < 613 00:49:30,630 --> 00:49:36,960 vì nó khá nhiều luôn luôn 00:49:44,860 Bây giờ chúng ta hãy suy nghĩ về lý do tại sao điều này đã thực sự bị hỏng. 615 00:49:44,860 --> 00:49:53,370 Có ai đã đoán tại sao tôi đặt lại là 0 thông qua mỗi lần lặp của vòng lặp? 616 00:50:01,300 --> 00:50:09,350 Điều duy nhất bên trong đang xảy ra là mảng [i] được thiết lập là 0. 617 00:50:09,350 --> 00:50:15,350 Vì vậy, bằng cách nào đó, dòng mã này đang gây ra int của chúng tôi được thiết lập là 0. 618 00:50:16,730 --> 00:50:23,130 [Sinh viên] Nó có thể được bởi vì nó ghi đè bộ nhớ của phần này của tôi 619 00:50:23,130 --> 00:50:27,970 khi nó nghĩ rằng nó là phần tử tiếp theo của mảng? >> [Bowden]. 620 00:50:27,970 --> 00:50:33,880 Khi chúng tôi đang đi xa hơn vào cuối mảng của chúng tôi, 621 00:50:33,880 --> 00:50:39,870 bằng cách nào đó mà không gian mà chúng ta đang trọng là trọng giá trị của i. 622 00:50:39,870 --> 00:50:48,030 Và như vậy nếu chúng ta nhìn vào buggy4, phá vỡ chính, chạy, 623 00:50:48,030 --> 00:50:53,120 hãy in địa chỉ của tôi. 624 00:50:53,120 --> 00:50:57,280 Có vẻ như đó là bffff124. 625 00:50:57,280 --> 00:51:03,930 Bây giờ chúng ta hãy in địa chỉ của mảng [0]. 110. 626 00:51:03,930 --> 00:51:06,290 [1] 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. array [5] là bfff124. 629 00:51:14,530 --> 00:51:26,990 Vì vậy, array [5] có cùng một địa chỉ như tôi, có nghĩa là mảng đó [5] là tôi. 630 00:51:26,990 --> 00:51:30,720 Nếu họ có cùng một địa chỉ, họ là những điều tương tự. 631 00:51:30,720 --> 00:51:38,410 Vì vậy, khi chúng tôi đặt array [5] đến 0, chúng tôi đang thiết lập i đến 0. 632 00:51:38,410 --> 00:51:46,070 Và nếu bạn nghĩ về điều này trong các điều khoản của ngăn xếp, 633 00:51:46,070 --> 00:51:55,590 int i được khai báo đầu tiên, có nghĩa là tôi nhận được một số không gian trên stack. 634 00:51:55,590 --> 00:52:04,730 Sau đó, array [5] được giao, do đó sau đó 20 byte được cấp phát trên stack. 635 00:52:04,730 --> 00:52:08,400 Vì vậy, tôi được phân bổ đầu tiên, sau đó 20 byte này được phân bổ. 636 00:52:08,400 --> 00:52:11,400 Vì vậy, tôi sẽ xảy ra ngay trước khi mảng, 637 00:52:11,400 --> 00:52:19,230 và vì cách, giống như tôi đã nói tuần trước, nơi mà kỹ thuật ngăn xếp phát triển xuống, 638 00:52:19,230 --> 00:52:28,520 khi bạn chỉ mục vào một mảng, chúng tôi được đảm bảo rằng vị trí 0 trong mảng 639 00:52:28,520 --> 00:52:31,970 luôn luôn xảy ra trước khi vị trí đầu tiên trong mảng. 640 00:52:31,970 --> 00:52:35,900 Đây là loại như thế nào tôi vẽ nó tuần trước. 641 00:52:35,900 --> 00:52:42,210 Chú ý rằng ở phía dưới, chúng tôi có địa chỉ 0 và ở đầu, chúng tôi có địa chỉ Max. 642 00:52:42,210 --> 00:52:44,880 Ngăn xếp luôn phát triển. 643 00:52:48,100 --> 00:52:53,500 Hãy nói rằng chúng tôi phân bổ i. 644 00:52:53,500 --> 00:52:59,680 Chúng tôi phân bổ số nguyên i, có nghĩa là chúng ta hãy chỉ nói lên ở đây số nguyên i được phân bổ. 645 00:52:59,680 --> 00:53:06,420 Sau đó, chúng tôi phân bổ mảng của chúng tôi gồm 5 số nguyên, có nghĩa là nằm bên dưới, 646 00:53:06,420 --> 00:53:11,230 kể từ khi ngăn xếp được phát triển, 5 số nguyên được phân bổ. 647 00:53:11,230 --> 00:53:15,900 Nhưng vì mảng làm việc như thế nào, chúng tôi đảm bảo rằng vị trí đầu tiên trong mảng 648 00:53:15,900 --> 00:53:22,260 luôn luôn có một địa chỉ ít hơn điều thứ hai trong mảng. 649 00:53:22,260 --> 00:53:28,270 Vì vậy, vị trí 0 mảng luôn luôn có thể xảy ra đầu tiên trong bộ nhớ, 650 00:53:28,270 --> 00:53:30,700 trong khi mảng vị trí số 1 đã xảy ra sau đó 651 00:53:30,700 --> 00:53:33,310 và một mảng vị trí thứ 2 có thể xảy ra sau đó, 652 00:53:33,310 --> 00:53:37,900 điều đó có nghĩa rằng 0 vị trí mảng sẽ xảy ra ở đâu đó xuống đây, 653 00:53:37,900 --> 00:53:40,690 mảng vị trí 1 sẽ xảy ra ở trên đó 654 00:53:40,690 --> 00:53:45,530 bởi vì di chuyển lên có nghĩa là địa chỉ cao hơn kể từ khi địa chỉ tối đa là ở đây. 655 00:53:45,530 --> 00:53:50,490 Vì vậy, array [0] xuống đây, mảng [1] lên ở đây, array [2] lên ở đây, mảng [3] ở đây. 656 00:53:50,490 --> 00:53:55,620 Chú ý trước khi chúng tôi phân bổ số nguyên i tất cả các con đường lên đây, 657 00:53:55,620 --> 00:54:01,040 khi chúng ta tiến xa hơn và sâu hơn vào mảng của chúng tôi, chúng tôi đang nhận được gần hơn và gần gũi hơn với số nguyên của chúng tôi i. 658 00:54:01,040 --> 00:54:07,640 Nó chỉ như vậy sẽ xảy ra rằng mảng [5], đó là một vị trí vượt ra ngoài mảng của chúng tôi, 659 00:54:07,640 --> 00:54:13,010 chính xác nơi mà số nguyên i xảy ra được phân bổ. 660 00:54:13,010 --> 00:54:16,920 Vì vậy, đó là điểm mà chúng tôi tình cờ được nhấn không gian trên stack 661 00:54:16,920 --> 00:54:21,680 được phân bổ cho số nguyên i, và chúng ta đang cài đặt mà đến 0. 662 00:54:21,680 --> 00:54:26,160 >> Đó là làm thế nào mà các công trình. Câu hỏi? Yeah. 663 00:54:26,160 --> 00:54:30,710 [Sinh viên] Không bao giờ tâm trí. Okay. 664 00:54:30,710 --> 00:54:33,090 [Sinh viên] Làm thế nào để bạn tránh những loại lỗi? 665 00:54:33,090 --> 00:54:41,190 Những loại lỗi? Không sử dụng C là ngôn ngữ lập trình của bạn. 666 00:54:41,190 --> 00:54:45,840 Sử dụng một ngôn ngữ đó có mảng giới hạn kiểm tra. 667 00:54:45,840 --> 00:54:55,900 Miễn là bạn đang cẩn thận, bạn chỉ cần để tránh đi qua các giới hạn của mảng của bạn. 668 00:54:55,900 --> 00:54:58,300 [Sinh viên] Vì vậy, ở đây khi chúng tôi đi qua các giới hạn của mảng của bạn 669 00:54:58,300 --> 00:55:01,840 Bowden] Đó là nơi mà mọi thứ bắt đầu đi sai. >> [Sinh viên] Oh, okay. 670 00:55:01,840 --> 00:55:05,730 Miễn là bạn ở trong cấp phát bộ nhớ cho mảng của bạn, bạn đã đúng. 671 00:55:05,730 --> 00:55:12,400 Nhưng C không có kiểm tra lỗi. Nếu tôi làm mảng [1000], nó sẽ sẵn sàng chỉ cần thay đổi bất cứ điều gì xảy ra - 672 00:55:12,400 --> 00:55:16,500 Nó đi vào đầu của mảng, sau đó nó đi 1000 vị trí sau và đặt nó là 0. 673 00:55:16,500 --> 00:55:20,000 Nó không làm bất kỳ kiểm tra rằng oh, điều này không thực sự có 1000 điều trong đó. 674 00:55:20,000 --> 00:55:22,750 1000 là cách xa hơn những gì tôi nên được thay đổi, 675 00:55:22,750 --> 00:55:26,940 trong khi Java hoặc một cái gì đó bạn sẽ nhận được mảng giới hạn chỉ số 676 00:55:26,940 --> 00:55:29,820 hoặc chỉ số giới hạn ngoại lệ. 677 00:55:29,820 --> 00:55:33,950 Đó là lý do tại sao rất nhiều ngôn ngữ cấp cao hơn có những việc này 678 00:55:33,950 --> 00:55:37,340 mà nếu bạn đi vượt ra ngoài giới hạn của mảng, bạn không 679 00:55:37,340 --> 00:55:40,070 do đó, bạn không thể thay đổi mọi thứ từ bên dưới bạn 680 00:55:40,070 --> 00:55:42,590 và sau đó mọi thứ đi tồi tệ hơn nhiều hơn là chỉ nhận một ngoại lệ 681 00:55:42,590 --> 00:55:44,940 nói rằng bạn đã đi vượt ra ngoài cuối của mảng. 682 00:55:44,940 --> 00:55:50,970 [Sinh viên] Và vì vậy nên chúng ta chỉ cần thay đổi <= chỉ > [Bowden] Yeah. 683 00:55:50,970 --> 00:55:54,800 Nó nên được 00:55:59,560 bởi vì sizeof (array) là 20, nhưng chúng tôi chỉ muốn 5. >> [Sinh viên] Right. 685 00:55:59,560 --> 00:56:04,060 Câu hỏi nhiều hơn? Okay. 686 00:56:04,060 --> 00:56:07,380 >> [Sinh viên] Tôi có một câu hỏi. >> Yeah. 687 00:56:07,380 --> 00:56:16,440 [Sinh viên] biến mảng thực tế là gì? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Giống như những gì là mảng? 689 00:56:20,000 --> 00:56:24,930 Mảng chính nó là một biểu tượng. 690 00:56:24,930 --> 00:56:31,490 Nó chỉ là địa chỉ của sự bắt đầu của 20 byte mà chúng tôi đang tham khảo. 691 00:56:31,490 --> 00:56:38,070 Bạn có thể nghĩ về nó như một con trỏ, nhưng nó là một con trỏ hằng. 692 00:56:38,070 --> 00:56:44,140 Ngay sau khi mọi thứ có được biên dịch, biến mảng không tồn tại nữa. 693 00:56:44,140 --> 00:56:48,210 [Sinh viên] Vì vậy, làm thế nào để tìm thấy kích thước của mảng? 694 00:56:48,210 --> 00:56:54,130 Kích thước của mảng đề cập đến kích thước của khối đó mà biểu tượng mà đề cập đến. 695 00:56:54,130 --> 00:57:01,240 Khi tôi làm một cái gì đó giống như printf ("% p \ n", array); 696 00:57:01,240 --> 00:57:05,140 chúng ta hãy chạy nó. 697 00:57:12,960 --> 00:57:15,530 Tôi đã làm gì chỉ cần làm sai? 698 00:57:15,530 --> 00:57:19,220 Mảng 'mảng' tuyên bố đây. 699 00:57:20,820 --> 00:57:23,200 Oh, ở đây. 700 00:57:23,200 --> 00:57:31,250 Clang là thông minh, và nó xảy ra để thông báo rằng tôi tuyên bố các mảng như 5 yếu tố 701 00:57:31,250 --> 00:57:34,540 nhưng tôi lập chỉ mục vào vị trí 1000. 702 00:57:34,540 --> 00:57:38,450 Nó có thể làm điều đó bởi vì đây chỉ là hằng số. 703 00:57:38,450 --> 00:57:43,370 Nó chỉ có thể đi cho đến nay nhận thấy rằng tôi sẽ vượt ra ngoài giới hạn của mảng. 704 00:57:43,370 --> 00:57:46,880 Nhưng hãy chú ý trước khi chúng tôi đã có tôi là không chính xác, 705 00:57:46,880 --> 00:57:51,040 nó không thể xác định có bao nhiêu giá trị tôi có thể đưa vào, 706 00:57:51,040 --> 00:57:55,540 vì vậy nó không thể xác định rằng tôi đã được đi xa hơn vào cuối mảng. 707 00:57:55,540 --> 00:57:59,430 Đó chỉ là Clang là thông minh. 708 00:57:59,430 --> 00:58:03,340 >> Nhưng bây giờ làm cho buggy4. Vì vậy, những gì khác tôi làm sai? 709 00:58:03,340 --> 00:58:05,970 Ngầm tuyên bố thư viện chức năng 'printf'. 710 00:58:05,970 --> 00:58:14,960 Tôi sẽ muốn # include. 711 00:58:14,960 --> 00:58:18,710 Okay. Bây giờ chạy buggy4. 712 00:58:18,710 --> 00:58:24,840 In giá trị của mảng như tôi đã làm ở đây, in nó như một con trỏ 713 00:58:24,840 --> 00:58:30,060 in cái gì đó trông như thế này - bfb8805c - đó là một số địa chỉ 714 00:58:30,060 --> 00:58:33,450 đó là trong khu vực ngăn xếp-ish. 715 00:58:33,450 --> 00:58:41,820 Mảng chính nó như một con trỏ, nhưng nó không phải là một con trỏ thực tế, 716 00:58:41,820 --> 00:58:45,410 kể từ khi một con trỏ thường xuyên, chúng ta có thể thay đổi. 717 00:58:45,410 --> 00:58:54,700 Mảng là chỉ là một số không đổi. 20 khối bộ nhớ bắt đầu tại địa chỉ 0xbfb8805c. 718 00:58:54,700 --> 00:59:09,020 Vì vậy, bfb8805c thông qua địa chỉ này +20- hoặc tôi đoán -20 - 719 00:59:09,020 --> 00:59:17,400 là tất cả các cấp phát bộ nhớ cho mảng này. 720 00:59:17,400 --> 00:59:20,350 Array, biến chính nó là không lưu trữ bất cứ nơi nào. 721 00:59:20,350 --> 00:59:27,660 Khi bạn đang biên soạn, biên dịch - tay sóng tại - 722 00:59:27,660 --> 00:59:33,060 nhưng trình biên dịch sẽ chỉ sử dụng nó biết mảng được. 723 00:59:33,060 --> 00:59:36,090 Nó biết nơi mảng đó bắt đầu, 724 00:59:36,090 --> 00:59:40,910 và do đó, nó có thể luôn luôn chỉ làm những việc về đối tượng dời từ đầu đó. 725 00:59:40,910 --> 00:59:43,960 Nó không cần một biến riêng của mình để đại diện cho mảng. 726 00:59:43,960 --> 00:59:53,730 Nhưng khi tôi làm một cái gì đó giống như int * array = p; p là một con trỏ chỉ vào mảng đó, 727 00:59:53,730 --> 00:59:57,830 và bây giờ p thực sự tồn tại trên stack. 728 00:59:57,830 --> 01:00:01,950 Tôi là miễn phí để thay đổi p. Tôi có thể làm p = malloc. 729 01:00:01,950 --> 01:00:06,500 Vì vậy, ban đầu nó chỉ vào mảng, bây giờ nó chỉ vào một số không gian trên heap. 730 01:00:06,500 --> 01:00:09,620 Tôi không thể làm mảng = malloc. 731 01:00:09,620 --> 01:00:13,710 Nếu Clang là thông minh, nó sẽ hét vào mặt tôi ngay off the bat. 732 01:00:17,000 --> 01:00:21,430 Trên thực tế, tôi khá chắc chắn gcc sẽ làm điều này quá. 733 01:00:21,430 --> 01:00:25,010 Vì vậy, array loại 'int [5]' là không thể chuyển nhượng. 734 01:00:25,010 --> 01:00:28,040 Bạn không thể chỉ định một cái gì đó để một loại mảng 735 01:00:28,040 --> 01:00:30,500 vì mảng chỉ là một hằng số. 736 01:00:30,500 --> 01:00:34,760 Đó là một biểu tượng đó tài liệu tham khảo 20 byte. Tôi không thể thay đổi nó. 737 01:00:34,760 --> 01:00:37,690 >> [Sinh viên] mà là kích thước của mảng được lưu trữ? 738 01:00:37,690 --> 01:00:40,670 [Bowden không được lưu trữ bất cứ nơi nào. Đó là khi nó được biên dịch. 739 01:00:40,670 --> 01:00:46,310 Vì vậy, nơi kích thước của mảng được lưu trữ? 740 01:00:46,310 --> 01:00:51,870 Bạn chỉ có thể sử dụng sizeof (array) bên trong chức năng rằng các mảng được khai báo. 741 01:00:51,870 --> 01:01:03,150 Vì vậy, nếu tôi làm một số chức năng, foo, và tôi làm (int array []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 và sau đó xuống đây tôi gọi foo (array); 744 01:01:21,330 --> 01:01:24,840 bên trong của chức năng này - chúng ta hãy chạy nó. 745 01:01:34,200 --> 01:01:36,840 Đây là Clang thông minh một lần nữa. 746 01:01:36,840 --> 01:01:43,890 Nó nói với tôi rằng sizeof trên tham số của hàm mảng 747 01:01:43,890 --> 01:01:46,690 sẽ trở lại kích thước của '* int'. 748 01:01:46,690 --> 01:01:55,150 Đây sẽ là một lỗi, nếu nó không phải là những gì tôi muốn xảy ra. 749 01:01:55,150 --> 01:01:58,960 Hãy thực sự tắt Werror. 750 01:02:14,950 --> 01:02:17,590 Cảnh báo. Cảnh báo là tốt. 751 01:02:17,590 --> 01:02:19,960 Nó vẫn sẽ biên dịch miễn là nó có một cảnh báo. 752 01:02:19,960 --> 01:02:22,910 . / A.out sẽ in 4. 753 01:02:22,910 --> 01:02:28,650 Những cảnh báo đã được tạo ra là một chỉ báo rõ ràng về những gì đã đi sai. 754 01:02:28,650 --> 01:02:34,120 Mảng int này là chỉ cần đi in sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Ngay cả nếu tôi đặt array [5] ở đây, nó vẫn chỉ là sẽ in sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Vì vậy, ngay sau khi bạn vượt qua nó vào một hàm, sự khác biệt giữa các mảng và con trỏ 757 01:02:47,440 --> 01:02:49,670 là không tồn tại. 758 01:02:49,670 --> 01:02:52,640 Điều này xảy ra là một mảng đã được khai báo trên stack, 759 01:02:52,640 --> 01:02:58,300 nhưng ngay sau khi chúng tôi vượt qua giá trị đó, 0xbf blah, blah, blah vào chức năng này, 760 01:02:58,300 --> 01:03:03,350 sau đó con trỏ này trỏ đến mảng đó trên stack. 761 01:03:03,350 --> 01:03:08,310 Vì vậy, đó có nghĩa là sizeof chỉ được áp dụng trong các chức năng mà mảng này được tuyên bố, 762 01:03:08,310 --> 01:03:11,230 có nghĩa là khi bạn đang biên dịch chức năng này, 763 01:03:11,230 --> 01:03:17,330 khi Clang thông qua chức năng này, nó thấy mảng là một mảng int có kích thước 5. 764 01:03:17,330 --> 01:03:20,640 Vì vậy, sau đó nó thấy sizeof (array). Vâng, đó là 20. 765 01:03:20,640 --> 01:03:26,440 Đó thực sự là như thế nào sizeof về cơ bản làm việc cho hầu hết các trường hợp. 766 01:03:26,440 --> 01:03:31,150 Sizeof là không phải là một chức năng, nó là một nhà điều hành. 767 01:03:31,150 --> 01:03:33,570 Bạn không gọi hàm sizeof. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), trình biên dịch sẽ dịch đến 4. 769 01:03:41,480 --> 01:03:43,700 Đã nhận nó? Okay. 770 01:03:43,700 --> 01:03:47,520 >> [Sinh viên] Vì vậy, sự khác biệt giữa sizeof (array) chính và trong foo là gì? 771 01:03:47,520 --> 01:03:52,840 Điều này là bởi vì chúng ta đang nói sizeof (array), mà là của kiểu int *, 772 01:03:52,840 --> 01:03:57,120 trong khi mảng xuống đây không phải là kiểu int *, nó là một mảng int. 773 01:03:57,120 --> 01:04:04,540 >> [Sinh viên] Vì vậy, nếu bạn đã có các tham số trong mảng [] thay vì mảng int * 774 01:04:04,540 --> 01:04:09,230 đó có nghĩa là bạn vẫn có thể thay đổi mảng, vì bây giờ nó là một con trỏ? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Như thế này? >> [Sinh viên] Yeah. Bạn có thể thay đổi mảng trong phạm vi chức năng bây giờ? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Bạn có thể thay đổi mảng trong cả hai trường hợp. 777 01:04:18,420 --> 01:04:23,130 Trong cả hai trường hợp, bạn được tự do để nói array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Sinh viên] Nhưng bạn có thể làm cho điểm mảng đến cái gì khác? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Yeah. Trong cả hai trường hợp - >> [sinh viên] Yeah. 780 01:04:30,230 --> 01:04:38,410 Bowden] Sự khác biệt giữa mảng [] và một mảng int *, không có. 781 01:04:38,410 --> 01:04:42,570 Bạn cũng có thể nhận được một số mảng đa chiều ở đây 782 01:04:42,570 --> 01:04:47,050 đối với một số cú pháp thuận tiện, nhưng nó vẫn chỉ là một con trỏ. 783 01:04:47,050 --> 01:04:56,400 Điều này có nghĩa rằng tôi là miễn phí để làm mảng = malloc (sizeof (int)), và bây giờ chỉ ở một nơi khác. 784 01:04:56,400 --> 01:04:59,610 Nhưng giống như cách làm việc này mãi mãi và luôn luôn, 785 01:04:59,610 --> 01:05:03,210 thay đổi mảng này bằng cách làm cho nó trỏ đến cái gì khác 786 01:05:03,210 --> 01:05:07,570 không thay đổi mảng này ở đây vì nó là một bản sao của các đối số, 787 01:05:07,570 --> 01:05:10,780 nó không phải là một con trỏ đến đối số đó. 788 01:05:10,780 --> 01:05:16,070 Và trên thực tế, cũng giống như dấu hiệu cho thấy rằng nó chính xác như nhau - 789 01:05:16,070 --> 01:05:21,100 chúng tôi đã nhìn thấy những gì in mảng in ấn - 790 01:05:21,100 --> 01:05:31,410 điều gì sẽ xảy ra nếu chúng tôi in địa chỉ của mảng hoặc địa chỉ của địa chỉ của mảng 791 01:05:31,410 --> 01:05:36,290 hoặc của những người? 792 01:05:41,770 --> 01:05:45,220 Hãy bỏ qua một trong những điều này. 793 01:05:48,140 --> 01:05:51,660 Okay. Điều này là tốt. Nó bây giờ chạy / a.out.. 794 01:05:51,660 --> 01:06:00,220 In ấn mảng, sau đó in địa chỉ của mảng, điều tương tự. 795 01:06:00,220 --> 01:06:02,870 Mảng chỉ không tồn tại. 796 01:06:02,870 --> 01:06:08,190 Nó biết khi bạn đang in mảng, bạn đang in ấn các biểu tượng mà đề cập đến 20 byte. 797 01:06:08,190 --> 01:06:11,940 In địa chỉ của mảng, mảng không tồn tại. 798 01:06:11,940 --> 01:06:17,200 Nó không có một địa chỉ, do đó, nó chỉ in địa chỉ của 20 byte. 799 01:06:20,820 --> 01:06:28,150 Ngay sau khi bạn biên dịch xuống, như trong buggy4 biên soạn của bạn / a.out. 800 01:06:28,150 --> 01:06:30,340 mảng là không tồn tại. 801 01:06:30,340 --> 01:06:33,640 Con trỏ tồn tại. Mảng không. 802 01:06:34,300 --> 01:06:38,060 Các khối của bộ nhớ đại diện cho mảng vẫn còn tồn tại, 803 01:06:38,060 --> 01:06:43,270 nhưng các mảng biến và các biến của loại đó không tồn tại. 804 01:06:46,260 --> 01:06:50,270 Đó là giống như những khác biệt chính giữa các mảng và con trỏ 805 01:06:50,270 --> 01:06:55,590 ngay sau khi bạn thực hiện cuộc gọi chức năng, không có sự khác biệt. 806 01:06:55,590 --> 01:07:00,460 Nhưng bên trong các chức năng mà các mảng chính nó được khai báo, sizeof công trình khác nhau 807 01:07:00,460 --> 01:07:05,190 kể từ khi bạn đang in kích thước của các khối thay vì kích thước của các loại, 808 01:07:05,190 --> 01:07:08,950 và bạn không thể thay đổi nó vì nó là một biểu tượng. 809 01:07:08,950 --> 01:07:14,370 In ấn điều và địa chỉ của điều in cùng một điều. 810 01:07:14,370 --> 01:07:18,480 Và đó là khá nhiều đó. 811 01:07:18,480 --> 01:07:20,820 [Sinh viên] bạn có thể nói rằng một lần nữa? 812 01:07:21,170 --> 01:07:24,170 Tôi có thể đã bị mất một cái gì đó. 813 01:07:24,170 --> 01:07:29,260 In ấn và mảng và địa chỉ của mảng in cùng một điều, 814 01:07:29,260 --> 01:07:33,180 trong khi đó nếu bạn in một con trỏ so với địa chỉ của con trỏ, 815 01:07:33,180 --> 01:07:36,010 một trong những điều in địa chỉ của những gì bạn đang trỏ đến, 816 01:07:36,010 --> 01:07:40,360 in địa chỉ của con trỏ trên stack. 817 01:07:40,360 --> 01:07:47,040 Bạn có thể thay đổi một con trỏ, bạn không thể thay đổi một biểu tượng mảng. 818 01:07:47,740 --> 01:07:53,270 Và sizeof con trỏ sẽ in kích thước của kiểu con trỏ. 819 01:07:53,270 --> 01:07:57,470 Vì vậy, int * p sizeof (p) sẽ in 4, 820 01:07:57,470 --> 01:08:04,110 nhưng int array [5] in sizeof (array) sẽ in 20. 821 01:08:04,110 --> 01:08:07,480 [Sinh viên] Vì vậy, int array [5] sẽ in 20? >>. 822 01:08:07,480 --> 01:08:13,300 Đó là lý do tại sao bên trong của buggy4 khi nó được sử dụng là sizeof (array) 823 01:08:13,300 --> 01:08:16,660 điều này đã làm i <20, không phải là những gì chúng ta muốn. 824 01:08:16,660 --> 01:08:20,880 Chúng tôi muốn i <5. >> [Sinh viên] Okay. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Và sau đó ngay khi bạn bắt đầu đi qua trong các chức năng, 826 01:08:25,569 --> 01:08:34,340 nếu chúng ta đã làm int * p = array; 827 01:08:34,340 --> 01:08:39,779 bên trong chức năng này, chúng tôi về cơ bản có thể sử dụng p và mảng chính xác trong cùng một cách, 828 01:08:39,779 --> 01:08:43,710 ngoại trừ vấn đề sizeof và vấn đề thay đổi. 829 01:08:43,710 --> 01:08:49,810 Nhưng p [0] = 1; giống như nói array [0] = 1; 830 01:08:49,810 --> 01:08:55,600 Và ngay khi chúng tôi nói foo (array); foo (p); 831 01:08:55,600 --> 01:08:59,760 bên trong foo chức năng, đây là các cuộc gọi cùng một hai lần. 832 01:08:59,760 --> 01:09:03,350 Không có sự khác biệt giữa hai cuộc gọi. 833 01:09:07,029 --> 01:09:11,080 >> Mọi người đều tốt về điều đó? Okay. 834 01:09:14,620 --> 01:09:17,950 Chúng tôi có 10 phút. 835 01:09:17,950 --> 01:09:28,319 >> Chúng tôi sẽ cố gắng để có được thông qua chương trình này Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 trang web này, mà ra đến năm ngoái hoặc một cái gì đó. 837 01:09:34,149 --> 01:09:41,100 Nó chỉ là nghĩa vụ phải được như bạn gõ ngẫu nhiên và nó in ra - 838 01:09:41,100 --> 01:09:46,729 Bất kỳ tập tin nó sẽ xảy ra đã tải là những gì nó trông giống như bạn đang gõ. 839 01:09:46,729 --> 01:09:52,069 Nó trông giống như một số loại hệ điều hành mã. 840 01:09:53,760 --> 01:09:56,890 Đó là những gì chúng tôi muốn thực hiện. 841 01:10:08,560 --> 01:10:11,690 Bạn cần phải có một file thực thi nhị phân có tên là hacker_typer 842 01:10:11,690 --> 01:10:14,350 mà mất trong một đối số duy nhất, các tập tin loại "tin tặc". 843 01:10:14,350 --> 01:10:16,480 Chạy thực thi nên xóa màn hình 844 01:10:16,480 --> 01:10:20,850 và sau đó in ra một trong những nhân vật từ các tập tin thông qua trong mỗi lần người dùng nhấn một phím. 845 01:10:20,850 --> 01:10:24,990 Vì vậy, bất cứ điều gì bạn bấm phím, nên vứt bỏ và thay vào đó in một ký tự từ tập tin 846 01:10:24,990 --> 01:10:27,810 đó là tham số. 847 01:10:29,880 --> 01:10:34,350 Tôi khá nhiều sẽ cho bạn biết những điều chúng ta sẽ cần phải biết. 848 01:10:34,350 --> 01:10:36,440 Nhưng chúng tôi muốn kiểm tra thư viện termios. 849 01:10:36,440 --> 01:10:44,840 Tôi đã không bao giờ được sử dụng thư viện này trong toàn bộ cuộc sống của tôi, vì vậy nó có mục đích rất tối thiểu. 850 01:10:44,840 --> 01:10:48,610 Nhưng điều này là có được các thư viện, chúng ta có thể sử dụng để ném đi những nhân vật bạn nhấn 851 01:10:48,610 --> 01:10:52,390 khi bạn đang gõ vào tiêu chuẩn. 852 01:10:56,970 --> 01:11:05,840 Vì vậy, hacker_typer.c, và chúng tôi sẽ muốn # include. 853 01:11:05,840 --> 01:11:12,870 Nhìn vào trang người đàn ông cho termios - tôi đoán thiết bị đầu cuối của hệ điều hành hoặc một cái gì đó - 854 01:11:12,870 --> 01:11:16,240 Tôi không biết làm thế nào để đọc nó. 855 01:11:16,240 --> 01:11:21,040 Nhìn này, nó nói để bao gồm 2 file này, vì vậy chúng tôi sẽ làm điều đó. 856 01:11:37,620 --> 01:11:46,820 >> Điều đầu tiên đầu tiên, chúng tôi muốn để có trong một đối số duy nhất, đó là các tập tin, chúng tôi sẽ mở ra. 857 01:11:46,820 --> 01:11:52,420 Vì vậy, tôi phải làm gì muốn làm gì? Làm thế nào để kiểm tra xem tôi có một đối số duy nhất? 858 01:11:52,420 --> 01:11:56,480 [Sinh viên] Nếu argc bằng nó. >> [Bowden] Yeah. 859 01:11:56,480 --> 01:12:21,250 Vì vậy, nếu (argc = 2) printf ("sử dụng:% s [file để mở]"). 860 01:12:21,250 --> 01:12:32,750 Vì vậy, bây giờ nếu tôi chạy mà không cần cung cấp một số thứ hai - oh, tôi cần dòng mới - 861 01:12:32,750 --> 01:12:36,240 bạn sẽ thấy nó nói sử dụng: / hacker_typer. 862 01:12:36,240 --> 01:12:39,770 và sau đó đối số thứ hai nên được các tập tin tôi muốn mở. 863 01:12:58,430 --> 01:13:01,260 Bây giờ tôi phải làm gì? 864 01:13:01,260 --> 01:13:08,490 Tôi muốn đọc từ tập tin này. Làm thế nào để đọc từ một tập tin? 865 01:13:08,490 --> 01:13:11,920 [Sinh viên] Bạn mở nó đầu tiên. >> Yeah. 866 01:13:11,920 --> 01:13:15,010 Vì vậy, fopen Fopen trông như thế nào? 867 01:13:15,010 --> 01:13:22,980 [Sinh viên] Filename. >> [Bowden] ảnh Tên ảnh là có được argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Sinh viên] Và sau đó những gì bạn muốn làm gì với nó, vì vậy - >> [Bowden] Yeah. 869 01:13:26,110 --> 01:13:28,740 Vì vậy, nếu bạn không nhớ, bạn chỉ có thể làm người đàn ông fopen, 870 01:13:28,740 --> 01:13:32,960 nơi mà nó sẽ là một const char * path, nơi đường dẫn là tên tập tin, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Nếu bạn xảy ra để không nhớ những gì chế độ, sau đó bạn có thể tìm cho chế độ. 873 01:13:38,660 --> 01:13:44,660 Bên trong trang người đàn ông, nhân vật dấu gạch chéo là những gì bạn có thể sử dụng để tìm kiếm cho những thứ. 874 01:13:44,660 --> 01:13:49,790 Vì vậy, tôi gõ / chế độ tìm kiếm cho chế độ. 875 01:13:49,790 --> 01:13:57,130 n và N là những gì bạn có thể sử dụng để chu kỳ thông qua các trận đấu tìm kiếm. 876 01:13:57,130 --> 01:13:59,800 Ở đây nó nói các điểm chế độ đối số cho một chuỗi 877 01:13:59,800 --> 01:14:01,930 bắt đầu với một trong các trình tự sau đây. 878 01:14:01,930 --> 01:14:06,480 Vì vậy, r, Mở tập tin văn bản để đọc. Đó là những gì chúng tôi muốn làm. 879 01:14:08,930 --> 01:14:13,210 Để đọc, và tôi muốn để lưu trữ. 880 01:14:13,210 --> 01:14:18,720 Điều là có được một tập tin *. Bây giờ tôi muốn làm những gì? 881 01:14:18,720 --> 01:14:21,200 Hãy cho tôi một giây. 882 01:14:28,140 --> 01:14:30,430 Okay. Bây giờ tôi muốn làm những gì? 883 01:14:30,430 --> 01:14:32,940 [Sinh viên] Kiểm tra nếu nó là NULL. >> [Bowden] Yeah. 884 01:14:32,940 --> 01:14:38,690 Bất cứ khi nào bạn mở một tập tin, hãy chắc chắn rằng bạn đang thành công có thể để mở nó. 885 01:14:58,930 --> 01:15:10,460 >> Bây giờ tôi muốn làm những thứ termios nơi tôi muốn lần đầu tiên đọc các thiết lập hiện tại của tôi 886 01:15:10,460 --> 01:15:14,050 và lưu những người thành một cái gì đó, sau đó tôi muốn thay đổi các thiết lập của tôi 887 01:15:14,050 --> 01:15:19,420 vứt bỏ bất kỳ nhân vật mà tôi gõ, 888 01:15:19,420 --> 01:15:22,520 và sau đó tôi muốn để cập nhật các thiết lập. 889 01:15:22,520 --> 01:15:27,250 Và sau đó ở phần cuối của chương trình, tôi muốn thay đổi trở lại các thiết lập ban đầu của tôi. 890 01:15:27,250 --> 01:15:32,080 Vì vậy, các cấu trúc sẽ có termios loại, và tôi sẽ muốn hai của những người. 891 01:15:32,080 --> 01:15:35,600 Người đầu tiên là sẽ là current_settings của tôi, 892 01:15:35,600 --> 01:15:42,010 và sau đó họ sẽ là hacker_settings của tôi. 893 01:15:42,010 --> 01:15:48,070 Đầu tiên, tôi sẽ muốn lưu các thiết lập hiện tại của tôi, 894 01:15:48,070 --> 01:15:53,790 sau đó tôi sẽ muốn cập nhật hacker_settings, 895 01:15:53,790 --> 01:16:01,570 và rồi con đường ở phần cuối của chương trình của tôi, tôi muốn trở lại các thiết lập hiện hành. 896 01:16:01,570 --> 01:16:08,660 Vì vậy, tiết kiệm thiết lập hiện tại, cách làm việc, termios người đàn ông chúng tôi. 897 01:16:08,660 --> 01:16:15,810 Chúng tôi thấy rằng chúng tôi có này tcsetattr int, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Tôi vượt qua trong một struct termios con trỏ của nó. 899 01:16:22,960 --> 01:16:30,640 Cách này sẽ xem xét - Tôi đã đã quên những gì chức năng được gọi là. 900 01:16:30,640 --> 01:16:34,930 Sao chép và dán. 901 01:16:39,150 --> 01:16:45,500 Vì vậy, tcgetattr, sau đó tôi muốn vượt qua trong cấu trúc mà tôi đang lưu thông tin, 902 01:16:45,500 --> 01:16:49,650 đó là sẽ là current_settings, 903 01:16:49,650 --> 01:16:59,120 và tham số đầu tiên là mô tả tập tin cho điều tôi muốn lưu các thuộc tính của. 904 01:16:59,120 --> 01:17:04,360 Mô tả tập tin là giống như bất kỳ thời điểm nào bạn mở một tập tin, nó được một mô tả tập tin. 905 01:17:04,360 --> 01:17:14,560 Khi tôi fopen argv [1], nó được một mô tả tập tin mà bạn đang tham khảo 906 01:17:14,560 --> 01:17:16,730 bất cứ khi nào bạn muốn đọc hoặc viết thư cho nó. 907 01:17:16,730 --> 01:17:19,220 Đó không phải là mô tả tập tin tôi muốn sử dụng ở đây. 908 01:17:19,220 --> 01:17:21,940 Có ba mô tả tập tin mà bạn có theo mặc định, 909 01:17:21,940 --> 01:17:24,310 là tiêu chuẩn, tiêu chuẩn ra, và sai số chuẩn. 910 01:17:24,310 --> 01:17:29,960 Theo mặc định, tôi nghĩ rằng nó là tiêu chuẩn trong là 0, tiêu chuẩn ra 1, và lỗi tiêu chuẩn là 2. 911 01:17:29,960 --> 01:17:33,980 Vì vậy, tôi phải làm gì muốn thay đổi các thiết lập của? 912 01:17:33,980 --> 01:17:37,370 Tôi muốn thay đổi các thiết lập của bất cứ khi nào tôi nhấn một nhân vật, 913 01:17:37,370 --> 01:17:41,590 Tôi muốn nó ném rằng nhân vật thay vì in ấn nó vào màn hình. 914 01:17:41,590 --> 01:17:45,960 Dòng tiêu chuẩn, ra tiêu chuẩn, hoặc lỗi tiêu chuẩn - 915 01:17:45,960 --> 01:17:52,050 đáp ứng điều khi tôi gõ vào bàn phím? >> [Sinh viên] Standard. >> Vâng. 916 01:17:52,050 --> 01:17:56,450 Vì vậy, tôi có thể làm 0 hoặc tôi có thể làm stdin. 917 01:17:56,450 --> 01:17:59,380 Tôi nhận được current_settings của tiêu chuẩn. 918 01:17:59,380 --> 01:18:01,720 >> Bây giờ tôi muốn để cập nhật các thiết lập, 919 01:18:01,720 --> 01:18:07,200 do đó, đầu tiên tôi sẽ sao chép vào hacker_settings những gì current_settings của tôi. 920 01:18:07,200 --> 01:18:10,430 Và làm thế nào để cấu trúc làm việc là nó sẽ chỉ sao chép. 921 01:18:10,430 --> 01:18:14,510 Điều này bản sao tất cả các lĩnh vực, như bạn mong chờ. 922 01:18:14,510 --> 01:18:17,410 >> Bây giờ tôi muốn để cập nhật một số lĩnh vực. 923 01:18:17,410 --> 01:18:21,670 Nhìn vào termios, bạn sẽ phải đọc qua rất nhiều này 924 01:18:21,670 --> 01:18:24,110 chỉ để xem những gì bạn sẽ muốn tìm, 925 01:18:24,110 --> 01:18:28,210 nhưng những lá cờ bạn sẽ muốn tìm echo, 926 01:18:28,210 --> 01:18:33,110 như vậy ECHO Echo ký tự đầu vào. 927 01:18:33,110 --> 01:18:37,710 Trước tiên tôi muốn thiết lập - I've đã quên những gì các lĩnh vực. 928 01:18:45,040 --> 01:18:47,900 Đây là những gì cấu trúc trông giống như. 929 01:18:47,900 --> 01:18:51,060 Vì vậy, các chế độ nhập, tôi nghĩ rằng chúng tôi muốn thay đổi. 930 01:18:51,060 --> 01:18:54,210 Chúng tôi sẽ xem xét các giải pháp để đảm bảo rằng đó là những gì chúng ta muốn thay đổi. 931 01:19:04,060 --> 01:19:12,610 Chúng tôi muốn thay đổi lflag để ngăn chặn cần phải xem xét thông qua tất cả những điều này. 932 01:19:12,610 --> 01:19:14,670 Chúng tôi muốn thay đổi chế độ địa phương. 933 01:19:14,670 --> 01:19:17,710 Bạn sẽ phải đọc thông qua toàn bộ điều này để hiểu, nơi tất cả mọi thứ thuộc về 934 01:19:17,710 --> 01:19:19,320 mà chúng ta muốn thay đổi. 935 01:19:19,320 --> 01:19:24,120 Tuy nhiên, bên trong các chế độ địa phương, nơi chúng tôi sẽ muốn thay đổi điều đó. 936 01:19:27,080 --> 01:19:33,110 Vì vậy, hacker_settings.cc_lmode là những gì nó được gọi là. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Đây là nơi mà chúng tôi nhận được vào các nhà khai thác Bitwise. 939 01:19:52,280 --> 01:19:54,860 Chúng tôi đang loại ra khỏi thời gian, nhưng chúng tôi sẽ đi qua nó thực sự nhanh chóng. 940 01:19:54,860 --> 01:19:56,600 Đây là nơi mà chúng tôi nhận được vào nhà khai thác Bitwise, 941 01:19:56,600 --> 01:19:59,950 mà tôi nghĩ rằng tôi đã nói một thời gian dài trước đây rằng bất cứ khi nào bạn bắt đầu giao dịch với cờ, 942 01:19:59,950 --> 01:20:03,370 bạn sẽ được sử dụng Bitwise nhà điều hành rất nhiều. 943 01:20:03,370 --> 01:20:08,240 Mỗi bit trong lá cờ tương ứng với một số loại hành vi. 944 01:20:08,240 --> 01:20:14,090 Vì vậy, ở đây, lá cờ này có một loạt các thứ khác nhau, nơi mà tất cả chúng có nghĩa là một cái gì đó khác nhau. 945 01:20:14,090 --> 01:20:18,690 Nhưng những gì tôi muốn làm là chỉ cần tắt các bit tương ứng với ECHO. 946 01:20:18,690 --> 01:20:25,440 Vì vậy, để biến mà off I & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Thực ra, tôi nghĩ rằng đó là như tECHO hoặc một cái gì đó. Tôi chỉ cần đi để kiểm tra một lần nữa. 948 01:20:30,110 --> 01:20:34,050 Tôi có thể termios. Nó chỉ ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO là có được một chút. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO sẽ có nghĩa là tất cả các bit được thiết lập để 1, có nghĩa là tất cả các lá cờ được thiết lập để thực 951 01:20:44,230 --> 01:20:47,140 trừ cho bit ECHO. 952 01:20:47,140 --> 01:20:53,830 Bằng cách kết thúc cờ địa phương của tôi với điều này, nó có nghĩa là tất cả các lá cờ hiện đang được thiết lập để thực 953 01:20:53,830 --> 01:20:56,520 vẫn sẽ được thiết lập là true. 954 01:20:56,520 --> 01:21:03,240 Nếu cờ ECHO của tôi được thiết lập là true, sau đó điều này cần thiết phải được thiết lập để sai trên lá cờ ECHO. 955 01:21:03,240 --> 01:21:07,170 Vì vậy, dòng mã này chỉ cần tắt cờ ECHO. 956 01:21:07,170 --> 01:21:16,270 Các dòng khác của mã, tôi sẽ chỉ sao chép chúng trong sự quan tâm của thời gian và sau đó giải thích chúng. 957 01:21:27,810 --> 01:21:30,180 Trong giải pháp này, ông nói 0. 958 01:21:30,180 --> 01:21:33,880 Đây có thể là tốt hơn một cách rõ ràng nói stdin. 959 01:21:33,880 --> 01:21:42,100 >> Chú ý rằng tôi cũng làm ECHO | icanon đây. 960 01:21:42,100 --> 01:21:46,650 Icanon đề cập đến một cái gì đó riêng biệt, mà có nghĩa là chế độ kinh điển. 961 01:21:46,650 --> 01:21:50,280 Chế độ phương tiện kinh điển là thông thường khi bạn đang gõ dòng lệnh, 962 01:21:50,280 --> 01:21:54,670 tiêu chuẩn trong không xử lý bất cứ điều gì cho đến khi bạn nhấn xuống dòng. 963 01:21:54,670 --> 01:21:58,230 Vì vậy, khi bạn GetString, bạn gõ một bó của những điều, sau đó bạn nhấn xuống dòng. 964 01:21:58,230 --> 01:22:00,590 Đó là khi nó được gửi đến tiêu chuẩn. 965 01:22:00,590 --> 01:22:02,680 Đó là mặc định. 966 01:22:02,680 --> 01:22:05,830 Khi tôi tắt chế độ kinh điển, bây giờ tất cả các nhân vật duy nhất bạn nhấn 967 01:22:05,830 --> 01:22:10,910 là những gì được chế biến, mà thường là loại xấu bởi vì nó làm chậm để xử lý những việc này, 968 01:22:10,910 --> 01:22:14,330 đó là lý do tại sao nó rất tốt để đệm vào dây chuyền toàn bộ. 969 01:22:14,330 --> 01:22:16,810 Nhưng tôi muốn mỗi nhân vật để được xử lý 970 01:22:16,810 --> 01:22:18,810 vì tôi không muốn nó chờ đợi cho tôi để nhấn xuống dòng 971 01:22:18,810 --> 01:22:21,280 trước khi nó xử lý tất cả các ký tự đã gõ. 972 01:22:21,280 --> 01:22:24,760 Tắt chế độ kinh điển. 973 01:22:24,760 --> 01:22:31,320 Công cụ này chỉ có nghĩa là khi nó thực sự xử lý nhân vật. 974 01:22:31,320 --> 01:22:35,830 Điều này có nghĩa là xử lý chúng ngay lập tức, ngay sau khi tôi gõ chúng, xử lý chúng. 975 01:22:35,830 --> 01:22:42,510 Và đây là chức năng được cập nhật cài đặt của tôi cho các tiêu chuẩn, 976 01:22:42,510 --> 01:22:45,480 và các phương tiện TCSA làm điều đó ngay bây giờ. 977 01:22:45,480 --> 01:22:50,310 Các tùy chọn khác được chờ đợi cho đến khi tất cả mọi thứ hiện tại trên suối được xử lý. 978 01:22:50,310 --> 01:22:52,030 Điều đó không thực sự quan trọng. 979 01:22:52,030 --> 01:22:56,920 Chỉ cần thay đổi các thiết lập của tôi ngay bây giờ để được bất cứ điều gì hiện đang trong hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Tôi đoán tôi gọi nó là hacker_settings, vì vậy hãy thay đổi điều đó. 981 01:23:09,610 --> 01:23:13,500 Thay đổi tất cả mọi thứ để hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Bây giờ ở phần cuối của chương trình của chúng tôi, chúng tôi sẽ muốn trở lại 983 01:23:16,870 --> 01:23:20,210 những gì hiện đang trong normal_settings, 984 01:23:20,210 --> 01:23:26,560 đó là sẽ chỉ cần nhìn như & normal_settings. 985 01:23:26,560 --> 01:23:30,650 Thấy rằng chúng tôi không thay đổi bất kỳ normal_settings của tôi kể từ khi ban đầu nhận được nó. 986 01:23:30,650 --> 01:23:34,520 Sau đó, để chỉ cần thay đổi chúng trở lại, tôi vượt qua chúng trở lại ở cuối. 987 01:23:34,520 --> 01:23:38,390 Đây là bản cập nhật. Okay. 988 01:23:38,390 --> 01:23:43,900 >> Bây giờ, bên đây tôi sẽ chỉ giải thích các mã trong sự quan tâm của thời gian. 989 01:23:43,900 --> 01:23:46,350 Nó không phải là nhiều mã. 990 01:23:50,770 --> 01:24:03,750 Chúng tôi nhìn thấy chúng tôi đọc một ký tự từ tập tin. Chúng tôi gọi nó là f. 991 01:24:03,750 --> 01:24:07,850 Bây giờ bạn có thể người đàn ông fgetc, nhưng như thế nào fgetc là sẽ làm việc 992 01:24:07,850 --> 01:24:11,910 chỉ là nó sẽ trở lại nhân vật mà bạn chỉ cần đọc hoặc EOF, 993 01:24:11,910 --> 01:24:15,680 tương ứng với kết thúc của tập tin hoặc một số lỗi xảy ra. 994 01:24:15,680 --> 01:24:19,900 Chúng tôi vòng lặp, tiếp tục đọc một ký tự từ tập tin duy nhất, 995 01:24:19,900 --> 01:24:22,420 cho đến khi chúng tôi đã chạy ra khỏi các ký tự để đọc. 996 01:24:22,420 --> 01:24:26,650 Và trong khi chúng tôi đang làm điều đó, chúng tôi chờ đợi vào một nhân vật duy nhất từ ​​tiêu chuẩn. 997 01:24:26,650 --> 01:24:29,090 Mỗi khi bạn gõ một cái gì đó tại dòng lệnh, 998 01:24:29,090 --> 01:24:32,820 đọc một ký tự từ tiêu chuẩn. 999 01:24:32,820 --> 01:24:38,330 Sau đó, putchar là chỉ cần đi để đưa các char chúng ta đọc từ các tập tin để ra tiêu chuẩn. 1000 01:24:38,330 --> 01:24:42,890 Bạn có thể người đàn ông putchar, nhưng nó chỉ cần đặt tiêu chuẩn, nó in rằng nhân vật. 1001 01:24:42,890 --> 01:24:51,600 Bạn cũng có thể chỉ cần làm printf ("% c", c); cùng một ý tưởng. 1002 01:24:53,330 --> 01:24:56,670 Điều đó sẽ làm phần lớn công việc của chúng tôi. 1003 01:24:56,670 --> 01:25:00,300 >> Điều cuối cùng chúng ta sẽ muốn làm là chỉ cần fclose tập tin của chúng tôi. 1004 01:25:00,300 --> 01:25:03,310 Nếu bạn không fclose, đó là một rò rỉ bộ nhớ. 1005 01:25:03,310 --> 01:25:06,680 Chúng tôi muốn fclose tập tin chúng tôi ban đầu được mở, và tôi nghĩ rằng đó là nó. 1006 01:25:06,680 --> 01:25:13,810 Nếu chúng ta thực hiện điều đó, tôi đã có vấn đề. 1007 01:25:13,810 --> 01:25:17,260 Hãy xem. 1008 01:25:17,260 --> 01:25:19,960 Nó đã khiếu nại? 1009 01:25:19,960 --> 01:25:30,220 Dự kiến ​​'int' nhưng đối số là loại 'struct _IO_FILE *'. 1010 01:25:36,850 --> 01:25:39,370 Chúng ta sẽ thấy rằng các công trình. 1011 01:25:45,210 --> 01:25:53,540 Chỉ được phép trong C99. Augh. Được rồi, hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Bây giờ chúng tôi nhận được mô tả hữu ích hơn. 1013 01:25:57,760 --> 01:25:59,900 Vì vậy, sử dụng định danh không khai báo 'normal_settings'. 1014 01:25:59,900 --> 01:26:04,170 Tôi đã không gọi nó normal_settings. Tôi gọi nó là current_settings. 1015 01:26:04,170 --> 01:26:12,090 Vì vậy, hãy thay đổi tất cả những điều đó. 1016 01:26:17,920 --> 01:26:21,710 Bây giờ đi qua đối số. 1017 01:26:26,290 --> 01:26:29,500 Tôi sẽ làm cho này 0 cho bây giờ. 1018 01:26:29,500 --> 01:26:36,720 Okay. / Hacker_typer. Cp.c. 1019 01:26:36,720 --> 01:26:39,590 Tôi cũng không xóa màn hình lúc đầu. 1020 01:26:39,590 --> 01:26:42,960 Nhưng bạn có thể nhìn lại các thiết lập vấn đề cuối cùng để xem làm thế nào bạn xóa màn hình. 1021 01:26:42,960 --> 01:26:45,160 Nó chỉ cần in một số ký tự 1022 01:26:45,160 --> 01:26:47,210 trong khi điều này đang làm những gì tôi muốn làm. 1023 01:26:47,210 --> 01:26:48,900 Okay. 1024 01:26:48,900 --> 01:26:55,280 Và suy nghĩ về lý do tại sao điều này cần thiết để là 0 thay vì stdin, 1025 01:26:55,280 --> 01:27:00,560 cần được # xác định 0, 1026 01:27:00,560 --> 01:27:03,890 này là phàn nàn rằng - 1027 01:27:13,150 --> 01:27:19,360 Trước khi tôi nói rằng có mô tả tập tin, nhưng sau đó bạn cũng có FILE *, 1028 01:27:19,360 --> 01:27:23,210 một mô tả tập tin chỉ là một số nguyên duy nhất, 1029 01:27:23,210 --> 01:27:26,970 trong khi một * FILE có một bó toàn bộ công cụ liên kết với nó. 1030 01:27:26,970 --> 01:27:30,380 Lý do chúng tôi cần phải nói 0 thay vì stdin 1031 01:27:30,380 --> 01:27:37,480 được stdin đó là một * FILE mà điểm đến điều đó là tham khảo mô tả tập tin 0. 1032 01:27:37,480 --> 01:27:45,070 Vì vậy, ngay cả ở đây khi tôi làm fopen (argv [1], tôi nhận được một * FILE. 1033 01:27:45,070 --> 01:27:51,180 Tuy nhiên, ở một nơi nào đó trong đó * FILE là một điều tương ứng với mô tả tập tin cho tập tin đó. 1034 01:27:51,180 --> 01:27:57,430 Nếu bạn nhìn vào trang người đàn ông mở, vì vậy tôi nghĩ rằng bạn sẽ phải làm mở man 3 - nope - 1035 01:27:57,430 --> 01:27:59,380 mở man 2 -. 1036 01:27:59,380 --> 01:28:06,250 Nếu bạn nhìn vào trang để mở, mở là như fopen cấp dưới, 1037 01:28:06,250 --> 01:28:09,350 và nó trở về mô tả tập tin thực tế. 1038 01:28:09,350 --> 01:28:12,050 fopen hiện một loạt các công cụ trên đầu trang của mở, 1039 01:28:12,050 --> 01:28:17,640 thay vì trả lại chỉ là mô tả tập tin trả về toàn bộ tập tin con trỏ 1040 01:28:17,640 --> 01:28:20,590 trong số đó là ít mô tả tập tin của chúng tôi. 1041 01:28:20,590 --> 01:28:25,020 Vì vậy, tiêu chuẩn đề cập đến điều * FILE, 1042 01:28:25,020 --> 01:28:29,120 trong khi đó 0 là để chỉ các tiêu chuẩn mô tả tập tin của riêng mình. 1043 01:28:29,120 --> 01:28:32,160 >> Câu hỏi? 1044 01:28:32,160 --> 01:28:35,930 [Cười] Blew thông qua đó. 1045 01:28:35,930 --> 01:28:39,140 Được rồi. Chúng tôi đang thực hiện. [Cười] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]