1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Ενότητα 5 - Άνετα Περισσότερα] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Πανεπιστήμιο του Χάρβαρντ] 3 00:00:04,690 --> 00:00:07,250 [Αυτό είναι CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Όπως είπα και στο e-mail μου, υπάρχουν πολλά πράγματα που μπορείτε να χρησιμοποιήσετε 5 00:00:14,250 --> 00:00:17,060 εκτός από τη συσκευή για να κάνουν πραγματικότητα τα σύνολα πρόβλημα. 6 00:00:17,060 --> 00:00:19,910 Σας προτείνουμε να το κάνουμε με τη συσκευή μόνο και μόνο επειδή τότε μπορούμε πιο εύκολα να σας βοηθήσει 7 00:00:19,910 --> 00:00:22,070 και γνωρίζουμε πως ό, τι πρόκειται να λειτουργήσει. 8 00:00:22,070 --> 00:00:26,950 Αλλά ως ένα παράδειγμα όπου μπορείτε να κάνετε τα πράγματα αν, ας πούμε, δεν έχετε πρόσβαση 9 00:00:26,950 --> 00:00:31,570 σε μια συσκευή ή θέλετε να εργαστείτε στο υπόγειο Κέντρο Διάδοσης Επιστημών - 10 00:00:31,570 --> 00:00:33,090 που πραγματικά έχουν τη συσκευή πάρα πολύ - 11 00:00:33,090 --> 00:00:35,150 αν θέλετε να εργαστείτε οπουδήποτε. 12 00:00:35,150 --> 00:00:42,370 Ένα παράδειγμα είναι έχετε δει / ακούσει SSH; 13 00:00:44,380 --> 00:00:47,780 SSH είναι βασικά ακριβώς όπως σύνδεση με κάτι. 14 00:00:47,780 --> 00:00:51,340 Στην πραγματικότητα, αυτή τη στιγμή είμαι SSHed στη συσκευή. 15 00:00:51,340 --> 00:00:54,290 Ποτέ δεν εργάζονται απευθείας στη συσκευή. 16 00:00:55,930 --> 00:01:01,060 Εδώ είναι η συσκευή, και αν κοιτάξετε εδώ κάτω να δείτε αυτήν τη διεύθυνση IP. 17 00:01:01,060 --> 00:01:03,650 Ποτέ δεν εργάζονται στην ίδια τη συσκευή? 18 00:01:03,650 --> 00:01:08,840 Πάντα έρχονται πάνω σε ένα παράθυρο παράθυρο iTerm2 / τερματικό. 19 00:01:08,840 --> 00:01:15,910 Μπορείτε να SSH σε αυτήν τη διεύθυνση IP, το ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Θυμάμαι ότι ο αριθμός είναι πολύ εύκολα γιατί είναι τόσο ωραίο μοτίβο. 21 00:01:20,390 --> 00:01:24,920 Αλλά ότι θα με ρωτήσετε για τον κωδικό μου, και τώρα είμαι στη συσκευή. 22 00:01:24,920 --> 00:01:33,060 Βασικά, σε αυτό το σημείο, εάν ανοίξει ένα τερματικό στο εσωτερικό της ίδιας της συσκευής, 23 00:01:33,060 --> 00:01:36,350 αυτή η διασύνδεση, όμως θα το χρησιμοποιήσετε, είναι ακριβώς το ίδιο 24 00:01:36,350 --> 00:01:40,010 ως διεπαφή είμαι με τη χρήση πάνω από εδώ, αλλά τώρα είστε SSHed. 25 00:01:42,240 --> 00:01:44,920 Δεν χρειάζεται να SSH στη συσκευή. 26 00:01:44,920 --> 00:01:52,360 Ένα παράδειγμα από ένα άλλο μέρος που θα μπορούσε να είναι SSH είμαι σίγουρος ότι έχετε από προεπιλογή - 27 00:01:52,360 --> 00:01:55,020 Αχ. Μεγαλύτερο. 28 00:01:55,020 --> 00:02:01,130 Όλοι θα πρέπει να έχετε από τους λογαριασμούς FAS προεπιλογή στους διακομιστές FAS. 29 00:02:01,130 --> 00:02:06,840 Για μένα, θα ήθελα να rbowden@nice.fas.harvard.edu SSH. 30 00:02:06,840 --> 00:02:11,610 Είναι πρόκειται να σας ρωτήσω ότι είναι η πρώτη φορά, και θα πω ναι. 31 00:02:11,610 --> 00:02:15,840 Κωδικό μου είναι ακριβώς πρόκειται να είναι FAS τον κωδικό μου. 32 00:02:15,840 --> 00:02:22,650 Και έτσι τώρα, είμαι SSHed με τα ωραία servers, και μπορώ να κάνω οτιδήποτε θέλω εδώ. 33 00:02:22,650 --> 00:02:28,560 Πολλά μαθήματα που θα μπορούσε να λάβει, όπως η 124, θα έχετε να ανεβάσετε τα πράγματα εδώ 34 00:02:28,560 --> 00:02:30,950 να υποβάλουν πραγματικά σύνολα πρόβλημά σας. 35 00:02:30,950 --> 00:02:34,100 Αλλά λένε ότι δεν έχουν πρόσβαση στην συσκευή σας. 36 00:02:34,100 --> 00:02:37,910 Στη συνέχεια, μπορείτε να κάνετε τα πράγματα, όπως για εδώ θα πω - 37 00:02:37,910 --> 00:02:42,160 Αυτό είναι ακριβώς το τμήμα των ερωτήσεων. 38 00:02:42,160 --> 00:02:45,070 Θα σας ζητήσει να το κάνετε αυτό στη συσκευή. 39 00:02:45,070 --> 00:02:47,790 Αντ 'αυτού θα το κάνω μόνο στο διακομιστή. 40 00:02:47,790 --> 00:02:50,560 Πάω να αποσυμπιέσετε αυτό. 41 00:02:50,560 --> 00:02:55,670 Το πρόβλημα θα είναι ότι έχετε συνηθίσει να χρησιμοποιείτε κάτι σαν το gedit 42 00:02:55,670 --> 00:02:58,160 ή οτιδήποτε άλλο στο εσωτερικό της συσκευής. 43 00:02:58,160 --> 00:03:01,830 Δεν πρόκειται να έχουμε ότι στο διακομιστή FAS. 44 00:03:01,830 --> 00:03:04,110 Είναι όλα ακριβώς πρόκειται να είναι αυτό το περιβάλλον κειμένου. 45 00:03:04,110 --> 00:03:09,180 Έτσι, θα μπορούσατε είτε το ένα, προσπαθήστε να μάθετε ένα πρόγραμμα επεξεργασίας κειμένου που έχουν. 46 00:03:09,180 --> 00:03:12,130 Έχουν Nano. 47 00:03:12,130 --> 00:03:14,990 Nano είναι συνήθως αρκετά εύκολο στη χρήση. 48 00:03:14,990 --> 00:03:19,470 Μπορείτε να χρησιμοποιήσετε τα βέλη σας και πληκτρολογήστε κανονικά. 49 00:03:19,470 --> 00:03:21,250 Έτσι, αυτό δεν είναι δύσκολο. 50 00:03:21,250 --> 00:03:24,720 Αν θέλετε να πάρετε πραγματικά φανταχτερό, μπορείτε να χρησιμοποιήσετε τον Emacs, 51 00:03:24,720 --> 00:03:29,850 που εγώ κατά πάσα πιθανότητα δεν θα πρέπει να έχουν ανοίξει γιατί δεν γνωρίζουν καν πώς να κλείσει το Emacs. 52 00:03:29,850 --> 00:03:32,760 Έλεγχος X, C Ελέγχου; Ναι. 53 00:03:32,760 --> 00:03:35,310 Ή μπορείτε να χρησιμοποιήσετε Vim, το οποίο είναι αυτό που μπορώ να χρησιμοποιήσω. 54 00:03:35,310 --> 00:03:37,800 Και έτσι αυτές είναι οι επιλογές σας. 55 00:03:37,800 --> 00:03:43,830 Αν δεν θέλετε να το κάνετε αυτό, μπορείτε επίσης, αν κοιτάξετε manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Αχ. 57 00:03:45,410 --> 00:03:49,920 Σε έναν υπολογιστή, μπορείτε να χρησιμοποιείτε SSH PuTTY, 58 00:03:49,920 --> 00:03:51,940 που θα πάμε να πρέπει να κατεβάσετε ξεχωριστά. 59 00:03:51,940 --> 00:03:55,460 Σε Mac, μπορείτε απλά με τη χρήση τερματικού προεπιλογή ή μπορείτε να κατεβάσετε iTerm2, 60 00:03:55,460 --> 00:03:58,490 η οποία είναι σαν ένα ωραίο, φανταχτερό Terminal. 61 00:03:58,490 --> 00:04:03,780 Αν πάτε να manual.cs50.net θα δείτε ένα σύνδεσμο για να Notepad + +, 62 00:04:03,780 --> 00:04:07,120 το οποίο είναι αυτό που μπορείτε να χρησιμοποιήσετε σε έναν υπολογιστή. 63 00:04:07,120 --> 00:04:13,340 Σας επιτρέπει να SFTP από Notepad + +, το οποίο είναι ουσιαστικά SSH. 64 00:04:13,340 --> 00:04:17,750 Αυτό θα σας επιτρέψει να κάνετε είναι να επεξεργαστείτε τα αρχεία σας σε τοπικό επίπεδο, 65 00:04:17,750 --> 00:04:20,670 και στη συνέχεια, κάθε φορά που θέλετε να τους σώσει, θα εξοικονομήσει να nice.fas, 66 00:04:20,670 --> 00:04:23,670 όπου μπορείτε να εκτελέσετε στη συνέχεια. 67 00:04:23,670 --> 00:04:26,880 Και το ισοδύναμο σε ένα Mac θα είναι TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Γι 'αυτό σας επιτρέπει να κάνετε το ίδιο πράγμα. 69 00:04:28,760 --> 00:04:32,800 Αυτό σας επιτρέπει να επεξεργαστείτε αρχεία τοπικά και να τα αποθηκεύσετε σε nice.fas, 70 00:04:32,800 --> 00:04:35,730 όπου μπορείτε να εκτελέσετε στη συνέχεια. 71 00:04:35,730 --> 00:04:40,400 Έτσι, εάν είστε ποτέ κολλήσει χωρίς συσκευή, έχετε αυτές τις επιλογές 72 00:04:40,400 --> 00:04:44,230 ακόμα να κάνετε σετ πρόβλημά σας. 73 00:04:44,230 --> 00:04:48,250 Το μόνο πρόβλημα θα είναι ότι δεν πρόκειται να έχουν την CS50 βιβλιοθήκη 74 00:04:48,250 --> 00:04:51,580 nice.fas επειδή δεν έχουν από προεπιλογή αυτό. 75 00:04:51,580 --> 00:04:55,970 Μπορείτε να κατεβάσετε είτε το CS50 βιβλιοθήκη - 76 00:04:55,970 --> 00:04:58,470 Δεν νομίζω ότι χρειάζομαι σε αυτό το σημείο. 77 00:04:58,470 --> 00:05:03,270 Μπορείτε να κατεβάσετε είτε το CS50 βιβλιοθήκη και να το αντιγράψετε πάνω σε nice.fas, 78 00:05:03,270 --> 00:05:07,450 ή Νομίζω ότι σε αυτό το σημείο δεν το χρησιμοποιούν πια ούτως ή άλλως. 79 00:05:07,450 --> 00:05:12,720 Ή αν το κάνουμε, μπορείτε προς το παρόν να το αντικαταστήσει με 80 00:05:12,720 --> 00:05:18,480 οι υλοποιήσεις των λειτουργιών της βιβλιοθήκης CS50 ούτως ή άλλως. 81 00:05:18,480 --> 00:05:21,370 Έτσι, αυτό δεν θα πρέπει να είναι ότι ένα μεγάλο μέρος ενός περιορισμού. 82 00:05:21,370 --> 00:05:23,710 Και αυτό είναι αυτό. 83 00:05:26,460 --> 00:05:29,820 >> Θα πάω πίσω στη συσκευή τώρα? Θα κάνουμε τα πάντα μέσα στη συσκευή. 84 00:05:29,820 --> 00:05:37,510 Κοιτάζοντας το τμήμα των ερωτήσεων, στην αρχή, όπως είπα και στο e-mail μου, 85 00:05:37,510 --> 00:05:43,620 έχουμε να μιλήσουμε για το ένα κοντό που έπρεπε να παρακολουθήσουν. 86 00:05:43,620 --> 00:05:51,980 Έχουμε τον αναπροσανατολισμό & Σωλήνες και αυτά τα τρία ερωτήματα. 87 00:05:51,980 --> 00:05:56,070 >> Σε ποια ρεύμα δεν λειτουργεί όπως printf γράψει από προεπιλογή; 88 00:05:56,070 --> 00:05:59,130 Έτσι ρεύμα. Τι είναι το ρεύμα; 89 00:06:06,520 --> 00:06:15,100 Ένα ρεύμα είναι βασικά σαν να είναι μόνο μερικά - 90 00:06:15,100 --> 00:06:21,450 Δεν είναι καν μια πηγή του 1s και 0s. 91 00:06:21,450 --> 00:06:24,920 Το ρεύμα αυτό είναι ζητώντας εδώ είναι τυποποιημένα. 92 00:06:24,920 --> 00:06:27,250 Και έτσι η τυπική έξω είναι ότι ένα ρεύμα όταν γράφετε σε αυτό, 93 00:06:27,250 --> 00:06:30,940 εμφανίζεται στην οθόνη. 94 00:06:30,940 --> 00:06:36,860 Πρότυπο έξω, με ρεύμα, αυτό σημαίνει ότι μπορείτε απλά γράψτε 1s και 0s σε αυτό, 95 00:06:36,860 --> 00:06:40,220 και το άλλο άκρο του προτύπου έξω διαβάζει μόνο από το ρεύμα. 96 00:06:40,220 --> 00:06:43,540 Είναι απλά μια σειρά από 1 και 0. 97 00:06:43,540 --> 00:06:45,570 Μπορείτε να γράψετε σε ρέματα ή μπορείτε να διαβάσετε από τις ροές 98 00:06:45,570 --> 00:06:47,950 ανάλογα με το τι το ρεύμα είναι στην πραγματικότητα. 99 00:06:47,950 --> 00:06:52,800 Τα άλλα δύο ρεύματα προεπιλογή είναι στάνταρ σε και τυπικό σφάλμα. 100 00:06:52,800 --> 00:06:57,540 Πρότυπο είναι κάθε φορά που κάνετε GetString, σας περιμένει για να σας πράγματα εισόδου. 101 00:06:57,540 --> 00:07:01,570 Γι 'αυτό σας περιμένει, είναι στην πραγματικότητα περιμένει για πρότυπο, 102 00:07:01,570 --> 00:07:04,880 η οποία είναι πραγματικά αυτό που παίρνετε όταν πληκτρολογείτε στο πληκτρολόγιο. 103 00:07:04,880 --> 00:07:07,530 Είσαι πληκτρολογώντας στο πρότυπο μέσα 104 00:07:07,530 --> 00:07:10,050 Τυπικό σφάλμα είναι βασικά ισοδύναμη με τις τυποποιημένες, 105 00:07:10,050 --> 00:07:13,280 αλλά είναι εξειδικευμένη σε ότι όταν εκτυπώνετε σε τυπικό σφάλμα, 106 00:07:13,280 --> 00:07:16,770 είστε υποτίθεται για να εκτυπώσετε μόνο μηνύματα λάθους στο ότι 107 00:07:16,770 --> 00:07:20,200 έτσι ώστε να μπορεί να γίνει διάκριση μεταξύ τακτικών μηνύματα στην οθόνη 108 00:07:20,200 --> 00:07:24,560 έναντι μηνύματα λάθους, ανάλογα με το αν πήγαν στο τυποποιημένες ή τυπικό σφάλμα. 109 00:07:24,560 --> 00:07:28,660 Αρχεία πάρα πολύ. 110 00:07:28,660 --> 00:07:32,440 Πρότυπο έξω, πρότυπο, και τυπικό σφάλμα είναι μόνο ειδικές κατηγορίες, 111 00:07:32,440 --> 00:07:36,810 αλλά πραγματικά οποιοδήποτε αρχείο, όταν ανοίγετε ένα αρχείο, γίνεται ένα ρεύμα από bytes 112 00:07:36,810 --> 00:07:40,740 όπου μπορείτε απλά να διαβαστεί από αυτό το ρεύμα. 113 00:07:40,740 --> 00:07:47,770 Εσείς, ως επί το πλείστον, μπορεί απλά σκεφτείτε ένα αρχείο ως ένα ρεύμα byte. 114 00:07:47,770 --> 00:07:51,190 Έτσι ρεύματα τι γράφουν από προεπιλογή; Πρότυπο έξω. 115 00:07:51,190 --> 00:07:56,980 >> Ποια είναι η διαφορά μεταξύ> και >>; 116 00:07:58,140 --> 00:08:03,710 Μήπως κάποιος δείτε το βίντεο εκ των προτέρων; Εντάξει. 117 00:08:03,710 --> 00:08:10,960 > Πρόκειται να είναι το πώς θα ανακατευθύνει σε αρχεία, 118 00:08:10,960 --> 00:08:15,240 >> και είναι, επίσης, πρόκειται να ανακατευθύνετε την έξοδο σε αρχεία, 119 00:08:15,240 --> 00:08:17,820 αλλά είναι αντ 'αυτού πρόκειται να επισυνάπτει στον φάκελο. 120 00:08:17,820 --> 00:08:23,430 Για παράδειγμα, ας υποθέσουμε ότι τυχαίνει να έχουν δικαίωμα dict εδώ, 121 00:08:23,430 --> 00:08:27,020 και η μόνη ουσία στο εσωτερικό του dict είναι, γάτα, σκύλος, ψάρι, σκύλος. 122 00:08:27,020 --> 00:08:31,530 Μια εντολή που έχετε στη γραμμή εντολών είναι η γάτα, 123 00:08:31,530 --> 00:08:34,539 το οποίο είναι ακριβώς πρόκειται να εκτυπώσετε ό, τι είναι σε ένα αρχείο. 124 00:08:34,539 --> 00:08:40,679 Έτσι, όταν λέω dict γάτα, πρόκειται να εκτυπώσετε γάτα, γάτα, σκύλος, τα ψάρια, το σκυλί. Αυτό είναι το μόνο γάτα κάνει. 125 00:08:40,679 --> 00:08:46,280 Αυτό σημαίνει ότι το έντυπο με το πρότυπο από γάτα, γάτα, σκύλος, τα ψάρια, το σκυλί. 126 00:08:46,280 --> 00:08:53,240 Αν αντί να θέλετε να ανακατευθύνετε ότι σε ένα αρχείο, μπορώ να χρησιμοποιήσω> και να τις κατευθύνουν σε ό, τι είναι το αρχείο. 127 00:08:53,240 --> 00:08:56,460 Θα καλέσω το αρχείο αρχείο. 128 00:08:56,460 --> 00:09:00,320 Έτσι τώρα, αν μου ls, θα δω έχω ένα νέο αρχείο με το όνομα αρχείου. 129 00:09:00,320 --> 00:09:05,700 Και αν το ανοίξουμε, πρόκειται να έχουν ό, τι ακριβώς γάτα που τίθεται στη γραμμή εντολών. 130 00:09:05,700 --> 00:09:11,040 Έτσι τώρα, αν το κάνω αυτό και πάλι, τότε πρόκειται να ανακατευθύνετε την έξοδο σε αρχείο, 131 00:09:11,040 --> 00:09:13,930 και είμαι πρόκειται να έχουν το ίδιο ακριβώς πράγμα. 132 00:09:13,930 --> 00:09:17,910 Έτσι, από τεχνική άποψη, το αγνόησε εντελώς ό, τι είχαμε. 133 00:09:17,910 --> 00:09:22,970 Και θα δούμε αν μπορώ να αλλάξω dict, έβγαλα το σκυλί. 134 00:09:22,970 --> 00:09:29,980 Τώρα, αν η γάτα dict σε αρχείο και πάλι, θα πάμε να έχουν τη νέα έκδοση αφαιρεθεί με το σκυλί. 135 00:09:29,980 --> 00:09:32,400 Γι 'αυτό αντικαθιστά εντελώς. 136 00:09:32,400 --> 00:09:36,640 Αντ 'αυτού, αν χρησιμοποιήσουμε >>, πρόκειται να προσθέσετε το αρχείο. 137 00:09:36,640 --> 00:09:40,860 Τώρα, το άνοιγμα αρχείων, βλέπουμε έχουμε ακριβώς το ίδιο πράγμα δύο φορές τυπωμένο 138 00:09:40,860 --> 00:09:44,920 διότι υπήρχε κάποτε, τότε προσαρτάται στο πρωτότυπο. 139 00:09:44,920 --> 00:09:48,130 Έτσι, ό, τι αυτό είναι> και >> κάνουν. 140 00:09:48,130 --> 00:09:50,580 Μήπως η επόμενη ζητήσει - Δεν ρωτήσω κάτι σχετικά με αυτό. 141 00:09:50,580 --> 00:09:59,050 >> Το άλλο που έχουμε είναι <, το οποίο αν> ανακατευθύνει πρότυπο έξω, 142 00:09:59,050 --> 00:10:01,970 <Πρόκειται να ανακατευθύνει πρότυπο μέσα 143 00:10:01,970 --> 00:10:12,050 Ας δούμε αν έχουμε ένα παράδειγμα. 144 00:10:14,750 --> 00:10:16,930 Μπορώ να γράψω ένα πραγματικά γρήγορα. 145 00:10:17,870 --> 00:10:25,700 Ας πάρουμε οποιοδήποτε αρχείο, hello.c. 146 00:10:56,060 --> 00:10:59,070 Σχετικά απλό αρχείο. 147 00:10:59,070 --> 00:11:03,570 Παίρνω απλώς ένα string και μετά την εκτύπωση "Hello" ό, τι η σειρά που μόλις εισήλθε ήταν. 148 00:11:03,570 --> 00:11:07,990 Γι 'αυτό και στη συνέχεια, γεια. / Γεια. 149 00:11:07,990 --> 00:11:10,720 Τώρα είναι μου ζητά να εισάγετε κάτι, 150 00:11:10,720 --> 00:11:15,070 πράγμα που σημαίνει ότι είναι σε αναμονή για τα πράγματα που πρέπει να τεθεί σε πρότυπο μέσα 151 00:11:15,070 --> 00:11:20,450 Έτσι αρχίζει ό, τι θέλω μέσα στο πρότυπο Είμαστε ακριβώς πρόκειται να πω Γεια σας, Rob! 152 00:11:20,450 --> 00:11:23,310 Στη συνέχεια εκτυπώνεται από το πρότυπο Γεια σας, Rob! 153 00:11:23,310 --> 00:11:28,860 Αν το κάνω. / Γεια και στη συνέχεια ανακατευθύνει, 154 00:11:30,740 --> 00:11:34,310 Προς το παρόν μπορείτε μόνο να ανακατευθύνει από ένα αρχείο. 155 00:11:34,310 --> 00:11:41,720 Έτσι, αν έβαλα σε κάποιο αρχείο, txt, και έβαλα τον Rob, 156 00:11:41,720 --> 00:11:52,300 αν τρέξω γεια και στη συνέχεια ανακατευθύνει το αρχείο txt σε. / γειά σου, πρόκειται να πω Γεια σας, Rob! αμέσως. 157 00:11:52,300 --> 00:11:57,160 Όταν παίρνει πρώτος που θα GetString και σας περιμένει στο πρότυπο, 158 00:11:57,160 --> 00:12:01,730 πρότυπο δεν είναι πλέον περιμένει στο πληκτρολόγιο για να πάρει τα στοιχεία εισαχθεί. 159 00:12:01,730 --> 00:12:05,980 Αντ 'αυτού, έχουμε ανακατευθύνονται πρότυπο για να διαβάσετε από το αρχείο txt. 160 00:12:05,980 --> 00:12:10,290 Και γι 'αυτό πρόκειται να διαβάσει από το αρχείο txt, το οποίο είναι ακριβώς η γραμμή Rob, 161 00:12:10,290 --> 00:12:13,380 και στη συνέχεια πρόκειται να εκτυπώσετε Γεια σας, Rob! 162 00:12:13,380 --> 00:12:18,180 Και αν ήθελα, θα μπορούσα να κάνω επίσης. / Γεια 00:12:21,500 και στη συνέχεια το πρότυπο από ότι η εκτύπωση του, η οποία είναι Γεια σας, Rob!, 164 00:12:21,500 --> 00:12:24,700 Μπορώ να ανακατευθύνει ότι στο δικό του αρχείο. 165 00:12:24,700 --> 00:12:29,790 Θα καλέσω μόνο το αρχείο γειά σου - όχι, δεν θα το κάνω, γιατί αυτό είναι το εκτελέσιμο - txt2. 166 00:12:29,790 --> 00:12:40,150 Τώρα, txt2 πρόκειται να έχουν την έξοδο του. / Γεια 00:12:43,520 >> Ερωτήσεις; 168 00:12:45,900 --> 00:12:49,090 >> Εντάξει. Έτσι λοιπόν εδώ έχουμε αγωγού. 169 00:12:49,090 --> 00:12:53,510 Σωλήνες είναι η τελευταία μονάδα της ανακατεύθυνσης. 170 00:12:53,510 --> 00:12:58,750 >> Αχ. Υποθέτω ότι μία μονάδα της ανακατεύθυνσης είναι αν αντί> κάνεις 2>, 171 00:12:58,750 --> 00:13:01,070 Αυτός είναι ο αναπροσανατολισμός τυπικό σφάλμα. 172 00:13:01,070 --> 00:13:06,280 Έτσι, αν κάτι πήγε σε τυπικό σφάλμα, δεν θα πάρει θέσει σε txt2. 173 00:13:06,280 --> 00:13:12,480 Αλλά αν παρατηρήσετε κάνω 2>, τότε είναι ακόμα εκτύπωση Γεια σας, Rob! στη γραμμή εντολών 174 00:13:12,480 --> 00:13:18,600 επειδή είμαι ανακατεύθυνση μόνο τυπικό σφάλμα, δεν είμαι από τον αναπροσανατολισμό πρότυπο. 175 00:13:18,600 --> 00:13:22,210 Τυπικό σφάλμα και έξω προτύπου είναι διαφορετικά. 176 00:13:24,210 --> 00:13:27,080 Αν πραγματικά ήθελε να γράψει σε τυπικό σφάλμα, 177 00:13:27,080 --> 00:13:35,080 τότε θα μπορούσε να αλλάξει αυτό είναι να fprintf stderr. 178 00:13:35,080 --> 00:13:37,850 Έτσι printf, από προεπιλογή, εκτυπώνει σε τυποποιημένες. 179 00:13:37,850 --> 00:13:41,720 Αν θέλετε να εκτυπώσετε σε τυπικό σφάλμα το χέρι, τότε θα πρέπει να χρησιμοποιήσετε fprintf 180 00:13:41,720 --> 00:13:45,010 και να καθορίσετε τι θέλετε να εκτυπώσετε σε. 181 00:13:45,010 --> 00:13:49,720 Αν, αντίθετα, έκανα fprintf stdout, τότε αυτό είναι ουσιαστικά ισοδύναμο με printf. 182 00:13:49,720 --> 00:13:55,530 Αλλά fprintf σε τυπικό σφάλμα. 183 00:13:57,790 --> 00:14:03,650 Έτσι τώρα, αν αυτό ανακατευθύνει σε txt2, Γεια σας, Rob! εξακολουθεί να πάρει τυπωμένο στη γραμμή εντολών 184 00:14:03,650 --> 00:14:08,270 δεδομένου ότι είναι να πάρει τυπωμένο σε τυπικό σφάλμα και είμαι ανακατεύθυνσης μόνο του πρότυπου έξω. 185 00:14:08,270 --> 00:14:16,420 Αν τώρα ανακατευθύνει τυπικό σφάλμα, τώρα δεν πάρει τυπωμένα, και txt2 πρόκειται να είναι Γεια σας, Rob! 186 00:14:16,420 --> 00:14:21,910 Έτσι τώρα, μπορείτε να εκτυπώσετε την πραγματική λάθη σας σε τυπικό σφάλμα 187 00:14:21,910 --> 00:14:24,720 και να εκτυπώσετε κανονικά μηνύματα σας σε τυποποιημένες. 188 00:14:24,720 --> 00:14:31,420 Και έτσι, όταν εκτελείτε το πρόγραμμα σας, μπορείτε να το εκτελέσετε ως. / Γειά σου αυτό το είδος με το 2> 189 00:14:31,420 --> 00:14:33,800 έτσι ώστε το πρόγραμμά σας θα τρέξει κανονικά, 190 00:14:33,800 --> 00:14:38,400 αλλά όλα τα μηνύματα λάθους που μπορείτε να πάρετε να ελέγξετε αργότερα στο αρχείο καταγραφής σφαλμάτων σας, 191 00:14:38,400 --> 00:14:44,500 έτσι τα λάθη, και στη συνέχεια να εξετάσουμε αργότερα και λάθη αρχείο σας θα έχουν τυχόν λάθη που συνέβη. 192 00:14:45,200 --> 00:14:47,540 >> Ερωτήσεις; 193 00:14:47,540 --> 00:14:58,070 >> Το τελευταίο είναι σωλήνα, το οποίο μπορείτε να σκεφτείτε τη λήψη του ως πρότυπο έξω από μία εντολή 194 00:14:58,070 --> 00:15:01,210 και καθιστώντας το πρότυπο στην από την επόμενη εντολή. 195 00:15:01,210 --> 00:15:05,570 Ένα παράδειγμα είναι εδώ ηχώ είναι ένα πράγμα της γραμμής εντολών 196 00:15:05,570 --> 00:15:11,840 που είναι ακριβώς πρόκειται να επαναλάβω ό, τι έχω θέσει ως επιχείρημα. Δεν θα βάλει εισαγωγικά. 197 00:15:11,840 --> 00:15:16,150 Echo μπλα, μπλα, μπλα είναι ακριβώς πρόκειται να εκτυπώσετε μπλα, μπλα, μπλα. 198 00:15:16,150 --> 00:15:20,600 Πριν, όταν είπα ότι έπρεπε να βάλει Rob σε ένα αρχείο txt 199 00:15:20,600 --> 00:15:28,830 γιατί μπορώ να ανακατευθύνει μόνο txt αρχεία, αντ 'αυτού, / αν συμμερίζομαι Rob 200 00:15:28,830 --> 00:15:35,520 σωλήνα και στη συνέχεια σε αυτό. / γειά σου, που θα κάνει επίσης το ίδιο είδος του πράγματος. 201 00:15:35,520 --> 00:15:39,160 Αυτό παίρνει την έξοδο της εντολής αυτής, echo Rob, 202 00:15:39,160 --> 00:15:43,610 και το χρησιμοποιεί ως είσοδο για. / γεια. 203 00:15:44,790 --> 00:15:49,560 Μπορείτε να σκεφτείτε από το ως ανακατεύθυνση πρώτη εντολή echo Rob σε ένα αρχείο 204 00:15:49,560 --> 00:15:54,160 και στη συνέχεια εισαγωγή στο. / γειά σου ότι το αρχείο που μόλις εξάγεται. 205 00:15:54,160 --> 00:15:57,850 Αλλά παίρνει το προσωρινό αρχείο από την εικόνα. 206 00:16:01,890 --> 00:16:04,460 >> Ερωτήσεις σχετικά με αυτό; 207 00:16:04,460 --> 00:16:07,150 >> Η επόμενη ερώτηση θα περιλαμβάνει αυτό. 208 00:16:07,150 --> 00:16:15,310 Τι αγωγός θα μπορούσατε να χρησιμοποιήσετε για να βρείτε τον αριθμό των μοναδικών ονομάτων σε ένα αρχείο που ονομάζεται names.txt; 209 00:16:15,310 --> 00:16:24,160 Οι εντολές θα πάμε να θέλετε να χρησιμοποιήσετε εδώ είναι μοναδικό, έτσι uniq, και στη συνέχεια, wc. 210 00:16:24,160 --> 00:16:28,840 Μπορείτε να κάνετε uniq άνθρωπος πραγματικά να δούμε τι κάνει, 211 00:16:28,840 --> 00:16:34,840 και αυτό είναι ακριβώς πρόκειται να φιλτράρει γραμμές που ταιριάζουν δίπλα από την είσοδο. 212 00:16:34,840 --> 00:16:40,690 Και ο άνθρωπος wc πρόκειται να εκτυπώσετε τη νέα γραμμή, λέξη, και byte Η για κάθε αρχείο. 213 00:16:40,690 --> 00:16:43,760 Και το τελευταίο που θα πάμε να θέλετε να χρησιμοποιήσετε είναι το είδος, 214 00:16:43,760 --> 00:16:47,410 η οποία πρόκειται να ταξινομήσετε μόνο γραμμές του αρχείου txt. 215 00:16:47,410 --> 00:16:58,080 Αν κάνω κάποιο αρχείο txt, names.txt, και είναι ο Rob, Tommy, Ιωσήφ, Tommy, Ιωσήφ, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 αυτό που θέλω να κάνω εδώ είναι να βρείτε τον αριθμό των μοναδικών ονομάτων σε αυτό το αρχείο. 217 00:17:03,910 --> 00:17:08,750 Έτσι τι θα έπρεπε να είναι η απάντηση; >> [Φοιτητής] 4. Ναι >>. 218 00:17:08,750 --> 00:17:13,780 Θα πρέπει να είναι 4 από Rob, Tommy, Ιωσήφ, RJ είναι τα μοναδικά ονόματα μόνο σε αυτό το αρχείο. 219 00:17:13,780 --> 00:17:20,180 Το πρώτο βήμα, αν το κάνω μόνο αριθμό λέξεων για names.txt, 220 00:17:20,180 --> 00:17:24,290 αυτό είναι πραγματικά να μου λέει τα πάντα. 221 00:17:24,290 --> 00:17:32,560 Αυτό είναι στην πραγματικότητα εκτύπωση - Ας δούμε, ο άνθρωπος wc - νέες γραμμές, οι λέξεις, και πλήθος bytes. 222 00:17:32,560 --> 00:17:38,270 Αν το μόνο που νοιάζονται για τις γραμμές, τότε μπορώ να κάνω ακριβώς wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Έτσι, αυτό είναι το βήμα 1. 224 00:17:44,300 --> 00:17:50,510 Αλλά δεν θέλω να wc-l names.txt names.txt επειδή περιέχει ακριβώς όλα τα ονόματα, 225 00:17:50,510 --> 00:17:54,170 και θέλω να φιλτράρει όλα τα μη μοναδικά αυτά. 226 00:17:54,170 --> 00:18:01,200 Έτσι, αν κάνω uniq names.txt, αυτό δεν μου δίνει ακριβώς αυτό που θέλω 227 00:18:01,200 --> 00:18:03,760 επειδή τα διπλά ονόματα είναι ακόμα εκεί. 228 00:18:03,760 --> 00:18:07,690 Γιατί συμβαίνει αυτό; Γιατί δεν είναι uniq κάνει ό, τι θέλω; 229 00:18:07,690 --> 00:18:10,500 [Φοιτητής] Τα αντίγραφα δεν είναι [δεν ακούγεται] >> Ναι. 230 00:18:10,500 --> 00:18:16,370 Θυμηθείτε τη σελίδα man για uniq λέει φίλτρο γειτονικών γραμμών που ταιριάζουν. 231 00:18:16,370 --> 00:18:19,680 Δεν είναι δίπλα, και έτσι δεν θα τα φιλτράρει. 232 00:18:19,680 --> 00:18:31,100 Αν μπορώ να ταξινομήσω για πρώτη φορά, names.txt είδος πρόκειται να θέσει όλες τις διπλές γραμμές μεταξύ τους. 233 00:18:31,100 --> 00:18:34,450 Έτσι τώρα names.txt είδος είναι αυτό. 234 00:18:34,450 --> 00:18:40,550 Πάω να θέλετε να χρησιμοποιήσετε ότι ως την είσοδο στην uniq, η οποία είναι | uniq. 235 00:18:40,550 --> 00:18:43,390 Αυτό μου δίνει Ιωσήφ, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 και θέλω να το χρησιμοποιήσουμε αυτό ως την είσοδο στην wc-l, 237 00:18:49,260 --> 00:18:52,740 η οποία πρόκειται να μου δώσει 4. 238 00:18:52,740 --> 00:18:56,930 Όπως λέει εδώ, τι θα μπορούσε να αγωγού που χρησιμοποιείτε; 239 00:18:56,930 --> 00:19:01,390 Μπορείτε να κάνετε πολλά πράγματα, όπως η χρήση μια σειρά από εντολές 240 00:19:01,390 --> 00:19:05,130 όπου μπορείτε να χρησιμοποιήσετε την έξοδο από μία εντολή, όπως την είσοδο στην επόμενη εντολή. 241 00:19:05,130 --> 00:19:08,780 Μπορείτε να κάνετε πολλά πράγματα, πολλά έξυπνα πράγματα. 242 00:19:08,780 --> 00:19:11,440 >> Ερωτήσεις; 243 00:19:12,910 --> 00:19:14,600 Εντάξει. 244 00:19:14,600 --> 00:19:17,880 Αυτό είναι το για σωλήνες και ανακατεύθυνση. 245 00:19:18,370 --> 00:19:24,090 >> Τώρα πάμε για την πραγματική ουσία, η κωδικοποίηση πράγματα. 246 00:19:24,090 --> 00:19:29,100 Μέσα από αυτό το PDF, θα δείτε αυτή την εντολή, 247 00:19:29,100 --> 00:19:32,950 και θα θέλετε να εκτελέσετε αυτήν την εντολή στη συσκευή σας. 248 00:19:36,240 --> 00:19:42,250 wget είναι η εντολή για να πάρει μόνο κάτι από το Internet, βασικά, 249 00:19:42,250 --> 00:19:45,180 wget έτσι και αυτό το URL. 250 00:19:45,180 --> 00:19:49,110 Αν πήγε σε αυτή τη διεύθυνση URL στο πρόγραμμα περιήγησής σας, θα κατεβάσετε το αρχείο. 251 00:19:49,110 --> 00:19:52,510 Μόλις κάνετε κλικ σε αυτό, έτσι ώστε να κατεβάσει το αρχείο για μένα. 252 00:19:52,510 --> 00:19:55,650 Αλλά γράφοντας wget από αυτό το πράγμα μέσα από το τερματικό 253 00:19:55,650 --> 00:19:58,620 πρόκειται ακριβώς για να το κατεβάσετε σε τερματικό σας. 254 00:19:58,620 --> 00:20:02,750 Έχω section5.zip, και θα θέλετε να αποσυμπιέσετε section5.zip, 255 00:20:02,750 --> 00:20:06,520 η οποία πρόκειται να σας δώσει ένα φάκελο που ονομάζεται σημείου 5, 256 00:20:06,520 --> 00:20:11,550 το οποίο θα έχει όλα τα αρχεία θα πάμε να χρησιμοποιούν σήμερα μέσα από αυτό. 257 00:20:33,380 --> 00:20:37,710 Όπως δείχνουν τα ονόματα των αρχείων αυτών των προγραμμάτων, είναι λίγο buggy, 258 00:20:37,710 --> 00:20:40,990 έτσι ώστε η αποστολή σας είναι να καταλάβω γιατί η χρήση gdb. 259 00:20:40,990 --> 00:20:44,560 Μήπως όλοι τους έχουν κατεβάσει / ξέρουν πώς να πάρουν τη λήψη τους 260 00:20:44,560 --> 00:20:47,480 στην συσκευή τους; Εντάξει. 261 00:20:47,480 --> 00:20:56,400 >> Τρέχοντας ./buggy1, θα πει σφάλμα Segmentation (πυρήνας ντάμπινγκ), 262 00:20:56,400 --> 00:21:00,500 την οποία κάθε φορά που θα πάρετε μια segfault, αυτό είναι ένα κακό πράγμα. 263 00:21:00,500 --> 00:21:03,810 Κάτω από ποιες συνθήκες θα πάρετε μια segfault; 264 00:21:03,810 --> 00:21:08,210 [Φοιτητής] Αποαναφορά ένα null δείκτη. Ναι >>. Έτσι, αυτό είναι ένα παράδειγμα. 265 00:21:08,210 --> 00:21:11,580 Έμμεση αναφορά σε ένα κενό δείκτη θα πάμε για να πάρετε μια segfault. 266 00:21:11,580 --> 00:21:16,720 Τι σημαίνει segfault είστε αγγίζει μνήμη σας δεν θα πρέπει να αγγίζουν. 267 00:21:16,720 --> 00:21:21,350 Έτσι, μια εύρεση τιμών null δείκτη αγγίζει διεύθυνση 0, 268 00:21:21,350 --> 00:21:28,060 και ουσιαστικά, όλοι οι υπολογιστές στις μέρες μας λένε ότι το 0 είναι η διεύθυνση μνήμης που δεν θα πρέπει να αγγίζουν. 269 00:21:28,060 --> 00:21:31,920 Έτσι, γι 'αυτό ένα εύρεση τιμών null αποτελέσματα δείκτη σε μια segfault. 270 00:21:31,920 --> 00:21:37,210 Όταν συμβεί να μην προετοιμαστεί ένα δείκτη, τότε έχει αξία σκουπίδια, 271 00:21:37,210 --> 00:21:41,520 και έτσι όταν προσπαθείτε να dereference αυτό, κατά πάσα πιθανότητα είστε αγγίζει μνήμη 272 00:21:41,520 --> 00:21:43,540 που είναι στη μέση του πουθενά. 273 00:21:43,540 --> 00:21:45,650 Αν συμβεί να πάρετε τυχεροί και η αξία σκουπίδια 274 00:21:45,650 --> 00:21:48,440 συνέβη στο σημείο κάπου στη στοίβα ή κάτι, 275 00:21:48,440 --> 00:21:50,820 στη συνέχεια, όταν dereference ότι ο δείκτης που δεν έχουν προετοιμαστεί, 276 00:21:50,820 --> 00:21:52,730 τίποτα δεν θα πάει στραβά. 277 00:21:52,730 --> 00:21:55,480 Αλλά αν είναι κατάδειξης, ας πούμε, κάπου μεταξύ της στοίβας και του σωρού, 278 00:21:55,480 --> 00:21:59,850 ή αυτό είναι μόνο για να δείχνει κάπου που δεν έχει χρησιμοποιηθεί από το πρόγραμμα σας ακόμα, 279 00:21:59,850 --> 00:22:02,240 τότε είστε αγγίζοντας μνήμη σας δεν θα πρέπει να αγγίζει και να segfault. 280 00:22:02,240 --> 00:22:06,370 Όταν γράφετε μια αναδρομική συνάρτηση και recurses πάρα πολλές φορές 281 00:22:06,370 --> 00:22:08,720 και το stack σας μεγαλώνει πάρα πολύ μεγάλο και οι συγκρούεται σε στοίβα τα πράγματα 282 00:22:08,720 --> 00:22:12,270 ότι δεν θα πρέπει να συγκρούονται με, είστε αγγίζει μνήμη σας δεν θα πρέπει να αγγίζουν, 283 00:22:12,270 --> 00:22:14,810 έτσι ώστε να segfault. 284 00:22:14,810 --> 00:22:17,010 Αυτό είναι ό, τι είναι ένα segfault. 285 00:22:17,010 --> 00:22:21,810 >> Είναι, επίσης, για τον ίδιο λόγο ότι αν έχετε μια σειρά σαν - 286 00:22:21,810 --> 00:22:23,930 ας πάμε πίσω στο προηγούμενο πρόγραμμα. 287 00:22:23,930 --> 00:22:28,530 Σε hello.c--Είμαι ακριβώς πρόκειται να κάνει κάτι άλλο. 288 00:22:28,530 --> 00:22:33,770 char * s = "Γειά σου Κόσμε!"? 289 00:22:33,770 --> 00:22:42,310 Αν μπορώ να χρησιμοποιήσω * s = s ή κάτι [0] = 'Χ'? 290 00:22:42,310 --> 00:22:47,290 Γι 'αυτό γειά σου,. / γειά σου, γιατί ότι segfault; 291 00:22:48,410 --> 00:22:51,250 Γιατί αυτό segfault; 292 00:22:55,660 --> 00:22:57,890 Τι θα περιμένατε να συμβεί; 293 00:22:57,890 --> 00:23:06,640 Αν έκανα printf ("% s \ n", s)? Τι θα περιμένατε να εκτυπωθούν; 294 00:23:06,640 --> 00:23:09,930 [Φοιτητής] Χ γειά σου. Ναι >>. 295 00:23:09,930 --> 00:23:15,140 Το πρόβλημα είναι ότι όταν δηλώνετε μια σειρά σαν αυτή, 296 00:23:15,140 --> 00:23:18,190 s είναι ένας δείκτης που πρόκειται να πάει στη στοίβα, 297 00:23:18,190 --> 00:23:25,880 και τι s είναι στραμμένη προς αυτό είναι συμβολοσειρά η οποία περιέχεται σε μνήμη μόνο για ανάγνωση. 298 00:23:25,880 --> 00:23:30,560 Έτσι, μόνο από το όνομα, μόνο για ανάγνωση μνήμης, θα πρέπει να πάρετε την ιδέα 299 00:23:30,560 --> 00:23:33,010 ότι αν προσπαθήσετε να αλλάξετε ό, τι είναι στην μνήμη μόνο για ανάγνωση, 300 00:23:33,010 --> 00:23:36,670 κάνεις κάτι που δεν θα πρέπει να κάνει με τη μνήμη σας και segfault. 301 00:23:36,670 --> 00:23:45,360 Αυτό είναι πραγματικά μια μεγάλη διαφορά μεταξύ char * s και char s []. 302 00:23:45,360 --> 00:23:48,790 Έτσι, char s [], τώρα αυτή η συμβολοσειρά θα πρέπει να τοποθετούνται στη στοίβα, 303 00:23:48,790 --> 00:23:53,960 και η στοίβα δεν είναι μόνο για ανάγνωση, πράγμα που σημαίνει ότι αυτό θα πρέπει να λειτουργεί τέλεια πρόστιμο. 304 00:23:55,500 --> 00:23:57,370 Και το κάνει. 305 00:23:57,370 --> 00:24:06,250 Να θυμάστε ότι όταν κάνω char * s = "Γειά σου Κόσμε!", S είναι το ίδιο στη στοίβα 306 00:24:06,250 --> 00:24:10,390 αλλά επισημαίνει s για κάπου αλλού, και ότι κάπου αλλού συμβαίνει να είναι μόνο για ανάγνωση. 307 00:24:10,390 --> 00:24:15,640 Αλλά char s [] είναι απλώς κάτι στη στοίβα. 308 00:24:17,560 --> 00:24:21,760 Έτσι, αυτό είναι ένα άλλο παράδειγμα από μια segfault συμβαίνει. 309 00:24:21,760 --> 00:24:27,820 >> Είδαμε ότι ./buggy1 οδήγησε σε segfault. 310 00:24:27,820 --> 00:24:31,810 Στη θεωρία, δεν θα πρέπει να εξετάσουμε buggy1.c αμέσως. 311 00:24:31,810 --> 00:24:35,170 Αντ 'αυτού, θα εξετάσουμε αυτό με το gdb. 312 00:24:35,170 --> 00:24:37,750 Παρατηρήστε ότι όταν παίρνετε σφάλμα Segmentation (πυρήνας ντάμπινγκ), 313 00:24:37,750 --> 00:24:40,850 μπορείτε να πάρετε αυτό το αρχείο εδώ ονομάζεται πυρήνας. 314 00:24:40,850 --> 00:24:45,200 Αν ls-l, θα δούμε ότι ο πυρήνας είναι συνήθως ένα αρκετά μεγάλο αρχείο. 315 00:24:45,200 --> 00:24:51,580 Αυτός είναι ο αριθμός των bytes του αρχείου, έτσι ώστε να φαίνεται σαν να είναι 250-κάτι kilobytes. 316 00:24:51,580 --> 00:24:56,120 Ο λόγος για αυτό είναι ότι αυτό η χωματερή πυρήνα είναι πραγματικά 317 00:24:56,120 --> 00:25:01,410 είναι όταν κολλάει το πρόγραμμα, η κατάσταση της μνήμης του προγράμματός σας 318 00:25:01,410 --> 00:25:05,230 απλά παίρνει αντιγραφεί και επικολληθεί σε αυτό το αρχείο. 319 00:25:05,230 --> 00:25:07,270 Παίρνει ντάμπινγκ σε αυτό το αρχείο. 320 00:25:07,270 --> 00:25:13,060 Αυτό το πρόγραμμα, ενώ έτρεχε, έτυχε να έχουν μια χρήση της μνήμης της τάξης των 250 kilobytes, 321 00:25:13,060 --> 00:25:17,040 και έτσι αυτό είναι που πήρε ντάμπινγκ σε αυτό το αρχείο. 322 00:25:17,040 --> 00:25:23,630 Τώρα μπορείτε να δείτε σε αυτό το αρχείο, αν κάνουμε gdb buggy1 πυρήνα. 323 00:25:23,630 --> 00:25:30,130 Μπορούμε να κάνουμε μόνο buggy1 gdb, και ότι απλά θα ξεκινήσει gdb τακτικά, 324 00:25:30,130 --> 00:25:33,800 buggy1 χρησιμοποιώντας ως αρχείο εισόδου του. 325 00:25:33,800 --> 00:25:38,260 Αλλά αν το κάνετε gdb buggy1 πυρήνα, τότε είναι ειδικά πρόκειται να ξεκινήσει το gdb 326 00:25:38,260 --> 00:25:40,330 κοιτάζοντας αυτό το αρχείο πυρήνα. 327 00:25:40,330 --> 00:25:45,560 Και λέτε buggy1 gdb μέσα ξέρει ότι ο φάκελος πυρήνας προέρχεται από την buggy1 πρόγραμμα. 328 00:25:45,560 --> 00:25:49,580 Έτσι gdb buggy1 πυρήνα πρόκειται να μας φέρει άμεσα 329 00:25:49,580 --> 00:25:52,060 στο σημείο όπου συνέβη το πρόγραμμα να τερματίσει. 330 00:25:57,720 --> 00:26:02,340 Βλέπουμε εδώ Πρόγραμμα τερματίστηκε με το σήμα 11, Τμηματοποίηση σφάλμα. 331 00:26:02,340 --> 00:26:10,110 Θα συμβεί για να δείτε μια γραμμή συναρμολόγησης, η οποία κατά πάσα πιθανότητα δεν είναι πολύ χρήσιμη. 332 00:26:10,110 --> 00:26:15,360 Αλλά αν πληκτρολογήσετε bt ή backtrace, η οποία πρόκειται να είναι η λειτουργία 333 00:26:15,360 --> 00:26:19,430 η οποία μας δίνει τη λίστα των σημερινών πλαισίων στοίβας μας. 334 00:26:19,430 --> 00:26:23,150 Έτσι backtrace. Μοιάζει έχουμε μόνο δύο πλαίσια στοίβα. 335 00:26:23,150 --> 00:26:26,310 Το πρώτο είναι το κύριο πλαίσιο στοίβας μας, 336 00:26:26,310 --> 00:26:29,810 και η δεύτερη είναι η στοίβα πλαισίου για τη λειτουργία αυτή που τυχαίνει να είναι σε, 337 00:26:29,810 --> 00:26:34,440 που μοιάζει έχουμε μόνο τον κωδικό συναρμολόγησης. 338 00:26:34,440 --> 00:26:38,050 Ας πάμε πίσω σε κύρια λειτουργία μας, 339 00:26:38,050 --> 00:26:42,300 και να κάνουμε ότι μπορούμε να κάνουμε πλαίσιο 1, και νομίζω ότι μπορούμε να κάνουμε, επίσης, προς τα κάτω, 340 00:26:42,300 --> 00:26:45,160 αλλά σχεδόν ποτέ δεν κάνει τα κάτω - ή πάνω. Ναι. 341 00:26:45,160 --> 00:26:50,710 Πάνω και κάτω. Μέχρι σας φέρνει επάνω ένα πλαίσιο στοίβας, σας φέρνει κάτω κάτω ένα πλαίσιο στοίβας. 342 00:26:50,710 --> 00:26:53,240 Τείνω να μην το χρησιμοποιήσετε. 343 00:26:53,240 --> 00:26:59,120 Θέλω μόνο να πω συγκεκριμένα πλαισίου 1, που είναι να πάτε με το πλαίσιο με την ένδειξη 1. 344 00:26:59,120 --> 00:27:01,750 Πλαίσιο 1 θα μας φέρει στο κύριο πλαίσιο στοίβας, 345 00:27:01,750 --> 00:27:05,570 και λέει εδώ τη γραμμή του κώδικα που τυχαίνει να είναι σε. 346 00:27:05,570 --> 00:27:07,950 Αν θέλαμε ένα ζευγάρι περισσότερες γραμμές κώδικα, μπορούμε να πούμε λίστα, 347 00:27:07,950 --> 00:27:11,280 και ότι πρόκειται να μας δώσει όλες τις γραμμές κώδικα γύρω από αυτό. 348 00:27:11,280 --> 00:27:13,360 Η γραμμή που ήταν segfaulted σε 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 Εάν δεν είναι εμφανής ακόμα, μπορείτε να το πάρετε κατευθείαν από εδώ μόνο με τη σκέψη γιατί segfaulted. 351 00:27:24,130 --> 00:27:28,800 Αλλά μπορούμε να το πάρετε ένα βήμα παραπέρα και να πω, "Γιατί θα argv [1] segfault;" 352 00:27:28,800 --> 00:27:38,830 Εκτύπωση Ας argv [1], και μοιάζει με το 0x0, η οποία είναι η μηδενική δείκτη. 353 00:27:38,830 --> 00:27:44,750 Είμαστε strcmping CS50 βράχια και άκυρη, έτσι και αυτό πρόκειται να segfault. 354 00:27:44,750 --> 00:27:48,280 Και γιατί είναι argv [1] null; 355 00:27:48,640 --> 00:27:51,280 [Φοιτητής] Επειδή δεν είχαμε δώσει κάποια ορίσματα της γραμμής εντολών. 356 00:27:51,280 --> 00:27:53,390 Ναι. Εμείς δεν της έδωσε κάποια ορίσματα της γραμμής εντολών. 357 00:27:53,390 --> 00:27:58,460 Έτσι ./buggy1 θα είναι μόνο για να έχουν argv [0] είναι ./buggy1. 358 00:27:58,460 --> 00:28:02,100 Δεν πρόκειται να έχουμε μια argv [1], έτσι ώστε πρόκειται να segfault. 359 00:28:02,100 --> 00:28:07,450 Αλλά αν, αντ 'αυτού, να κάνω ακριβώς CS50, πρόκειται να πω Μπορείτε να πάρετε μια D 360 00:28:07,450 --> 00:28:09,950 επειδή αυτό είναι αυτό που θα έπρεπε να κάνει. 361 00:28:09,950 --> 00:28:15,240 Κοιτάζοντας buggy1.c, είναι υποτίθεται για να εκτυπώσετε "Μπορείτε να πάρετε μια D" - 362 00:28:15,240 --> 00:28:20,820 Αν argv [1] δεν είναι "CS50 βράχους», «Μπορείτε να πάρετε μια D", αλλιώς "Μπορείτε να πάρετε ένα Α!" 363 00:28:20,820 --> 00:28:25,660 Έτσι, αν θέλουμε ένα Α, θα πρέπει να συγκρίνει αυτό ως αλήθεια, 364 00:28:25,660 --> 00:28:28,710 πράγμα που σημαίνει ότι το συγκρίνει με μηδέν. 365 00:28:28,710 --> 00:28:31,100 Έτσι, argv [1] πρέπει να είναι "CS50 βράχια». 366 00:28:31,100 --> 00:28:35,660 Αν θέλετε να το κάνετε αυτό στη γραμμή εντολών, θα πρέπει να χρησιμοποιήσετε \ για να ξεφύγουν από το χώρο. 367 00:28:35,660 --> 00:28:41,690 Έτσι CS50 \ βράχια και μπορείτε να πάρετε μια Α! 368 00:28:41,690 --> 00:28:44,060 Αν δεν κάνετε την ανάστροφη κάθετο, γιατί αυτό δεν λειτουργεί; 369 00:28:44,060 --> 00:28:47,190 [Φοιτητής] Είναι δύο διαφορετικά επιχειρήματα. Ναι >>. 370 00:28:47,190 --> 00:28:52,540 Argv [1] θα είναι CS50, και argv [2] πρόκειται να είναι βράχια. Εντάξει. 371 00:28:52,540 --> 00:28:56,470 >> Τώρα ./buggy2 πρόκειται να segfault πάλι. 372 00:28:56,470 --> 00:29:01,880 Αντί να ανοίξετε το αρχείο με πυρήνα της, εμείς απλώς θα ανοίξει buggy2 άμεσα, 373 00:29:01,880 --> 00:29:05,000 έτσι gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Τώρα, αν θα τρέξει μόνο το πρόγραμμά μας, τότε πρόκειται να πω Πρόγραμμα λαμβανόμενο σήμα SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 η οποία είναι η segfault σήμα, και αυτό είναι που συνέβη να συμβεί. 376 00:29:15,530 --> 00:29:21,250 Κοιτάζοντας backtrace μας, θα δούμε ότι ήμασταν στο oh_no λειτουργία, 377 00:29:21,250 --> 00:29:23,900 η οποία κλήθηκε από το dinky λειτουργία, η οποία κλήθηκε από το binky λειτουργία, 378 00:29:23,900 --> 00:29:26,460 η οποία κλήθηκε από την κύρια. 379 00:29:26,460 --> 00:29:31,680 Μπορούμε επίσης να δούμε τα επιχειρήματα για αυτές τις λειτουργίες. 380 00:29:31,680 --> 00:29:34,680 Το επιχείρημα για Dinky και binky ήταν 1. 381 00:29:34,680 --> 00:29:44,390 Εάν λίστα τη λειτουργία oh_no, βλέπουμε ότι oh_no κάνει ακριβώς char ** s = NULL? 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"? 383 00:29:47,410 --> 00:29:50,330 Γιατί δεν θα ήταν αυτό; 384 00:29:54,330 --> 00:29:58,380 [Φοιτητής] Δεν μπορείτε να dereference το κενό δείκτη; Ναι >>. 385 00:29:58,380 --> 00:30:06,090 Αυτό ακριβώς λέει s είναι NULL, ανεξάρτητα αν αυτό συμβαίνει να είναι ένα char **, 386 00:30:06,090 --> 00:30:12,070 το οποίο, ανάλογα με το πώς θα το ερμηνεύσει, θα μπορούσε να είναι ένας δείκτης σε δείκτη σε μια σειρά 387 00:30:12,070 --> 00:30:15,550 ή μια σειρά από χορδές. 388 00:30:15,550 --> 00:30:21,430 Είναι s είναι NULL, έτσι * s είναι μια εύρεση τιμών null δείκτη, 389 00:30:21,430 --> 00:30:24,800 και έτσι αυτό πρόκειται να διακοπεί η λειτουργία του. 390 00:30:24,800 --> 00:30:27,540 Αυτός είναι ένας από τους γρηγορότερους τρόπους που μπορείτε ενδεχομένως να segfault. 391 00:30:27,540 --> 00:30:31,300 Είναι δηλώνοντας απλώς ένα null δείκτη και αμέσως segfaulting. 392 00:30:31,300 --> 00:30:34,570 Αυτό είναι ό, τι oh_no κάνει. 393 00:30:34,570 --> 00:30:43,400 Αν πάμε μέχρι ένα καρέ, τότε θα πάμε να μπει σε λειτουργία που ονομάζεται oh_no. 394 00:30:43,400 --> 00:30:44,830 Πρέπει να το κάνουμε αυτό κάτω. 395 00:30:44,830 --> 00:30:48,610 Εάν δεν εισάγετε μια εντολή και χτυπάτε απλά Enter και πάλι, 396 00:30:48,610 --> 00:30:52,350 θα επαναλάβω απλώς την προηγούμενη εντολή που εκτελέσατε. 397 00:30:52,350 --> 00:30:56,610 Είμαστε σε πλαίσιο 1. 398 00:30:56,610 --> 00:31:04,650 Καταχώρηση αυτό το πλαίσιο, βλέπουμε εδώ είναι η λειτουργία μας. 399 00:31:04,650 --> 00:31:08,520 Μπορείτε να χτυπήσει ξανά τη λίστα, ή μπορείτε να κάνετε λίστα των 20 ετών και θα περιλαμβάνει περισσότερους. 400 00:31:08,520 --> 00:31:13,640 Η λειτουργία dinky λέει ότι αν i είναι 1, τότε πάμε για τη λειτουργία oh_no, 401 00:31:13,640 --> 00:31:15,960 αλλιώς πηγαίνετε στο κρυψίνους λειτουργία. 402 00:31:15,960 --> 00:31:18,700 Και ξέρουμε i είναι 1, επειδή τυχαίνει να δείτε εδώ 403 00:31:18,700 --> 00:31:22,560 Dinky ότι κλήθηκε με το επιχείρημα 1. 404 00:31:22,560 --> 00:31:27,560 Ή μπορείτε απλά να μπορώ να εκτυπώσει και θα πω ότι είναι 1. 405 00:31:27,560 --> 00:31:33,770 Αυτή τη στιγμή είμαστε σε dinky, και αν πάμε ένα άλλο πλαίσιο, ξέρουμε ότι θα καταλήξουμε σε binky. 406 00:31:33,770 --> 00:31:36,600 Up. Τώρα είμαστε σε binky. 407 00:31:36,600 --> 00:31:41,340 Καταχώρηση αυτή τη λειτουργία - η λίστα από πριν από μισή μου κόψει - 408 00:31:41,340 --> 00:31:52,670 αυτό που ξεκίνησε ως εάν θ είναι 0, τότε θα πάμε να το ονομάσουμε oh_no, αλλιώς καλέστε dinky. 409 00:31:52,670 --> 00:31:57,000 Ξέρουμε ότι ήμουν 1, γι 'αυτό ονομάζεται dinky. 410 00:31:57,000 --> 00:32:05,030 Και τώρα είμαστε πίσω στην κύρια και βασικά είναι ακριβώς πρόκειται να είναι int i = rand ()% 3? 411 00:32:05,030 --> 00:32:08,790 Αυτό είναι ακριβώς πρόκειται να σας δώσω έναν τυχαίο αριθμό που είναι είτε 0, 1, ή 2. 412 00:32:08,790 --> 00:32:12,780 Είναι πρόκειται να καλέσετε binky με αυτόν τον αριθμό, και θα επιστρέψει 0. 413 00:32:12,780 --> 00:32:16,700 Κοιτάζοντας αυτό, 414 00:32:16,700 --> 00:32:19,880 απλά περπατώντας μέσα από το πρόγραμμα το χέρι, χωρίς να τρέχει αμέσως, 415 00:32:19,880 --> 00:32:25,400 θα ορίσετε ένα σημείο καμπής στο κεντρικό, πράγμα που σημαίνει ότι όταν εκτελείτε το πρόγραμμα 416 00:32:25,400 --> 00:32:31,020 πρόγραμμα σας τρέχει μέχρι να χτυπήσει το σημείο καμπής. 417 00:32:31,020 --> 00:32:35,450 Έτσι λειτουργεί το πρόγραμμα, που θα διαρκέσει και μετά θα χτυπήσει την κύρια λειτουργία και να σταματήσει να λειτουργεί. 418 00:32:35,450 --> 00:32:44,700 Τώρα είμαστε στο εσωτερικό των κύριων και βήμα ή την επόμενη θα μας φέρει στην επόμενη γραμμή του κώδικα. 419 00:32:44,700 --> 00:32:47,050 Μπορείτε να κάνετε το βήμα ή την επόμενη. 420 00:32:47,050 --> 00:32:51,800 Χτύπημα επόμενο, τώρα θ έχει οριστεί για την rand () 3%, έτσι ώστε να μπορεί να εκτυπώσει την τιμή του i, 421 00:32:51,800 --> 00:32:55,280 και θα πω ότι είναι 1. 422 00:32:55,280 --> 00:32:58,110 Τώρα έχει σημασία αν θα χρησιμοποιήσετε το επόμενο βήμα ή. 423 00:32:58,110 --> 00:33:01,000 Υποθέτω ότι πείραξε το προηγούμενο, αλλά θα θέλαμε να χρησιμοποιήσετε στη συνέχεια. 424 00:33:01,000 --> 00:33:06,000 Αν χρησιμοποιήσουμε το βήμα, το βήμα σε λειτουργία, πράγμα που σημαίνει ματιά στο πραγματικό πράγμα 425 00:33:06,000 --> 00:33:07,940 που συμβαίνει στο εσωτερικό του binky. 426 00:33:07,940 --> 00:33:10,510 Αν χρησιμοποιήσουμε επόμενη, τότε αυτό σημαίνει ότι πάει πέρα ​​από τη λειτουργία 427 00:33:10,510 --> 00:33:14,070 και πήγαινε στην επόμενη γραμμή του κώδικα στην κύρια λειτουργία μας. 428 00:33:14,070 --> 00:33:17,900 Ακριβώς εδώ σε αυτή τη γραμμή, ήμουν πού είπε rand ()% 3? 429 00:33:17,900 --> 00:33:21,320 αν έκανα το βήμα, θα πάει στην εφαρμογή του ραντ 430 00:33:21,320 --> 00:33:25,110 και να δούμε τι συμβαίνει εκεί, και θα μπορούσα να το βήμα μέσω της λειτουργίας ραντ. 431 00:33:25,110 --> 00:33:26,920 Αλλά εγώ δεν ενδιαφέρομαι για τη λειτουργία ραντ. 432 00:33:26,920 --> 00:33:30,190 Απλά θέλω να πάω στην επόμενη γραμμή του κώδικα στην κύρια, έτσι μπορώ να χρησιμοποιήσω επόμενη. 433 00:33:30,190 --> 00:33:35,800 Τώρα, όμως, να κάνω τη φροντίδα για την binky λειτουργία, γι 'αυτό θέλω να το βήμα σε αυτό. 434 00:33:35,800 --> 00:33:37,730 Τώρα είμαι σε binky. 435 00:33:37,730 --> 00:33:42,040 Η πρώτη γραμμή του κώδικα πρόκειται να πει εάν (i == 0), παίρνω ένα βήμα, 436 00:33:42,040 --> 00:33:44,930 βλέπουμε καταλήγουμε στο Dinky. 437 00:33:44,930 --> 00:33:51,620 Αν τα πράγματα λίστα, βλέπουμε ότι ελέγχεται είναι i = 0. 438 00:33:51,620 --> 00:33:55,470 i δεν είναι ίσο με μηδέν, οπότε πήγε στο άλλο όρο, 439 00:33:55,470 --> 00:33:59,540 η οποία πρόκειται να καλέσει Dinky (i). 440 00:33:59,540 --> 00:34:04,030 Μπορεί να μπερδευτείτε. 441 00:34:04,030 --> 00:34:07,380 Αν εξετάσουμε μόνο σε αυτές τις γραμμές άμεσα, θα μπορούσε κανείς να σκεφτεί αν (i == 0), 442 00:34:07,380 --> 00:34:10,800 εντάξει, τότε πήρα ένα βήμα και τώρα είμαι σε Dinky (i), 443 00:34:10,800 --> 00:34:14,120 Μπορείτε να σκεφτείτε ότι πρέπει να σημαίνει i = 0 ή κάτι τέτοιο. 444 00:34:14,120 --> 00:34:18,980 Όχι απλά σημαίνει ότι ξέρει ότι μπορεί να κολλήσει απευθείας στο dinky γραμμή (i). 445 00:34:18,980 --> 00:34:23,300 Επειδή εγώ δεν είναι 0, το επόμενο βήμα δεν πρόκειται να λήξει στο άλλο. 446 00:34:23,300 --> 00:34:26,239 Αλλιώς δεν είναι μια γραμμή πρόκειται να σταματήσει σε. 447 00:34:26,239 --> 00:34:31,570 Είναι ακριβώς πρόκειται να πάει στην επόμενη γραμμή μπορεί πραγματικά να εκτελέσει, η οποία είναι Dinky (i). 448 00:34:31,570 --> 00:34:36,090 Ενίσχυση σε Dinky (i), βλέπουμε αν (i == 1). 449 00:34:36,090 --> 00:34:42,670 Γνωρίζουμε i = 1, έτσι ώστε όταν το βήμα, ξέρουμε ότι πρόκειται να καταλήξει σε oh_no 450 00:34:42,670 --> 00:34:46,489 επειδή i = 1 καλεί την oh_no λειτουργία, το οποίο μπορείτε να μπείτε, 451 00:34:46,489 --> 00:34:52,969 η οποία πρόκειται να θέσει char ** s = NULL και να αμέσως "BOOM". 452 00:34:54,270 --> 00:34:59,690 Και τότε πραγματικά κοιτάζοντας την εφαρμογή του buggy2, 453 00:34:59,690 --> 00:35:04,590 αυτό, i παίρνει μόνο έναν τυχαίο αριθμό - 0, 1, ή 2 - καλώντας binky, 454 00:35:04,590 --> 00:35:10,610 η οποία αν θ είναι 0 καλεί oh_no, αλλιώς καλεί dinky, η οποία έρχεται εδώ. 455 00:35:10,610 --> 00:35:18,100 Αν i είναι 1, oh_no κλήση, καλέστε άλλο κρυψίνους, που έρχονται εδώ, 456 00:35:18,100 --> 00:35:20,460 αν i είναι 2, καλέστε oh_no. 457 00:35:20,460 --> 00:35:24,720 Δεν χρειάζεται καν να σκέφτονται ότι υπάρχει ένας τρόπος - 458 00:35:24,720 --> 00:35:30,030 Υπάρχει κάποιος που να δείτε έναν τρόπο να κάνει αυτό ένα πρόγραμμα που δεν θα segfault; 459 00:35:30,030 --> 00:35:37,530 Γιατί αν είμαι λείπει κάτι, αν θ είναι 0, θα segfault αμέσως, 460 00:35:37,530 --> 00:35:41,250 αλλιώς θα πάτε σε μια λειτουργία που αν i είναι 1 segfault σας, 461 00:35:41,250 --> 00:35:44,540 αλλιώς θα πάτε σε μια λειτουργία όπου αν i είναι 2 segfault σας. 462 00:35:44,540 --> 00:35:46,810 Έτσι, δεν έχει σημασία τι θα κάνεις, θα segfault. 463 00:35:46,810 --> 00:35:52,380 >> Υποθέτω ότι ένας τρόπος για να γίνει αυτό θα ήταν αντί να κάνει char ** s = NULL, 464 00:35:52,380 --> 00:35:55,610 θα μπορούσατε να malloc χώρος για την εν λόγω σειρά. 465 00:35:55,610 --> 00:36:04,230 Θα μπορούσαμε να κάνουμε malloc (sizeof) - sizeof τι; 466 00:36:09,910 --> 00:36:15,190 [Φοιτητής] (char) * 5; >> Μήπως αυτό φαίνεται σωστό; 467 00:36:15,190 --> 00:36:21,060 Υποθέτω αυτό θα λειτουργήσει, αν έτρεξα πραγματικά, αλλά δεν είναι αυτό που ψάχνω. 468 00:36:24,400 --> 00:36:32,940 Κοιτάξτε τον τύπο του s. Ας προσθέσω int *, έτσι int * x. 469 00:36:32,940 --> 00:36:35,600 Θα ήθελα να κάνω malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Ή αν ήθελα μια σειρά 5, θα ήθελα να κάνω (sizeof (int) * 5)? 471 00:36:40,490 --> 00:36:44,210 Τι γίνεται αν έχω ένα int **; 472 00:36:46,260 --> 00:36:49,140 Τι θα μου malloc; 473 00:36:49,140 --> 00:36:53,510 [Φοιτητής] Μέγεθος του δείκτη. Ναι >>. (Sizeof (int *))? 474 00:36:53,510 --> 00:36:56,960 Το ίδιο πράγμα εδώ κάτω. 475 00:36:56,960 --> 00:37:01,280 Θέλω (sizeof (char *))? 476 00:37:06,170 --> 00:37:12,840 Αυτό πρόκειται να διαθέσει χώρο για το δείκτη που δείχνει "BOOM". 477 00:37:12,840 --> 00:37:15,330 Δεν χρειάζεται να διαθέσουν χώρο για "BOOM" η ίδια 478 00:37:15,330 --> 00:37:17,210 γιατί αυτό είναι ουσιαστικά ισοδύναμο με αυτό που είπα πριν 479 00:37:17,210 --> 00:37:20,870 του char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "BOOM" υπάρχει ήδη. Συμβαίνει να υπάρχουν στην ανάγνωσης μόνο περιοχή της μνήμης. 481 00:37:27,950 --> 00:37:35,200 Αλλά υπάρχει ήδη, πράγμα που σημαίνει αυτή τη γραμμή του κώδικα, αν s είναι ένα char **, 482 00:37:35,200 --> 00:37:43,900 τότε * s είναι ένα char * και είστε ρύθμιση αυτή char * στο σημείο να "BOOM". 483 00:37:43,900 --> 00:37:50,040 Αν ήθελα να αντιγράψετε "BOOM" σε s, τότε θα πρέπει να διαθέσουν χώρο για s. 484 00:37:55,170 --> 00:38:03,900 Θα κάνω * s = malloc (sizeof (char) * 5)? 485 00:38:03,900 --> 00:38:06,210 Γιατί 5; 486 00:38:06,210 --> 00:38:10,860 Γιατί δεν 4; Μοιάζει με "BOOM" είναι 4 χαρακτήρες. >> [Φοιτητής] Ο χαρακτήρας null. 487 00:38:10,860 --> 00:38:14,580 Ναι. Όλα χορδές σας θα πρέπει να το null χαρακτήρα. 488 00:38:14,580 --> 00:38:23,590 Τώρα μπορώ να κάνω κάτι σαν strcat - Ποια είναι η λειτουργία για την αντιγραφή ένα string; 489 00:38:23,590 --> 00:38:28,520 [Φοιτητής] ορν; >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 strcpy άνθρωπος. 491 00:38:36,120 --> 00:38:39,590 Έτσι strcpy ή strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy είναι λίγο πιο ασφαλείς αφού μπορείτε να καθορίσετε ακριβώς πόσοι χαρακτήρες, 493 00:38:43,410 --> 00:38:46,190 αλλά εδώ δεν έχει σημασία, διότι ξέρουμε. 494 00:38:46,190 --> 00:38:50,340 Έτσι strcpy και να δούμε τα επιχειρήματα. 495 00:38:50,340 --> 00:38:53,100 Το πρώτο επιχείρημα είναι ο προορισμός μας. 496 00:38:53,100 --> 00:38:56,770 Το δεύτερο επιχείρημα είναι η πηγή μας. 497 00:38:56,770 --> 00:39:10,310 Εμείς πάμε για να αντιγράψετε σε * προορισμός μας βρέθηκε ο δείκτης "BOOM". 498 00:39:10,310 --> 00:39:19,820 Γιατί μπορεί να θέλετε να το κάνετε αυτό με ένα strcpy και όχι μόνο ό, τι είχαμε πριν 499 00:39:19,820 --> 00:39:22,800 του * s = "BOOM"; 500 00:39:22,800 --> 00:39:28,630 Υπάρχει ένας λόγος ίσως να θέλετε να το κάνετε αυτό, αλλά τι είναι αυτός ο λόγος; 501 00:39:28,630 --> 00:39:31,940 [Φοιτητής] Αν θέλετε να αλλάξετε κάτι σε "BOOM". Ναι >>. 502 00:39:31,940 --> 00:39:37,950 Τώρα μπορώ να κάνω κάτι σαν s [0] = 'Χ'? 503 00:39:37,950 --> 00:39:48,190 επειδή s σημεία στο σωρό και αυτό το χώρο στο σωρό αυτό είναι δείχνει να 504 00:39:48,190 --> 00:39:52,320 είναι ένας δείκτης για περισσότερο χώρο στο σωρό, η οποία αποθηκεύει "BOOM". 505 00:39:52,320 --> 00:39:55,150 Έτσι, αυτό το αντίγραφο του "BOOM" που αποθηκεύονται στο σωρό. 506 00:39:55,150 --> 00:39:58,780 Υπάρχουν τεχνικά δύο αντίγραφα του "BOOM" στο πρόγραμμά μας. 507 00:39:58,780 --> 00:40:03,500 Υπάρχει η πρώτη που μόλις δόθηκε από αυτό το "BOOM" σταθερή σειρά, 508 00:40:03,500 --> 00:40:09,250 και το δεύτερο αντίγραφο του "BOOM", strcpy δημιουργήθηκε το αντίγραφο του "BOOM". 509 00:40:09,250 --> 00:40:13,100 Όμως, το αντίγραφο του "BOOM" που αποθηκεύονται στο σωρό, και ο σωρός είστε ελεύθεροι να αλλάξει. 510 00:40:13,100 --> 00:40:17,250 Ο σωρός δεν είναι μόνο για ανάγνωση, έτσι αυτό σημαίνει ότι s [0] 511 00:40:17,250 --> 00:40:20,500 πρόκειται να σας αφήσει να αλλάξετε την τιμή του "BOOM". 512 00:40:20,500 --> 00:40:23,130 Είναι πρόκειται να σας αφήσει να αλλάξει αυτούς τους χαρακτήρες. 513 00:40:23,130 --> 00:40:26,640 >> Ερωτήσεις; 514 00:40:27,740 --> 00:40:29,290 Εντάξει. 515 00:40:29,290 --> 00:40:35,500 >> Προχωρώντας σε buggy3, gdb ας buggy3. 516 00:40:35,500 --> 00:40:39,840 Θα τρέξει ακριβώς βλέπουμε και παίρνουμε μια segfault. 517 00:40:39,840 --> 00:40:46,550 Αν θέλουμε backtrace, υπάρχουν μόνο δύο λειτουργίες. 518 00:40:46,550 --> 00:40:52,970 Αν ανεβαίνουμε σε κύρια λειτουργία μας, θα δούμε ότι segfaulted σε αυτή τη γραμμή. 519 00:40:52,970 --> 00:41:00,180 Έτσι απλά κοιτάζοντας αυτή τη γραμμή, για (int γραμμή = 0? Fgets αυτά τα πράγματα δεν είναι ίσο με NULL? 520 00:41:00,180 --> 00:41:03,770 γραμμή + +). 521 00:41:03,770 --> 00:41:08,010 Προηγούμενο καρέ μας ονομαζόταν _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Θα δείτε ότι πολλοί με ενσωματωμένες λειτουργίες C, 523 00:41:10,720 --> 00:41:15,350 ότι, όταν μπορείτε να πάρετε το segfault, θα υπάρξει πραγματικά αινιγματικό ονόματα λειτουργία 524 00:41:15,350 --> 00:41:18,090 όπως αυτό _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Αλλά αυτό πρόκειται να σχετίζονται με την παρούσα πρόσκληση fgets. 526 00:41:21,770 --> 00:41:25,850 Κάπου εδώ μέσα, είμαστε segfaulting. 527 00:41:25,850 --> 00:41:30,340 Αν κοιτάξουμε τα επιχειρήματα για fgets, μπορούμε να τυπώσουμε ρυθμιστικό. 528 00:41:30,340 --> 00:41:41,180 Ας εκτυπωθεί ως - Ω, όχι. 529 00:41:48,980 --> 00:41:51,900 Εκτύπωση δεν πρόκειται να λειτουργήσει ακριβώς όπως θέλω να. 530 00:41:55,460 --> 00:41:58,000 Ας δούμε το πραγματικό πρόγραμμα. 531 00:42:02,200 --> 00:42:09,640 Ρυθμιστικό είναι μια σειρά χαρακτήρων. Είναι μια σειρά χαρακτήρων από 128 χαρακτήρες. 532 00:42:09,640 --> 00:42:14,980 Έτσι, όταν λέω ρυθμιστικό εκτύπωσης, πρόκειται για την εκτύπωση αυτών των 128 χαρακτήρες, 533 00:42:14,980 --> 00:42:18,300 η οποία υποθέτω ότι είναι ό, τι αναμένεται. 534 00:42:18,300 --> 00:42:21,390 Αυτό που έψαχνα είναι εκτυπώσετε τη διεύθυνση του buffer, 535 00:42:21,390 --> 00:42:23,680 αλλά αυτό δεν πραγματικά να μου πείτε πολλά. 536 00:42:23,680 --> 00:42:30,770 Έτσι, όταν τυχαίνει να πω εδώ x ρυθμιστικό, αυτό μου δείχνει 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 το οποίο, αν θυμάστε από τις προηγούμενες ή κάποιο σημείο, Oxbffff τείνει να είναι μια στοίβα-ish περιοχή. 538 00:42:38,690 --> 00:42:46,020 Η στοίβα τείνει να ξεκινήσει από κάπου λίγο κάτω από 0xC000. 539 00:42:46,020 --> 00:42:51,890 Απλά βλέποντας αυτή τη διεύθυνση, ξέρω ότι το ρυθμιστικό συμβαίνει στη στοίβα. 540 00:42:51,890 --> 00:43:04,500 Επανέναρξη του προγράμματος μου, τρέχει, μέχρι, buffer είδαμε ήταν αυτή τη σειρά των χαρακτήρων 541 00:43:04,500 --> 00:43:06,530 που είναι λίγο πολύ νόημα. 542 00:43:06,530 --> 00:43:12,270 Στη συνέχεια, εκτύπωση αρχείων, το αρχείο αυτό δεν μοιάζει; 543 00:43:15,120 --> 00:43:17,310 [Φοιτητής] Null. Ναι >>. 544 00:43:17,310 --> 00:43:22,610 Το αρχείο είναι ένα αρχείο * του τύπου, έτσι ώστε να είναι ένας δείκτης, 545 00:43:22,610 --> 00:43:26,610 και η αξία του εν λόγω δείκτη είναι μηδενική. 546 00:43:26,610 --> 00:43:33,240 Έτσι fgets πρόκειται να προσπαθήσει να διαβαστεί από αυτό το δείκτη σε ένα έμμεσο τρόπο, 547 00:43:33,240 --> 00:43:37,320 αλλά για να πρόσβαση σε αυτό το δείκτη, πρέπει να dereference αυτό. 548 00:43:37,320 --> 00:43:40,550 Ή, για να αποκτήσετε πρόσβαση σε αυτό θα πρέπει να δείχνει προς, αυτό το dereferences. 549 00:43:40,550 --> 00:43:43,810 Γι 'αυτό είναι μια εύρεση τιμών null δείκτη και segfaults. 550 00:43:46,600 --> 00:43:48,730 Θα μπορούσα να έχω την επανεκκίνηση εκεί. 551 00:43:48,730 --> 00:43:52,170 Αν σπάσει σε κεντρικό σημείο μας και να τρέξει, 552 00:43:52,170 --> 00:43:57,320 η πρώτη γραμμή του κώδικα είναι char * filename = "nonexistent.txt"? 553 00:43:57,320 --> 00:44:00,870 Αυτό θα πρέπει να δώσει μια αρκετά μεγάλη υπόδειξη ως προς το γιατί αυτό το πρόγραμμα αποτυγχάνει. 554 00:44:00,870 --> 00:44:06,080 Πληκτρολογώντας δίπλα μου φέρνει στην επόμενη γραμμή, όπου θα ανοίξετε αυτό το αρχείο, 555 00:44:06,080 --> 00:44:11,140 και τότε αμέσως να μπει σε γραμμή μας, όπου μια φορά χτύπησα επόμενο, πρόκειται να segfault. 556 00:44:11,140 --> 00:44:16,880 Υπάρχει κάποιος που θέλει να ρίξει ένα λόγος για τον οποίο θα μπορούσε να segfaulting; 557 00:44:16,880 --> 00:44:19,130 [Φοιτητής] Το αρχείο δεν υπάρχει. Ναι >>. 558 00:44:19,130 --> 00:44:22,250 Αυτό υποτίθεται ότι είναι ένας υπαινιγμός 559 00:44:22,250 --> 00:44:29,570 ότι κάθε φορά που είστε το άνοιγμα ενός αρχείου που χρειάζεστε για να βεβαιωθείτε ότι το αρχείο υπάρχει στην πραγματικότητα. 560 00:44:29,570 --> 00:44:31,510 Έτσι, εδώ, "nonexistent.txt"? 561 00:44:31,510 --> 00:44:34,700 Όταν fopen αρχείου για ανάγνωση, τότε θα πρέπει να πούμε 562 00:44:34,700 --> 00:44:45,870 αν (αρχείο == NULL) και να πω printf ("Το αρχείο δεν υπάρχει!" 563 00:44:45,870 --> 00:44:56,340 ή - ακόμα καλύτερα - αρχείου)? επιστροφή 1? 564 00:44:56,340 --> 00:45:00,300 Έτσι τώρα έχουμε ελέγξτε αν είναι NULL 565 00:45:00,300 --> 00:45:03,930 πριν από πραγματικά να συνεχίζει και προσπαθεί να διαβαστεί από αυτό το αρχείο. 566 00:45:03,930 --> 00:45:08,800 Μπορούμε να το ξανακάνω απλά για να δείτε ότι τα έργα. 567 00:45:11,020 --> 00:45:14,970 Είχα σκοπό να συμπεριλάβει μια νέα γραμμή. 568 00:45:21,090 --> 00:45:25,290 Έτσι τώρα nonexistent.txt δεν υπάρχει. 569 00:45:26,890 --> 00:45:30,040 Θα πρέπει πάντα να ελέγξετε για αυτό το είδος του πράγματος. 570 00:45:30,040 --> 00:45:33,870 Θα πρέπει πάντα να ελέγξετε για να δείτε αν fopen επιστρέφει NULL. 571 00:45:33,870 --> 00:45:38,170 Θα πρέπει πάντα να ελέγξετε για να βεβαιωθείτε ότι η malloc δεν επιστρέφει NULL, 572 00:45:38,170 --> 00:45:41,410 ή αλλιώς segfault. 573 00:45:42,200 --> 00:45:45,930 >> Τώρα buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Τρέχοντας. Υποθέτω ότι αυτό είναι σε αναμονή για την είσοδο ή ενδεχομένως άπειρο looping. 575 00:45:58,440 --> 00:46:01,870 Ναι, είναι άπειρη looping. 576 00:46:01,870 --> 00:46:05,560 Έτσι buggy4. Μοιάζει σαν να είμαστε άπειρη looping. 577 00:46:05,560 --> 00:46:12,590 Μπορούμε να σπάσει σε κεντρικό, εκτελέστε το πρόγραμμα μας. 578 00:46:12,590 --> 00:46:20,180 Στην gdb, εφ 'όσον η συντομογραφία που χρησιμοποιείτε είναι σαφής 579 00:46:20,180 --> 00:46:23,420 ή ειδικές συντομογραφίες που παρέχουν για σας, 580 00:46:23,420 --> 00:46:29,020 τότε μπορείτε να χρησιμοποιήσετε για να χρησιμοποιήσετε n επόμενο αντί να χρειάζεται να πληκτρολογήσετε τον επόμενο σε όλη τη διαδρομή. 581 00:46:29,020 --> 00:46:33,730 Και τώρα που έχω χτυπήσει n μία φορά, μπορώ να χτυπήσει ακριβώς το Enter για να συνεχίσετε επόμενη 582 00:46:33,730 --> 00:46:36,640 αντί να χτυπήσει Εισάγετε n, n Enter, n Enter. 583 00:46:36,640 --> 00:46:44,630 Φαίνεται σαν να είμαι σε κάποιο είδος του βρόχου for που είναι για τη διάταξη [i] στο 0. 584 00:46:44,630 --> 00:46:50,510 Φαίνεται σαν να είμαι ποτέ να βγουν από αυτό για το βρόχο. 585 00:46:50,510 --> 00:46:54,780 Αν θ εκτύπωση, γι 'αυτό είναι 2, τότε θα πάω δίπλα. 586 00:46:54,780 --> 00:46:59,250 Θα εκτυπώσετε i, i είναι 3, τότε θα πάω δίπλα. 587 00:46:59,250 --> 00:47:05,360 Θα εκτυπώσετε i και i είναι 3. Στη συνέχεια, εκτυπώστε i, i είναι 4. 588 00:47:05,360 --> 00:47:14,520 Στην πραγματικότητα, η εκτύπωση sizeof (array), έτσι ώστε το μέγεθος του πίνακα είναι 20. 589 00:47:16,310 --> 00:47:32,870 Αλλά φαίνεται σαν να υπάρχει κάποια ειδική εντολή gdb για να πάει έως ότου συμβεί κάτι. 590 00:47:32,870 --> 00:47:37,620 Είναι σαν τον καθορισμό ενός προϋπόθεση για την τιμή της μεταβλητής. Αλλά δεν θυμάμαι τι είναι. 591 00:47:37,620 --> 00:47:44,100 Έτσι, αν εμείς συνεχίσουμε - 592 00:47:44,100 --> 00:47:47,120 Τι έλεγες; Τι σας φέρει μέχρι; 593 00:47:47,120 --> 00:47:50,500 [Φοιτητής] Δεν εμφανίζει μπορώ να προσθέσω - >> Ναι. Έτσι εμφανίζεται μπορώ να βοηθήσω. 594 00:47:50,500 --> 00:47:54,530 Εάν εμφανίσετε εγώ απλά, θα βάλει εδώ ποια είναι η αξία του i είναι 595 00:47:54,530 --> 00:47:56,470 γι 'αυτό δεν πρέπει να το εκτυπώσετε κάθε φορά. 596 00:47:56,470 --> 00:48:02,930 Αν απλά συνεχίστε επόμενο, βλέπουμε 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 Κάτι πρόκειται τρομερά λάθος, και θ γίνεται επαναφορά στο 0. 598 00:48:13,330 --> 00:48:22,220 Κοιτάζοντας buggy4.c, βλέπουμε μόνο που συμβαίνει είναι 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 array [i] = 0? 601 00:48:28,550 --> 00:48:31,390 Τι βλέπουμε ότι είναι λάθος εδώ; 602 00:48:31,390 --> 00:48:39,480 Ως έναν υπαινιγμό, όταν έκανα το gdb buggy4 - ας σπάσει κύρια, τρέξιμο - 603 00:48:39,480 --> 00:48:45,980 Έκανα εκτύπωσης sizeof (array), μόνο και μόνο για να δούμε τι είναι η κατάσταση όπου θα πρέπει τελικά να ξεσπάσει. 604 00:48:47,690 --> 00:48:51,100 Πού είμαι; Μήπως μπορώ να εκτελέσω; 605 00:48:51,100 --> 00:48:54,280 Δεν είχα δηλώσει ακόμη. 606 00:48:54,280 --> 00:48:58,680 Έτσι εκτύπωση sizeof (array) και αυτό είναι 20, 607 00:48:58,680 --> 00:49:06,690 η οποία αναμένεται από σειρά μου έχει μέγεθος 5 και είναι ακέραιοι από 5, 608 00:49:06,690 --> 00:49:12,410 έτσι το όλο πράγμα θα πρέπει να είναι 5 * sizeof (int) bytes, όπου sizeof (int) τείνει να είναι 4. 609 00:49:12,410 --> 00:49:14,780 Έτσι, sizeof (array) είναι 20. 610 00:49:14,780 --> 00:49:17,420 Τι θα πρέπει να είναι αυτό; 611 00:49:17,420 --> 00:49:21,720 [Φοιτητής] Χωρίζεται από sizeof (int). >> Ναι, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Φαίνεται σαν να υπάρχει ακόμα ένα πρόβλημα εδώ. Νομίζω ότι αυτό θα πρέπει απλώς να είναι < 613 00:49:30,630 --> 00:49:36,960 δεδομένου ότι είναι λίγο πολύ πάντα <και ποτέ <=. 614 00:49:36,960 --> 00:49:44,860 Τώρα, ας σκεφτούμε γιατί αυτό στην πραγματικότητα σπάσει. 615 00:49:44,860 --> 00:49:53,370 Υπάρχει κάποιος που να μαντεύει γιατί ήταν i επαναφορά στο 0 με κάθε επανάληψη του βρόχου; 616 00:50:01,300 --> 00:50:09,350 Το μόνο πράγμα εδώ μέσα που συμβαίνει είναι ότι η διάταξη [i], η οποία προβλέπεται στο 0. 617 00:50:09,350 --> 00:50:15,350 Έτσι, κατά κάποιο τρόπο, αυτή η γραμμή του κώδικα προκαλεί int i μας πρέπει να οριστεί σε 0. 618 00:50:16,730 --> 00:50:23,130 [Φοιτητής] Θα μπορούσε να είναι επειδή είναι επιτακτικό τη μνήμη του αυτό το μέρος του i 619 00:50:23,130 --> 00:50:27,970 όταν νομίζει ότι είναι το επόμενο στοιχείο του πίνακα; >> [Bowden] Ναι. 620 00:50:27,970 --> 00:50:33,880 Όταν θα πάμε πέρα ​​από το τέλος του πίνακα μας, 621 00:50:33,880 --> 00:50:39,870 κατά κάποιο τρόπο ότι το διάστημα που είμαστε επιτακτικούς είναι επιτακτικό η τιμή του i. 622 00:50:39,870 --> 00:50:48,030 Και έτσι, αν κοιτάξουμε σε buggy4, να σπάσει κύρια, τρέξιμο, 623 00:50:48,030 --> 00:50:53,120 ας εκτυπώσετε τη διεύθυνση του i. 624 00:50:53,120 --> 00:50:57,280 Φαίνεται σαν να είναι bffff124. 625 00:50:57,280 --> 00:51:03,930 Τώρα ας εκτυπώσετε τη διεύθυνση του array [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] είναι bfff124. 629 00:51:14,530 --> 00:51:26,990 Έτσι, array [5] έχει την ίδια διεύθυνση, όπως εγώ, που σημαίνει ότι array [5] i. 630 00:51:26,990 --> 00:51:30,720 Εάν έχουν την ίδια διεύθυνση, που είναι το ίδιο πράγμα. 631 00:51:30,720 --> 00:51:38,410 Έτσι, όταν θέτουμε array [5] στο 0, εμείς θ ρύθμιση στο 0. 632 00:51:38,410 --> 00:51:46,070 Και αν νομίζετε γι 'αυτό από την άποψη της στοίβας, 633 00:51:46,070 --> 00:51:55,590 int i έχει δηλωθεί κατ 'αρχάς, το οποίο σημαίνει ότι θ παίρνει λίγο χώρο στη στοίβα. 634 00:51:55,590 --> 00:52:04,730 Στη συνέχεια, array [5] κατανέμεται, ώστε στη συνέχεια 20 bytes που διατίθενται στη στοίβα. 635 00:52:04,730 --> 00:52:08,400 Γι 'αυτό και παίρνει κατανέμεται πρώτα, στη συνέχεια, να πάρει κατανέμονται αυτά τα 20 bytes. 636 00:52:08,400 --> 00:52:11,400 Γι 'αυτό θα συμβεί ακριβώς πριν από τη σειρά, 637 00:52:11,400 --> 00:52:19,230 και λόγω του τρόπου που, όπως είπα και την περασμένη εβδομάδα, όπου αυτό είναι τεχνικά η στοίβα μεγαλώνει προς τα κάτω, 638 00:52:19,230 --> 00:52:28,520 όταν δείκτη σε ένα πίνακα, θα είναι εγγυημένο ότι η 0th θέση στη συστοιχία 639 00:52:28,520 --> 00:52:31,970 συμβαίνει πάντα πριν από την πρώτη θέση στη συστοιχία. 640 00:52:31,970 --> 00:52:35,900 Αυτό είναι το είδος του πώς επέστησε την περασμένη εβδομάδα. 641 00:52:35,900 --> 00:52:42,210 Παρατηρήστε ότι στο κάτω μέρος έχουμε τη διεύθυνση 0 και στην κορυφή έχουμε Max διεύθυνση. 642 00:52:42,210 --> 00:52:44,880 Η στοίβα είναι πάντα αυξάνεται προς τα κάτω. 643 00:52:48,100 --> 00:52:53,500 Ας πούμε ότι εγώ κατανέμουν. 644 00:52:53,500 --> 00:52:59,680 Διαθέτουμε ακέραιο i, το οποίο σημαίνει ας πούμε εδώ ακέραιο i παίρνει διατεθεί. 645 00:52:59,680 --> 00:53:06,420 Στη συνέχεια, διαθέτουμε μας σειρά από 5 ακέραιους αριθμούς, που σημαίνει ότι κάτω από αυτό, 646 00:53:06,420 --> 00:53:11,230 δεδομένου ότι η στοίβα μεγαλώνει προς τα κάτω, να πάρει εκείνα τα 5 κατανέμονται ακέραιοι. 647 00:53:11,230 --> 00:53:15,900 Όμως, λόγω του τρόπου με συστοιχίες δουλειά, είμαστε εγγυάται ότι η πρώτη θέση του πίνακα 648 00:53:15,900 --> 00:53:22,260 έχει πάντα μια διεύθυνση μικρότερη από τη δεύτερη πράγμα στη συστοιχία. 649 00:53:22,260 --> 00:53:28,270 Έτσι σειρά θέση 0 έχει πάντα να συμβεί πρώτα στην μνήμη, 650 00:53:28,270 --> 00:53:30,700 λαμβάνοντας υπόψη ότι η θέση του πίνακα 1 πρέπει να συμβεί μετά από αυτό 651 00:53:30,700 --> 00:53:33,310 και θέση του πίνακα 2 έχει να συμβεί μετά από αυτό, 652 00:53:33,310 --> 00:53:37,900 πράγμα που σημαίνει ότι η θέση 0 array θα συμβεί κάπου εδώ, 653 00:53:37,900 --> 00:53:40,690 θέση σειρά 1 θα συμβεί παραπάνω ότι 654 00:53:40,690 --> 00:53:45,530 γιατί κινείται επάνω σημαίνει υψηλότερες διευθύνσεις από το μέγιστο διεύθυνση είναι εδώ. 655 00:53:45,530 --> 00:53:50,490 Έτσι, array [0] εδώ κάτω, array [1] μέχρι εδώ, array [2] μέχρι εδώ, array [3] μέχρι εδώ. 656 00:53:50,490 --> 00:53:55,620 Παρατηρήστε πως πριν χορηγηθεί ακέραιος i όλη τη διαδρομή μέχρι εδώ, 657 00:53:55,620 --> 00:54:01,040 καθώς προχωράμε όλο και περισσότερο σε σειρά μας, είμαστε όλο και πιο κοντά στο ακέραιο i μας. 658 00:54:01,040 --> 00:54:07,640 Συμβαίνει ότι array [5], η οποία είναι μια θέση πέρα ​​από σειρά μας, 659 00:54:07,640 --> 00:54:13,010 είναι ακριβώς όπου ακέραιος i έτυχε να διατεθεί. 660 00:54:13,010 --> 00:54:16,920 Έτσι, αυτό είναι το σημείο όπου τυχαίνει να χτυπήσει το χώρο στη στοίβα 661 00:54:16,920 --> 00:54:21,680 που κατανεμήθηκε για ακέραιο αριθμό i, και είμαστε ρύθμιση ότι στο 0. 662 00:54:21,680 --> 00:54:26,160 >> Αυτός είναι ο τρόπος που λειτουργεί. Ερωτήσεις; Ναι. 663 00:54:26,160 --> 00:54:30,710 [Φοιτητής] Δεν πειράζει. Εντάξει. 664 00:54:30,710 --> 00:54:33,090 [Φοιτητής] Πώς μπορείτε να αποφύγετε αυτά τα λάθη είδος; 665 00:54:33,090 --> 00:54:41,190 Τέτοιου είδους λάθη; Μην χρησιμοποιείτε C ως γλώσσα προγραμματισμού σας. 666 00:54:41,190 --> 00:54:45,840 Χρησιμοποιήστε μια γλώσσα που έχει σειρά όρια ελέγχου. 667 00:54:45,840 --> 00:54:55,900 Εφ 'όσον είστε προσεκτικοί, το μόνο που χρειάζεται για να αποφύγω να πάω πέρα ​​από τα όρια του πίνακα σας. 668 00:54:55,900 --> 00:54:58,300 [Φοιτητής] Έτσι, εδώ όταν πήγαμε παρελθόν τα όρια του πίνακα σας - 669 00:54:58,300 --> 00:55:01,840 [Bowden] Αυτό είναι όπου τα πράγματα αρχίζουν πηγαίνει στραβά. >> [Φοιτητής] Ω, εντάξει. 670 00:55:01,840 --> 00:55:05,730 Όσο μένετε στο πλαίσιο της μνήμης που εκχωρείται για την σειρά σας, είστε μια χαρά. 671 00:55:05,730 --> 00:55:12,400 Αλλά C δεν κάνει έλεγχο σφαλμάτων. Αν κάνω array [1000], ευχαρίστως θα τροποποιήσει μόνο ό, τι συμβαίνει - 672 00:55:12,400 --> 00:55:16,500 Πηγαίνει στην αρχή της συστοιχίας, τότε πηγαίνει 1000 θέσεις μετά και το θέτει σε 0. 673 00:55:16,500 --> 00:55:20,000 Δεν κάνει κανένα έλεγχο ότι ω, αυτό δεν έχει στην πραγματικότητα 1000 τα πράγματα σε αυτό. 674 00:55:20,000 --> 00:55:22,750 1000 είναι πολύ πέρα ​​από αυτό που θα πρέπει να αλλάζει, 675 00:55:22,750 --> 00:55:26,940 λαμβάνοντας υπόψη ότι η Java ή κάτι που θα πάρει σειρά από τα όρια του δείκτη 676 00:55:26,940 --> 00:55:29,820 ή δείκτης εκτός ορίων εξαίρεση. 677 00:55:29,820 --> 00:55:33,950 Αυτός είναι ο λόγος που πολλοί από υψηλότερο επίπεδο γλώσσες έχουν αυτά τα πράγματα 678 00:55:33,950 --> 00:55:37,340 όπου κι αν πάτε πέρα ​​από τα όρια του πίνακα, μπορείτε να αποτύχει 679 00:55:37,340 --> 00:55:40,070 έτσι ώστε δεν μπορείτε να αλλάξετε τα πράγματα από κάτω σας 680 00:55:40,070 --> 00:55:42,590 και τότε τα πράγματα πάνε πολύ χειρότερα από ό, τι ακριβώς να πάρει μια εξαίρεση 681 00:55:42,590 --> 00:55:44,940 λέγοντας ότι πήγατε πέρα ​​από το τέλος του πίνακα. 682 00:55:44,940 --> 00:55:50,970 [Φοιτητής] Και έτσι έπρεπε να είχαμε μόλις αλλάξει το <= σε μόλις > [Bowden] Ναι. 683 00:55:50,970 --> 00:55:54,800 Θα πρέπει να είναι 00:55:59,560 από το sizeof (array) είναι 20, αλλά θέλουμε μόνο 5. >> [Φοιτητής] Δεξιά. 685 00:55:59,560 --> 00:56:04,060 Περισσότερες ερωτήσεις; Εντάξει. 686 00:56:04,060 --> 00:56:07,380 >> [Φοιτητής] Έχω μια ερώτηση. Ναι >>. 687 00:56:07,380 --> 00:56:16,440 [Φοιτητής] Ποια είναι η πραγματική μεταβλητή πίνακα; 688 00:56:16,440 --> 00:56:20,000 [Bowden] Όπως Τι είναι η σειρά; 689 00:56:20,000 --> 00:56:24,930 Array είναι ένα σύμβολο. 690 00:56:24,930 --> 00:56:31,490 Είναι ακριβώς η διεύθυνση της έναρξης των 20 bytes που μας αναφορά. 691 00:56:31,490 --> 00:56:38,070 Μπορείτε να σκεφτείτε από το ως ένα δείκτη, αλλά είναι μια συνεχής δείκτη. 692 00:56:38,070 --> 00:56:44,140 Από τη στιγμή που τα πράγματα παίρνουν καταρτίζονται, η μεταβλητή πίνακα δεν υπάρχει πια. 693 00:56:44,140 --> 00:56:48,210 [Φοιτητής] Έτσι, πώς να βρείτε το μέγεθος του πίνακα; 694 00:56:48,210 --> 00:56:54,130 Μέγεθος του πίνακα αναφέρεται στο μέγεθος των εν λόγω μπλοκ ότι σύμβολο αναφέρεται σε. 695 00:56:54,130 --> 00:57:01,240 Όταν κάνω κάτι σαν printf ("% p \ n", σειρά)? 696 00:57:01,240 --> 00:57:05,140 ας το τρέξει. 697 00:57:12,960 --> 00:57:15,530 Τι έκανα ακριβώς κάνω λάθος; 698 00:57:15,530 --> 00:57:19,220 Οι «συστοιχίες» δήλωσε Array εδώ. 699 00:57:20,820 --> 00:57:23,200 Ω, εδώ. 700 00:57:23,200 --> 00:57:31,250 Clang είναι έξυπνος, και συμβαίνει να παρατηρήσετε ότι έχω δηλώσει τον πίνακα ως 5 στοιχεία 701 00:57:31,250 --> 00:57:34,540 αλλά είμαι σε θέση ευρετηρίαση 1000. 702 00:57:34,540 --> 00:57:38,450 Μπορεί να το κάνει αυτό, διότι αυτά είναι μόνο σταθερές. 703 00:57:38,450 --> 00:57:43,370 Το μόνο που μπορεί να φθάσει μέχρι το παρατηρήσει ότι θα πάω πέρα ​​από τα όρια του πίνακα. 704 00:57:43,370 --> 00:57:46,880 Αλλά παρατηρήσετε πριν όταν είχαμε i να είναι εσφαλμένη, 705 00:57:46,880 --> 00:57:51,040 δεν είναι δυνατόν να προσδιορίσουν πόσες τιμές θα μπορούσα να αναλάβει, 706 00:57:51,040 --> 00:57:55,540 έτσι ώστε να μπορεί να προσδιορίσει ότι πήγαινα πέρα ​​από το τέλος του πίνακα. 707 00:57:55,540 --> 00:57:59,430 Αυτό είναι ακριβώς Clang είναι έξυπνος. 708 00:57:59,430 --> 00:58:03,340 >> Αλλά να τώρα buggy4. Λοιπόν, τι άλλο κάνω λάθος; 709 00:58:03,340 --> 00:58:05,970 Εμμέσως δηλώνοντας λειτουργία βιβλιοθήκης printf ». 710 00:58:05,970 --> 00:58:14,960 Πάω να θέλετε να συμπεριλάβετε # . 711 00:58:14,960 --> 00:58:18,710 Εντάξει. Τώρα τρέχει buggy4. 712 00:58:18,710 --> 00:58:24,840 Εκτύπωση της αξίας του πίνακα, όπως έκανα εδώ, την εκτύπωση ως δείκτης 713 00:58:24,840 --> 00:58:30,060 εκτυπώσεις κάτι που μοιάζει με αυτό - bfb8805c - η οποία είναι κάποια διεύθυνση 714 00:58:30,060 --> 00:58:33,450 αυτό είναι στη στοίβα-ish περιοχή. 715 00:58:33,450 --> 00:58:41,820 Array μόνη της είναι σαν ένα δείκτη, αλλά δεν είναι ένας πραγματικός δείκτης, 716 00:58:41,820 --> 00:58:45,410 από ένα κανονικό δείκτη μπορούμε να αλλάξουμε. 717 00:58:45,410 --> 00:58:54,700 Array είναι μερικά μόνο σταθερή. Τα 20 μπλοκ μνήμης ξεκινούν από 0xbfb8805c διεύθυνση. 718 00:58:54,700 --> 00:59:09,020 Έτσι, μέσα από αυτό το bfb8805c διεύθυνση ή +20--υποθέτω -20 - 719 00:59:09,020 --> 00:59:17,400 είναι το σύνολο της μνήμης που διατίθενται για αυτή τη διάταξη. 720 00:59:17,400 --> 00:59:20,350 Array, η μεταβλητή είναι η ίδια δεν αποθηκεύονται πουθενά. 721 00:59:20,350 --> 00:59:27,660 Όταν την κατάρτιση, ο compiler - κύμα χέρι σε αυτό - 722 00:59:27,660 --> 00:59:33,060 αλλά ο compiler θα χρησιμοποιήσει μόνο όταν γνωρίζει σειρά να είναι. 723 00:59:33,060 --> 00:59:36,090 Δεν ξέρει πού αρχίζει η σειρά, 724 00:59:36,090 --> 00:59:40,910 και γι 'αυτό μπορεί πάντα να κάνει ακριβώς τα πράγματα όσον αφορά τις αποζημιώσεις από την αρχή. 725 00:59:40,910 --> 00:59:43,960 Δεν χρειάζεται μια μεταβλητή η ίδια να εκπροσωπεί συστοιχία. 726 00:59:43,960 --> 00:59:53,730 Αλλά όταν κάνω κάτι σαν int * p = array? Τώρα p είναι ένας δείκτης που δείχνει την σειρά, 727 00:59:53,730 --> 00:59:57,830 και τώρα σ. πραγματικότητα δεν υπάρχει στη στοίβα. 728 00:59:57,830 --> 01:00:01,950 Είμαι ελεύθερος να αλλάξει p. Μπορώ να κάνω p = malloc. 729 01:00:01,950 --> 01:00:06,500 Έτσι, αρχικά επεσήμανε σειρά? Τώρα δείχνει σε κάποιο χώρο στο σωρό. 730 01:00:06,500 --> 01:00:09,620 Δεν μπορώ να κάνω σειρά = malloc. 731 01:00:09,620 --> 01:00:13,710 Αν Clang είναι έξυπνος, θα μου φωνάζεις δεξιά από το ρόπαλο. 732 01:00:17,000 --> 01:00:21,430 Στην πραγματικότητα, είμαι σίγουρος ότι gcc θα το κάνετε αυτό πάρα πολύ. 733 01:00:21,430 --> 01:00:25,010 Έτσι τύπου σειρά «int [5]» δεν μπορεί να αντιστοιχηθεί. 734 01:00:25,010 --> 01:00:28,040 Δεν μπορείτε να εκχωρήσετε κάτι σε έναν τύπο πίνακα 735 01:00:28,040 --> 01:00:30,500 επειδή πίνακας είναι απλά μια σταθερά. 736 01:00:30,500 --> 01:00:34,760 Είναι ένα σύμβολο το οποίο οι αναφορές αυτές 20 bytes. Δεν μπορώ να το αλλάξετε. 737 01:00:34,760 --> 01:00:37,690 >> [Φοιτητής] Και πού είναι το μέγεθος του πίνακα αποθηκεύονται; 738 01:00:37,690 --> 01:00:40,670 [Bowden] Δεν είναι αποθηκευμένο πουθενά. Είναι όταν είναι κατάρτιση. 739 01:00:40,670 --> 01:00:46,310 Έτσι, όταν είναι το μέγεθος του πίνακα αποθηκεύονται; 740 01:00:46,310 --> 01:00:51,870 Μπορείτε να χρησιμοποιήσετε μόνο sizeof (array), μέσα από τη λειτουργία ότι η σειρά είναι η ίδια δήλωσε. 741 01:00:51,870 --> 01:01:03,150 Έτσι, αν κάνω κάποια λειτουργία, foo, και να κάνω (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 και στη συνέχεια κάτω από εδώ καλώ foo (array)? 744 01:01:21,330 --> 01:01:24,840 μέσα από αυτή τη λειτουργία - ας το τρέξει. 745 01:01:34,200 --> 01:01:36,840 Αυτό είναι Clang είναι έξυπνος και πάλι. 746 01:01:36,840 --> 01:01:43,890 Είναι μου λέει ότι sizeof παράμετρος για τη λειτουργία πίνακα 747 01:01:43,890 --> 01:01:46,690 θα επιστρέψει το μέγεθος του «int *». 748 01:01:46,690 --> 01:01:55,150 Αυτό θα ήταν ένα λάθος, αν δεν είναι αυτό που ήθελα να συμβεί. 749 01:01:55,150 --> 01:01:58,960 Ας πραγματικά να απενεργοποιήσετε Werror. 750 01:02:14,950 --> 01:02:17,590 Προειδοποίηση. Προειδοποιήσεις είναι μια χαρά. 751 01:02:17,590 --> 01:02:19,960 Θα εξακολουθούν να συγκεντρώνουν όσο έχει μια προειδοποίηση. 752 01:02:19,960 --> 01:02:22,910 . / A.out πρόκειται να εκτυπώσετε 4. 753 01:02:22,910 --> 01:02:28,650 Η προειδοποίηση που δημιουργήθηκε αποτελεί σαφή ένδειξη για το τι πήγε στραβά. 754 01:02:28,650 --> 01:02:34,120 Αυτό int array είναι ακριβώς πρόκειται να εκτυπώσετε sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Ακόμα κι αν έβαλα array [5] εδώ, είναι ακόμα ακριβώς πρόκειται να εκτυπώσετε sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Έτσι, το συντομότερο μπορείτε να το δώσετε σε μια λειτουργία, η διάκριση μεταξύ πινάκων και δεικτών 757 01:02:47,440 --> 01:02:49,670 είναι ανύπαρκτη. 758 01:02:49,670 --> 01:02:52,640 Αυτό συμβαίνει να είναι ένας πίνακας που δηλώθηκε στη στοίβα, 759 01:02:52,640 --> 01:02:58,300 αλλά μόλις περάσουμε αυτή την τιμή, ότι 0xbf μπλα, μπλα, μπλα σε αυτή τη λειτουργία, 760 01:02:58,300 --> 01:03:03,350 τότε αυτό δείχνει δείκτη στην εν λόγω συστοιχία επί της στοίβας. 761 01:03:03,350 --> 01:03:08,310 Έτσι, αυτό σημαίνει ότι sizeof ισχύει μόνο για τη λειτουργία που η σειρά είχε δηλώσει, 762 01:03:08,310 --> 01:03:11,230 πράγμα που σημαίνει ότι όταν είστε κατάρτιση αυτή τη λειτουργία, 763 01:03:11,230 --> 01:03:17,330 Clang όταν περνά μέσα από αυτή τη λειτουργία, βλέπει ένα πίνακα είναι int πίνακα μεγέθους 5. 764 01:03:17,330 --> 01:03:20,640 Άρα, λοιπόν, βλέπει sizeof (array). Λοιπόν, αυτό είναι 20. 765 01:03:20,640 --> 01:03:26,440 Αυτό είναι πραγματικά πώς λειτουργεί sizeof βασικά για σχεδόν όλες τις περιπτώσεις. 766 01:03:26,440 --> 01:03:31,150 Sizeof δεν είναι μια λειτουργία? Είναι ένας επιχειρηματίας. 767 01:03:31,150 --> 01:03:33,570 Δεν καλέστε το sizeof λειτουργία. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), ο compiler θα μεταφράσει απλώς ότι έως 4. 769 01:03:41,480 --> 01:03:43,700 Κατάλαβες; Εντάξει. 770 01:03:43,700 --> 01:03:47,520 >> [Φοιτητής] Έτσι ποια είναι η διαφορά μεταξύ sizeof (array) στην κύρια και στην foo; 771 01:03:47,520 --> 01:03:52,840 Αυτό συμβαίνει επειδή λέμε sizeof (array), η οποία είναι τύπου int *, 772 01:03:52,840 --> 01:03:57,120 ενώ ο πίνακας εδώ κάτω δεν είναι του τύπου int *, είναι μια int array. 773 01:03:57,120 --> 01:04:04,540 >> [Φοιτητής] Έτσι, αν είχατε την παράμετρο σε array [] αντί int * array, 774 01:04:04,540 --> 01:04:09,230 ότι θα σημαίνει ότι θα μπορούσε να αλλάξει παράταξη γιατί τώρα είναι ένας δείκτης; 775 01:04:09,230 --> 01:04:14,250 [Bowden] Σας αρέσει αυτό; >> [Φοιτητής] Ναι. Μπορείτε να αλλάξετε σειρά στο πλαίσιο της λειτουργίας τώρα; 776 01:04:14,250 --> 01:04:18,420 [Bowden] Θα μπορούσε να αλλάξει σειρά και στις δύο περιπτώσεις. 777 01:04:18,420 --> 01:04:23,130 Και στις δύο αυτές περιπτώσεις, είστε ελεύθεροι να πείτε array [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Μαθητής] Αλλά μπορεί να σας κάνει το σημείο σειρά για κάτι άλλο; 779 01:04:26,590 --> 01:04:30,230 [Bowden] Αχ. Ναι. Σε κάθε περίπτωση - >> [φοιτητής] Ναι. 780 01:04:30,230 --> 01:04:38,410 [Bowden] Η διάκριση μεταξύ array [] και int * array, δεν υπάρχει κανένας. 781 01:04:38,410 --> 01:04:42,570 Μπορείτε επίσης να πάρετε κάποια πολυδιάστατη array εδώ 782 01:04:42,570 --> 01:04:47,050 για κάποιο βολικό σύνταξη, αλλά είναι ακόμα μόνο ένα δείκτη. 783 01:04:47,050 --> 01:04:56,400 Αυτό σημαίνει ότι είμαι ελεύθερος να κάνω array = malloc (sizeof (int))? Και τώρα το σημείο κάπου αλλού. 784 01:04:56,400 --> 01:04:59,610 Αλλά ακριβώς όπως το πώς αυτό λειτουργεί για πάντα και πάντα, 785 01:04:59,610 --> 01:05:03,210 αλλαγή αυτή σειρά, καθιστώντας το σημείο σε κάτι άλλο 786 01:05:03,210 --> 01:05:07,570 δεν αλλάξει αυτή η σειρά εδώ κάτω επειδή είναι ένα αντίγραφο του επιχειρήματος, 787 01:05:07,570 --> 01:05:10,780 δεν είναι ένας δείκτης σε αυτό το επιχείρημα. 788 01:05:10,780 --> 01:05:16,070 Και στην πραγματικότητα, ακριβώς όπως ακόμη ένδειξη ότι είναι ακριβώς το ίδιο - 789 01:05:16,070 --> 01:05:21,100 είδαμε ήδη τι εκτυπώσεις σειρά εκτύπωσης - 790 01:05:21,100 --> 01:05:31,410 τι θα γίνει αν εμείς εκτυπώσετε τη διεύθυνση του πίνακα ή τη διεύθυνση της διεύθυνσης του πίνακα 791 01:05:31,410 --> 01:05:36,290 είτε από αυτούς; 792 01:05:41,770 --> 01:05:45,220 Ας αγνοήσουμε αυτό. 793 01:05:48,140 --> 01:05:51,660 Εντάξει. Αυτό είναι μια χαρά. Είναι τρέχει τώρα. / A.out. 794 01:05:51,660 --> 01:06:00,220 Σειρά εκτύπωσης, στη συνέχεια να εκτυπώσετε τη διεύθυνση του πίνακα, είναι το ίδιο πράγμα. 795 01:06:00,220 --> 01:06:02,870 Array, απλά δεν υπάρχει. 796 01:06:02,870 --> 01:06:08,190 Ξέρει πότε είστε εκτύπωση σειρά, τυπώνετε το σύμβολο που αναφέρεται σε αυτά τα 20 bytes. 797 01:06:08,190 --> 01:06:11,940 Εκτύπωση τη διεύθυνση του πίνακα, επίσης, σειρά δεν υπάρχει. 798 01:06:11,940 --> 01:06:17,200 Δεν έχει μια διεύθυνση, έτσι ώστε να εκτυπώνει μόνο την διεύθυνση των 20 bytes. 799 01:06:20,820 --> 01:06:28,150 Μόλις μεταγλωττίσετε τα κάτω, όπως στην καταρτίζονται buggy4 σας. / A.out, 800 01:06:28,150 --> 01:06:30,340 πίνακα είναι ανύπαρκτη. 801 01:06:30,340 --> 01:06:33,640 Δείκτες υπάρχουν. Οι πίνακες δεν το κάνουν. 802 01:06:34,300 --> 01:06:38,060 Τα μπλοκ της μνήμης που αντιπροσωπεύει τη συστοιχία εξακολουθούν να υπάρχουν, 803 01:06:38,060 --> 01:06:43,270 αλλά η μεταβλητή πίνακα και μεταβλητές αυτού του τύπου δεν υπάρχουν. 804 01:06:46,260 --> 01:06:50,270 Αυτά είναι σαν τις κύριες διαφορές μεταξύ πινάκων και δεικτών 805 01:06:50,270 --> 01:06:55,590 Οι συντομότερο μπορείτε να πραγματοποιήσετε κλήσεις λειτουργία, δεν υπάρχει καμία διαφορά. 806 01:06:55,590 --> 01:07:00,460 Αλλά μέσα από τη λειτουργία που η ίδια η σειρά έχει δηλωθεί, sizeof λειτουργεί με διαφορετικό τρόπο 807 01:07:00,460 --> 01:07:05,190 δεδομένου τυπώνετε το μέγεθος των μπλοκ αντί του μεγέθους του τύπου, 808 01:07:05,190 --> 01:07:08,950 και δεν μπορείτε να το αλλάξετε γιατί είναι ένα σύμβολο. 809 01:07:08,950 --> 01:07:14,370 Εκτύπωση του το πράγμα και τη διεύθυνση του πράγματος εκτυπώνει το ίδιο πράγμα. 810 01:07:14,370 --> 01:07:18,480 Και αυτό είναι λίγο πολύ αυτό. 811 01:07:18,480 --> 01:07:20,820 [Φοιτητής] Θα μπορούσατε να πείτε ότι για άλλη μια φορά; 812 01:07:21,170 --> 01:07:24,170 Θα μπορούσα να έχω χάσει κάτι. 813 01:07:24,170 --> 01:07:29,260 Σειρά εκτύπωσης και τη διεύθυνση του πίνακα εκτυπώνει το ίδιο πράγμα, 814 01:07:29,260 --> 01:07:33,180 ενώ αν εκτυπώσετε ένα δείκτη σε σχέση με τη διεύθυνση του δείκτη, 815 01:07:33,180 --> 01:07:36,010 το μόνο πράγμα που τυπώνει τη διεύθυνση του τι είστε επισημαίνοντας, 816 01:07:36,010 --> 01:07:40,360 το άλλο εκτυπώνει τη διεύθυνση του δείκτη στη στοίβα. 817 01:07:40,360 --> 01:07:47,040 Μπορείτε να αλλάξετε το δείκτη? Δεν μπορείτε να αλλάξετε μια σειρά σύμβολο. 818 01:07:47,740 --> 01:07:53,270 Και sizeof δείκτης πρόκειται να εκτυπώσετε το μέγεθος αυτού του τύπου δείκτη. 819 01:07:53,270 --> 01:07:57,470 Έτσι, int * p sizeof (ιστ) πρόκειται να εκτυπώσετε 4, 820 01:07:57,470 --> 01:08:04,110 αλλά int array [5] εκτύπωσης sizeof (array) πρόκειται να εκτυπώσετε 20. 821 01:08:04,110 --> 01:08:07,480 [Φοιτητής] Έτσι int array [5] θα εκτυπώσει 20; >> Ναι. 822 01:08:07,480 --> 01:08:13,300 Αυτός είναι ο λόγος που μέσα από buggy4 όταν χρησιμοποιείται για να είναι sizeof (array) 823 01:08:13,300 --> 01:08:16,660 αυτό έκανε i <20, το οποίο δεν είναι αυτό που θέλαμε. 824 01:08:16,660 --> 01:08:20,880 Θέλουμε i <5. >> [Φοιτητής] Εντάξει. 825 01:08:20,880 --> 01:08:25,569 [Bowden] Και στη συνέχεια, μόλις αρχίσει περνώντας στις λειτουργίες, 826 01:08:25,569 --> 01:08:34,340 αν κάναμε int * p = array? 827 01:08:34,340 --> 01:08:39,779 μέσα από αυτή τη λειτουργία, μπορούμε να χρησιμοποιήσουμε βασικά σ. σειρά και με τον ίδιο ακριβώς τρόπο, 828 01:08:39,779 --> 01:08:43,710 εκτός από το πρόβλημα sizeof και το μεταβαλλόμενο πρόβλημα. 829 01:08:43,710 --> 01:08:49,810 Αλλά ρ [0] = 1? Είναι η ίδια όπως λέγοντας array [0] = 1? 830 01:08:49,810 --> 01:08:55,600 Και το συντομότερο λέμε foo (array)? Ή foo (ιστ)? 831 01:08:55,600 --> 01:08:59,760 εσωτερικό του συνάρτηση foo, αυτή είναι η ίδια κλήση δύο φορές. 832 01:08:59,760 --> 01:09:03,350 Δεν υπάρχει καμία διαφορά μεταξύ αυτών των δύο κλήσεων. 833 01:09:07,029 --> 01:09:11,080 >> Όλοι καλό σε αυτό; Εντάξει. 834 01:09:14,620 --> 01:09:17,950 Έχουμε 10 λεπτά. 835 01:09:17,950 --> 01:09:28,319 >> Θα προσπαθήσουμε να ξεπεράσουμε αυτό το πρόγραμμα Typer Hacker, 836 01:09:28,319 --> 01:09:32,350 αυτή η ιστοσελίδα, η οποία βγήκε πέρυσι ή κάτι τέτοιο. 837 01:09:34,149 --> 01:09:41,100 Είναι ακριβώς υποτίθεται ότι είναι σαν να πληκτρολογήσετε τυχαία και εκτυπώνει - 838 01:09:41,100 --> 01:09:46,729 Όποια και αν είναι το αρχείο που συμβαίνει να έχουν φορτωθεί είναι αυτό που μοιάζει με πληκτρολογείτε. 839 01:09:46,729 --> 01:09:52,069 Μοιάζει με κάποιο είδος λειτουργικού συστήματος κώδικα. 840 01:09:53,760 --> 01:09:56,890 Αυτό είναι που θέλουμε να υλοποιήσουμε. 841 01:10:08,560 --> 01:10:11,690 Πρέπει να έχετε ένα εκτελέσιμο ονομάζεται hacker_typer 842 01:10:11,690 --> 01:10:14,350 που παίρνει σε ένα επιχείρημα, το αρχείο "τύπος χάκερ." 843 01:10:14,350 --> 01:10:16,480 Τρέχοντας το εκτελέσιμο θα πρέπει να καθαρίσετε την οθόνη 844 01:10:16,480 --> 01:10:20,850 και στη συνέχεια να εκτυπώσετε ένα χαρακτήρα από το πέρασαν-σε αρχείο κάθε φορά που ο χρήστης πατήσει ένα πλήκτρο. 845 01:10:20,850 --> 01:10:24,990 Έτσι, ό, τι πλήκτρο που θα πατήσετε, θα πρέπει να ρίξει μακριά και αντί να εκτυπώσετε ένα χαρακτήρα από το αρχείο 846 01:10:24,990 --> 01:10:27,810 αυτό είναι το επιχείρημα. 847 01:10:29,880 --> 01:10:34,350 Θα λίγο πολύ να σας πω ποια είναι τα πράγματα που θα πάμε να πρέπει να ξέρετε. 848 01:10:34,350 --> 01:10:36,440 Αλλά θέλουμε να ελέγξετε έξω τη βιβλιοθήκη termios. 849 01:10:36,440 --> 01:10:44,840 Δεν έχω χρησιμοποιήσει ποτέ αυτή τη βιβλιοθήκη σε ολόκληρη τη ζωή μου, γι 'αυτό έχει πολύ ελάχιστη σκοπούς. 850 01:10:44,840 --> 01:10:48,610 Αλλά αυτό πρόκειται να είναι η βιβλιοθήκη που μπορούμε να χρησιμοποιήσουμε για να ρίξει μακριά το χαρακτήρα που έπληξε 851 01:10:48,610 --> 01:10:52,390 όταν πληκτρολογείτε σε πρότυπο μέσα 852 01:10:56,970 --> 01:11:05,840 Έτσι hacker_typer.c, και θα πάμε να θέλετε να συμπεριλάβετε # . 853 01:11:05,840 --> 01:11:12,870 Κοιτάζοντας την σελίδα man για termios - I'm μαντέψουν το τερματικό του λειτουργικού συστήματος ή κάτι τέτοιο - 854 01:11:12,870 --> 01:11:16,240 Δεν ξέρω πώς να το διαβάσετε. 855 01:11:16,240 --> 01:11:21,040 Κοιτάζοντας αυτό, το λέει για να συμπεριλάβει αυτά τα 2 αρχεία, οπότε θα το κάνουμε αυτό. 856 01:11:37,620 --> 01:11:46,820 >> Το πρώτο πράγμα πρώτα, θέλουμε να λάβει ένα επιχείρημα, το οποίο είναι το αρχείο θα πρέπει να ανοίξει. 857 01:11:46,820 --> 01:11:52,420 Έτσι, αυτό που θέλω να κάνω; Πώς μπορώ να ελέγξω να δω δεν έχω ούτε ένα επιχείρημα; 858 01:11:52,420 --> 01:11:56,480 [Φοιτητής] Αν argc είναι ίσοι. >> [Bowden] Ναι. 859 01:11:56,480 --> 01:12:21,250 Έτσι, αν (argc = 2!) Printf ("Χρήση:% s [για να ανοίξετε το αρχείο]"). 860 01:12:21,250 --> 01:12:32,750 Έτσι τώρα, αν μπορώ να εκτελέσω αυτό, χωρίς να παρέχει ένα δεύτερο επιχείρημα - OH, χρειάζομαι τη νέα γραμμή - 861 01:12:32,750 --> 01:12:36,240 θα δείτε ότι λέει χρήσης:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 και στη συνέχεια το δεύτερο επιχείρημα πρέπει να είναι το αρχείο που θέλετε να ανοίξετε. 863 01:12:58,430 --> 01:13:01,260 Τώρα τι μπορώ να κάνω; 864 01:13:01,260 --> 01:13:08,490 Θέλω να διαβάσετε από αυτό το αρχείο. Πώς μπορώ να διαβάσω από ένα αρχείο; 865 01:13:08,490 --> 01:13:11,920 [Φοιτητής] Μπορείτε να το ανοίξετε πρώτα. Ναι >>. 866 01:13:11,920 --> 01:13:15,010 Έτσι fopen. Τι σημαίνει fopen μοιάζει; 867 01:13:15,010 --> 01:13:22,980 [Φοιτητής] Όνομα. >> [Bowden] Όνομα πρόκειται να είναι argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Φοιτητής] Και τότε τι θέλετε να κάνετε με αυτό, έτσι ώστε το - >> [Bowden] Ναι. 869 01:13:26,110 --> 01:13:28,740 Έτσι, αν δεν θυμάστε, μπορείτε να το κάνετε μόνο fopen άνθρωπος, 870 01:13:28,740 --> 01:13:32,960 όπου πρόκειται να είναι μια const char * path όπου διαδρομή είναι όνομα αρχείου, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Αν συμβεί να μην θυμάται τι κατάσταση είναι, τότε μπορείτε να ψάξετε για λειτουργία. 873 01:13:38,660 --> 01:13:44,660 Μέσα από τις σελίδες του ανθρώπου, ο χαρακτήρας της καθέτου είναι αυτό που μπορείτε να χρησιμοποιήσετε για να αναζητήσετε τα πράγματα. 874 01:13:44,660 --> 01:13:49,790 Γι 'αυτό τον τύπο / τρόπο για να αναζητήσετε λειτουργία. 875 01:13:49,790 --> 01:13:57,130 n και Ν είναι αυτό που μπορείτε να χρησιμοποιήσετε για να μετακινηθείτε μέσα από τους αγώνες αναζήτησης. 876 01:13:57,130 --> 01:13:59,800 Εδώ λέει τα σημεία λειτουργίας επιχείρημα σε μια σειρά 877 01:13:59,800 --> 01:14:01,930 αρχίζοντας με μία από τις ακόλουθες αλληλουχίες. 878 01:14:01,930 --> 01:14:06,480 Έτσι, r, Άνοιγμα αρχείου κειμένου για ανάγνωση. Αυτό είναι ό, τι θέλουμε να κάνουμε. 879 01:14:08,930 --> 01:14:13,210 Για την ανάγνωση, και θέλω να αποθηκεύσετε αυτό. 880 01:14:13,210 --> 01:14:18,720 Το θέμα πρόκειται να είναι ένα αρχείο *. Τώρα τι θέλω να κάνω; 881 01:14:18,720 --> 01:14:21,200 Δώσε μου μια δεύτερη. 882 01:14:28,140 --> 01:14:30,430 Εντάξει. Τώρα τι θέλω να κάνω; 883 01:14:30,430 --> 01:14:32,940 [Φοιτητής] Ελέγξτε αν είναι NULL. >> [Bowden] Ναι. 884 01:14:32,940 --> 01:14:38,690 Κάθε φορά που ανοίγετε ένα αρχείο, βεβαιωθείτε ότι είστε σε θέση να με επιτυχία να το ανοίξετε. 885 01:14:58,930 --> 01:15:10,460 >> Τώρα θέλω να κάνω ότι termios πράγματα που θέλω να διαβάσετε πρώτα τις τρέχουσες ρυθμίσεις μου 886 01:15:10,460 --> 01:15:14,050 και να σώσει αυτούς σε κάτι, τότε θέλω να αλλάξω τις ρυθμίσεις μου 887 01:15:14,050 --> 01:15:19,420 να πετάει κάθε χαρακτήρα που πληκτρολογείτε, 888 01:15:19,420 --> 01:15:22,520 και στη συνέχεια θέλω να ενημερώσετε αυτές τις ρυθμίσεις. 889 01:15:22,520 --> 01:15:27,250 Και στη συνέχεια, στο τέλος του προγράμματος, θέλω να αλλάξω πίσω στις αρχικές ρυθμίσεις μου. 890 01:15:27,250 --> 01:15:32,080 Έτσι, το struct θα είναι του τύπου termios, και είμαι πρόκειται να θέλουν δύο από αυτά. 891 01:15:32,080 --> 01:15:35,600 Η πρώτη θα είναι current_settings μου, 892 01:15:35,600 --> 01:15:42,010 και στη συνέχεια, από όπου και αν πρόκειται να είναι hacker_settings μου. 893 01:15:42,010 --> 01:15:48,070 Κατ 'αρχάς, θα πάω να θέλετε να αποθηκεύσετε τις τρέχουσες ρυθμίσεις μου, 894 01:15:48,070 --> 01:15:53,790 τότε Πάω να θέλετε να ενημερώσετε hacker_settings, 895 01:15:53,790 --> 01:16:01,570 και στη συνέχεια το δρόμο στο τέλος του προγράμματός μου, θέλω να επαναφέρετε τις τρέχουσες ρυθμίσεις. 896 01:16:01,570 --> 01:16:08,660 Έτσι, εξοικονομώντας τις τρέχουσες ρυθμίσεις, ο τρόπος που λειτουργεί, εμείς termios άνθρωπος. 897 01:16:08,660 --> 01:16:15,810 Βλέπουμε ότι έχουμε αυτό το int tcsetattr, int tcgetattr. 898 01:16:15,810 --> 01:16:22,960 Περνώ σε ένα struct termios με το δείκτη του. 899 01:16:22,960 --> 01:16:30,640 Ο τρόπος με τον οποίο θα δούμε είναι - έχω ήδη ξεχάσει τι η συνάρτηση κλήθηκε. 900 01:16:30,640 --> 01:16:34,930 Αντιγράψτε και επικολλήστε. 901 01:16:39,150 --> 01:16:45,500 Έτσι tcgetattr, τότε θέλω να περάσει στο struct ότι είμαι αποθήκευση των πληροφοριών σε, 902 01:16:45,500 --> 01:16:49,650 η οποία πρόκειται να είναι current_settings, 903 01:16:49,650 --> 01:16:59,120 και το πρώτο επιχείρημα είναι ο file descriptor για το πράγμα που θέλετε να αποθηκεύσετε τα χαρακτηριστικά του. 904 01:16:59,120 --> 01:17:04,360 Τι το Περιγραφέας αρχείο είναι είναι όπως κάθε φορά που ανοίγετε ένα αρχείο, παίρνει ένα περιγραφέα αρχείου. 905 01:17:04,360 --> 01:17:14,560 Όταν fopen argv [1], παίρνει ένα περιγραφέα αρχείου που έχετε αναφορά 906 01:17:14,560 --> 01:17:16,730 κάθε φορά που θέλετε να διαβάσει ή να γράψει σε αυτό. 907 01:17:16,730 --> 01:17:19,220 Αυτό δεν είναι το Περιγραφέας αρχείο που θέλετε να χρησιμοποιήσετε εδώ. 908 01:17:19,220 --> 01:17:21,940 Υπάρχουν τρεις περιγραφείς αρχείων που έχετε από προεπιλογή, 909 01:17:21,940 --> 01:17:24,310 που είναι στάνταρ σε, τυποποιημένα, και τυπικό σφάλμα. 910 01:17:24,310 --> 01:17:29,960 Από προεπιλογή, νομίζω ότι είναι πρότυπο είναι 0, από πρότυπο είναι 1, και τυπικό σφάλμα είναι 2. 911 01:17:29,960 --> 01:17:33,980 Έτσι, αυτό που μπορώ να θέλετε να αλλάξετε τις ρυθμίσεις του; 912 01:17:33,980 --> 01:17:37,370 Θέλω να αλλάξω τις ρυθμίσεις της κάθε φορά που χτύπησα ένα χαρακτήρα, 913 01:17:37,370 --> 01:17:41,590 Θέλω να ρίξει αυτό το χαρακτήρα μακριά αντί να τα εκτυπώνει στην οθόνη. 914 01:17:41,590 --> 01:17:45,960 Τι ρεύμα - πρότυπο, πρότυπο έξω, ή τυπικό σφάλμα - 915 01:17:45,960 --> 01:17:52,050 ανταποκρίνεται στα πράγματα, όταν πληκτρολογείτε στο πληκτρολόγιο; >> [Φοιτητής] Πρότυπο μέσα >> Ναι. 916 01:17:52,050 --> 01:17:56,450 Έτσι, μπορώ να κάνω είτε 0 ή μπορώ να κάνω stdin. 917 01:17:56,450 --> 01:17:59,380 Παίρνω το current_settings του προτύπου μέσα 918 01:17:59,380 --> 01:18:01,720 >> Τώρα θέλω να ενημερώσετε αυτές τις ρυθμίσεις, 919 01:18:01,720 --> 01:18:07,200 Έτσι, πρώτα θα αντιγράψουμε σε hacker_settings τι είναι current_settings μου. 920 01:18:07,200 --> 01:18:10,430 Και πώς structs έργο θα είναι απλά να αντιγράψετε. 921 01:18:10,430 --> 01:18:14,510 Αυτό αντιγράφει όλα τα πεδία, όπως θα περίμενε κανείς. 922 01:18:14,510 --> 01:18:17,410 >> Τώρα θέλω να ενημερώσετε μερικά από τα πεδία. 923 01:18:17,410 --> 01:18:21,670 Κοιτάζοντας termios, θα πρέπει να διαβάσετε πολλά από αυτό 924 01:18:21,670 --> 01:18:24,110 ακριβώς για να δούμε τι θα θέλετε να αναζητήσετε, 925 01:18:24,110 --> 01:18:28,210 αλλά οι σημαίες θα πάμε να θέλετε να αναζητήσετε είναι ηχώ, 926 01:18:28,210 --> 01:18:33,110 έτσι ECHO χαρακτήρες εισόδου Echo. 927 01:18:33,110 --> 01:18:37,710 Πρώτα θέλω να - έχω ήδη ξεχάσει τι είναι τα πεδία. 928 01:18:45,040 --> 01:18:47,900 Αυτό είναι ό, τι το struct μοιάζει. 929 01:18:47,900 --> 01:18:51,060 Έτσι τρόπους εισόδου νομίζω θέλουμε να αλλάξουμε. 930 01:18:51,060 --> 01:18:54,210 Θα εξετάσουμε τη λύση για να βεβαιωθείτε ότι είναι αυτό που θέλουμε να αλλάξουμε. 931 01:19:04,060 --> 01:19:12,610 Θέλουμε να αλλάξουμε lflag προκειμένου να αποτραπεί χρειάζεται να κοιτάξετε μέσα από όλα αυτά. 932 01:19:12,610 --> 01:19:14,670 Θέλουμε να αλλάξουμε τους τρόπους τοπικό. 933 01:19:14,670 --> 01:19:17,710 Θα πρέπει να διαβάσετε όλο αυτό το πράγμα που πρέπει να κατανοήσουμε, όπου τα πάντα ανήκει 934 01:19:17,710 --> 01:19:19,320 ότι θέλουμε να αλλάξουμε. 935 01:19:19,320 --> 01:19:24,120 Αλλά είναι μέσα από τις τοπικές τρόπους μεταφοράς, όπου θα πάμε να θέλουν να το αλλάξουμε αυτό. 936 01:19:27,080 --> 01:19:33,110 Έτσι hacker_settings.cc_lmode είναι ό, τι λέγεται. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 Αυτό είναι όπου θα μπει σε bitwise φορείς. 939 01:19:52,280 --> 01:19:54,860 Είμαστε είδος του από του χρόνου, αλλά θα περάσει μέσα από αυτό πραγματικά γρήγορα. 940 01:19:54,860 --> 01:19:56,600 Αυτό είναι όπου θα μπει σε bitwise φορείς, 941 01:19:56,600 --> 01:19:59,950 όπου Νομίζω ότι είπε μια φορά εδώ και πολύ καιρό ότι κάθε φορά που ξεκινάτε ασχολούνται με σημαίες, 942 01:19:59,950 --> 01:20:03,370 θα πάμε να χρησιμοποιούν bitwise χειριστή πολλά. 943 01:20:03,370 --> 01:20:08,240 Κάθε bit της σημαίας αντιστοιχεί σε κάποιο είδος της συμπεριφοράς. 944 01:20:08,240 --> 01:20:14,090 Έτσι, εδώ, αυτή η σημαία έχει ένα σωρό διαφορετικά πράγματα, όπου όλα αυτά σημαίνουν κάτι διαφορετικό. 945 01:20:14,090 --> 01:20:18,690 Αλλά αυτό που θέλω να κάνω είναι απλά να απενεργοποιήσετε το κομμάτι που αντιστοιχεί στην ECHO. 946 01:20:18,690 --> 01:20:25,440 Έτσι για να τη σειρά του ότι εκτός κάνω & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Στην πραγματικότητα, νομίζω ότι είναι σαν Techo ή κάτι τέτοιο. Είμαι ακριβώς πρόκειται να ελέγξει και πάλι. 948 01:20:30,110 --> 01:20:34,050 Μπορώ να termios. Είναι ακριβώς ECHO. 949 01:20:34,050 --> 01:20:38,440 ECHO πρόκειται να είναι ένα ενιαίο κομμάτι. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO πρόκειται να σημαίνει όλα τα bits οριστεί σε 1, το οποίο σημαίνει ότι όλες οι σημαίες που να ισχύει 951 01:20:44,230 --> 01:20:47,140 εκτός από το κομμάτι της ECHO. 952 01:20:47,140 --> 01:20:53,830 Με το που έληξε στις τοπικές σημαίες μου με αυτό, αυτό σημαίνει ότι όλα τα σημαίες που χρησιμοποιούνται σήμερα για την αλήθεια που 953 01:20:53,830 --> 01:20:56,520 θα εξακολουθεί να ρυθμιστεί σε αλήθεια. 954 01:20:56,520 --> 01:21:03,240 Εάν η σημαία της ECHO μου έχει οριστεί σε true, τότε αυτό είναι κατ 'ανάγκη οριστεί σε FALSE στη σημαία της ECHO. 955 01:21:03,240 --> 01:21:07,170 Έτσι, αυτή η γραμμή του κώδικα γίνεται ακριβώς έξω από τη σημαία της ECHO. 956 01:21:07,170 --> 01:21:16,270 Οι υπόλοιπες γραμμές κώδικα, θα αντιγράψετε μόνο τους προς το συμφέρον του χρόνου και στη συνέχεια να εξηγήσει τους. 957 01:21:27,810 --> 01:21:30,180 Στο διάλυμα, είπε 0. 958 01:21:30,180 --> 01:21:33,880 Είναι ίσως καλύτερα να πω ρητά stdin. 959 01:21:33,880 --> 01:21:42,100 >> Παρατηρήστε ότι κάνω επίσης ECHO | ICANON εδώ. 960 01:21:42,100 --> 01:21:46,650 ICANON αναφέρεται σε κάτι ξεχωριστό, κάτι που σημαίνει κανονική λειτουργία. 961 01:21:46,650 --> 01:21:50,280 Τι σημαίνει κανονική λειτουργία είναι συνήθως όταν πληκτρολογείτε τη γραμμή εντολών, 962 01:21:50,280 --> 01:21:54,670 πρότυπο δεν επεξεργάζεται τίποτα μέχρι να χτυπήσει νέα γραμμή. 963 01:21:54,670 --> 01:21:58,230 Έτσι, όταν κάνετε GetString, πληκτρολογείτε ένα σωρό πράγματα, τότε θα χτυπήσει νέα γραμμή. 964 01:21:58,230 --> 01:22:00,590 Αυτό είναι όταν έχει σταλεί με το πρότυπο μέσα 965 01:22:00,590 --> 01:22:02,680 Αυτή είναι η προεπιλεγμένη. 966 01:22:02,680 --> 01:22:05,830 Όταν απενεργοποιήσετε την κανονική λειτουργία, τώρα κάθε μεμονωμένο χαρακτήρα πατήσετε 967 01:22:05,830 --> 01:22:10,910 είναι αυτό που παίρνει επεξεργασία, η οποία είναι συνήθως το είδος των κακών γιατί είναι αργή για να επεξεργαστεί αυτά τα πράγματα, 968 01:22:10,910 --> 01:22:14,330 και γι 'αυτό είναι καλό να το buffer σε ολόκληρες σειρές. 969 01:22:14,330 --> 01:22:16,810 Αλλά θέλω κάθε χαρακτήρα για να υποβληθούν σε επεξεργασία 970 01:22:16,810 --> 01:22:18,810 δεδομένου ότι δεν θέλω να περιμένω για μένα να χτυπήσει newline 971 01:22:18,810 --> 01:22:21,280 πριν επεξεργάζεται όλους τους χαρακτήρες που έχω την πληκτρολόγηση. 972 01:22:21,280 --> 01:22:24,760 Αυτό απενεργοποιεί κανονική λειτουργία. 973 01:22:24,760 --> 01:22:31,320 Αυτό σημαίνει ότι τα πράγματα μόνο όταν πραγματικά επεξεργάζεται χαρακτήρες. 974 01:22:31,320 --> 01:22:35,830 Αυτό σημαίνει ότι η επεξεργασία τους αμέσως? Το συντομότερο είμαι πληκτρολογώντας τους, την επεξεργασία τους. 975 01:22:35,830 --> 01:22:42,510 Και αυτή είναι η λειτουργία, η οποία είναι η ενημέρωση για τις ρυθμίσεις μου σε πρότυπο, 976 01:22:42,510 --> 01:22:45,480 TCSA μέσα και να το κάνουμε τώρα. 977 01:22:45,480 --> 01:22:50,310 Οι άλλες επιλογές είναι να περιμένετε μέχρι ό, τι είναι σήμερα για το ρεύμα σε επεξεργασία. 978 01:22:50,310 --> 01:22:52,030 Αυτό δεν πειράζει πραγματικά. 979 01:22:52,030 --> 01:22:56,920 Ακριβώς αυτή τη στιγμή να αλλάξετε τις ρυθμίσεις μου να είναι ό, τι είναι σήμερα hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Υποθέτω ότι αυτό που ονομάζεται hacker_settings, οπότε ας το αλλάξουμε αυτό. 981 01:23:09,610 --> 01:23:13,500 Αλλάξτε τα πάντα για να hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Τώρα, στο τέλος του προγράμματος μας, θα πάμε να θέλουν να επιστρέψουν 983 01:23:16,870 --> 01:23:20,210 σε ό, τι είναι σήμερα μέσα από normal_settings, 984 01:23:20,210 --> 01:23:26,560 η οποία πρόκειται να δούμε ακριβώς όπως και normal_settings. 985 01:23:26,560 --> 01:23:30,650 Παρατηρήστε Δεν έχω αλλάξει καμία από normal_settings μου αφού αρχικά το πάρει. 986 01:23:30,650 --> 01:23:34,520 Στη συνέχεια, για να αλλάξετε τους ακριβώς πίσω, θα τους περάσει πίσω στο τέλος. 987 01:23:34,520 --> 01:23:38,390 Αυτή ήταν η ενημέρωση. Εντάξει. 988 01:23:38,390 --> 01:23:43,900 >> Τώρα, μέσα από εδώ θα εξηγήσω ακριβώς τον κώδικα προς το συμφέρον του χρόνου. 989 01:23:43,900 --> 01:23:46,350 Δεν είναι ότι μεγάλο μέρος του κώδικα. 990 01:23:50,770 --> 01:24:03,750 Βλέπουμε διαβάζουμε ένα χαρακτήρα από το αρχείο. Ζητήσαμε την f. 991 01:24:03,750 --> 01:24:07,850 Τώρα μπορείτε να fgetc άνθρωπος, αλλά πώς fgetc πρόκειται να λειτουργήσει 992 01:24:07,850 --> 01:24:11,910 είναι ακριβώς πρόκειται να επιστρέψει το χαρακτήρα που μόλις διαβάσατε ή ΕΟΦ, 993 01:24:11,910 --> 01:24:15,680 η οποία αντιστοιχεί στο τέλος του αρχείου ή κάποιο happening σφάλματος. 994 01:24:15,680 --> 01:24:19,900 Είμαστε looping, συνεχίζοντας να διαβάσει έναν χαρακτήρα από το αρχείο, 995 01:24:19,900 --> 01:24:22,420 έως ότου έχουμε ξεμείνει από χαρακτήρες να διαβάσετε. 996 01:24:22,420 --> 01:24:26,650 Και ενώ το κάνουμε αυτό, περιμένουμε σε ένα μόνο χαρακτήρα από το πρότυπο μέσα 997 01:24:26,650 --> 01:24:29,090 Κάθε φορά που πληκτρολογείτε κάτι στη γραμμή εντολών, 998 01:24:29,090 --> 01:24:32,820 που διαβάζει ένα χαρακτήρα από το πρότυπο μέσα 999 01:24:32,820 --> 01:24:38,330 Στη συνέχεια, putchar είναι ακριβώς πρόκειται να θέσει το char διαβάζουμε εδώ από το αρχείο έξω πρότυπο. 1000 01:24:38,330 --> 01:24:42,890 Μπορείτε να putchar άνθρωπος, αλλά αυτό είναι απλά βάζοντας το πρότυπο έξω, είναι ότι ο χαρακτήρας εκτύπωση. 1001 01:24:42,890 --> 01:24:51,600 Θα μπορούσατε επίσης να κάνετε απλά printf ("% c", γ)? Ίδια ιδέα. 1002 01:24:53,330 --> 01:24:56,670 Αυτό πρόκειται να κάνει το μεγαλύτερο μέρος της δουλειάς μας. 1003 01:24:56,670 --> 01:25:00,300 >> Το τελευταίο πράγμα που θα πάμε να θέλετε να κάνετε είναι απλά fclose αρχείο μας. 1004 01:25:00,300 --> 01:25:03,310 Αν δεν fclose, αυτό είναι μια διαρροή μνήμης. 1005 01:25:03,310 --> 01:25:06,680 Θέλουμε να fclose το αρχείο που άνοιξε αρχικά, και νομίζω ότι αυτό είναι αυτό. 1006 01:25:06,680 --> 01:25:13,810 Αν κάνουμε αυτό, πήρα ήδη προβλήματα. 1007 01:25:13,810 --> 01:25:17,260 Ας δούμε. 1008 01:25:17,260 --> 01:25:19,960 Τι να διαμαρτύρονται για? 1009 01:25:19,960 --> 01:25:30,220 Αναμενόμενη «int», αλλά είναι επιχείρημα του τύπου «struct _IO_FILE *». 1010 01:25:36,850 --> 01:25:39,370 Θα δούμε αν αυτό λειτουργεί. 1011 01:25:45,210 --> 01:25:53,540 Επιτρέπεται μόνο σε C99. Augh. Εντάξει, να hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Τώρα έχουμε πιο χρήσιμες περιγραφές. 1013 01:25:57,760 --> 01:25:59,900 Έτσι, η χρήση της αδήλωτης αναγνωριστικό »normal_settings». 1014 01:25:59,900 --> 01:26:04,170 Εγώ δεν το ονομάσουμε normal_settings. Κάλεσα το current_settings. 1015 01:26:04,170 --> 01:26:12,090 Οπότε ας αλλάξει όλα αυτά. 1016 01:26:17,920 --> 01:26:21,710 Τώρα περνάει το επιχείρημα. 1017 01:26:26,290 --> 01:26:29,500 Θα κάνω αυτό 0 για τώρα. 1018 01:26:29,500 --> 01:26:36,720 Εντάξει. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Επίσης, δεν καθαρίσετε την οθόνη από την αρχή. 1020 01:26:39,590 --> 01:26:42,960 Αλλά μπορείτε να κοιτάξετε πίσω στο τελευταίο σετ πρόβλημα για να δείτε πώς μπορείτε να καθαρίσετε την οθόνη. 1021 01:26:42,960 --> 01:26:45,160 Είναι εκτύπωση μόνο μερικά χαρακτήρες 1022 01:26:45,160 --> 01:26:47,210 ενώ αυτή κάνει ό, τι θέλω να κάνω. 1023 01:26:47,210 --> 01:26:48,900 Εντάξει. 1024 01:26:48,900 --> 01:26:55,280 Και να σκεφτόμαστε γιατί αυτό έπρεπε να είναι 0 αντί του stdin, 1025 01:26:55,280 --> 01:27:00,560 η οποία θα πρέπει να καθορίσει # 0, 1026 01:27:00,560 --> 01:27:03,890 αυτό διαμαρτύρονται ότι - 1027 01:27:13,150 --> 01:27:19,360 Πριν, όταν είπα ότι δεν υπάρχει περιγραφείς αρχείων, αλλά τότε θα πρέπει επίσης * Το αρχείο σας, 1028 01:27:19,360 --> 01:27:23,210 Περιγραφέας ένα αρχείο είναι μόνο ένα ακέραιο, 1029 01:27:23,210 --> 01:27:26,970 λαμβάνοντας υπόψη ότι ένα αρχείο * έχει ένα σωρό πράγματα που συνδέονται με αυτό. 1030 01:27:26,970 --> 01:27:30,380 Ο λόγος που πρέπει να πούμε 0 αντί του stdin 1031 01:27:30,380 --> 01:27:37,480 stdin είναι ότι είναι ένα αρχείο * που δείχνει το πράγμα που έχει αναφορά περιγραφέας αρχείου 0. 1032 01:27:37,480 --> 01:27:45,070 Έτσι, ακόμη και εδώ, όταν κάνω fopen (argv [1], παίρνω ένα αρχείο * πίσω. 1033 01:27:45,070 --> 01:27:51,180 Αλλά κάπου σε αυτό το αρχείο * είναι ένα πράγμα που αντιστοιχεί στο περιγραφέα αρχείου για το αρχείο. 1034 01:27:51,180 --> 01:27:57,430 Αν κοιτάξετε την σελίδα man για ανοικτή, έτσι νομίζω ότι θα πρέπει να κάνουμε Man 3 ανοικτό - nope - 1035 01:27:57,430 --> 01:27:59,380 2 ανοικτές άνθρωπος - ναι. 1036 01:27:59,380 --> 01:28:06,250 Αν κοιτάξετε τη σελίδα για ανοικτή, ανοικτό είναι σαν ένα χαμηλότερο επίπεδο fopen, 1037 01:28:06,250 --> 01:28:09,350 και αυτό είναι το πραγματικό επιστροφή περιγραφέα αρχείου. 1038 01:28:09,350 --> 01:28:12,050 fopen κάνει ένα σωρό πράγματα στην κορυφή των ανοικτών, 1039 01:28:12,050 --> 01:28:17,640 που αντί να επιστρέψει μόνο ότι περιγραφέα αρχείου επιστρέφει ένα σύνολο FILE * δείκτης 1040 01:28:17,640 --> 01:28:20,590 μέσα από τα οποία είναι λίγο Περιγραφέας αρχείο μας. 1041 01:28:20,590 --> 01:28:25,020 Έτσι, στο πρότυπο αναφέρεται στο αρχείο * πράγμα, 1042 01:28:25,020 --> 01:28:29,120 ενώ 0 αναφέρεται στο ακριβώς το πρότυπο περιγραφέα αρχείου από μόνη της. 1043 01:28:29,120 --> 01:28:32,160 >> Ερωτήσεις; 1044 01:28:32,160 --> 01:28:35,930 [Γέλια] ανατίναξε μέσα από αυτό. 1045 01:28:35,930 --> 01:28:39,140 Εντάξει. Εμείς τελειώσαμε. [Γέλια] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]