1 00:00:00,000 --> 00:00:02,730 [Powered by Google Translate] [Mục 5: LESS COMFORTABLE] 2 00:00:02,730 --> 00:00:05,180 [Nate hardison, Đại học Harvard] 3 00:00:05,180 --> 00:00:08,260 [Đây là CS50.] [CS50.TV] 4 00:00:08,260 --> 00:00:11,690 Vì vậy, chào đón trở lại, guys. 5 00:00:11,690 --> 00:00:16,320 Chào mừng bạn đến phần 5. 6 00:00:16,320 --> 00:00:20,220 Tại thời điểm này, đã hoàn thành bài kiểm tra 0 và sau khi nhìn thấy bạn đã thực hiện như thế nào, 7 00:00:20,220 --> 00:00:25,770 hy vọng bạn cảm thấy thực sự tốt bởi vì tôi đã rất ấn tượng bởi điểm số trong phần này. 8 00:00:25,770 --> 00:00:28,050 Cho người xem trực tuyến của chúng tôi, chúng tôi đã có một vài câu hỏi 9 00:00:28,050 --> 00:00:33,680 về hai vấn đề cuối cùng trên các thiết lập vấn đề - hoặc trên các bài kiểm tra, thay vì. 10 00:00:33,680 --> 00:00:39,690 Vì vậy, chúng ta sẽ đi qua những người thực sự nhanh chóng để mọi người thấy những gì đã xảy ra 11 00:00:39,690 --> 00:00:45,060 và làm thế nào để đi qua các giải pháp thực tế hơn là chỉ xem các giải pháp riêng của mình. 12 00:00:45,060 --> 00:00:50,330 Chúng ta sẽ đi qua vài vấn đề thực sự nhanh chóng, 32 và 33. 13 00:00:50,330 --> 00:00:53,240 Chỉ là, một lần nữa, vì vậy mà người xem trực tuyến có thể thấy điều này. 14 00:00:53,240 --> 00:00:59,080 >> Nếu bạn chuyển sang vấn đề của bạn 32, mà là trên trang 13, 15 00:00:59,080 --> 00:01:02,730 13 trong số 16, vấn đề 32 là tất cả về giao dịch hoán đổi. 16 00:01:02,730 --> 00:01:05,010 Đó là tất cả về trao đổi hai số nguyên. 17 00:01:05,010 --> 00:01:08,740 Đó là vấn đề mà chúng tôi muốn đi qua một vài lần trong bài giảng. 18 00:01:08,740 --> 00:01:13,590 Và ở đây, những gì chúng tôi đã yêu cầu bạn làm một dấu vết bộ nhớ nhanh chóng. 19 00:01:13,590 --> 00:01:17,000 Để điền vào các giá trị của các biến như họ đang ở trên stack 20 00:01:17,000 --> 00:01:20,250 như là mã đi qua chức năng này trao đổi. 21 00:01:20,250 --> 00:01:24,500 Đặc biệt, những gì chúng tôi đang tìm kiếm tại - tôi sẽ đặt này iPad - 22 00:01:24,500 --> 00:01:29,650 Đặc biệt, những gì chúng tôi đang tìm kiếm ở dòng này số 6 ngay tại đây. 23 00:01:29,650 --> 00:01:36,740 Và nó số 6 chỉ tiếp giáp với các vấn đề trước. 24 00:01:36,740 --> 00:01:41,720 Những gì chúng tôi muốn làm là hiển thị hoặc nhãn trạng thái của bộ nhớ 25 00:01:41,720 --> 00:01:46,090 vì nó là vào thời điểm khi chúng tôi thực hiện này số dòng 6, 26 00:01:46,090 --> 00:01:52,540 đó là hiệu quả trở lại từ chức năng trao đổi của chúng tôi ngay tại đây. 27 00:01:52,540 --> 00:01:59,450 Nếu chúng ta di chuyển xuống đây, chúng tôi thấy rằng các địa chỉ của tất cả mọi thứ trong bộ nhớ đã được cung cấp cho chúng tôi. 28 00:01:59,450 --> 00:02:02,540 Điều này là rất quan trọng, chúng ta sẽ trở về với nó trong thời điểm này chỉ là một. 29 00:02:02,540 --> 00:02:09,240 Và sau đó xuống đây ở phía dưới, chúng tôi đã có một sơ đồ rất ít bộ nhớ mà chúng tôi sẽ giới thiệu cho. 30 00:02:09,240 --> 00:02:12,490 Tôi đã thực sự làm được điều này trên iPad của tôi. 31 00:02:12,490 --> 00:02:20,720 Vì vậy, tôi sẽ phải luân phiên qua lại giữa iPad và mã này chỉ để tham khảo. 32 00:02:20,720 --> 00:02:26,540 >> Hãy bắt đầu. Trước tiên, chúng ta hãy tập trung vào các cặp vợ chồng đầu tiên của dòng chính quyền ở đây. 33 00:02:26,540 --> 00:02:30,220 Để bắt đầu, chúng ta sẽ khởi tạo x 1 và y đến 2. 34 00:02:30,220 --> 00:02:33,040 Vì vậy, chúng tôi có hai biến số nguyên, họ cả hai sẽ được đặt trên stack. 35 00:02:33,040 --> 00:02:36,050 Chúng ta sẽ đặt một 1 và 2 trong chúng. 36 00:02:36,050 --> 00:02:43,150 Vì vậy, nếu tôi lật qua iPad của tôi, hy vọng, chúng ta hãy xem - 37 00:02:43,150 --> 00:02:48,660 Apple TV phản chiếu, và ở đó chúng tôi đi. Okay. 38 00:02:48,660 --> 00:02:51,670 Vì vậy, nếu tôi đưa bạn đến iPad của tôi, 39 00:02:51,670 --> 00:02:56,220 Tôi muốn khởi tạo x 1 và y đến 2. 40 00:02:56,220 --> 00:03:00,580 Chúng tôi làm điều đó khá đơn giản bằng cách viết một 1 trong hộp đánh dấu x 41 00:03:00,580 --> 00:03:07,730 và 2 trong hộp đánh dấu y. Khá đơn giản. 42 00:03:07,730 --> 00:03:11,620 Vì vậy, bây giờ chúng ta hãy quay trở lại máy tính xách tay, xem những gì sẽ xảy ra tiếp theo. 43 00:03:11,620 --> 00:03:15,810 Vì vậy, dòng này tiếp theo là nơi mà mọi thứ trở nên khó khăn. 44 00:03:15,810 --> 00:03:28,110 Chúng tôi vượt qua địa chỉ của x và địa chỉ của y là tham số a và b đến chức năng trao đổi. 45 00:03:28,110 --> 00:03:32,380 Địa chỉ của x và địa chỉ của y là điều mà chúng tôi không thể tính toán 46 00:03:32,380 --> 00:03:36,360 mà không đề cập đến những viên đạn chỉ phải xuống ở đây. 47 00:03:36,360 --> 00:03:39,750 Và may mắn thay, hai điểm đạn đầu tiên cho chúng tôi biết chính xác những gì các câu trả lời. 48 00:03:39,750 --> 00:03:44,740 Địa chỉ của x trong bộ nhớ là 10, và địa chỉ của y trong bộ nhớ là 14. 49 00:03:44,740 --> 00:03:51,870 Vì vậy, những giá trị mà có được thông qua tại như a và b lên hàng đầu trong chức năng trao đổi của chúng tôi. 50 00:03:51,870 --> 00:04:00,760 Vì vậy, một lần nữa, chuyển đổi trở lại sơ đồ của chúng tôi, tôi có thể viết 10 trong một 51 00:04:00,760 --> 00:04:07,400 và 14 in b. 52 00:04:07,400 --> 00:04:11,610 Bây giờ, thời điểm này là nơi mà chúng tôi tiến hành trao đổi. 53 00:04:11,610 --> 00:04:14,520 Vì vậy, lật lại cho máy tính xách tay một lần nữa, 54 00:04:14,520 --> 00:04:21,079 chúng ta thấy rằng cách trao đổi các công trình là lần đầu tiên tôi tới đích và lưu trữ các kết quả trong tmp. 55 00:04:21,079 --> 00:04:27,650 Vì vậy, các nhà điều hành dereference nói, "Hey Hãy đối xử với các nội dung của một biến như là một địa chỉ. 56 00:04:27,650 --> 00:04:33,830 Tới bất cứ điều gì được lưu trữ tại địa chỉ đó, và tải nó. " 57 00:04:33,830 --> 00:04:41,720 Những gì bạn nạp của biến sẽ được lưu trữ vào một biến tmp của chúng tôi. 58 00:04:41,720 --> 00:04:45,150 Lật lại iPad. 59 00:04:45,150 --> 00:04:51,690 Nếu chúng tôi đi để giải quyết 10, chúng ta biết rằng địa chỉ 10 là x varible 60 00:04:51,690 --> 00:04:55,480 bởi vì chúng tôi mới biết điểm bullet của chúng tôi là địa chỉ của x trong bộ nhớ là 10. 61 00:04:55,480 --> 00:05:00,180 Vì vậy, chúng ta có thể đi đến đó, nhận được giá trị của nó, mà là 1, như chúng ta thấy trên iPad của chúng tôi, 62 00:05:00,180 --> 00:05:06,300 và tải đó vào tmp. 63 00:05:06,300 --> 00:05:08,250 Một lần nữa, đây không phải là nội dung cuối cùng. 64 00:05:08,250 --> 00:05:14,350 Chúng ta sẽ phải đi bộ qua và chúng tôi sẽ nhận được trạng thái của chương trình cuối cùng của chúng tôi ở cuối. 65 00:05:14,350 --> 00:05:17,210 Nhưng ngay bây giờ, chúng tôi có giá trị 1 được lưu trữ trong tmp. 66 00:05:17,210 --> 00:05:19,210 >> Và có một câu hỏi nhanh chóng hơn ở đây. 67 00:05:19,210 --> 00:05:23,980 Alexander dereference điều hành - đó chỉ là quyền ngôi sao ở phía trước của biến? 68 00:05:23,980 --> 00:05:27,600 >>. Vì vậy, các nhà điều hành dereference, khi chúng tôi lật lại cho máy tính xách tay của chúng tôi một lần nữa, 69 00:05:27,600 --> 00:05:33,780 là ngôi sao này ngay trước mặt. 70 00:05:33,780 --> 00:05:37,460 Trong ý nghĩa đó, nó là bạn tương phản với các nhà điều hành nhân 71 00:05:37,460 --> 00:05:42,400 đòi hỏi hai điều, các nhà điều hành dereference là một nhà điều hành unary. 72 00:05:42,400 --> 00:05:46,130 Chỉ cần áp dụng một giá trị như trái ngược với một nhà điều hành nhị phân, 73 00:05:46,130 --> 00:05:48,810 nơi bạn áp dụng hai giá trị khác nhau. 74 00:05:48,810 --> 00:05:52,080 Vì vậy, đó là những gì xảy ra trong dòng này. 75 00:05:52,080 --> 00:05:58,390 Chúng tôi được nạp giá trị 1 và lưu trữ nó vào một biến số nguyên của chúng tôi tạm thời. 76 00:05:58,390 --> 00:06:05,800 Dòng tiếp theo, chúng tôi lưu trữ các nội dung của b vào - 77 00:06:05,800 --> 00:06:12,630 hoặc, đúng hơn, chúng tôi lưu trữ các nội dung mà b đang trỏ vào nơi được trỏ đến. 78 00:06:12,630 --> 00:06:17,690 Nếu chúng ta phân tích từ phải sang trái, chúng ta sẽ để b dereference, 79 00:06:17,690 --> 00:06:23,580 chúng ta sẽ để giải quyết 14, chúng ta sẽ lấy các số nguyên đó là có, 80 00:06:23,580 --> 00:06:26,900 và sau đó chúng ta sẽ đi đến địa chỉ 10, 81 00:06:26,900 --> 00:06:34,240 và chúng ta sẽ ném kết quả của dereference của chúng tôi của b vào không gian đó. 82 00:06:34,240 --> 00:06:40,080 Flipping trở lại iPad của chúng tôi, nơi chúng tôi có thể làm cho nhiều hơn một chút cụ thể, 83 00:06:40,080 --> 00:06:44,070 nó có thể giúp nếu tôi viết con số trên tất cả các địa chỉ ở đây. 84 00:06:44,070 --> 00:06:53,820 Vì vậy, chúng ta biết rằng ở y, chúng tôi tại địa chỉ 14, x là tại địa chỉ 10. 85 00:06:53,820 --> 00:07:00,180 Khi chúng tôi bắt đầu b, chúng tôi dereference b, chúng tôi đang đi để lấy giá trị 2. 86 00:07:00,180 --> 00:07:08,320 Chúng tôi sẽ lấy giá trị này bởi vì đó là giá trị sống tại địa chỉ 14. 87 00:07:08,320 --> 00:07:15,700 Và chúng ta sẽ phải đặt nó vào biến sống tại địa chỉ 10, 88 00:07:15,700 --> 00:07:19,160 mà là phải có, tương ứng với biến x của chúng tôi. 89 00:07:19,160 --> 00:07:21,810 Vì vậy, chúng ta có thể làm một ít ghi đè 90 00:07:21,810 --> 00:07:35,380 nơi mà chúng tôi nhận được thoát khỏi 1 của chúng tôi và thay vào đó chúng ta viết 2. 91 00:07:35,380 --> 00:07:39,560 Vì vậy, tất cả là tốt và tốt nhất trên thế giới, mặc dù chúng tôi đã x ghi đè. 92 00:07:39,560 --> 00:07:44,890 Chúng tôi đã được lưu trữ giá trị cũ của x trong biến tmp của chúng tôi. 93 00:07:44,890 --> 00:07:50,210 Vì vậy, chúng ta có thể hoàn thành việc trao đổi với các dòng tiếp theo. 94 00:07:50,210 --> 00:07:53,030 Lật lại để máy tính xách tay của chúng tôi. 95 00:07:53,030 --> 00:07:58,150 Bây giờ tất cả còn lại đó là lấy nội dung của biến số nguyên của chúng tôi tạm thời 96 00:07:58,150 --> 00:08:05,630 và lưu trữ chúng vào biến sống tại địa chỉ mà b đang nắm giữ. 97 00:08:05,630 --> 00:08:10,230 Vì vậy, chúng ta sẽ để b dereference hiệu quả để có được quyền truy cập vào biến 98 00:08:10,230 --> 00:08:14,340 đó là tại địa chỉ mà b nắm giữ trong nó, 99 00:08:14,340 --> 00:08:19,190 và chúng tôi sẽ công cụ giá trị tmp đang nắm giữ vào nó. 100 00:08:19,190 --> 00:08:23,280 Lật lại để iPad một lần nữa. 101 00:08:23,280 --> 00:08:31,290 Tôi có thể xóa giá trị này ở đây, 2, 102 00:08:31,290 --> 00:08:41,010 và thay vào đó chúng tôi sẽ sao chép các quyền 1 vào nó. 103 00:08:41,010 --> 00:08:43,059 Sau đó, các dòng tiếp theo, được thực hiện, tất nhiên - 104 00:08:43,059 --> 00:08:47,150 nếu chúng ta lật trở lại cho máy tính xách tay - là điểm 6, 105 00:08:47,150 --> 00:08:52,500 đó là điểm mà tại đó, chúng tôi muốn có sơ đồ của chúng tôi điền đầy đủ. 106 00:08:52,500 --> 00:08:58,940 Vì vậy, lật trở lại với iPad một lần nữa, chỉ cần như vậy bạn có thể xem sơ đồ hoàn thành, 107 00:08:58,940 --> 00:09:06,610 bạn có thể thấy rằng chúng tôi có 10 trong một, 14 in b, 1 trong tmp, a 2 trong x, và 1 trong y. 108 00:09:06,610 --> 00:09:11,000 Có bất kỳ câu hỏi nào về điều này? 109 00:09:11,000 --> 00:09:14,640 Điều này có ý nghĩa hơn, sau khi đã đi qua nó? 110 00:09:14,640 --> 00:09:24,850 Ít có ý nghĩa hơn? Hy vọng rằng không. Okay. 111 00:09:24,850 --> 00:09:28,230 >> Con trỏ là một chủ đề rất khó khăn. 112 00:09:28,230 --> 00:09:33,420 Một trong những kẻ chúng ta làm việc với có một câu nói rất phổ biến: 113 00:09:33,420 --> 00:09:36,590 "Để hiểu được con trỏ, trước tiên bạn phải hiểu con trỏ." 114 00:09:36,590 --> 00:09:40,530 Mà tôi nghĩ là rất đúng. Nó có phải mất một thời gian để làm quen với nó. 115 00:09:40,530 --> 00:09:45,360 Vẽ rất nhiều hình ảnh, bản vẽ rất nhiều sơ đồ bộ nhớ như thế này rất hữu ích, 116 00:09:45,360 --> 00:09:49,480 và sau khi bạn đi bộ thông qua ví dụ sau ví dụ sau ví dụ, 117 00:09:49,480 --> 00:09:54,450 nó sẽ bắt đầu có ý nghĩa nhiều hơn một chút và ý thức hơn một chút và một ít ý nghĩa hơn. 118 00:09:54,450 --> 00:10:01,560 Cuối cùng, một ngày, bạn sẽ có tất cả hoàn toàn làm chủ. 119 00:10:01,560 --> 00:10:13,800 Bất kỳ câu hỏi trước khi chúng ta chuyển sang vấn đề tiếp theo? Được rồi. 120 00:10:13,800 --> 00:10:18,840 Vì vậy, lật trở lại cho máy tính xách tay. 121 00:10:18,840 --> 00:10:23,300 Vấn đề tiếp theo chúng ta có là số 33 vấn đề trên tập tin I / O. 122 00:10:23,300 --> 00:10:26,350 Phóng to chút này một chút. 123 00:10:26,350 --> 00:10:28,710 Vấn đề 33 -? 124 00:10:28,710 --> 00:10:32,110 >> [Daniel] Tôi chỉ có một câu hỏi nhanh chóng. Ngôi sao này, hoặc dấu hoa thị, 125 00:10:32,110 --> 00:10:35,590 nó được gọi là dereferencing khi bạn sử dụng một dấu hoa thị trước. 126 00:10:35,590 --> 00:10:38,820 Đó là những gì được gọi là khi bạn sử dụng dấu "và" trước? 127 00:10:38,820 --> 00:10:43,140 >> Dấu "và" trước khi là địa chỉ của nhà điều hành. 128 00:10:43,140 --> 00:10:45,880 Vì vậy, hãy di chuyển trở lại. 129 00:10:45,880 --> 00:10:49,310 Rất tiếc. Tôi đang ở chế độ phóng to để tôi có thể không thực sự di chuyển. 130 00:10:49,310 --> 00:10:52,780 Nếu chúng ta nhìn vào mã này thực sự nhanh chóng ngay tại đây, 131 00:10:52,780 --> 00:10:54,980 một lần nữa, cùng một điều xảy ra. 132 00:10:54,980 --> 00:10:59,180 Nếu chúng ta nhìn vào mã này ngay tại đây, trên đường dây này, nơi chúng tôi thực hiện cuộc gọi để trao đổi, 133 00:10:59,180 --> 00:11:10,460 dấu và chỉ nói "có được địa chỉ mà ở đó cuộc sống của biến x." 134 00:11:10,460 --> 00:11:14,460 Khi trình biên dịch của bạn biên dịch mã của bạn, 135 00:11:14,460 --> 00:11:20,590 nó có thể chất thực sự đánh dấu một vị trí trong bộ nhớ cho tất cả các biến của bạn để sinh sống. 136 00:11:20,590 --> 00:11:24,910 Và vì vậy những gì các trình biên dịch sau đó có thể làm một khi nó được biên dịch tất cả mọi thứ, 137 00:11:24,910 --> 00:11:31,110 nó biết, "Ồ, tôi đặt x tại địa chỉ 10 tôi đặt y tại địa chỉ 14." 138 00:11:31,110 --> 00:11:34,640 Sau đó nó có thể điền vào các giá trị cho bạn. 139 00:11:34,640 --> 00:11:44,740 Vì vậy, bạn có thể sau đó - sau đó nó có thể vượt qua điều này và vượt qua & y cũng. 140 00:11:44,740 --> 00:11:50,730 Những anh chàng này có được địa chỉ, nhưng họ cũng có, khi bạn vượt qua chúng vào các chức năng trao đổi, 141 00:11:50,730 --> 00:11:55,690 loại thông tin này, int * ngay tại đây, cho trình biên dịch, 142 00:11:55,690 --> 00:12:01,350 "Được rồi, chúng ta sẽ được giải thích địa chỉ này như là một địa chỉ của một biến số nguyên". 143 00:12:01,350 --> 00:12:05,900 Như một địa chỉ của một int, mà là khác nhau từ địa chỉ của một biến ký tự 144 00:12:05,900 --> 00:12:09,930 bởi vì một int chiếm, trên một máy tính 32-bit, chiếm 4 byte của không gian, 145 00:12:09,930 --> 00:12:13,310 trong khi một nhân vật chỉ chiếm 1 byte của không gian. 146 00:12:13,310 --> 00:12:17,310 Vì vậy, nó là quan trọng để biết những gì là - những gì cuộc sống, những gì loại có giá trị 147 00:12:17,310 --> 00:12:20,340 đang sống tại địa chỉ đã thông qua nhập 148 00:12:20,340 --> 00:12:22,020 Hoặc địa chỉ mà bạn đang xử lý. 149 00:12:22,020 --> 00:12:29,020 Bằng cách đó, bạn biết có bao nhiêu byte thông tin để thực sự tải của bộ nhớ RAM của bạn. 150 00:12:29,020 --> 00:12:31,780 Và sau đó, có, nhà điều hành này dereference, giống như bạn đã được yêu cầu, 151 00:12:31,780 --> 00:12:37,200 đi và truy cập thông tin tại một địa chỉ cụ thể. 152 00:12:37,200 --> 00:12:42,820 Vì vậy, nó nói, với một biến ở đây, điều trị các nội dung của một như một địa chỉ, 153 00:12:42,820 --> 00:12:47,880 đi đến địa chỉ đó, và kéo ra, nạp vào bộ vi xử lý, tải vào đăng ký 154 00:12:47,880 --> 00:12:56,340 thực tế các giá trị hoặc các nội dung sống tại địa chỉ đó. 155 00:12:56,340 --> 00:12:59,620 Bất kỳ câu hỏi? Đây là những câu hỏi hay. 156 00:12:59,620 --> 00:13:01,650 Đó là rất nhiều thuật ngữ mới. 157 00:13:01,650 --> 00:13:09,800 Nó cũng loại của funky, nhìn thấy & và * ở những nơi khác nhau. 158 00:13:09,800 --> 00:13:13,180 >> Được rồi. 159 00:13:13,180 --> 00:13:18,530 Vì vậy, trở lại vấn đề 33, nộp I / O. 160 00:13:18,530 --> 00:13:22,540 Đây là một trong những vấn đề mà tôi nghĩ rằng một vài điều đã xảy ra. 161 00:13:22,540 --> 00:13:25,400 Một, nó là một chủ đề khá mới. 162 00:13:25,400 --> 00:13:30,590 Nó đã được trình bày khá sớm trước khi bài kiểm tra, 163 00:13:30,590 --> 00:13:33,400 và sau đó tôi nghĩ rằng đó là loại giống như một trong những vấn đề từ trong toán học 164 00:13:33,400 --> 00:13:39,720 nơi mà họ cung cấp cho bạn rất nhiều thông tin, nhưng bạn thực sự không phải sử dụng một tấn của nó. 165 00:13:39,720 --> 00:13:44,060 Phần đầu tiên của vấn đề này được mô tả một tập tin CSV. 166 00:13:44,060 --> 00:13:50,620 Bây giờ, một tập tin CSV, theo mô tả, là một giá trị được phân cách bằng dấu phẩy tập tin. 167 00:13:50,620 --> 00:13:55,300 Lý do đây là ở tất cả các thú vị, và lý do bạn đã bao giờ sử dụng chúng, 168 00:13:55,300 --> 00:14:00,800 , bởi vì, có bao nhiêu bạn đã từng sử dụng các công cụ như Excel? 169 00:14:00,800 --> 00:14:03,240 Hình hầu hết các bạn có, có lẽ, hoặc sẽ sử dụng tại một số điểm trong cuộc sống của bạn. 170 00:14:03,240 --> 00:14:06,430 Bạn sẽ sử dụng một cái gì đó giống như Excel. 171 00:14:06,430 --> 00:14:10,940 Để có được các dữ liệu của một bảng tính Excel hoặc làm bất kỳ loại chế biến với nó, 172 00:14:10,940 --> 00:14:17,240 nếu bạn muốn viết một chương trình C hoặc chương trình Python, Java chương trình, 173 00:14:17,240 --> 00:14:20,070 để đối phó với các số liệu đã được lưu trữ trong đó, 174 00:14:20,070 --> 00:14:23,170 một trong những cách phổ biến nhất để có được nó trong một tập tin CSV. 175 00:14:23,170 --> 00:14:26,850 Và bạn có thể mở Excel và khi bạn đi đến 'Save as' đối thoại, 176 00:14:26,850 --> 00:14:32,840 bạn có thể nhận ra một tập tin CSV thực tế. 177 00:14:32,840 --> 00:14:35,890 >> Tiện dụng để biết làm thế nào để đối phó với những điều này. 178 00:14:35,890 --> 00:14:42,010 Cách nó hoạt động là nó tương tự như - Ý tôi là, nó chủ yếu bắt chước một bảng tính, 179 00:14:42,010 --> 00:14:47,590 ở đâu, như chúng ta thấy ở đây, trong phần rất trái nhất, 180 00:14:47,590 --> 00:14:49,910 chúng tôi có tất cả các tên cuối cùng. 181 00:14:49,910 --> 00:14:54,670 Vì vậy, chúng tôi có Malan, sau đó hardison, và sau đó Bowden, MacWilliam, và sau đó Chan. 182 00:14:54,670 --> 00:14:59,470 Cuối cùng tên. Và sau đó một dấu phẩy tách tên cuối cùng từ cái tên đầu tiên. 183 00:14:59,470 --> 00:15:02,970 David, Nate, Rob, Tommy, và Zamyla. 184 00:15:02,970 --> 00:15:06,850 Tôi luôn luôn pha trộn lên Robby và Tom. 185 00:15:06,850 --> 00:15:10,940 Và sau đó, cuối cùng, cột thứ ba là các địa chỉ email. 186 00:15:10,940 --> 00:15:18,500 Khi bạn hiểu rằng, phần còn lại của chương trình là khá đơn giản để thực hiện. 187 00:15:18,500 --> 00:15:23,850 Những gì chúng tôi đã làm để bắt chước cấu trúc này tương tự trong chương trình C của chúng tôi 188 00:15:23,850 --> 00:15:27,510 là chúng tôi đã sử dụng một cấu trúc. 189 00:15:27,510 --> 00:15:30,520 Chúng tôi sẽ bắt đầu chơi với những nhiều hơn một chút là tốt. 190 00:15:30,520 --> 00:15:35,790 Chúng tôi nhìn thấy chút đầu tiên trong 3 bộ vấn đề, khi chúng tôi đang đối phó với các từ điển. 191 00:15:35,790 --> 00:15:40,290 Nhưng điều này struct nhân viên lưu trữ một tên cuối cùng, một tên đầu tiên, và một email. 192 00:15:40,290 --> 00:15:44,500 Cũng giống như tập tin CSV của chúng tôi đã được lưu trữ. 193 00:15:44,500 --> 00:15:47,950 Vì vậy, đây chỉ là chuyển đổi từ một định dạng khác. 194 00:15:47,950 --> 00:15:54,630 Chúng tôi phải chuyển đổi, trong trường hợp này, một cấu trúc nhân viên thành một dòng, 195 00:15:54,630 --> 00:15:59,060 một dòng được phân cách bằng dấu phẩy, chỉ như thế. 196 00:15:59,060 --> 00:16:01,500 Điều đó làm cho tinh thần? Tất cả các bạn đã thực hiện các bài kiểm tra, 197 00:16:01,500 --> 00:16:07,680 vì vậy tôi tưởng tượng bạn đã ít nhất đã có một thời gian để nghĩ về điều này. 198 00:16:07,680 --> 00:16:16,410 >> Trong các chức năng cho thuê, vấn đề đòi hỏi chúng ta phải thực hiện trong - zoom we'll chút này một chút - 199 00:16:16,410 --> 00:16:22,480 trong một cấu trúc nhân viên, một cấu trúc nhân viên, tên, 200 00:16:22,480 --> 00:16:30,900 và thêm nội dung của nó tập tin staff.csv của chúng tôi. 201 00:16:30,900 --> 00:16:34,230 Nó chỉ ra rằng điều này là khá đơn giản để sử dụng. 202 00:16:34,230 --> 00:16:37,430 Chúng tôi loại sẽ chơi xung quanh với các chức năng hiện nay hơn một chút. 203 00:16:37,430 --> 00:16:44,510 Tuy nhiên, trong trường hợp này, hàm fprintf thực sự là chìa khóa. 204 00:16:44,510 --> 00:16:51,960 Vì vậy, với fprintf, chúng tôi có thể in, giống như các bạn đã được sử dụng printf cả nhiệm kỳ này. 205 00:16:51,960 --> 00:16:55,050 Bạn có thể printf một dòng vào một tập tin. 206 00:16:55,050 --> 00:16:59,030 Vì vậy, thay vì chỉ làm cho các cuộc gọi thông thường printf nơi bạn cung cấp cho nó các chuỗi định dạng 207 00:16:59,030 --> 00:17:05,380 và sau đó bạn thay thế tất cả các biến với các đối số sau đây, 208 00:17:05,380 --> 00:17:11,290 với fprintf, lập luận của bạn đầu tiên là thay vì tập tin bạn muốn viết thư cho. 209 00:17:11,290 --> 00:17:21,170 Nếu chúng ta xem xét điều này trong thiết bị, ví dụ, người đàn ông fprintf, 210 00:17:21,170 --> 00:17:25,980 chúng ta có thể thấy sự khác biệt giữa printf và fprintf. 211 00:17:25,980 --> 00:17:28,960 Tôi sẽ phóng to ở đây một chút. 212 00:17:28,960 --> 00:17:33,140 Vì vậy, với printf, chúng tôi cung cấp cho nó một chuỗi định dạng, và sau đó các đối số tiếp theo 213 00:17:33,140 --> 00:17:37,580 là tất cả các biến để thay thế hoặc thay thế vào chuỗi định dạng của chúng tôi. 214 00:17:37,580 --> 00:17:47,310 Trong khi với fprintf, tham số đầu tiên thực sự là tập tin * này được gọi là một dòng suối. 215 00:17:47,310 --> 00:17:51,800 >> Di chuyển trở lại trên đây cho thuê của chúng tôi, 216 00:17:51,800 --> 00:17:54,550 chúng tôi đã có dòng * tập tin của chúng tôi mở ra cho ta. 217 00:17:54,550 --> 00:17:57,810 Đó là những dòng đầu tiên này, nó mở tập tin staff.csv, 218 00:17:57,810 --> 00:18:01,690 mở nó trong chế độ phụ thêm, và tất cả những gì còn lại cho chúng ta làm là 219 00:18:01,690 --> 00:18:08,640 viết cấu trúc nhân viên vào tập tin. 220 00:18:08,640 --> 00:18:10,870 Và, chúng ta hãy xem, tôi muốn sử dụng iPad? 221 00:18:10,870 --> 00:18:17,900 Tôi sẽ sử dụng iPad. Chúng tôi có void - cho là đặt trên bàn để tôi có thể viết tốt hơn một chút - 222 00:18:17,900 --> 00:18:33,680 làm mất hiệu lực thuê và phải mất một đối số, cơ cấu cán bộ gọi là s. 223 00:18:33,680 --> 00:18:44,120 Niềng răng của chúng tôi, chúng tôi đã có tập tin * của chúng tôi tập tin gọi là, 224 00:18:44,120 --> 00:18:48,380 chúng tôi có dòng fopen của chúng tôi ban cho chúng ta, 225 00:18:48,380 --> 00:18:51,890 và tôi chỉ sẽ viết nó như một dấu chấm vì nó đã có trong các Pedia. 226 00:18:51,890 --> 00:19:00,530 Và sau đó trên dòng tiếp theo của chúng tôi, chúng tôi sẽ làm cho một cuộc gọi đến fprintf 227 00:19:00,530 --> 00:19:03,700 và chúng ta sẽ phải vượt qua trong tập tin mà chúng ta muốn in, 228 00:19:03,700 --> 00:19:10,290 và sau đó định dạng chuỗi của chúng tôi, trong đó - 229 00:19:10,290 --> 00:19:14,300 Tôi sẽ cho các bạn cho tôi biết những gì nó trông giống như. 230 00:19:14,300 --> 00:19:20,500 Làm thế nào về bạn, Stella? Bạn có biết những gì phần đầu tiên của chuỗi định dạng trông giống như? 231 00:19:20,500 --> 00:19:24,270 Stella] Tôi không chắc chắn. >> Hãy hỏi Jimmy. 232 00:19:24,270 --> 00:19:27,690 Bạn có biết, Jimmy? 233 00:19:27,690 --> 00:19:31,000 [Jimmy] có nó chỉ là cuối cùng? Tôi không biết. Tôi không hoàn toàn chắc chắn. 234 00:19:31,000 --> 00:19:39,020 >> Okay. Làm thế nào về, không ai có được điều này đúng vào kỳ thi? 235 00:19:39,020 --> 00:19:41,770 Số Tất cả các quyền. 236 00:19:41,770 --> 00:19:47,920 Nó chỉ ra rằng ở đây tất cả chúng ta phải làm là chúng tôi muốn mỗi một phần của cấu trúc nhân viên của chúng tôi 237 00:19:47,920 --> 00:19:53,290 được in ra như là một chuỗi vào tập tin của chúng tôi. 238 00:19:53,290 --> 00:19:59,900 Chúng tôi chỉ cần sử dụng chuỗi ký tự thay thế ba lần khác nhau, vì chúng ta có một tên cuối cùng 239 00:19:59,900 --> 00:20:07,160 theo sau dấu phẩy, sau đó một tên đầu tiên sau dấu phẩy, 240 00:20:07,160 --> 00:20:12,430 và sau đó cuối cùng là địa chỉ email mà được theo sau - đó là không 241 00:20:12,430 --> 00:20:15,140 phù hợp trên màn hình của tôi, nhưng nó tiếp theo ký tự xuống dòng. 242 00:20:15,140 --> 00:20:20,060 Vì vậy, tôi sẽ viết nó xuống đó. 243 00:20:20,060 --> 00:20:23,560 Và sau đó sau chuỗi định dạng của chúng tôi, 244 00:20:23,560 --> 00:20:27,880 chúng tôi chỉ có thay thế, mà chúng ta truy cập bằng cách sử dụng các ký hiệu dấu chấm 245 00:20:27,880 --> 00:20:31,370 mà chúng ta thấy trong 3 bộ vấn đề. 246 00:20:31,370 --> 00:20:48,820 Chúng tôi có thể sử dụng s.last, s.first, và s.email 247 00:20:48,820 --> 00:20:58,990 để thay thế trong ba giá trị vào chuỗi định dạng của chúng tôi. 248 00:20:58,990 --> 00:21:06,190 Vậy làm thế nào mà đi? Có ý nghĩa? 249 00:21:06,190 --> 00:21:09,700 Vâng? Không? Có thể? Okay. 250 00:21:09,700 --> 00:21:14,180 >> Điều cuối cùng mà chúng ta làm sau khi chúng tôi đã in và sau khi chúng tôi đã mở tập tin của chúng tôi: 251 00:21:14,180 --> 00:21:17,370 bất cứ khi nào chúng tôi đã mở một tập tin, chúng tôi luôn luôn phải nhớ để đóng nó. 252 00:21:17,370 --> 00:21:19,430 Bởi vì nếu không chúng tôi sẽ kết thúc rò rỉ bộ nhớ, 253 00:21:19,430 --> 00:21:22,500 sử dụng mô tả tập tin. 254 00:21:22,500 --> 00:21:25,950 Vì vậy, để đóng nó, chúng tôi sử dụng có chức năng nào? Daniel? 255 00:21:25,950 --> 00:21:30,120 [Daniel] fclose? >> Fclose, chính xác. 256 00:21:30,120 --> 00:21:37,520 Vì vậy, phần cuối cùng của vấn đề này là đúng đóng tập tin, bằng cách sử dụng các chức năng fclose, 257 00:21:37,520 --> 00:21:40,370 mà chỉ trông như thế. 258 00:21:40,370 --> 00:21:43,880 Không quá điên rồ. 259 00:21:43,880 --> 00:21:46,990 Cool. 260 00:21:46,990 --> 00:21:49,520 Vì vậy, đó là vấn đề 33 trên quiz. 261 00:21:49,520 --> 00:21:52,480 Chúng tôi sẽ có tập tin chắc chắn hơn I / O đến. 262 00:21:52,480 --> 00:21:55,130 Chúng tôi sẽ làm hơn một chút trong bài giảng ngày hôm nay, hoặc trong phần ngày hôm nay, 263 00:21:55,130 --> 00:22:01,710 bởi vì đó là những gì đang xảy ra để tạo thành phần lớn này pset sắp tới. 264 00:22:01,710 --> 00:22:05,020 Chúng ta hãy chuyển từ các bài kiểm tra vào thời điểm này. Vâng? 265 00:22:05,020 --> 00:22:10,880 >> [Charlotte]] Tại sao fclose (file) thay vì fclose (staff.csv)? 266 00:22:10,880 --> 00:22:19,100 >> Ah. Bởi vì nó chỉ ra đó - vì vậy câu hỏi, mà là một tuyệt vời, 267 00:22:19,100 --> 00:22:27,800 là lý do tại sao, khi chúng tôi viết fclose, chúng ta viết sao biến fclose (file) 268 00:22:27,800 --> 00:22:33,680 như trái ngược với tên tập tin, staff.csv? Là đúng? Yeah. 269 00:22:33,680 --> 00:22:39,570 Vì vậy, chúng ta hãy có một cái nhìn. Nếu tôi chuyển về máy tính xách tay của tôi, 270 00:22:39,570 --> 00:22:45,040 và chúng ta hãy nhìn vào các chức năng fclose. 271 00:22:45,040 --> 00:22:51,460 Vì vậy, các chức năng fclose đóng một dòng suối và phải mất trong con trỏ vào dòng mà chúng tôi muốn đóng, 272 00:22:51,460 --> 00:22:57,010 như trái ngược với tên tập tin thực tế mà chúng tôi muốn đóng. 273 00:22:57,010 --> 00:23:01,620 Và điều này là bởi vì đằng sau hậu trường, khi bạn thực hiện một cuộc gọi đến fopen, 274 00:23:01,620 --> 00:23:12,020 khi bạn mở một tập tin, bạn đang thực sự cấp phát bộ nhớ để lưu trữ thông tin về tập tin. 275 00:23:12,020 --> 00:23:16,380 Vì vậy, bạn có con trỏ tập tin có thông tin về tập tin, 276 00:23:16,380 --> 00:23:23,080 như nó mở, kích thước của nó, nơi mà bạn đang xem trong tập tin, 277 00:23:23,080 --> 00:23:29,100 để bạn có thể làm cho việc đọc và viết các cuộc gọi đến mà địa điểm cụ thể trong tập tin. 278 00:23:29,100 --> 00:23:38,060 Bạn kết thúc đóng con trỏ thay vì đóng tên tập tin. 279 00:23:38,060 --> 00:23:48,990 >> Vâng? [Daniel] Vì vậy, để sử dụng cho thuê, bạn sẽ nói - như thế nào có được những người sử dụng đầu vào? 280 00:23:48,990 --> 00:23:53,830 Fprintf hành động như GetString trong ý nghĩa rằng nó sẽ chỉ chờ đợi cho người sử dụng đầu vào 281 00:23:53,830 --> 00:23:57,180 và yêu cầu bạn gõ này - hoặc chờ đợi để bạn có thể gõ ba điều này? 282 00:23:57,180 --> 00:24:00,480 Hoặc bạn có cần phải sử dụng một cái gì đó để thực hiện cho thuê? 283 00:24:00,480 --> 00:24:04,100 >> Yeah. Vì vậy, chúng tôi không câu hỏi, làm thế nào để chúng ta có được những người sử dụng đầu vào 284 00:24:04,100 --> 00:24:09,220 để thực hiện cho thuê? Và những gì chúng tôi có ở đây là người gọi của thuê, 285 00:24:09,220 --> 00:24:17,690 được thông qua trong cấu trúc nhân viên với tất cả các dữ liệu được lưu trữ trong một cấu trúc đã. 286 00:24:17,690 --> 00:24:22,990 Vì vậy, fprintf là có thể chỉ cần viết rằng dữ liệu trực tiếp vào tập tin. 287 00:24:22,990 --> 00:24:25,690 Không phải chờ đợi cho đầu vào của người sử dụng. 288 00:24:25,690 --> 00:24:32,110 Người sử dụng đã được đưa ra đầu vào bằng đúng cách đặt nó trong cấu trúc nhân viên này. 289 00:24:32,110 --> 00:24:36,510 Và những thứ, tất nhiên, sẽ phá vỡ nếu có của những người con trỏ là vô giá trị, 290 00:24:36,510 --> 00:24:40,370 vì vậy chúng tôi di chuyển trở lại lên ở đây và chúng ta nhìn vào cấu trúc của chúng tôi. 291 00:24:40,370 --> 00:24:43,640 Chúng tôi có chuỗi cuối cùng, chuỗi đầu tiên, chuỗi email. 292 00:24:43,640 --> 00:24:48,530 Bây giờ chúng ta biết rằng tất cả những người thực sự, dưới mui xe, là các biến char *. 293 00:24:48,530 --> 00:24:53,470 Có thể có hoặc có thể không được chỉ để null. 294 00:24:53,470 --> 00:24:55,800 Họ có thể được trỏ đến bộ nhớ trên heap, 295 00:24:55,800 --> 00:24:59,650 có thể bộ nhớ trên stack. 296 00:24:59,650 --> 00:25:04,580 Chúng tôi không thực sự biết, nhưng nếu bất kỳ của các con trỏ là null, hoặc không hợp lệ, 297 00:25:04,580 --> 00:25:08,120 mà chắc chắn sẽ sụp đổ chức năng cho thuê của chúng tôi. 298 00:25:08,120 --> 00:25:11,050 Đó là một cái gì đó đã được loại vượt ra ngoài phạm vi của kỳ thi. 299 00:25:11,050 --> 00:25:16,440 Chúng tôi không lo lắng về điều đó. 300 00:25:16,440 --> 00:25:22,170 Lớn. Okay. Vì vậy, chuyển từ quiz. 301 00:25:22,170 --> 00:25:25,760 >> Hãy đóng anh chàng này, và chúng ta sẽ nhìn vào pset 4. 302 00:25:25,760 --> 00:25:34,700 Vì vậy, nếu bạn nhìn vào spec pset, một khi bạn có thể truy cập vào nó, cs50.net/quizzes, 303 00:25:34,700 --> 00:25:42,730 chúng ta sẽ đi qua một vài trong những vấn đề phần hôm nay. 304 00:25:42,730 --> 00:25:52,240 Tôi đang di chuyển xuống phần các câu hỏi bắt đầu trên trang thứ ba của spec pset. 305 00:25:52,240 --> 00:25:57,800 Và phần đầu tiên sẽ yêu cầu bạn đi và xem ngắn chuyển hướng và ống dẫn. 306 00:25:57,800 --> 00:26:02,820 Đó là loại một ngăn mát, cho bạn thấy một số người, thủ đoạn dòng lệnh mát mẻ mà bạn có thể sử dụng. 307 00:26:02,820 --> 00:26:06,050 Và sau đó chúng tôi đã có một số câu hỏi cho bạn là tốt. 308 00:26:06,050 --> 00:26:10,860 Câu hỏi này đầu tiên về dòng suối, mà printf viết theo mặc định, 309 00:26:10,860 --> 00:26:15,920 chúng ta đề cập đến một chút ít một chút thời gian trước đây. 310 00:26:15,920 --> 00:26:22,380 Này fprintf rằng chúng tôi chỉ thảo luận về mất trong một dòng tập tin * như là đối số của nó. 311 00:26:22,380 --> 00:26:26,580 fclose mất trong một dòng * tập tin là tốt, 312 00:26:26,580 --> 00:26:32,660 và giá trị trả lại fopen cung cấp cho bạn một dòng * tập tin là tốt. 313 00:26:32,660 --> 00:26:36,060 Lý do chúng tôi đã không nhìn thấy trước khi những người khi chúng tôi đã xử lý với printf 314 00:26:36,060 --> 00:26:39,450 là bởi vì printf có một dòng suối mặc định. 315 00:26:39,450 --> 00:26:41,810 Và dòng mặc định mà nó viết 316 00:26:41,810 --> 00:26:45,190 bạn sẽ tìm ra trong ngắn. 317 00:26:45,190 --> 00:26:50,080 Vì vậy, chắc chắn có một cái nhìn vào nó. 318 00:26:50,080 --> 00:26:53,010 >> Trong phần ngày nay, chúng ta sẽ nói một chút về GDB, 319 00:26:53,010 --> 00:26:57,720 kể từ khi bạn đang quen thuộc hơn với nó, càng thực hành nhiều, bạn nhận được với nó, 320 00:26:57,720 --> 00:27:01,390 có khả năng tốt hơn, bạn sẽ có để thực sự săn lùng lỗi trong mã của riêng bạn. 321 00:27:01,390 --> 00:27:05,540 Điều này tốc độ quá trình gỡ lỗi lên rất nhiều. 322 00:27:05,540 --> 00:27:09,230 Vì vậy, bằng cách sử dụng printf, mỗi khi bạn làm điều đó bạn phải biên dịch lại mã của bạn, 323 00:27:09,230 --> 00:27:13,000 bạn phải chạy nó một lần nữa, đôi khi bạn phải di chuyển các cuộc gọi printf xung quanh, 324 00:27:13,000 --> 00:27:17,100 nhận xét ra mã, nó chỉ mất một thời gian. 325 00:27:17,100 --> 00:27:20,850 Mục tiêu của chúng tôi là để thử và thuyết phục bạn rằng với GDB, bạn có thể cơ bản 326 00:27:20,850 --> 00:27:26,810 printf bất cứ điều gì tại bất kỳ điểm nào trong mã của bạn và bạn không bao giờ phải biên dịch lại nó. 327 00:27:26,810 --> 00:27:35,120 Bạn không bao giờ có bắt đầu và tiếp tục đoán nơi printf tiếp theo. 328 00:27:35,120 --> 00:27:40,910 Điều đầu tiên cần làm là copy dòng này và nhận được các mã phần của trang web. 329 00:27:40,910 --> 00:27:47,530 Tôi là sao chép dòng mã này nói rằng, "wget ​​http://cdn.cs50.net". 330 00:27:47,530 --> 00:27:49,510 Tôi sẽ để sao chép nó. 331 00:27:49,510 --> 00:27:55,950 Tôi sẽ đi qua vào thiết bị của tôi, thu nhỏ để bạn có thể nhìn thấy những gì tôi đang làm, 332 00:27:55,950 --> 00:28:01,890 dán trong đó, và khi tôi nhấn Enter, lệnh wget này theo nghĩa đen là một trang web có được. 333 00:28:01,890 --> 00:28:06,210 Nó sẽ để kéo xuống tập tin này tắt của Internet, 334 00:28:06,210 --> 00:28:11,790 và nó sẽ để lưu nó vào thư mục hiện hành. 335 00:28:11,790 --> 00:28:21,630 Bây giờ nếu tôi liệt kê thư mục hiện tại của tôi, bạn có thể thấy rằng tôi đã có tập tin này section5.zip ngay trong đó. 336 00:28:21,630 --> 00:28:25,260 Cách để đối phó với anh chàng đó là để giải nén nó, 337 00:28:25,260 --> 00:28:27,650 mà bạn có thể làm trong dòng lệnh, chỉ cần như thế này. 338 00:28:27,650 --> 00:28:31,880 Section5.zip. 339 00:28:31,880 --> 00:28:36,980 Điều đó sẽ giải nén nó, tạo ra các thư mục cho tôi, 340 00:28:36,980 --> 00:28:40,410 thổi phồng tất cả các nội dung, đặt chúng ở đó. 341 00:28:40,410 --> 00:28:47,410 Vì vậy, bây giờ tôi có thể đi vào 5 thư mục phần của tôi bằng cách sử dụng lệnh cd. 342 00:28:47,410 --> 00:28:58,310 Xóa màn hình bằng cách sử dụng rõ ràng. Vì vậy, xóa màn hình. 343 00:28:58,310 --> 00:29:02,280 Bây giờ tôi đã có một thiết bị đầu cuối sạch đẹp để đối phó với. 344 00:29:02,280 --> 00:29:06,200 >> Bây giờ nếu tôi liệt kê tất cả các tập tin mà tôi nhìn thấy trong thư mục này, 345 00:29:06,200 --> 00:29:12,270 bạn thấy rằng tôi đã có bốn tập tin: buggy1, buggy2, buggy3, và buggy4. 346 00:29:12,270 --> 00:29:16,180 Tôi cũng có tương ứng. C tập tin của họ. 347 00:29:16,180 --> 00:29:20,400 Chúng tôi sẽ không nhìn vào các tập tin c. Bây giờ. 348 00:29:20,400 --> 00:29:24,140 Thay vào đó, chúng ta sẽ sử dụng chúng khi chúng ta mở ra GDB. 349 00:29:24,140 --> 00:29:28,220 Chúng tôi đã giữ chúng xung quanh để chúng tôi có thể truy cập vào mã nguồn thực tế khi chúng ta đang sử dụng GDB, 350 00:29:28,220 --> 00:29:32,740 nhưng mục tiêu này là một phần của phần này là để tinker xung quanh với GDB 351 00:29:32,740 --> 00:29:40,370 và xem làm thế nào chúng ta có thể sử dụng nó để tìm ra những gì đang xảy ra sai với mỗi người trong số bốn các chương trình lỗi. 352 00:29:40,370 --> 00:29:43,380 Vì vậy, chúng tôi chỉ cần đi quanh phòng thực sự nhanh chóng, 353 00:29:43,380 --> 00:29:47,000 và tôi sẽ hỏi ai đó để chạy một trong những chương trình lỗi, 354 00:29:47,000 --> 00:29:54,730 và sau đó chúng tôi sẽ đi như là một nhóm thông qua GDB, và chúng ta sẽ thấy những gì chúng ta có thể làm gì để sửa chữa các chương trình này, 355 00:29:54,730 --> 00:29:58,460 hoặc ít nhất là xác định những gì đang xảy ra sai trong mỗi người trong số họ. 356 00:29:58,460 --> 00:30:04,760 Hãy bắt đầu với Daniel. Bạn sẽ chạy buggy1? Hãy xem những gì xảy ra. 357 00:30:04,760 --> 00:30:09,470 Daniel nói rằng có một lỗi ứng dụng. >> Yeah. Chính xác. 358 00:30:09,470 --> 00:30:12,460 Vì vậy, nếu tôi chạy buggy1, tôi nhận được một lỗi seg. 359 00:30:12,460 --> 00:30:16,210 Tại thời điểm này, tôi có thể đi và mở buggy1.c, 360 00:30:16,210 --> 00:30:19,450 cố gắng tìm ra những gì đang xảy ra sai, 361 00:30:19,450 --> 00:30:22,000 nhưng một trong những điều khó chịu nhất về lỗi này lỗi seg 362 00:30:22,000 --> 00:30:27,610 là nó không cho bạn biết những gì trong những điều chương trình thực sự đã đi sai và đã phá vỡ. 363 00:30:27,610 --> 00:30:29,880 Bạn loại phải nhìn vào mã 364 00:30:29,880 --> 00:30:33,990 và tìm ra bằng cách sử dụng đoán và kiểm tra hoặc printf để xem những gì đang xảy ra sai. 365 00:30:33,990 --> 00:30:37,840 Một trong những điều thú vị nhất về GDB là nó thực sự, thực sự dễ dàng 366 00:30:37,840 --> 00:30:42,170 để tìm ra các dòng của bạn bị treo chương trình. 367 00:30:42,170 --> 00:30:46,160 Nó hoàn toàn giá trị nó để sử dụng nó, ngay cả khi chỉ cho điều đó. 368 00:30:46,160 --> 00:30:56,190 Vì vậy, để khởi động GDB, tôi gõ GDB, và sau đó tôi cung cấp cho nó đường dẫn đến thực thi mà tôi muốn chạy. 369 00:30:56,190 --> 00:31:01,960 Ở đây tôi đang gõ gdb ./buggy1. 370 00:31:01,960 --> 00:31:06,600 Nhấn Enter. Mang lại cho tôi tất cả thông tin bản quyền này, 371 00:31:06,600 --> 00:31:13,000 và xuống ở đây bạn sẽ nhìn thấy dòng này mà nói, "biểu tượng Đọc từ / home / 372 00:31:13,000 --> 00:31:17,680 jharvard/section5/buggy1 ". 373 00:31:17,680 --> 00:31:22,060 Và nếu mọi việc suôn sẻ, bạn sẽ thấy nó in ra một thông điệp trông như thế này. 374 00:31:22,060 --> 00:31:25,500 Nó sẽ đọc các ký hiệu, nó sẽ nói "Tôi đang đọc biểu tượng từ tập tin thực thi của bạn," 375 00:31:25,500 --> 00:31:29,900 và sau đó nó sẽ có điều này "thực hiện" tin nhắn ở đây. 376 00:31:29,900 --> 00:31:35,410 Nếu bạn thấy một số biến thể khác của điều này, hoặc bạn nhìn thấy nó không thể tìm thấy các biểu tượng 377 00:31:35,410 --> 00:31:41,460 hoặc một cái gì đó như thế, điều đó có nghĩa rằng bạn chỉ không được biên dịch thực thi của bạn đúng cách. 378 00:31:41,460 --> 00:31:49,980 Khi chúng tôi biên dịch chương trình để sử dụng với GDB, chúng ta phải sử dụng lá cờ đặc biệt-g, 379 00:31:49,980 --> 00:31:54,540 và đó là thực hiện theo mặc định nếu bạn biên dịch chương trình của bạn, chỉ bằng cách gõ làm 380 00:31:54,540 --> 00:31:59,320 hoặc lỗi hoặc phục hồi, bất kỳ của những người. 381 00:31:59,320 --> 00:32:07,800 Tuy nhiên, nếu bạn đang biên soạn bằng tay với Clang, sau đó bạn sẽ phải đi vào và bao gồm rằng-g cờ. 382 00:32:07,800 --> 00:32:10,310 >> Tại thời điểm này, bây giờ mà chúng tôi có nhắc GDB của chúng tôi, 383 00:32:10,310 --> 00:32:12,310 nó khá đơn giản để chạy chương trình. 384 00:32:12,310 --> 00:32:19,740 Chúng ta có thể gõ chạy, hoặc chúng tôi có thể chỉ cần gõ r. 385 00:32:19,740 --> 00:32:22,820 Hầu hết các lệnh GDB có thể được viết tắt. 386 00:32:22,820 --> 00:32:25,940 Thông thường để chỉ một hoặc một vài chữ, mà là khá tốt đẹp. 387 00:32:25,940 --> 00:32:30,980 Saad Vì vậy, nếu bạn gõ r và nhấn Enter, những gì xảy ra? 388 00:32:30,980 --> 00:32:39,390 Saad SIGSEGV, lỗi phân khúc, và sau đó tất cả các gobbledygook này. 389 00:32:39,390 --> 00:32:43,650 >> Yeah. 390 00:32:43,650 --> 00:32:47,990 Giống như chúng ta đang thấy trên màn hình ngay bây giờ, và giống như Saad cho biết, 391 00:32:47,990 --> 00:32:53,430 khi chúng tôi loại chạy hoặc r và nhấn Enter, chúng tôi vẫn nhận được cùng một lỗi seg. 392 00:32:53,430 --> 00:32:55,830 Vì vậy, bằng cách sử dụng GDB không giải quyết vấn đề của chúng tôi. 393 00:32:55,830 --> 00:32:59,120 Nhưng nó mang lại cho chúng tôi một số gobbledygook, và nó quay ra rằng gobbledygook 394 00:32:59,120 --> 00:33:03,080 thực sự cho chúng ta biết nơi mà nó đang xảy ra. 395 00:33:03,080 --> 00:33:10,680 Để phân tích một chút, bit đầu tiên là chức năng, trong đó tất cả mọi thứ đang xảy ra sai. 396 00:33:10,680 --> 00:33:20,270 Có __ strcmp_sse4_2 này, và nó cho chúng ta biết rằng nó đang diễn ra trong tập tin này 397 00:33:20,270 --> 00:33:29,450 gọi là sysdeps/i386, tất cả những điều này, một lần nữa, loại của một mess - nhưng dòng 254. 398 00:33:29,450 --> 00:33:31,670 Đó là loại khó để phân tích. Thông thường khi bạn nhìn thấy các công cụ như thế này, 399 00:33:31,670 --> 00:33:38,770 điều đó có nghĩa rằng nó seg đứt gãy trong một trong những hệ thống thư viện. 400 00:33:38,770 --> 00:33:43,220 Vì vậy, một cái gì đó để làm với strcmp. Các bạn đã thấy strcmp trước đây. 401 00:33:43,220 --> 00:33:52,730 Không quá điên rồ, nhưng thực hiện điều này có nghĩa là strcmp là bị hỏng hoặc rằng có một vấn đề với strcmp? 402 00:33:52,730 --> 00:33:57,110 Bạn nghĩ gì, Alexander? 403 00:33:57,110 --> 00:34:04,890 Alexander - là 254 dòng? Và không phải là nhị phân, nhưng nó không phải là trần, 404 00:34:04,890 --> 00:34:10,590 và sau đó có một ngôn ngữ khác cho từng chức năng. Là 254 trong chức năng đó, hoặc -? 405 00:34:10,590 --> 00:34:21,460 >> Dòng 254. Nó trông giống như trong tập tin này., Vì vậy nó là lắp ráp mã có thể. 406 00:34:21,460 --> 00:34:25,949 >> Nhưng, tôi đoán điều cấp bách hơn, bởi vì chúng tôi đã nhận được một lỗi seg, 407 00:34:25,949 --> 00:34:29,960 và có vẻ như nó đến từ strcmp chức năng, 408 00:34:29,960 --> 00:34:38,030 Điều này hàm ý, sau đó, strcmp mà là bị hỏng? 409 00:34:38,030 --> 00:34:42,290 Nó không nên, hy vọng. Vì vậy, chỉ vì bạn có một lỗi phân khúc 410 00:34:42,290 --> 00:34:49,480 trong một trong các chức năng hệ thống, thường có nghĩa mà bạn chỉ cần không được gọi một cách chính xác. 411 00:34:49,480 --> 00:34:52,440 Điều nhanh nhất để làm để tìm hiểu những gì đang thực sự xảy ra 412 00:34:52,440 --> 00:34:55,500 khi bạn nhìn thấy một chuyện điên rồ như thế này, bất cứ khi nào bạn thấy một lỗi seg, 413 00:34:55,500 --> 00:34:59,800 đặc biệt là nếu bạn có một chương trình bằng cách sử dụng nhiều hơn là chỉ chính, 414 00:34:59,800 --> 00:35:03,570 là sử dụng một backtrace. 415 00:35:03,570 --> 00:35:13,080 Tôi viết tắt backtrace bằng cách viết bt, như trái ngược với từ backtrace đầy đủ. 416 00:35:13,080 --> 00:35:16,510 Nhưng Charlotte, điều gì sẽ xảy ra khi bạn gõ bt và nhấn Enter? 417 00:35:16,510 --> 00:35:23,200 Charlotte Nó cho thấy hai dòng, dòng 0 và dòng 1. 418 00:35:23,200 --> 00:35:26,150 >> Yeah. Vì vậy, dòng 0 và dòng 1. 419 00:35:26,150 --> 00:35:34,560 Đây là những khung stack thực tế hiện khi chương trình của bạn bị rơi. 420 00:35:34,560 --> 00:35:42,230 Bắt đầu từ khung trên cùng, khung 0, và dưới cùng nhất, đó là frame 1. 421 00:35:42,230 --> 00:35:45,140 Khung trên cùng của chúng tôi là khung strcmp. 422 00:35:45,140 --> 00:35:50,080 Bạn có thể nghĩ về điều này tương tự như vấn đề đó chúng ta chỉ cần làm bài kiểm tra với các con trỏ, 423 00:35:50,080 --> 00:35:54,890 nơi mà chúng tôi đã trao đổi stack frame trên stack frame chính, 424 00:35:54,890 --> 00:35:59,700 và chúng tôi đã có các biến rằng trao đổi đã được sử dụng trên các biến mà chính đã được sử dụng. 425 00:35:59,700 --> 00:36:08,440 Đây vụ tai nạn xảy ra trong chức năng strcmp của chúng tôi, được gọi là chức năng chính của chúng tôi, 426 00:36:08,440 --> 00:36:14,370 và backtrace là cho chúng ta không chỉ các chức năng trong đó mọi thứ không, 427 00:36:14,370 --> 00:36:16,440 nhưng nó cũng nói với chúng tôi, nơi tất cả mọi thứ được gọi là từ. 428 00:36:16,440 --> 00:36:18,830 Vì vậy, nếu tôi di chuyển trên nhiều hơn một chút về bên phải, 429 00:36:18,830 --> 00:36:26,110 chúng ta có thể thấy rằng, chúng ta trên đường dây 254 trong tập tin này strcmp-sse4.s. 430 00:36:26,110 --> 00:36:32,540 Tuy nhiên, cuộc gọi đã được thực hiện tại buggy1.c, dòng 6. 431 00:36:32,540 --> 00:36:35,960 Vì vậy, điều đó có nghĩa là chúng ta có thể làm là chúng ta chỉ có thể đi kiểm tra và xem những gì đang xảy ra 432 00:36:35,960 --> 00:36:39,930 tại buggy1.c, dòng 6. 433 00:36:39,930 --> 00:36:43,780 Một lần nữa, có một vài cách để làm điều này. Một là để thoát ra khỏi GDB 434 00:36:43,780 --> 00:36:49,460 hoặc có mã của bạn mở trong một cửa sổ và tham chiếu chéo. 435 00:36:49,460 --> 00:36:54,740 Rằng, trong và của chính nó, là khá tiện dụng bởi vì bây giờ nếu bạn đang ở giờ hành chính 436 00:36:54,740 --> 00:36:57,220 và bạn đã có một lỗi seg và TF của bạn đang tự hỏi, nơi tất cả mọi thứ đã được phá vỡ, 437 00:36:57,220 --> 00:36:59,710 bạn chỉ có thể nói rằng, "Ồ, dòng 6. Tôi không biết những gì đang xảy ra, 438 00:36:59,710 --> 00:37:03,670 nhưng một cái gì đó về dòng 6 gây ra chương trình của tôi để phá vỡ. " 439 00:37:03,670 --> 00:37:10,430 Một cách khác để làm điều đó là bạn có thể sử dụng lệnh này danh sách gọi là trong GDB. 440 00:37:10,430 --> 00:37:13,650 Bạn cũng có thể viết tắt với l. 441 00:37:13,650 --> 00:37:18,910 Vì vậy, nếu chúng ta nhấn l, chúng tôi làm những gì có được ở đây? 442 00:37:18,910 --> 00:37:21,160 Chúng tôi nhận được một bó toàn bộ các thứ lạ. 443 00:37:21,160 --> 00:37:26,030 Đây là mã lắp ráp thực tế 444 00:37:26,030 --> 00:37:29,860 đó là vào strcmp_sse4_2. 445 00:37:29,860 --> 00:37:32,440 Điều này có vẻ loại của funky, 446 00:37:32,440 --> 00:37:36,520 và lý do chúng tôi đang nhận được điều này là bởi vì hiện tại 447 00:37:36,520 --> 00:37:40,160 GDB chúng tôi trong khung 0. 448 00:37:40,160 --> 00:37:43,070 >> Vì vậy, bất cứ lúc nào chúng ta nhìn vào các biến, bất cứ lúc nào chúng ta nhìn vào mã nguồn, 449 00:37:43,070 --> 00:37:50,530 chúng tôi đang tìm kiếm mã nguồn liên quan đến stack frame chúng tôi hiện đang. 450 00:37:50,530 --> 00:37:53,200 Vì vậy, để có được bất cứ điều gì có ý nghĩa, chúng ta phải 451 00:37:53,200 --> 00:37:57,070 di chuyển đến một khung stack mà làm cho ý nghĩa hơn. 452 00:37:57,070 --> 00:38:00,180 Trong trường hợp này, khung chính stack sẽ có ý nghĩa nhiều hơn một chút, 453 00:38:00,180 --> 00:38:02,680 bởi vì đó là thực sự là mã mà chúng tôi đã viết. 454 00:38:02,680 --> 00:38:05,330 Không phải là mã strcmp. 455 00:38:05,330 --> 00:38:08,650 Cách bạn có thể di chuyển giữa các khung hình, trong trường hợp này, bởi vì chúng tôi có hai, 456 00:38:08,650 --> 00:38:10,430 chúng tôi có 0 và 1, 457 00:38:10,430 --> 00:38:13,650 bạn làm điều đó với lên và lệnh xuống. 458 00:38:13,650 --> 00:38:18,480 Nếu tôi di chuyển một khung hình, 459 00:38:18,480 --> 00:38:21,770 bây giờ tôi đang trong khung chính stack. 460 00:38:21,770 --> 00:38:24,330 Tôi có thể di chuyển xuống để trở lại nơi mà tôi đã, 461 00:38:24,330 --> 00:38:32,830 tăng trở lại, đi xuống một lần nữa, và đi lên một lần nữa. 462 00:38:32,830 --> 00:38:39,750 Nếu bạn đã từng làm chương trình của bạn trong GDB, bạn sẽ có được một vụ tai nạn, bạn sẽ có được backtrace, 463 00:38:39,750 --> 00:38:42,380 và bạn thấy rằng nó ở một số tập tin mà bạn không biết những gì đang xảy ra. 464 00:38:42,380 --> 00:38:45,460 Bạn hãy thử danh sách, các mã này không nhìn quen thuộc với bạn, 465 00:38:45,460 --> 00:38:48,150 nhìn vào khung hình của bạn và tìm ra nơi bạn đang. 466 00:38:48,150 --> 00:38:51,010 Có lẽ bạn đang trong khung ngăn xếp sai. 467 00:38:51,010 --> 00:38:58,760 Hoặc ít nhất bạn đang ở trong một khung stack không phải là một mà bạn thực sự có thể gỡ lỗi. 468 00:38:58,760 --> 00:39:03,110 Bây giờ chúng ta đang ở trong stack frame thích hợp, chúng tôi đang ở trong chính, 469 00:39:03,110 --> 00:39:08,100 bây giờ chúng ta có thể sử dụng lệnh danh sách để tìm ra dòng là gì. 470 00:39:08,100 --> 00:39:13,590 Và bạn có thể nhìn thấy nó, nó in nó cho chúng tôi tại đây. 471 00:39:13,590 --> 00:39:19,470 Nhưng chúng ta có thể nhấn liệt kê tất cả như nhau, và danh sách này cho chúng ta bản in đẹp 472 00:39:19,470 --> 00:39:23,920 mã nguồn thực tế đang diễn ra ở đây. 473 00:39:23,920 --> 00:39:26,420 >> Đặc biệt, chúng tôi có thể nhìn vào dòng 6. 474 00:39:26,420 --> 00:39:29,330 Chúng ta có thể xem những gì đang xảy ra ở đây. 475 00:39:29,330 --> 00:39:31,250 Và có vẻ như chúng tôi đang làm một so sánh chuỗi 476 00:39:31,250 --> 00:39:41,050 giữa chuỗi "CS50 đá" và argv [1]. 477 00:39:41,050 --> 00:39:45,700 Một cái gì đó về việc này đã bị rơi. 478 00:39:45,700 --> 00:39:54,120 Vì vậy, Missy, làm bạn có bất kỳ suy nghĩ về những gì có thể xảy ra ở đây? 479 00:39:54,120 --> 00:39:59,400 [Missy] Tôi không biết tại sao nó bị rơi. >> Bạn không biết tại sao nó bị rơi? 480 00:39:59,400 --> 00:40:02,700 Jimmy, bất kỳ suy nghĩ? 481 00:40:02,700 --> 00:40:06,240 [Jimmy] Tôi không hoàn toàn chắc chắn, nhưng thời gian qua chúng tôi sử dụng chuỗi so sánh, 482 00:40:06,240 --> 00:40:10,260 hoặc strcmp, chúng tôi đã có ba trường hợp khác nhau theo nó. 483 00:40:10,260 --> 00:40:12,800 Chúng tôi không có một ==, tôi không nghĩ rằng, ngay trong dòng đầu tiên. 484 00:40:12,800 --> 00:40:16,700 Thay vào đó, nó đã được tách thành ba, và một là == 0, 485 00:40:16,700 --> 00:40:19,910 một là <0, tôi nghĩ, và một là> 0. 486 00:40:19,910 --> 00:40:22,590 Vì vậy, có thể một cái gì đó như thế? >> Yeah. Vì vậy, có vấn đề này 487 00:40:22,590 --> 00:40:27,200 chúng ta làm sự so sánh chính xác? 488 00:40:27,200 --> 00:40:31,660 Stella? Bất kỳ suy nghĩ? 489 00:40:31,660 --> 00:40:38,110 Stella] Tôi không chắc chắn. >> Không chắc chắn. Daniel? Suy nghĩ? Okay. 490 00:40:38,110 --> 00:40:44,770 Hóa ra những gì đang xảy ra ngay ở đây là khi chúng ta chạy chương trình 491 00:40:44,770 --> 00:40:48,370 và chúng tôi đã lỗi seg, khi bạn chạy chương trình lần đầu tiên, Daniel, 492 00:40:48,370 --> 00:40:50,800 bạn cho nó bất kỳ đối số dòng lệnh? 493 00:40:50,800 --> 00:40:58,420 [Daniel] số >> số Trong trường hợp đó, những gì là giá trị của argv [1]? 494 00:40:58,420 --> 00:41:00,920 >> Không có là không có giá trị. >> Right. 495 00:41:00,920 --> 00:41:06,120 Vâng, đó là không có giá trị chuỗi thích hợp. 496 00:41:06,120 --> 00:41:10,780 Nhưng có một số giá trị. Giá trị được lưu trữ trong đó là gì? 497 00:41:10,780 --> 00:41:15,130 >> Một giá trị rác? >> Nó là giá trị rác hoặc, trong trường hợp này, 498 00:41:15,130 --> 00:41:19,930 cuối của mảng argv luôn luôn chấm dứt với null. 499 00:41:19,930 --> 00:41:26,050 Vì vậy, những gì thực sự đã được lưu trữ trong có là null. 500 00:41:26,050 --> 00:41:30,810 Một cách khác để giải quyết vấn đề này, thay vì nghĩ nó thông qua, 501 00:41:30,810 --> 00:41:33,420 là để thử in nó ra. 502 00:41:33,420 --> 00:41:35,880 Đây là nơi tôi đã nói rằng bằng cách sử dụng GDB là rất tốt, 503 00:41:35,880 --> 00:41:40,640 bởi vì bạn có thể in ra tất cả các biến, tất cả các giá trị mà bạn muốn 504 00:41:40,640 --> 00:41:43,230 bằng cách sử dụng này tiện dụng-dandy p lệnh. 505 00:41:43,230 --> 00:41:48,520 Vì vậy, nếu tôi gõ p và sau đó tôi gõ giá trị của một biến hoặc tên của một biến, 506 00:41:48,520 --> 00:41:55,320 nói, argc, tôi thấy rằng argc là 1. 507 00:41:55,320 --> 00:42:01,830 Nếu tôi muốn in ra argv [0], tôi có thể làm như vậy chỉ như thế. 508 00:42:01,830 --> 00:42:04,840 Và cũng giống như chúng ta đã thấy, argv [0] luôn luôn là tên của chương trình của bạn, 509 00:42:04,840 --> 00:42:06,910 luôn luôn là tên của các thực thi. 510 00:42:06,910 --> 00:42:09,740 Ở đây bạn thấy nó có tên đường dẫn đầy đủ. 511 00:42:09,740 --> 00:42:15,920 Tôi cũng có thể in ra argv [1] và xem những gì sẽ xảy ra. 512 00:42:15,920 --> 00:42:20,890 >> Ở đây chúng tôi có loại có giá trị thần bí. 513 00:42:20,890 --> 00:42:23,890 Chúng tôi đã nhận 0x0 này. 514 00:42:23,890 --> 00:42:27,850 Ghi vào đầu của thuật ngữ này khi chúng tôi nói chuyện về những con số thập lục phân? 515 00:42:27,850 --> 00:42:34,680 Hoặc là câu hỏi ở phần cuối của pset 0 về làm thế nào để đại diện cho 50 trong hex? 516 00:42:34,680 --> 00:42:39,410 Cách chúng ta ghi mã số hex trong CS, chỉ để không nhầm lẫn giữa bản thân 517 00:42:39,410 --> 00:42:46,080 với các số thập phân, chúng tôi luôn luôn tiền tố với 0x. 518 00:42:46,080 --> 00:42:51,420 Vì vậy, tiền tố 0x này luôn luôn chỉ có nghĩa là giải thích các số sau đây là một số thập lục phân, 519 00:42:51,420 --> 00:42:57,400 không phải là một chuỗi, không phải là một số thập phân, không phải là một số nhị phân. 520 00:42:57,400 --> 00:43:02,820 Kể từ khi số 5-0 là một số hợp lệ trong hệ thập lục phân. 521 00:43:02,820 --> 00:43:06,240 Và đó là một số trong số thập phân, 50. 522 00:43:06,240 --> 00:43:10,050 Vì vậy, đây chỉ là cách chúng tôi disambiguate. 523 00:43:10,050 --> 00:43:14,860 Vì vậy, 0x0 có nghĩa là hệ thập lục phân 0, đó cũng là số thập phân 0, nhị phân 0. 524 00:43:14,860 --> 00:43:17,030 Nó chỉ là giá trị 0. 525 00:43:17,030 --> 00:43:22,630 Nó chỉ ra rằng đây là những gì null là, trên thực tế, trong bộ nhớ. 526 00:43:22,630 --> 00:43:25,940 Null chỉ là 0. 527 00:43:25,940 --> 00:43:37,010 Ở đây, các phần tử được lưu trữ tại argv [1] là null. 528 00:43:37,010 --> 00:43:45,220 Vì vậy, chúng tôi đang cố gắng để so sánh "CS50 đá" chuỗi một chuỗi null. 529 00:43:45,220 --> 00:43:48,130 Vì vậy, dereferencing null, cố gắng để truy cập mọi thứ tại vô giá trị, 530 00:43:48,130 --> 00:43:55,050 những người thường sẽ gây ra một số loại lỗi phân khúc hoặc những điều xấu xảy ra. 531 00:43:55,050 --> 00:43:59,350 Và nó chỉ ra rằng strcmp không kiểm tra xem 532 00:43:59,350 --> 00:44:04,340 có hoặc không bạn đã được thông qua trong một giá trị đó là vô giá trị. 533 00:44:04,340 --> 00:44:06,370 Thay vào đó, nó chỉ cần đi về phía trước, cố gắng để làm điều này, 534 00:44:06,370 --> 00:44:14,640 và nếu nó seg lỗi, seg lỗi lầm, và đó là vấn đề của bạn. Bạn phải đi sửa chữa nó. 535 00:44:14,640 --> 00:44:19,730 Thực sự nhanh chóng, làm thế nào chúng ta có thể khắc phục vấn đề này? Charlotte? 536 00:44:19,730 --> 00:44:23,540 Charlotte] Bạn có thể kiểm tra sử dụng nếu. 537 00:44:23,540 --> 00:44:32,240 Vì vậy, nếu argv [1] là null, == 0, sau đó trở về 1, hoặc một cái gì đó khó hiểu. 538 00:44:32,240 --> 00:44:34,590 >> Yeah. Vì vậy, đó là một cách tuyệt vời để làm điều đó, như chúng ta có thể kiểm tra xem, 539 00:44:34,590 --> 00:44:39,230 giá trị chúng tôi đang về để đi vào strcmp, argv [1], là nó vô giá trị? 540 00:44:39,230 --> 00:44:45,830 Nếu đó là vô giá trị, sau đó chúng tôi có thể nói không sao, hủy bỏ. 541 00:44:45,830 --> 00:44:49,450 >> Một cách phổ biến hơn để làm điều này là sử dụng giá trị argc. 542 00:44:49,450 --> 00:44:52,040 Bạn có thể thấy ngay tại đây vào đầu của chính, 543 00:44:52,040 --> 00:44:58,040 chúng ta bỏ qua đó thử nghiệm đầu tiên mà chúng ta thường làm khi chúng ta sử dụng các đối số dòng lệnh, 544 00:44:58,040 --> 00:45:05,240 đó là để kiểm tra hay không giá trị argc của chúng tôi là những gì chúng tôi mong đợi. 545 00:45:05,240 --> 00:45:10,290 Trong trường hợp này, chúng tôi hy vọng ít nhất hai đối số, 546 00:45:10,290 --> 00:45:13,660 tên của chương trình cộng với một người khác. 547 00:45:13,660 --> 00:45:17,140 Bởi vì chúng ta đang sử dụng đối số thứ hai ngay tại đây. 548 00:45:17,140 --> 00:45:21,350 Vì vậy, có một số loại thử nghiệm trước, trước khi cuộc gọi strcmp của chúng tôi 549 00:45:21,350 --> 00:45:37,390 rằng các xét nghiệm hay không argv ít nhất là 2, cũng sẽ làm cùng một loại điều. 550 00:45:37,390 --> 00:45:40,620 Chúng ta có thể thấy rằng nếu các hoạt động bằng cách chạy chương trình một lần nữa. 551 00:45:40,620 --> 00:45:45,610 Bạn luôn có thể khởi động lại chương trình của bạn trong GDB, mà thực sự là tốt đẹp. 552 00:45:45,610 --> 00:45:49,310 Bạn có thể chạy, và khi bạn vượt qua trong đối số cho chương trình của bạn, 553 00:45:49,310 --> 00:45:53,060 bạn vượt qua chúng trong khi bạn gọi chạy, không phải khi bạn khởi động GDB. 554 00:45:53,060 --> 00:45:57,120 Bằng cách đó bạn có thể gọi chương trình của bạn với các đối số khác nhau mỗi lần. 555 00:45:57,120 --> 00:46:08,080 Vì vậy, chạy, hay một lần nữa, tôi có thể loại r, và hãy xem những gì sẽ xảy ra nếu chúng ta gõ "hello". 556 00:46:08,080 --> 00:46:11,140 Nó sẽ luôn luôn hỏi bạn nếu bạn muốn bắt đầu từ đầu một lần nữa. 557 00:46:11,140 --> 00:46:17,490 Thông thường, bạn muốn bắt đầu nó từ đầu một lần nữa. 558 00:46:17,490 --> 00:46:25,010 Và tại thời điểm này, nó khởi động lại nó một lần nữa, nó in ra 559 00:46:25,010 --> 00:46:28,920 chương trình mà chúng tôi đang chạy, buggy1, với các đối số xin chào, 560 00:46:28,920 --> 00:46:32,720 và nó in này ra tiêu chuẩn, nó nói, "Bạn nhận được một D," khuôn mặt buồn. 561 00:46:32,720 --> 00:46:37,610 Nhưng chúng tôi đã không seg lỗi. Nói rằng quá trình đã thoát bình thường. 562 00:46:37,610 --> 00:46:39,900 Vì vậy, đó có vẻ khá tốt. 563 00:46:39,900 --> 00:46:43,050 Lỗi Không seg, chúng tôi đã thực hiện nó trong quá khứ, 564 00:46:43,050 --> 00:46:48,190 vậy có vẻ như đó là thực sự là lỗi lỗi seg mà chúng tôi đã nhận được. 565 00:46:48,190 --> 00:46:51,540 Thật không may, nó cho chúng ta biết rằng chúng tôi đang nhận được một D. 566 00:46:51,540 --> 00:46:54,090 >> Chúng ta có thể quay trở lại và nhìn vào mã và xem những gì đang xảy ra ở đó 567 00:46:54,090 --> 00:46:57,980 tìm ra những gì là lý do tại sao nó đã nói với chúng tôi rằng chúng tôi đã nhận một D. 568 00:46:57,980 --> 00:47:03,690 Hãy xem, ở đây đã được printf nói rằng bạn có một D. 569 00:47:03,690 --> 00:47:08,540 Nếu chúng tôi loại danh sách, như bạn giữ danh sách gõ, nó giữ iterating thông qua các chương trình của bạn, 570 00:47:08,540 --> 00:47:10,940 do đó, nó sẽ chỉ cho bạn vài dòng đầu tiên của chương trình của bạn. 571 00:47:10,940 --> 00:47:15,450 Sau đó, nó sẽ cho bạn thấy một vài dòng tiếp theo, và đoạn tiếp theo và đoạn tiếp theo. 572 00:47:15,450 --> 00:47:18,240 Và nó sẽ tiếp tục cố gắng để đi xuống. 573 00:47:18,240 --> 00:47:21,180 Và bây giờ chúng tôi sẽ nhận được để "xếp hàng số 16 ra khỏi phạm vi." 574 00:47:21,180 --> 00:47:23,940 Bởi vì nó chỉ có 15 dòng. 575 00:47:23,940 --> 00:47:30,310 Nếu bạn nhận được đến thời điểm này và tự hỏi: "Tôi phải làm gì?" bạn có thể sử dụng lệnh trợ giúp. 576 00:47:30,310 --> 00:47:34,340 Sử dụng giúp đỡ và sau đó cho nó cái tên của một lệnh. 577 00:47:34,340 --> 00:47:36,460 Và bạn thấy GDB ban cho chúng ta tất cả các loại công cụ này. 578 00:47:36,460 --> 00:47:43,870 Nó nói, "không có đối số, liệt kê hơn mười dòng sau hoặc xung quanh danh sách trước đó. 579 00:47:43,870 --> 00:47:47,920 - Danh sách liệt kê mười dòng trước " 580 00:47:47,920 --> 00:47:52,960 Vì vậy, hãy thử sử dụng trừ danh sách. 581 00:47:52,960 --> 00:47:57,000 Và đó liệt kê 10 dòng trước đó, bạn có thể chơi xung quanh với một danh sách ít. 582 00:47:57,000 --> 00:48:02,330 Bạn có thể làm danh sách danh sách, bạn thậm chí có thể cung cấp cho danh sách một số, như danh sách 8, 583 00:48:02,330 --> 00:48:07,500 và nó sẽ liệt kê 10 dòng trên dòng 8. 584 00:48:07,500 --> 00:48:10,290 Và bạn có thể xem những gì đang xảy ra ở đây là bạn đã có một đơn giản, nếu người nào khác. 585 00:48:10,290 --> 00:48:13,980 Nếu bạn gõ trong CS50 đá, nó in ra "Bạn nhận được một A." 586 00:48:13,980 --> 00:48:16,530 Nếu không thì nó in ra "Bạn nhận được một D." 587 00:48:16,530 --> 00:48:23,770 Bummer thị trấn. Được rồi. Vâng? 588 00:48:23,770 --> 00:48:26,730 >> [Daniel] Vì vậy, khi tôi đã cố gắng làm CS50 đá không có dấu ngoặc kép, 589 00:48:26,730 --> 00:48:29,290 nó nói "Bạn nhận được một D." 590 00:48:29,290 --> 00:48:32,560 Tôi cần có dấu ngoặc kép để có được nó để làm việc, tại sao vậy? 591 00:48:32,560 --> 00:48:38,490 >> Yeah. Nó chỉ ra rằng khi đây là một miếng ngon ít niềm vui - 592 00:48:38,490 --> 00:48:47,900 khi bạn chạy chương trình, nếu chúng ta chạy nó và chúng tôi gõ CS50 đá, 593 00:48:47,900 --> 00:48:50,800 giống như Daniel đã nói ông đã làm, và bạn nhấn Enter, 594 00:48:50,800 --> 00:48:52,870 nó vẫn nói chúng tôi nhận được một D. 595 00:48:52,870 --> 00:48:55,580 Và câu hỏi là, tại sao điều này? 596 00:48:55,580 --> 00:49:02,120 Và nó quay ra rằng cả hai thiết bị đầu cuối của chúng tôi và GDB phân tích này như là hai đối số riêng biệt. 597 00:49:02,120 --> 00:49:04,800 Bởi vì khi có một không gian, đó là ngụ ý là 598 00:49:04,800 --> 00:49:08,730 đối số đầu tiên kết thúc, các đối số tiếp theo là về để bắt đầu. 599 00:49:08,730 --> 00:49:13,260 Cách để kết hợp những người thành hai, hay xin lỗi, vào một đối số, 600 00:49:13,260 --> 00:49:18,510 là sử dụng dấu ngoặc kép. 601 00:49:18,510 --> 00:49:29,560 Vì vậy, bây giờ, nếu chúng ta đặt nó trong dấu ngoặc kép và chạy nó một lần nữa, chúng tôi nhận được một A. 602 00:49:29,560 --> 00:49:38,780 Vì vậy, chỉ cần để recap, không có dấu ngoặc kép, CS50 và đá được phân tích như hai đối số riêng biệt. 603 00:49:38,780 --> 00:49:45,320 Với dấu ngoặc kép, nó phân tích cú pháp như là một đối số hoàn toàn. 604 00:49:45,320 --> 00:49:53,070 >> Chúng tôi có thể thấy điều này với một breakpoint. 605 00:49:53,070 --> 00:49:54,920 Vì vậy, đến nay chúng tôi đã chạy chương trình của chúng tôi, và nó được chạy 606 00:49:54,920 --> 00:49:58,230 cho đến khi nào nó seg lỗi hoặc hits một lỗi 607 00:49:58,230 --> 00:50:05,930 hoặc cho đến khi nó đã thoát và tất cả đã được hoàn toàn tốt. 608 00:50:05,930 --> 00:50:08,360 Đây không phải là nhất thiết phải là điều hữu ích nhất, bởi vì đôi khi 609 00:50:08,360 --> 00:50:11,840 bạn có một lỗi trong chương trình của bạn, nhưng nó không gây ra một lỗi phân khúc. 610 00:50:11,840 --> 00:50:16,950 Nó không gây ra chương trình của bạn để ngăn chặn hoặc bất cứ điều gì như thế. 611 00:50:16,950 --> 00:50:20,730 Cách để có được GDB tạm dừng chương trình của bạn tại một điểm cụ 612 00:50:20,730 --> 00:50:23,260 là để thiết lập một breakpoint. 613 00:50:23,260 --> 00:50:26,520 Bạn có thể làm điều này bằng cách thiết lập một breakpoint trên một tên chức năng 614 00:50:26,520 --> 00:50:30,770 hoặc bạn có thể thiết lập một breakpoint trên một dòng cụ thể của mã. 615 00:50:30,770 --> 00:50:34,450 Tôi thích đặt breakpoint về tên chức năng, bởi vì - dễ nhớ, 616 00:50:34,450 --> 00:50:37,700 và nếu bạn thực sự đi vào và thay đổi mã nguồn của bạn lên một chút, 617 00:50:37,700 --> 00:50:42,020 sau đó breakpoint của bạn sẽ thực sự ở tại cùng một vị trí trong mã của bạn. 618 00:50:42,020 --> 00:50:44,760 Trong khi đó, nếu bạn đang sử dụng số dòng, và các số dòng thay đổi 619 00:50:44,760 --> 00:50:51,740 bởi vì bạn thêm hoặc xóa một số mã, sau đó breakpoint của bạn là tất cả hoàn toàn hơi say lên. 620 00:50:51,740 --> 00:50:58,590 Một trong những điều phổ biến nhất tôi làm là thiết lập một breakpoint trên các chức năng chính. 621 00:50:58,590 --> 00:51:05,300 Thường thì tôi sẽ khởi động GDB, tôi sẽ gõ b chính, nhấn Enter, và đó sẽ thiết lập một breakpoint 622 00:51:05,300 --> 00:51:10,630 các chức năng chính mà chỉ nói, "Tạm dừng chương trình ngay sau khi bạn bắt đầu chạy", 623 00:51:10,630 --> 00:51:17,960 và theo cách đó, khi tôi chạy chương trình của tôi với, nói, CS50 đá như hai đối số 624 00:51:17,960 --> 00:51:24,830 và nhấn Enter, nó được các chức năng chính và nó dừng lại ngay ở dòng đầu tiên, 625 00:51:24,830 --> 00:51:30,620 ngay trước khi nó đánh giá chức năng strcmp. 626 00:51:30,620 --> 00:51:34,940 >> Kể từ khi tôi đang bị tạm dừng, bây giờ tôi có thể bắt đầu mucking xung quanh và nhìn thấy những gì đang xảy 627 00:51:34,940 --> 00:51:40,250 với tất cả các biến khác nhau được thông qua vào chương trình của tôi. 628 00:51:40,250 --> 00:51:43,670 Ở đây tôi có thể in ra argc và xem những gì đang xảy ra. 629 00:51:43,670 --> 00:51:50,030 Xem argc là 3, bởi vì nó có 3 giá trị khác nhau trong đó. 630 00:51:50,030 --> 00:51:54,060 Nó có tên của chương trình, nó có tham số đầu tiên và đối số thứ hai. 631 00:51:54,060 --> 00:52:09,330 Chúng tôi có thể in ra những bằng cách nhìn vào argv [0], argv [1], và argv [2]. 632 00:52:09,330 --> 00:52:12,030 Vì vậy, bây giờ bạn cũng có thể thấy lý do tại sao điều này gọi strcmp là thất bại, 633 00:52:12,030 --> 00:52:21,650 bởi vì bạn thấy rằng nó đã chia tay CS50 và đá vào hai đối số riêng biệt. 634 00:52:21,650 --> 00:52:27,250 Tại thời điểm này, một khi bạn đã trúng một breakpoint, bạn có thể tiếp tục bước qua chương trình của bạn 635 00:52:27,250 --> 00:52:32,920 từng dòng một, như trái ngược với bắt đầu chương trình của bạn một lần nữa. 636 00:52:32,920 --> 00:52:35,520 Vì vậy, nếu bạn không muốn bắt đầu chương trình của bạn một lần nữa và chỉ cần tiếp tục từ đây, 637 00:52:35,520 --> 00:52:41,970 bạn có thể sử dụng lệnh tiếp tục và tiếp tục sẽ chạy chương trình để kết thúc. 638 00:52:41,970 --> 00:52:45,010 Cũng giống như nó đã làm ở đây. 639 00:52:45,010 --> 00:52:54,880 Tuy nhiên, nếu tôi khởi động chương trình, CS50 đá, nó cập breakpoint của tôi một lần nữa, 640 00:52:54,880 --> 00:52:59,670 và lần này, nếu tôi không muốn chỉ cần đi tất cả các cách thức thông qua phần còn lại của chương trình, 641 00:52:59,670 --> 00:53:08,040 Tôi có thể sử dụng lệnh kế tiếp, mà tôi cũng viết tắt với n. 642 00:53:08,040 --> 00:53:12,960 Và điều này sẽ bước qua các đường dây chương trình bằng dòng. 643 00:53:12,960 --> 00:53:17,530 Vì vậy, bạn có thể xem như là những thứ thực hiện, như là các biến thay đổi, như là những thứ được cập nhật. 644 00:53:17,530 --> 00:53:21,550 Đó là khá tốt đẹp. 645 00:53:21,550 --> 00:53:26,570 Điều thú vị khác là thay vì lặp đi lặp lại cùng một lệnh hơn và hơn và hơn một lần nữa, 646 00:53:26,570 --> 00:53:30,670 nếu bạn chỉ cần nhấn Enter - ở đây bạn thấy tôi đã không gõ vào bất cứ điều gì - 647 00:53:30,670 --> 00:53:33,780 nếu tôi chỉ cần nhấn Enter, nó sẽ lặp lại các lệnh trước đó, 648 00:53:33,780 --> 00:53:36,900 hoặc lệnh GDB trước đó mà tôi chỉ cần đặt. 649 00:53:36,900 --> 00:53:56,000 Tôi có thể giữ nhấn Enter và nó sẽ tiếp tục bước qua dòng mã của tôi dòng. 650 00:53:56,000 --> 00:53:59,310 Tôi khuyến khích các bạn đi kiểm tra các chương trình lỗi khác như là tốt. 651 00:53:59,310 --> 00:54:01,330 Chúng tôi không có thời gian để có được qua tất cả chúng ngày hôm nay trong phần. 652 00:54:01,330 --> 00:54:05,890 Mã nguồn là có, vì vậy bạn có thể loại xem những gì đang xảy ra 653 00:54:05,890 --> 00:54:07,730 đằng sau hậu trường nếu bạn nhận được thực sự khó khăn, 654 00:54:07,730 --> 00:54:11,940 nhưng ít nhất, chỉ cần thực hành khởi động GDB, 655 00:54:11,940 --> 00:54:13,940 chạy chương trình cho đến khi nó phá vỡ vào bạn, 656 00:54:13,940 --> 00:54:18,260 nhận được backtrace, tìm ra những gì hoạt động trí sự cố, 657 00:54:18,260 --> 00:54:24,450 dòng nó, in ra một số giá trị biến, 658 00:54:24,450 --> 00:54:30,140 chỉ để bạn có được một cảm giác về nó, bởi vì đó thực sự sẽ giúp bạn đi về phía trước. 659 00:54:30,140 --> 00:54:36,340 Tại thời điểm này, chúng ta sẽ bỏ ra của GDB, mà bạn sử dụng bỏ thuốc lá hoặc chỉ q. 660 00:54:36,340 --> 00:54:40,460 Nếu chương trình của bạn là ở giữa chạy vẫn còn, và nó đã không thoát, 661 00:54:40,460 --> 00:54:43,510 nó sẽ luôn luôn hỏi bạn, "Bạn có chắc chắn bạn thực sự muốn bỏ thuốc lá?" 662 00:54:43,510 --> 00:54:48,770 Bạn chỉ có thể đạt. 663 00:54:48,770 --> 00:54:55,250 >> Bây giờ chúng ta sẽ nhìn vào vấn đề tiếp theo chúng ta, đó là chương trình con mèo. 664 00:54:55,250 --> 00:54:59,880 Nếu bạn xem ngắn chuyển hướng và ống dẫn, bạn sẽ thấy rằng Tommy sử dụng chương trình này 665 00:54:59,880 --> 00:55:07,540 rằng về cơ bản in tất cả các đầu ra của một tập tin vào màn hình. 666 00:55:07,540 --> 00:55:12,660 Vì vậy, nếu tôi chạy cat, điều này thực sự là một chương trình được xây dựng trong thiết bị, 667 00:55:12,660 --> 00:55:16,860 và nếu bạn có máy Mac, bạn có thể làm điều này trên máy Mac của bạn, nếu bạn mở thiết bị đầu cuối. 668 00:55:16,860 --> 00:55:25,630 Và chúng tôi - mèo, hãy nói, cp.c, và nhấn Enter. 669 00:55:25,630 --> 00:55:29,640 Điều này đã làm, nếu chúng ta di chuyển lên một chút và nhìn thấy nơi chúng tôi chạy dòng, 670 00:55:29,640 --> 00:55:40,440 hoặc trong trường hợp chúng tôi chạy lệnh cat, nghĩa đen chỉ in ra nội dung của cp.c màn hình của chúng tôi. 671 00:55:40,440 --> 00:55:44,140 Chúng tôi có thể chạy nó một lần nữa và bạn có thể đặt trong nhiều tập tin với nhau. 672 00:55:44,140 --> 00:55:49,880 Vì vậy, bạn có thể làm cp.c mèo, và sau đó chúng ta cũng có thể ghép các tập tin cat.c, 673 00:55:49,880 --> 00:55:53,250 đó là chương trình chúng tôi đang viết, 674 00:55:53,250 --> 00:55:58,140 và nó sẽ in cả hai tập tin trở lại trở lại màn hình của chúng tôi. 675 00:55:58,140 --> 00:56:05,490 Vì vậy, nếu chúng ta di chuyển lên một chút, chúng ta thấy rằng khi chúng ta chạy cp.c mèo, cat.c, 676 00:56:05,490 --> 00:56:17,110 đầu tiên nó in ra các tập tin cp, và sau đó dưới nó, nó được in ra các tập tin cat.c phải xuống ở đây. 677 00:56:17,110 --> 00:56:19,650 Chúng ta sẽ sử dụng điều này để chỉ nhận được chân của chúng tôi ướt. 678 00:56:19,650 --> 00:56:25,930 Chơi xung quanh với việc in ấn đơn giản để thiết bị đầu cuối, xem làm thế nào mà làm việc. 679 00:56:25,930 --> 00:56:39,170 Nếu bạn mở with gedit cat.c, nhấn Enter, 680 00:56:39,170 --> 00:56:43,760 bạn có thể xem chương trình mà chúng tôi đang về để viết. 681 00:56:43,760 --> 00:56:48,980 Chúng tôi đã bao gồm đĩa này nồi hơi tốt đẹp, vì vậy chúng tôi không cần phải dành nhiều thời gian đánh máy tất cả mà ra. 682 00:56:48,980 --> 00:56:52,310 Chúng tôi cũng kiểm tra số đối số thông qua nhập 683 00:56:52,310 --> 00:56:56,910 Chúng tôi in ra một thông điệp sử dụng tốt đẹp. 684 00:56:56,910 --> 00:57:00,950 >> Đây là loại điều đó, một lần nữa, như chúng ta đã nói về, 685 00:57:00,950 --> 00:57:04,490 nó gần giống như bộ nhớ cơ bắp. 686 00:57:04,490 --> 00:57:07,190 Chỉ cần nhớ để tiếp tục làm cùng một loại công cụ 687 00:57:07,190 --> 00:57:11,310 và luôn luôn in ra một số loại thông điệp hữu ích 688 00:57:11,310 --> 00:57:17,670 để mọi người biết làm thế nào để chạy chương trình của bạn. 689 00:57:17,670 --> 00:57:21,630 Với con mèo, nó khá đơn giản, chúng ta sẽ đi qua tất cả các đối số khác nhau 690 00:57:21,630 --> 00:57:24,300 đã được thông qua chương trình của chúng tôi, và chúng tôi sẽ in 691 00:57:24,300 --> 00:57:29,950 nội dung ra màn hình tại một thời điểm. 692 00:57:29,950 --> 00:57:35,670 Để in các tập tin vào màn hình, chúng ta sẽ làm một cái gì đó rất giống nhau 693 00:57:35,670 --> 00:57:38,120 những gì chúng ta đã làm ở phần cuối của bài kiểm tra. 694 00:57:38,120 --> 00:57:45,350 Vào cuối của các bài kiểm tra, thuê chương trình, chúng tôi đã mở một tập tin, 695 00:57:45,350 --> 00:57:48,490 và sau đó chúng tôi đã in nó. 696 00:57:48,490 --> 00:57:54,660 Trong trường hợp này, chúng tôi sẽ mở một tập tin, và chúng ta sẽ đọc từ nó thay vì. 697 00:57:54,660 --> 00:58:00,630 Sau đó, chúng ta sẽ để in, thay vì vào một tập tin, chúng tôi sẽ in ra màn hình. 698 00:58:00,630 --> 00:58:05,830 Vì vậy, in ấn màn hình tất cả các bạn đã thực hiện trước khi với printf. 699 00:58:05,830 --> 00:58:08,290 Vì vậy, đó không phải là quá điên rồ. 700 00:58:08,290 --> 00:58:12,190 Tuy nhiên, đọc một tập tin là loại lạ. 701 00:58:12,190 --> 00:58:17,300 Chúng ta sẽ đi qua một chút ít tại một thời điểm. 702 00:58:17,300 --> 00:58:20,560 Nếu bạn quay trở lại với vấn đề cuối cùng trên quiz của bạn, vấn đề 33, 703 00:58:20,560 --> 00:58:27,280 dòng đầu tiên mà chúng tôi đang làm ở đây, mở các tập tin, rất giống với những gì chúng tôi đã làm ở đó. 704 00:58:27,280 --> 00:58:36,370 Vì vậy, Stella, những gì mà nhìn dòng như thế, khi chúng ta mở một tập tin? 705 00:58:36,370 --> 00:58:47,510 [Stella] Capital FILE *, tập tin - >> Được rồi. >> - Bằng fopen. >> Yup. 706 00:58:47,510 --> 00:58:55,980 Trong trường hợp này? Đó là trong các bình luận. 707 00:58:55,980 --> 00:59:06,930 >> Đó là trong các bình luận? argv [i] và r? 708 00:59:06,930 --> 00:59:11,300 >> Chính xác. Ngay trên. Vì vậy, Stella là hoàn toàn đúng. 709 00:59:11,300 --> 00:59:13,720 Đây là những dòng trông giống như. 710 00:59:13,720 --> 00:59:19,670 Chúng tôi đang đi để có được một biến dòng tập tin, lưu trữ nó trong một FILE *, do đó, tất cả các mũ, 711 00:59:19,670 --> 00:59:25,720 FILE, *, và tên của biến này sẽ được tập tin. 712 00:59:25,720 --> 00:59:32,250 Chúng ta có thể gọi nó là bất cứ điều gì chúng tôi muốn. Chúng ta có thể gọi nó first_file, hoặc file_i, bất cứ điều gì chúng tôi muốn. 713 00:59:32,250 --> 00:59:37,590 Và sau đó là tên của tập tin đã được thông qua vào dòng lệnh để chương trình này. 714 00:59:37,590 --> 00:59:44,450 Vì vậy, nó được lưu trữ trong argv [i] và sau đó chúng tôi đang đi để mở tập tin này trong chế độ đọc. 715 00:59:44,450 --> 00:59:48,100 Bây giờ chúng ta đã mở các tập tin, điều mà chúng ta luôn luôn phải nhớ để làm gì 716 00:59:48,100 --> 00:59:52,230 bất cứ khi nào chúng tôi đã mở một tập tin? Đóng nó lại. 717 00:59:52,230 --> 00:59:57,220 Vì vậy, Missy, làm thế nào để chúng ta đóng một tập tin? 718 00:59:57,220 --> 01:00:01,020 [Missy] fclose (file) >> fclose (file). Chính xác. 719 01:00:01,020 --> 01:00:05,340 Lớn. Okay. Nếu chúng ta nhìn vào điều này để làm bình luận ngay tại đây, 720 01:00:05,340 --> 01:00:11,940 nó nói, "Mở argv [i] và in nội dung của nó stdout." 721 01:00:11,940 --> 01:00:15,460 >> Tiêu chuẩn ra là một tên lạ. Thiết bị xuất chuẩn chỉ là cách nói của chúng tôi 722 01:00:15,460 --> 01:00:22,880 chúng ta muốn in nó đến thiết bị đầu cuối, chúng tôi muốn in nó vào dòng đầu ra tiêu chuẩn. 723 01:00:22,880 --> 01:00:26,450 Chúng tôi thực sự có thể nhận được thoát khỏi nhận xét này ngay tại đây. 724 01:00:26,450 --> 01:00:36,480 Tôi sẽ để sao chép và dán nó vì đó là những gì chúng tôi đã làm. 725 01:00:36,480 --> 01:00:41,290 Tại thời điểm này, bây giờ chúng ta phải đọc các bit tập tin bằng cách bit. 726 01:00:41,290 --> 01:00:46,300 Chúng tôi đã thảo luận một vài cách của các tập tin đọc. 727 01:00:46,300 --> 01:00:51,830 Mà những người ưa thích của bạn cho đến nay? 728 01:00:51,830 --> 01:00:57,960 Những cách đã nhìn thấy hoặc làm bạn nhớ, để đọc các tập tin? 729 01:00:57,960 --> 01:01:04,870 [Daniel] fread? >> Fread? Vì vậy, fread là một trong những. Jimmy, bạn có biết bất kỳ những người khác? 730 01:01:04,870 --> 01:01:12,150 [Jimmy] số >> Okay. Nope. Charlotte? Alexander? Bất cứ người khác? Okay. 731 01:01:12,150 --> 01:01:20,740 Vì vậy, những người khác fgetc, rằng chúng tôi sẽ sử dụng rất nhiều. 732 01:01:20,740 --> 01:01:26,410 Ngoài ra còn có fscanf, bạn thấy một mô hình ở đây? 733 01:01:26,410 --> 01:01:29,170 Tất cả họ đều bắt đầu với f. Bất cứ điều gì để làm với một tập tin. 734 01:01:29,170 --> 01:01:35,260 Có fread, fgetc, fscanf. Đây là tất cả các chức năng đọc. 735 01:01:35,260 --> 01:01:49,120 Đối với văn bản chúng tôi có fwrite, chúng tôi có fputc thay vì fgetc. 736 01:01:49,120 --> 01:01:58,250 Chúng tôi cũng đã fprintf như chúng ta đã thấy trên các bài kiểm tra. 737 01:01:58,250 --> 01:02:01,680 Vì đây là một vấn đề liên quan đến việc đọc từ một tập tin, 738 01:02:01,680 --> 01:02:04,940 chúng ta sẽ sử dụng một trong ba chức năng. 739 01:02:04,940 --> 01:02:10,890 Chúng tôi sẽ không sử dụng các chức năng này ở đây. 740 01:02:10,890 --> 01:02:14,880 Các chức năng này được tìm thấy trong thư viện I / O tiêu chuẩn. 741 01:02:14,880 --> 01:02:17,510 Vì vậy, nếu bạn nhìn ở phía trên cùng của chương trình này, 742 01:02:17,510 --> 01:02:24,110 bạn có thể thấy rằng chúng tôi đã bao gồm các tập tin tiêu đề cho thư viện I / O tiêu chuẩn. 743 01:02:24,110 --> 01:02:27,120 Nếu chúng ta muốn tìm ra cái nào chúng ta muốn sử dụng, 744 01:02:27,120 --> 01:02:29,690 chúng tôi luôn luôn có thể mở các trang người đàn ông. 745 01:02:29,690 --> 01:02:34,350 Vì vậy, chúng ta có thể gõ stdio người đàn ông 746 01:02:34,350 --> 01:02:43,180 và đọc tất cả về đầu vào stdio và chức năng đầu ra trong C. 747 01:02:43,180 --> 01:02:49,870 Và chúng tôi đã có thể nhìn thấy oh, nhìn. Nó đề cập đến fgetc, nó đề cập đến fputc. 748 01:02:49,870 --> 01:02:57,220 Vì vậy, bạn có thể đi sâu xuống một chút và nhìn vào, nói, fgetc 749 01:02:57,220 --> 01:03:00,060 và nhìn vào trang người đàn ông của mình. 750 01:03:00,060 --> 01:03:03,430 Bạn có thể thấy là nó đi cùng với một bó toàn bộ các chức năng khác: 751 01:03:03,430 --> 01:03:12,640 fgetc, fgets, getc, getchar, được, ungetc, và đầu vào của các ký tự và chuỗi. 752 01:03:12,640 --> 01:03:19,180 Vì vậy, đây là làm thế nào chúng ta đọc trong các ký tự và chuỗi từ các tập tin từ đầu vào tiêu chuẩn, 753 01:03:19,180 --> 01:03:21,990 mà chủ yếu là từ người dùng. 754 01:03:21,990 --> 01:03:24,780 Và đây là cách chúng tôi làm điều đó trong thực tế C. 755 01:03:24,780 --> 01:03:30,850 Vì vậy, điều này là không sử dụng GetString và các chức năng getchar 756 01:03:30,850 --> 01:03:36,840 mà chúng ta đã sử dụng từ thư viện CS50. 757 01:03:36,840 --> 01:03:39,710 Chúng tôi sẽ làm vấn đề này trong một vài cách 758 01:03:39,710 --> 01:03:43,430 để bạn có thể thấy hai cách khác nhau để làm việc đó. 759 01:03:43,430 --> 01:03:48,490 Cả hai chức năng fread rằng Daniel đã đề cập và fgetc là những cách tốt để làm điều đó. 760 01:03:48,490 --> 01:03:53,790 Tôi nghĩ rằng fgetc là một chút dễ dàng hơn, bởi vì nó chỉ có, như bạn thấy, 761 01:03:53,790 --> 01:03:59,660 một đối số, FILE * mà chúng tôi đang cố gắng để đọc các ký tự từ, 762 01:03:59,660 --> 01:04:02,740 và giá trị trả về của nó là một int. 763 01:04:02,740 --> 01:04:05,610 Và đây là một chút bối rối, phải không? 764 01:04:05,610 --> 01:04:11,450 >> Bởi vì chúng tôi đang nhận được một nhân vật, vậy tại sao không trở lại này là một char? 765 01:04:11,450 --> 01:04:18,700 Các bạn có bất kỳ ý tưởng về lý do tại sao điều này có thể không trả về một char? 766 01:04:18,700 --> 01:04:25,510 [Missy câu trả lời, không thể hiểu] >> Vâng. Vì vậy, Missy là hoàn toàn đúng. 767 01:04:25,510 --> 01:04:31,570 Nếu đó là ASCII, sau đó số nguyên này có thể được ánh xạ đến một char thực tế. 768 01:04:31,570 --> 01:04:33,520 Có thể là một ký tự ASCII, và đó là đúng. 769 01:04:33,520 --> 01:04:36,220 Đó là chính xác những gì đang xảy ra. 770 01:04:36,220 --> 01:04:39,190 Chúng tôi đang sử dụng một int chỉ đơn giản là bởi vì nó có nhiều bit hơn. 771 01:04:39,190 --> 01:04:44,750 Nó lớn hơn một char, char của chúng tôi chỉ có 8 bit, 1 byte trên máy 32-bit của chúng tôi. 772 01:04:44,750 --> 01:04:48,520 Và một int có giá trị tất cả 4 byte của không gian. 773 01:04:48,520 --> 01:04:50,940 Và nó chỉ ra rằng cách fgetc hoạt động, 774 01:04:50,940 --> 01:04:53,940 nếu chúng ta di chuyển xuống trong tóm tắt của chúng tôi trong trang người đàn ông này một chút, 775 01:04:53,940 --> 01:05:05,000 di chuyển tất cả các con đường xuống. Nó chỉ ra rằng họ sử dụng giá trị này đặc biệt được gọi là EOF. 776 01:05:05,000 --> 01:05:09,640 Đó là một hằng số đặc biệt như là giá trị trả về của hàm fgetc 777 01:05:09,640 --> 01:05:14,570 bất cứ khi nào bạn nhấn vào cuối của tập tin hoặc nếu bạn nhận được một lỗi. 778 01:05:14,570 --> 01:05:18,170 Và nó chỉ ra rằng để làm những so sánh với kết thúc tập tin đúng, 779 01:05:18,170 --> 01:05:24,060 bạn muốn có thêm số tiền đó thông tin mà bạn có trong một int 780 01:05:24,060 --> 01:05:28,420 như trái ngược với sử dụng một biến char. 781 01:05:28,420 --> 01:05:32,130 Mặc dù fgetc hiệu quả nhận được một nhân vật từ một tập tin, 782 01:05:32,130 --> 01:05:38,450 bạn muốn ghi nhớ rằng nó được trả lại một cái gì đó là kiểu int cho bạn. 783 01:05:38,450 --> 01:05:41,360 Điều đó nói rằng, nó khá dễ dàng để sử dụng. 784 01:05:41,360 --> 01:05:44,960 Nó sẽ cung cấp cho chúng ta một nhân vật, vì vậy tất cả chúng ta phải làm là tiếp tục yêu cầu các tập tin, 785 01:05:44,960 --> 01:05:48,440 "Hãy cho tôi ký tự tiếp theo, cung cấp cho tôi những nhân vật tiếp theo, cung cấp cho tôi những nhân vật tiếp theo," 786 01:05:48,440 --> 01:05:51,400 cho đến khi chúng tôi nhận được để kết thúc của tập tin. 787 01:05:51,400 --> 01:05:54,730 Và đó sẽ kéo trong một ký tự tại một thời gian từ tập tin của chúng tôi, 788 01:05:54,730 --> 01:05:56,250 và sau đó chúng ta có thể làm bất cứ điều gì chúng ta thích với nó. 789 01:05:56,250 --> 01:06:00,160 Chúng ta có thể lưu trữ nó, chúng ta có thể thêm nó vào một chuỗi, chúng ta có thể in nó ra. 790 01:06:00,160 --> 01:06:04,630 Làm được điều đó. 791 01:06:04,630 --> 01:06:09,600 >> Phóng to thu nhỏ lại và sẽ trở lại chương trình cat.c của chúng tôi, 792 01:06:09,600 --> 01:06:16,170 nếu chúng ta sử dụng fgetc, 793 01:06:16,170 --> 01:06:21,710 làm thế nào chúng ta có thể tiếp cận dòng tiếp theo của mã này? 794 01:06:21,710 --> 01:06:26,020 Chúng ta sẽ sử dụng - fread sẽ làm một cái gì đó hơi khác nhau. 795 01:06:26,020 --> 01:06:32,600 Và lần này, chúng ta chỉ cần sử dụng fgetc để có được một trong những nhân vật tại một thời điểm. 796 01:06:32,600 --> 01:06:40,910 Để xử lý một tập tin toàn bộ, những gì chúng ta có thể phải làm gì? 797 01:06:40,910 --> 01:06:44,030 Có bao nhiêu ký tự trong một tập tin? 798 01:06:44,030 --> 01:06:47,390 Hiện có rất nhiều. Vì vậy, bạn có thể muốn để có được một 799 01:06:47,390 --> 01:06:49,860 và sau đó nhận được một và nhận được một và nhận được một. 800 01:06:49,860 --> 01:06:53,330 Loại thuật toán bạn có nghĩ rằng chúng ta có thể phải sử dụng ở đây? 801 01:06:53,330 --> 01:06:55,470 Loại? [Alexander] A cho vòng lặp? >> Chính xác. 802 01:06:55,470 --> 01:06:57,500 Một số loại vòng lặp. 803 01:06:57,500 --> 01:07:03,380 A cho vòng lặp là thực sự tuyệt vời, trong trường hợp này. 804 01:07:03,380 --> 01:07:08,620 Và cũng giống như bạn đã nói, nó có vẻ như bạn muốn có một vòng lặp trên toàn bộ tập tin, 805 01:07:08,620 --> 01:07:11,820 nhận được một nhân vật tại một thời điểm. 806 01:07:11,820 --> 01:07:13,850 Bất kỳ đề xuất về những gì có thể trông như thế? 807 01:07:13,850 --> 01:07:22,090 [Alexander, khó hiểu] 808 01:07:22,090 --> 01:07:30,050 >> Được rồi, chỉ nói với tôi bằng tiếng Anh những gì bạn đang cố gắng để làm? [Alexander, khó hiểu] 809 01:07:30,050 --> 01:07:36,270 Vì vậy, trong trường hợp này, có vẻ như chúng tôi chỉ cố gắng để lặp trên toàn bộ tập tin. 810 01:07:36,270 --> 01:07:45,330 [Alexander] Vì vậy, i > Kích thước của? 811 01:07:45,330 --> 01:07:49,290 Tôi đoán kích thước của tập tin, phải không? Các kích thước - we'll chỉ cần viết nó như thế này. 812 01:07:49,290 --> 01:07:57,470 Kích thước của tập tin trong thời gian này, i + +. 813 01:07:57,470 --> 01:08:04,610 Vì vậy, nó chỉ ra rằng cách bạn làm điều này bằng cách sử dụng fgetc, và điều này là mới, 814 01:08:04,610 --> 01:08:10,460 là không có cách nào dễ dàng để có được kích thước của một tập tin 815 01:08:10,460 --> 01:08:16,979 với loại hình này "sizeof" xây dựng mà bạn đã thấy trước. 816 01:08:16,979 --> 01:08:20,910 Khi chúng tôi sử dụng chức năng fgetc, chúng tôi giới thiệu một số loại 817 01:08:20,910 --> 01:08:29,069 mới, lý thú, cú pháp này cho vòng lặp, thay vì chỉ sử dụng một truy cập cơ bản 818 01:08:29,069 --> 01:08:33,920 đi nhân vật bằng cách nhân vật, chúng tôi sẽ kéo một trong những nhân vật tại một thời điểm, 819 01:08:33,920 --> 01:08:37,120 một ký tự tại một thời điểm, và cách chúng ta biết chúng ta đang ở cuối 820 01:08:37,120 --> 01:08:41,290 không khi chúng tôi đã tính một số ký tự nhất định, 821 01:08:41,290 --> 01:08:49,939 nhưng khi nhân vật chúng tôi kéo ra là kết thúc đặc biệt của nhân vật tập tin. 822 01:08:49,939 --> 01:08:58,689 Vì vậy, chúng ta có thể làm điều này - Tôi gọi đây là ch, và chúng ta sẽ khởi tạo nó 823 01:08:58,689 --> 01:09:08,050 với cuộc gọi đầu tiên của chúng tôi để có được những ký tự đầu tiên trong số các tập tin. 824 01:09:08,050 --> 01:09:14,979 Vì vậy, phần này ngay tại đây, điều này là có được một ký tự của tập tin 825 01:09:14,979 --> 01:09:20,840 và lưu nó vào biến ch. 826 01:09:20,840 --> 01:09:25,420 Chúng tôi sẽ tiếp tục làm điều này cho đến khi chúng tôi nhận được để kết thúc của tập tin, 827 01:09:25,420 --> 01:09:41,170 mà chúng ta làm bằng cách thử nghiệm cho các nhân vật không phải là bằng với ký tự EOF đặc biệt. 828 01:09:41,170 --> 01:09:48,750 Và sau đó, thay vì làm ch + +, sẽ chỉ tăng giá trị, 829 01:09:48,750 --> 01:09:52,710 vì vậy nếu chúng ta đọc một out của tập tin, vốn, nói, 830 01:09:52,710 --> 01:09:56,810 ch + + sẽ cung cấp cho chúng tôi b, và sau đó chúng tôi nhận được c và sau đó d. 831 01:09:56,810 --> 01:09:59,310 Đó là rõ ràng không phải những gì chúng ta muốn. Những gì chúng tôi muốn ở đây 832 01:09:59,310 --> 01:10:05,830 trong này bit cuối cùng chúng tôi muốn để có được những nhân vật tiếp theo từ tập tin. 833 01:10:05,830 --> 01:10:09,500 >> Vì vậy, làm thế nào chúng ta có thể nhận được nhân vật tiếp theo từ tập tin? 834 01:10:09,500 --> 01:10:13,470 Làm thế nào để chúng ta được những nhân vật đầu tiên từ tập tin? 835 01:10:13,470 --> 01:10:17,200 [Sinh viên] fgetfile? >> Fgetc, hoặc xin lỗi, bạn đã hoàn toàn đúng. 836 01:10:17,200 --> 01:10:20,470 Tôi sai chính tả ngay tại đây. Vì vậy, yeah. 837 01:10:20,470 --> 01:10:26,240 Ở đây, thay vì làm ch + +, 838 01:10:26,240 --> 01:10:29,560 chúng tôi sẽ gọi fgetc (file) một lần nữa 839 01:10:29,560 --> 01:10:39,180 và lưu trữ kết quả trong biến ch cùng của chúng tôi. 840 01:10:39,180 --> 01:10:43,730 [Sinh viên câu hỏi, không thể hiểu] 841 01:10:43,730 --> 01:10:52,390 >> Đây là nơi mà những kẻ * FILE là đặc biệt. 842 01:10:52,390 --> 01:10:59,070 Cách họ làm việc là họ - khi bạn lần đầu tiên mở - khi lần đầu tiên thực hiện cuộc gọi fopen, 843 01:10:59,070 --> 01:11:04,260 * FILE hiệu quả phục vụ như là một con trỏ đến đầu của tập tin. 844 01:11:04,260 --> 01:11:12,830 Và sau đó mỗi khi bạn gọi fgetc, nó di chuyển một trong những nhân vật qua các tập tin. 845 01:11:12,830 --> 01:11:23,280 Vì vậy, bất cứ khi nào bạn gọi này, bạn đang incrementing con trỏ tập tin của một nhân vật. 846 01:11:23,280 --> 01:11:26,210 Và khi bạn fgetc một lần nữa, bạn di chuyển nó một nhân vật khác 847 01:11:26,210 --> 01:11:28,910 và một nhân vật khác và một nhân vật khác và một nhân vật khác. 848 01:11:28,910 --> 01:11:32,030 [Sinh viên câu hỏi, không thể hiểu] >> Đó - yeah. 849 01:11:32,030 --> 01:11:34,810 Nó là loại ma thuật này dưới mui xe. 850 01:11:34,810 --> 01:11:37,930 Bạn chỉ cần giữ incrementing qua. 851 01:11:37,930 --> 01:11:46,510 Tại thời điểm này, bạn có thể thực sự làm việc với một nhân vật. 852 01:11:46,510 --> 01:11:52,150 Vì vậy, làm thế nào chúng ta có thể in này ra đến màn hình, bây giờ không? 853 01:11:52,150 --> 01:11:58,340 Chúng tôi có thể sử dụng cùng một điều printf mà chúng tôi đã sử dụng trước. 854 01:11:58,340 --> 01:12:00,330 Mà chúng tôi đã sử dụng tất cả các học kỳ. 855 01:12:00,330 --> 01:12:05,450 Chúng ta có thể gọi printf, 856 01:12:05,450 --> 01:12:21,300 và chúng ta có thể vượt qua trong nhân vật như thế. 857 01:12:21,300 --> 01:12:27,430 Một cách khác để làm điều đó là thay vì sử dụng printf và phải làm điều này chuỗi định dạng, 858 01:12:27,430 --> 01:12:29,490 chúng tôi cũng có thể sử dụng một trong các chức năng khác. 859 01:12:29,490 --> 01:12:40,090 Chúng tôi có thể sử dụng fputc, in một ký tự lên màn hình, 860 01:12:40,090 --> 01:12:52,580 trừ khi chúng ta nhìn vào fputc - hãy để tôi thu nhỏ một chút. 861 01:12:52,580 --> 01:12:56,430 Chúng tôi nhìn thấy những gì tốt đẹp là nó có trong nhân vật mà chúng ta đọc ra bằng cách sử dụng fgetc, 862 01:12:56,430 --> 01:13:05,100 nhưng sau đó chúng ta phải cung cấp cho nó một dòng suối để in. 863 01:13:05,100 --> 01:13:11,850 Chúng tôi cũng có thể sử dụng chức năng putchar, mà sẽ đặt trực tiếp để ra tiêu chuẩn. 864 01:13:11,850 --> 01:13:16,070 Vì vậy, có một bó toàn bộ các tùy chọn khác nhau mà chúng ta có thể sử dụng cho việc in ấn. 865 01:13:16,070 --> 01:13:19,580 Họ đang tất cả trong thư viện I / O tiêu chuẩn. 866 01:13:19,580 --> 01:13:25,150 Bất cứ khi nào bạn muốn in - printf, theo mặc định, sẽ in với tiêu chuẩn đặc biệt ra khỏi dòng, 867 01:13:25,150 --> 01:13:27,910 là stdout đó. 868 01:13:27,910 --> 01:13:41,300 Vì vậy, chúng tôi chỉ có thể đề cập đến nó như là loại giá trị này ma thuật, thiết bị xuất chuẩn ở đây. 869 01:13:41,300 --> 01:13:48,410 Rất tiếc. Đặt dấu chấm phẩy bên ngoài. 870 01:13:48,410 --> 01:13:52,790 >> Này là rất nhiều thông tin mới funky, ở đây. 871 01:13:52,790 --> 01:13:58,600 Rất nhiều trong số này là rất thành ngữ, cảm giác rằng đây là mã 872 01:13:58,600 --> 01:14:05,700 được viết theo cách này chỉ vì nó sạch sẽ để đọc, dễ đọc. 873 01:14:05,700 --> 01:14:11,520 Có nhiều cách khác nhau để làm điều đó, nhiều chức năng khác nhau mà bạn có thể sử dụng, 874 01:14:11,520 --> 01:14:14,680 nhưng chúng ta có xu hướng chỉ cần làm theo các mô hình tương tự hơn và hơn. 875 01:14:14,680 --> 01:14:20,180 Vì vậy, không ngạc nhiên nếu bạn thấy mã như thế này đến một lần nữa và một lần nữa. 876 01:14:20,180 --> 01:14:25,690 Được rồi. Tại thời điểm này, chúng ta cần để phá vỡ trong ngày. 877 01:14:25,690 --> 01:14:31,300 Cảm ơn vì đã đến. Cảm ơn bạn đã cho xem nếu bạn đang trực tuyến. Và chúng ta sẽ thấy bạn vào tuần tới. 878 01:14:31,300 --> 01:14:33,890 [CS50.TV]