1 00:00:00,000 --> 00:00:02,730 [Powered by Google Translate] [סעיף 5: פחות נוח] 2 00:00:02,730 --> 00:00:05,180 [נייט Hardison, אוניברסיטת הרווארד] 3 00:00:05,180 --> 00:00:08,260 [זה CS50.] [CS50.TV] 4 00:00:08,260 --> 00:00:11,690 אז ברוך שובך, חבר 'ה. 5 00:00:11,690 --> 00:00:16,320 ברוכים באים לסעיף 5. 6 00:00:16,320 --> 00:00:20,220 בשלב זה, לאחר שהשלים חידון 0 ולאחר שראה את מה שעשית, 7 00:00:20,220 --> 00:00:25,770 אני מקווה שאתה מרגיש ממש טוב כי אני מאוד התרשמתי מהציונים בסעיף זה. 8 00:00:25,770 --> 00:00:28,050 לצופים המקוונים שלנו, היו לנו כמה שאלות 9 00:00:28,050 --> 00:00:33,680 על שתי הבעיות האחרונות על סט הבעיה - או בחידון, ולא. 10 00:00:33,680 --> 00:00:39,690 אז אנחנו הולכים לעבור עליהם ממש מהר, כך שכל אחד רואה את מה שקרה 11 00:00:39,690 --> 00:00:45,060 ואיך לעבור את הפתרון האמיתי ולא רק להצגת הפתרון עצמו. 12 00:00:45,060 --> 00:00:50,330 אנחנו הולכים לעבור על הזוג האחרון של בעיות ממש מהר, 32 ו 33. 13 00:00:50,330 --> 00:00:53,240 רק, שוב, כך שהצופים באינטרנט יכול לראות את זה. 14 00:00:53,240 --> 00:00:59,080 >> אם אתה פונה לבעיה שלך 32, שהוא בעמוד 13, 15 00:00:59,080 --> 00:01:02,730 13 מתוך 16, 32 בעיה הן על כל חילופים. 16 00:01:02,730 --> 00:01:05,010 זה היה הכל על החלפת שני מספרים שלמים. 17 00:01:05,010 --> 00:01:08,740 זה הבעיה שאנחנו הלכנו על כמה פעמים בהרצאה. 18 00:01:08,740 --> 00:01:13,590 וכאן, מה שאנחנו מבקשים ממך לעשות הוא עקבות של זיכרון מהירות. 19 00:01:13,590 --> 00:01:17,000 כדי למלא את הערכים של המשתנים כפי שהם במחסנית 20 00:01:17,000 --> 00:01:20,250 כקוד עובר דרך פונקצית עסקה זו. 21 00:01:20,250 --> 00:01:24,500 בפרט, מה שאנו מחפשים ב-- אני הולך לשים את האייפד הזה - 22 00:01:24,500 --> 00:01:29,650 בפרט, מה שאנחנו מחפשים הוא בקו הזה ממוספר 6 ממש כאן. 23 00:01:29,650 --> 00:01:36,740 וזה ממוספר 6 עבור פשוט רצף עם הבעיה הקודמת. 24 00:01:36,740 --> 00:01:41,720 מה שאנחנו רוצים לעשות הוא להציג או לתייג את מצב הזיכרון 25 00:01:41,720 --> 00:01:46,090 כפי שהוא בתקופה שבה אנו לבצע מספר קו זה 6, 26 00:01:46,090 --> 00:01:52,540 אשר הוא למעשה חזרה מפונקצית החליפין שלנו כאן. 27 00:01:52,540 --> 00:01:59,450 אם אנחנו לגלול למטה כאן, ראינו שאת הכתובות של כל דבר בזיכרון נמסרו לנו. 28 00:01:59,450 --> 00:02:02,540 זה מפתח מאוד, יהיה לנו לחזור אליו ברגע. 29 00:02:02,540 --> 00:02:09,240 ואז כאן למטה בתחתית, היה לנו תרשים זיכרון קטן שאנחנו הולכים להתייחס אליו. 30 00:02:09,240 --> 00:02:12,490 כבר עשיתי את זה על iPad שלי. 31 00:02:12,490 --> 00:02:20,720 אז אני הולך להחליף שוב ושוב בין האייפד ואת הקוד הזה רק עבור הפניה. 32 00:02:20,720 --> 00:02:26,540 >> בואו נתחיל. ראשית, בואו נתמקד בשורות הראשונות של עיקרי כאן. 33 00:02:26,540 --> 00:02:30,220 כדי להתחיל, אנחנו הולכים לאתחל x ו-y ל 1 ל 2. 34 00:02:30,220 --> 00:02:33,040 אז יש לנו שני משתנים שלמים, ששניהם הולכים להיות ממוקמים בערימה. 35 00:02:33,040 --> 00:02:36,050 אנחנו הולכים לשים את 1 ו 2 ב. 36 00:02:36,050 --> 00:02:43,150 אז אם אני מתהפך לiPad שלי, בתקווה, בואו נראים - 37 00:02:43,150 --> 00:02:48,660 שיקוף Apple TV, ושם אנחנו הולכים. אוקיי. 38 00:02:48,660 --> 00:02:51,670 אז אם אני מתהפך לiPad שלי, 39 00:02:51,670 --> 00:02:56,220 אני רוצה לאתחל x ו-y ל 1 ל 2. 40 00:02:56,220 --> 00:03:00,580 אנחנו עושים את זה בפשטות על ידי כתיבת 1 בתיבה המסומנת x 41 00:03:00,580 --> 00:03:07,730 ו2 בתיבה מסומנת y. פשוט למדי. 42 00:03:07,730 --> 00:03:11,620 אז עכשיו בואו נחזור למחשב הנייד, לראות מה קורה הלאה. 43 00:03:11,620 --> 00:03:15,810 אז השורה הבאה זה המקום שבי הדברים מקבלים מסובכים. 44 00:03:15,810 --> 00:03:28,110 אנחנו עוברים את הכתובת של x ו-y ככתובת של הפרמטרים וb לפונקצית swap. 45 00:03:28,110 --> 00:03:32,380 הכתובת של x ואת הכתובת של y הן דברים שאנחנו לא יכולים לחשב 46 00:03:32,380 --> 00:03:36,360 מבלי להתייחס לכדור אלה מצביע כאן למטה. 47 00:03:36,360 --> 00:03:39,750 ולמרבה המזל, שתי נקודתי הכדור הראשונות לספר לנו בדיוק מה התשובות. 48 00:03:39,750 --> 00:03:44,740 הכתובת של x בזיכרון היא 10, ואת הכתובת של Y בזיכרון היא 14. 49 00:03:44,740 --> 00:03:51,870 אז אלה הם הערכים שמקבלים עבר וכבב למעלה בתפקוד החליפין שלנו. 50 00:03:51,870 --> 00:04:00,760 אז שוב, חזור לתרשים שלנו, אני יכול לכתוב ב10 51 00:04:00,760 --> 00:04:07,400 ו14 בב. 52 00:04:07,400 --> 00:04:11,610 עכשיו, בשלב זה שבו אנחנו להמשיך בהחלפה. 53 00:04:11,610 --> 00:04:14,520 אז מתהפך לאחור למחשב הנייד שוב, 54 00:04:14,520 --> 00:04:21,079 אנו רואים שדרך ההחלפה עובדת היא אני dereference 1 וחנות התוצאה בtmp. 55 00:04:21,079 --> 00:04:27,650 אז מפעיל dereference אומר, "היי. פנק את התוכן משתנה ככתובת. 56 00:04:27,650 --> 00:04:33,830 עבור לכל מה שמאוחסן באותה כתובת, ולטעון אותו. " 57 00:04:33,830 --> 00:04:41,720 מה שאתה טוען מתוך משתנה הולך להיות מאוחסן במשתנת tmp שלנו. 58 00:04:41,720 --> 00:04:45,150 לדפדף אחורה לאייפד. 59 00:04:45,150 --> 00:04:51,690 אם נלך לטיפול 10, אנחנו יודעים שכתובת היא 10 x varible 60 00:04:51,690 --> 00:04:55,480 משום שנאמרנו לנו על ידי נקודת הכדור שלנו שהכתובת של x בזיכרון היא 10. 61 00:04:55,480 --> 00:05:00,180 אז אנחנו יכולים ללכת לשם, לקבל את הערך שלו, שהוא 1, כפי שאנו רואים על האייפד שלנו, 62 00:05:00,180 --> 00:05:06,300 ולטעון כי לtmp. 63 00:05:06,300 --> 00:05:08,250 שוב, זה לא את התוכן הסופי. 64 00:05:08,250 --> 00:05:14,350 אנחנו הולכים לעבור ואנחנו נגיע למצב הסופי של התכנית שלנו בסוף. 65 00:05:14,350 --> 00:05:17,210 אבל כרגע, יש לנו את הערך 1 המאוחסן בtmp. 66 00:05:17,210 --> 00:05:19,210 >> ויש שאלה מהירה לכאן. 67 00:05:19,210 --> 00:05:23,980 [אלכסנדר] האם מפעיל dereference - זה פשוט ממש הכוכב בחזית משתנים? 68 00:05:23,980 --> 00:05:27,600 >> כן. אז מפעיל dereference, כפי שאנו מדפדפים חזרה למחשב הנייד שלנו שוב, 69 00:05:27,600 --> 00:05:33,780 זה כוכב ממש בפתח. 70 00:05:33,780 --> 00:05:37,460 במובן זה, שהיא - אתה לעמת אותו עם מפעיל הכפל 71 00:05:37,460 --> 00:05:42,400 אשר דורש שני דברים; מפעיל dereference הוא מפעיל יונארית. 72 00:05:42,400 --> 00:05:46,130 מיושם רק לערך אחד בניגוד למפעיל בינארי, 73 00:05:46,130 --> 00:05:48,810 בך תחול על שני ערכים שונים. 74 00:05:48,810 --> 00:05:52,080 אז זה מה שקורה בתחום הזה. 75 00:05:52,080 --> 00:05:58,390 העמסנו את הערך 1 ואחסנתי אותו לתוך משתנה השלם הזמני שלנו. 76 00:05:58,390 --> 00:06:05,800 השורה הבאה, אנו מאחסנים את התוכן של b ל-- 77 00:06:05,800 --> 00:06:12,630 או, לייתר דיוק, אנו מאחסנים את התוכן שהוא ב מצביע אל המקום שבו הוא מצביע. 78 00:06:12,630 --> 00:06:17,690 אם תנתחו את זה מימין לשמאל, אנחנו הולכים ב dereference, 79 00:06:17,690 --> 00:06:23,580 אנחנו הולכים לטפל 14, אנחנו הולכים לתפוס את המספר השלם שהוא שם, 80 00:06:23,580 --> 00:06:26,900 ואז אנחנו הולכים לכתובת 10, 81 00:06:26,900 --> 00:06:34,240 ואנחנו הולכים לזרוק את התוצאה של dereference של b לתוך השטח. 82 00:06:34,240 --> 00:06:40,080 לדפדף אחורה לאייפד שלנו, שבו אנחנו יכולים לעשות את זה קצת יותר קונקרטי, 83 00:06:40,080 --> 00:06:44,070 זה עשוי לעזור אם אני כותב מספרים על כל הכתובות כאן. 84 00:06:44,070 --> 00:06:53,820 כך אנו יודעים כי בy, אנו נמצאים בכתובת 14, x נמצא בכתובת 10. 85 00:06:53,820 --> 00:07:00,180 כאשר אנחנו מתחילים בב, אנו dereference ב, אנחנו הולכים לתפוס את הערך 2. 86 00:07:00,180 --> 00:07:08,320 אנחנו הולכים לתפוס ערך זה משום שזהו הערך שמתגורר בכתובת 14. 87 00:07:08,320 --> 00:07:15,700 ואנחנו הולכים לשים אותו לתוך משתנים שמתגוררים בכתובת 10, 88 00:07:15,700 --> 00:07:19,160 שהוא ממש שם, מקביל לx המשתנה שלנו. 89 00:07:19,160 --> 00:07:21,810 אז אנחנו יכולים לעשות קצת דריסה כאן 90 00:07:21,810 --> 00:07:35,380 איפה אנחנו להיפטר מ1 שלנו, ובמקום זאת אנו כותבים 2. 91 00:07:35,380 --> 00:07:39,560 אז הכול טוב ויפה בעולם, למרות שיש לנו x נדרס עכשיו. 92 00:07:39,560 --> 00:07:44,890 יש לנו לאחסן הערך הישן של x במשתנת tmp שלנו. 93 00:07:44,890 --> 00:07:50,210 אז אנחנו יכולים להשלים את העסקה בשורה הבאה. 94 00:07:50,210 --> 00:07:53,030 לדפדף אחורה למחשב הנייד שלנו. 95 00:07:53,030 --> 00:07:58,150 כעת, כל שנותר הוא להוציא את התוכן שלנו משתנים השלם הזמני 96 00:07:58,150 --> 00:08:05,630 ולאחסן אותם לתוך משתנה שגר בכתובת שהוא מחזיק ב. 97 00:08:05,630 --> 00:08:10,230 אז אנחנו הולכים ליעילות ב dereference כדי לקבל גישה למשתנה 98 00:08:10,230 --> 00:08:14,340 שנמצא בכתובת שמחזיקה ב בזה, 99 00:08:14,340 --> 00:08:19,190 ואנחנו הולכים למלא את הערך שהוא מחזיק tmp לתוכו. 100 00:08:19,190 --> 00:08:23,280 לדפדף אחורה לאייפד פעם נוספת. 101 00:08:23,280 --> 00:08:31,290 אני יכול למחוק ערך זה כאן, 2, 102 00:08:31,290 --> 00:08:41,010 ובמקום שאליו יעתיק את הזכות 1 לתוכו. 103 00:08:41,010 --> 00:08:43,059 אז בשורה הבאה שמבצעת, כמובן - 104 00:08:43,059 --> 00:08:47,150 אם אנחנו מדפדפים חזרה למחשב הנייד - זה 6 נקודות, 105 00:08:47,150 --> 00:08:52,500 המהווה את הנקודה שבה אנחנו רוצים שנהיה לנו התרשים מלא לגמרי. 106 00:08:52,500 --> 00:08:58,940 אז מתהפך לאחור לאייפד עוד פעם אחת, רק כדי שתוכל לראות בתרשים הושלם, 107 00:08:58,940 --> 00:09:06,610 אתה יכול לראות שיש לנו 10 ב, 14 בב, 1 בtmp, 2 בx, ו1 בy. 108 00:09:06,610 --> 00:09:11,000 האם יש שאלות כלשהן לגבי זה? 109 00:09:11,000 --> 00:09:14,640 האם זה הגיוני יותר, אחרי שהלך לדרכו? 110 00:09:14,640 --> 00:09:24,850 הפוך פחות הגיוני? אני מקווה שלא. אוקיי. 111 00:09:24,850 --> 00:09:28,230 >> מצביעים הם נושא מאוד מסובך. 112 00:09:28,230 --> 00:09:33,420 אחד מהחבר 'ה שאנחנו עובדים איתי יש אמרה נפוצה מאוד: 113 00:09:33,420 --> 00:09:36,590 "כדי להבין מצביעים, אתה חייב להבין מצביעים ראשונים." 114 00:09:36,590 --> 00:09:40,530 אני חושב שזה נכון מאוד. זה לוקח זמן להתרגל אליו. 115 00:09:40,530 --> 00:09:45,360 ציור הרבה תמונות, הגרלה של דיאגרמות זיכרון כמו זה מאוד מועיל, 116 00:09:45,360 --> 00:09:49,480 אחרי שאתה עובר דרך דוגמה אחרי דוגמה אחרי דוגמה ו, 117 00:09:49,480 --> 00:09:54,450 זה יתחיל לעשות קצת יותר הגיוני וקצת יותר הגיוני ויותר הגיוני. 118 00:09:54,450 --> 00:10:01,560 לבסוף, יום אחד, תהיה לך את כל זה שולט לגמרי. 119 00:10:01,560 --> 00:10:13,800 כל שאלה לפני שאנחנו עוברים לבעיה הבאה? בסדר. 120 00:10:13,800 --> 00:10:18,840 אז להפוך בחזרה למחשב הנייד. 121 00:10:18,840 --> 00:10:23,300 הבעיה הבאה היא שיש לנו בעית מספר 33 בקובץ I / O. 122 00:10:23,300 --> 00:10:26,350 להתמקד על זה קצת. 123 00:10:26,350 --> 00:10:28,710 בעיה 33 - כן? 124 00:10:28,710 --> 00:10:32,110 >> [דניאל] פשוט הייתה לי שאלה מהירה. כוכב זה, או כוכבי, 125 00:10:32,110 --> 00:10:35,590 זה נקרא ביטול הפניה בעת השימוש בכוכבית. 126 00:10:35,590 --> 00:10:38,820 איך קוראים לזה בעת שימוש באמפרסנד לפני? 127 00:10:38,820 --> 00:10:43,140 >> האמפרסנד לפני הוא הכתובת של מפעיל. 128 00:10:43,140 --> 00:10:45,880 אז בואו לגלול חזרה למעלה. 129 00:10:45,880 --> 00:10:49,310 אופס. אני במצב זום אז אני לא ממש יכול גלילה. 130 00:10:49,310 --> 00:10:52,780 אם נסתכל על הקוד הזה ממש מהר ממש כאן, 131 00:10:52,780 --> 00:10:54,980 שוב, אותו דבר קורה. 132 00:10:54,980 --> 00:10:59,180 אם נסתכל על הקוד הזה כאן, בקו הזה שבו אנו עושים את הקריאה להחלפה, 133 00:10:59,180 --> 00:11:10,460 האמפרסנד פשוט אומר "לקבל את הכתובת שבחיי x משתנים." 134 00:11:10,460 --> 00:11:14,460 כאשר המהדר שלך הידור הקוד שלך, 135 00:11:14,460 --> 00:11:20,590 שיש לו ממש פיזי לסמן את המקום בזיכרון עבור כל המשתנים שלך לחיות. 136 00:11:20,590 --> 00:11:24,910 ואז מה מהדר יכול לעשות אז ברגע שהוא חבר את הכל, 137 00:11:24,910 --> 00:11:31,110 הוא יודע, "אה, אני מניח x בכתובת 10. שמתי y בכתובת 14." 138 00:11:31,110 --> 00:11:34,640 אז זה יכול למלא בערכים אלה עבורך. 139 00:11:34,640 --> 00:11:44,740 אז אתה יכול אז - זה יכול לאחר מכן להעביר את זה ובמעבר & y גם כן. 140 00:11:44,740 --> 00:11:50,730 החבר 'ה האלה מקבל את הכתובת, אבל הם גם, בעת שתעברו אותם לפונקצית swap, 141 00:11:50,730 --> 00:11:55,690 סוג מידע זה, int * זה ממש כאן, אומר למהדר, 142 00:11:55,690 --> 00:12:01,350 "טוב, אנחנו הולכים לפרשנות כתובת זו ככתובתו של משתנה שלם." 143 00:12:01,350 --> 00:12:05,900 ככתובת של int, שהוא שונה מהכתובת של משתנה אופי 144 00:12:05,900 --> 00:12:09,930 בגלל int תופס, במכונת 32-bit, תופס 4 בתים של שטח, 145 00:12:09,930 --> 00:12:13,310 בעוד שהדמות תופסת רק בית 1 של מרחב. 146 00:12:13,310 --> 00:12:17,310 לכן חשוב לדעת גם מה הוא - מה שחי, איזה סוג של ערך 147 00:12:17,310 --> 00:12:20,340 הוא גר בכתובה שעברה מייד פנימה 148 00:12:20,340 --> 00:12:22,020 או את הכתובת שיש לך עסק עם. 149 00:12:22,020 --> 00:12:29,020 באופן זה, אתה יודע כמה בתים של מידע למעשה לטעון מתוך זכרון RAM שלך. 150 00:12:29,020 --> 00:12:31,780 ואז, כן, מפעיל זה dereference, כמו ששאל, 151 00:12:31,780 --> 00:12:37,200 הולך וניגש למידע בכתובת מסוימת. 152 00:12:37,200 --> 00:12:42,820 אז זה אומר, עם משתנה זה כאן, יתייחס לתוכן של ככתובת, 153 00:12:42,820 --> 00:12:47,880 ללכת לכתובת זו, ולשלוף, לטעון לתוך המעבד, עומס להרשמה 154 00:12:47,880 --> 00:12:56,340 הערכים האמיתיים או את התוכן שגר באותה כתובת. 155 00:12:56,340 --> 00:12:59,620 עוד שאלות? אלה שאלות טובות. 156 00:12:59,620 --> 00:13:01,650 זה הרבה מינוח חדש מדי. 157 00:13:01,650 --> 00:13:09,800 זה גם סוג של פאנקי, רואה & ו* במקומות שונים. 158 00:13:09,800 --> 00:13:13,180 >> בסדר. 159 00:13:13,180 --> 00:13:18,530 אז בחזרה לבעיה 33, להגיש I / O. 160 00:13:18,530 --> 00:13:22,540 זו הייתה אחת מהבעיות האלה שאני חושב ששני דברים קרו. 161 00:13:22,540 --> 00:13:25,400 אחד, זה נושא חדש יחסית. 162 00:13:25,400 --> 00:13:30,590 היא הוצגה די מהר לפני החידון, 163 00:13:30,590 --> 00:13:33,400 ואז אני חושב שזה היה כמו סוג של אחת מבעיות המילים האלה במתמטיקה 164 00:13:33,400 --> 00:13:39,720 שם הם נותנים לך הרבה מידע, אבל למעשה אתה לא בסופו של דבר נאלץ להשתמש בטון שלו. 165 00:13:39,720 --> 00:13:44,060 החלק הראשון של בעיה זו הוא מתאר מה הוא קובץ CSV. 166 00:13:44,060 --> 00:13:50,620 עכשיו, קובץ CSV, על פי התיאור, הוא קובץ ערכים מופרד באמצעות פסיקים. 167 00:13:50,620 --> 00:13:55,300 הסיבה אלה הם בכלל מעניינים, והסיבה לך אי פעם להשתמש בם, 168 00:13:55,300 --> 00:14:00,800 הוא, כי, כמה מכם אי פעם נעשה שימוש דברים כמו אקסל? 169 00:14:00,800 --> 00:14:03,240 להבין שרובכם, כנראה, או ישתמשו בשלב כלשהו בחיים שלך. 170 00:14:03,240 --> 00:14:06,430 אתה משתמש במשהו כמו Excel. 171 00:14:06,430 --> 00:14:10,940 על מנת לקבל את הנתונים מתוך גיליון אלקטרוני של Excel או לעשות כל סוג של עיבוד עם זה, 172 00:14:10,940 --> 00:14:17,240 אם אתה רוצה לכתוב תכנית C או תכנית פייתון, תכנית Java, 173 00:14:17,240 --> 00:14:20,070 כדי להתמודד עם נתונים שמאוחסנים שם, 174 00:14:20,070 --> 00:14:23,170 אחת הדרכים הנפוצות ביותר כדי לקבל אותו הוא בקובץ CSV. 175 00:14:23,170 --> 00:14:26,850 ואתה יכול לפתוח את אקסל וכשאתה הולך "השמירה בשם" דיאלוג, 176 00:14:26,850 --> 00:14:32,840 אתה יכול לצאת קובץ CSV בפועל. 177 00:14:32,840 --> 00:14:35,890 >> שימושי לדעת איך להתמודד עם הדברים האלה. 178 00:14:35,890 --> 00:14:42,010 ככה זה עובד הוא שזה דומה ל-- אני מתכוון, זה בעצם מחקה גיליון אלקטרוני, 179 00:14:42,010 --> 00:14:47,590 שם, כפי שאנו רואים כאן, בשמאל הכי החתיכה מאוד, 180 00:14:47,590 --> 00:14:49,910 יש לנו את כל השמות האחרונים. 181 00:14:49,910 --> 00:14:54,670 אז יש לנו מלאן, אז Hardison, ולאחר מכן באודן, MacWilliam, ולאחר מכן צ'אן. 182 00:14:54,670 --> 00:14:59,470 כל השמות האחרונים. ולאחר מכן פסיק מפריד את שמות משפחה מהשמות הפרטיים. 183 00:14:59,470 --> 00:15:02,970 דוד, נייט, רוב, טומי, וZamyla. 184 00:15:02,970 --> 00:15:06,850 אני תמיד לערבב את רובי וטום. 185 00:15:06,850 --> 00:15:10,940 ואז, סוף סוף, העמודה השלישית את כתובות הדוא"ל. 186 00:15:10,940 --> 00:15:18,500 ברגע שאתה מבין את זה, שאר התכנית הוא פשוט למדי ליישום. 187 00:15:18,500 --> 00:15:23,850 מה שעשינו על מנת לחקות את אותו מבנה זה בתכנית C 188 00:15:23,850 --> 00:15:27,510 הוא שאנחנו מנצלים מבנה. 189 00:15:27,510 --> 00:15:30,520 נתחיל לשחק עם אלה קטנים יותר גם כן. 190 00:15:30,520 --> 00:15:35,790 ראינו אותם לקצת הראשון בסט הבעיה 3, כאשר אנחנו עוסקים במילונים. 191 00:15:35,790 --> 00:15:40,290 אבל struct צוות זה מאחסן את שם משפחה, שם פרטי, ודואר אלקטרוני. 192 00:15:40,290 --> 00:15:44,500 בדיוק כמו קובץ CSV אחסון. 193 00:15:44,500 --> 00:15:47,950 אז זה רק המרה מתבנית אחת לאחרת. 194 00:15:47,950 --> 00:15:54,630 יש לנו להמיר, במקרה זה, struct צוות לקו, 195 00:15:54,630 --> 00:15:59,060 קו מופרד באמצעות פסיקים, ככה סתם. 196 00:15:59,060 --> 00:16:01,500 האם זה הגיוני? אתם כל לקחתם את החידון, 197 00:16:01,500 --> 00:16:07,680 לכן אני מניח שלפחות יש לך קצת זמן לחשוב על זה. 198 00:16:07,680 --> 00:16:16,410 >> בפונקציה לשכור, הבעיה מבקשת מאתנו לקחת ב-- זום להכין מזה קצת - 199 00:16:16,410 --> 00:16:22,480 תיקח במבנה צוות, struct צוות, עם השם של, 200 00:16:22,480 --> 00:16:30,900 ולצרף את התוכן שלה לקובץ staff.csv. 201 00:16:30,900 --> 00:16:34,230 מתברר כי זו היא פשוטה למדי לשימוש. 202 00:16:34,230 --> 00:16:37,430 אנחנו סוג שלך לשחק עם הפונקציות האלה קצת יותר היום. 203 00:16:37,430 --> 00:16:44,510 אבל במקרה הזה, פונקצית fprintf היא באמת המפתח. 204 00:16:44,510 --> 00:16:51,960 אז עם fprintf, אנחנו יכולים להדפיס, בדיוק כמו שאתם כבר משתמשים כל printf מונח זה. 205 00:16:51,960 --> 00:16:55,050 אתה יכול printf קו לקובץ. 206 00:16:55,050 --> 00:16:59,030 אז במקום רק עושה שיחת printf הרגילה שבו אתה נותן לו את מחרוזת הפורמט 207 00:16:59,030 --> 00:17:05,380 ואז אתה תחליף את כל המשתנים בטיעונים הבאים, 208 00:17:05,380 --> 00:17:11,290 עם fprintf, הטיעון הראשון שלך הוא במקום קובץ שאתה רוצה לכתוב. 209 00:17:11,290 --> 00:17:21,170 אם היינו מסתכל על זה במכשיר, לדוגמה, אדם fprintf, 210 00:17:21,170 --> 00:17:25,980 אנחנו יכולים לראות את ההבדל בין printf וfprintf. 211 00:17:25,980 --> 00:17:28,960 אני להתקרב כאן קצת. 212 00:17:28,960 --> 00:17:33,140 אז עם printf, אנחנו נותנים לו מחרוזת בתבנית, ולאחר מכן את הטענות הבאות 213 00:17:33,140 --> 00:17:37,580 כל המשתנים להחלפה או להחלפה במחרוזת התבנית שלנו. 214 00:17:37,580 --> 00:17:47,310 ואילו עם fprintf, הטענה הראשונה היא אכן * הקובץ הזה שנקרא נחל. 215 00:17:47,310 --> 00:17:51,800 >> לחזור לגור כאן להשכרה שלנו, 216 00:17:51,800 --> 00:17:54,550 כבר יש לנו הזרם * הקובץ שלנו נפתח עבורנו. 217 00:17:54,550 --> 00:17:57,810 זה מה שהשורה הראשונה זה עושה, זה פותח את קובץ staff.csv, 218 00:17:57,810 --> 00:18:01,690 הוא פותח אותו במצב הוספה, וכל מה שנותר לנו לעשות הוא 219 00:18:01,690 --> 00:18:08,640 לכתוב את מבנה צוות לקובץ. 220 00:18:08,640 --> 00:18:10,870 ו, בואו נראים, אם אני רוצה להשתמש באייפד? 221 00:18:10,870 --> 00:18:17,900 אני אשתמש באייפד. יש לנו חלל - בואו נשים את זה על השולחן כדי שאוכל לכתוב קצת יותר טוב - 222 00:18:17,900 --> 00:18:33,680 לבטל את ההשכרה וזה לוקח בטיעון אחד, מבנה צוות הנקרא s. 223 00:18:33,680 --> 00:18:44,120 קבל הפלטה שלנו, יש לנו קובץ * נקרא קובץ, 224 00:18:44,120 --> 00:18:48,380 יש לנו קו fopen ניתן לנו, 225 00:18:48,380 --> 00:18:51,890 ואני רק כותב את זה כנקודות מכיוון שזה כבר בפדייה. 226 00:18:51,890 --> 00:19:00,530 ואז בשורה הבאה שלנו, אנחנו הולכים לבצע שיחה לfprintf 227 00:19:00,530 --> 00:19:03,700 ואנחנו הולכים להעביר בקובץ שאנחנו רוצים להדפיס, 228 00:19:03,700 --> 00:19:10,290 ואז המחרוזת שלנו בפורמט, אשר - 229 00:19:10,290 --> 00:19:14,300 אני אתן לכם לספר לי איך זה נראה. 230 00:19:14,300 --> 00:19:20,500 מה איתך, סטלה? האם אתה יודע מה החלק הראשון של מחרוזת התבנית נראה? 231 00:19:20,500 --> 00:19:24,270 [סטלה] אני לא בטוח. >> אל יהסס לשאול ג'ימי. 232 00:19:24,270 --> 00:19:27,690 אתה יודע, ג'ימי? 233 00:19:27,690 --> 00:19:31,000 [ג'ימי] האם זה פשוט תהיה אחרון? אני לא יודע. אני לא לגמרי בטוח. 234 00:19:31,000 --> 00:19:39,020 >> אוקיי. מה דעתך על, מישהו מקבל את זה נכון בבחינה? 235 00:19:39,020 --> 00:19:41,770 מספר בסדר. 236 00:19:41,770 --> 00:19:47,920 מתברר כי כאן כל מה שאנחנו צריכים לעשות הוא שאנחנו רוצים כל חלק של מבנה צוות שלנו 237 00:19:47,920 --> 00:19:53,290 ליודפס כמחרוזת לתוך הקובץ שלנו. 238 00:19:53,290 --> 00:19:59,900 אנחנו רק להשתמש בדמות החלפת המחרוזת שלוש פעמים שונות כי יש לנו שם משפחה 239 00:19:59,900 --> 00:20:07,160 אחרי פסיק, ולאחר מכן את השם פרטי ואחריו פסיק, 240 00:20:07,160 --> 00:20:12,430 ולבסוף כתובת הדוא"ל ואחריו - שהוא לא 241 00:20:12,430 --> 00:20:15,140 התאמה על המסך שלי - אבל זה אחרי תו שורה חדשה. 242 00:20:15,140 --> 00:20:20,060 אז אני הולך לכתוב אותו בדיוק שם למטה. 243 00:20:20,060 --> 00:20:23,560 ואז לאחר מחרוזת התבנית שלנו, 244 00:20:23,560 --> 00:20:27,880 אנחנו רק צריכים את ההחלפות, שאנו גישה באמצעות סימון הנקודה 245 00:20:27,880 --> 00:20:31,370 שראינו בסט הבעיה 3. 246 00:20:31,370 --> 00:20:48,820 אנחנו יכולים להשתמש בs.last, s.first, וs.email 247 00:20:48,820 --> 00:20:58,990 להחליף בשלושה הערכים האלה לתוך מחרוזת התבנית שלנו. 248 00:20:58,990 --> 00:21:06,190 אז איך זה הלך? הגיוני? 249 00:21:06,190 --> 00:21:09,700 כן? לא? אולי? אוקיי. 250 00:21:09,700 --> 00:21:14,180 >> הדבר האחרון שאנחנו עושים אחרי שאנחנו מודפסים ואחרי שפתחנו את התיק שלנו: 251 00:21:14,180 --> 00:21:17,370 בכל פעם שאנחנו פתחנו תיק, אנחנו תמיד צריכים לזכור לסגור אותו. 252 00:21:17,370 --> 00:21:19,430 כי אחר אנחנו בסופו של דולף הזיכרון, 253 00:21:19,430 --> 00:21:22,500 באמצעות עד מתארי קובץ. 254 00:21:22,500 --> 00:21:25,950 אז כדי לסגור אותו, שפונקציה שאנחנו משתמשים? דניאל? 255 00:21:25,950 --> 00:21:30,120 [דניאל] fclose? >> Fclose, בדיוק. 256 00:21:30,120 --> 00:21:37,520 אז את החלק האחרון של בעיה זו היה לסגור כראוי את הקובץ, באמצעות פונקצית fclose, 257 00:21:37,520 --> 00:21:40,370 שרק נראה ככה. 258 00:21:40,370 --> 00:21:43,880 לא יותר מדי מטורף. 259 00:21:43,880 --> 00:21:46,990 מגניב. 260 00:21:46,990 --> 00:21:49,520 אז זה בעיה 33 בחידון. 261 00:21:49,520 --> 00:21:52,480 יהיה לנו בהחלט יותר קובץ הקלט / פלט מתקרב. 262 00:21:52,480 --> 00:21:55,130 אנחנו נעשה קצת יותר בהרצאה היום, או בסעיף היום, 263 00:21:55,130 --> 00:22:01,710 כי זה מה שעומד להקים את חלק הארי של pset הקרוב. 264 00:22:01,710 --> 00:22:05,020 בואו לעבור מהחידון בשלב זה. כן? 265 00:22:05,020 --> 00:22:10,880 >> [שארלוט]] למה fclose (קובץ) במקום fclose (staff.csv)? 266 00:22:10,880 --> 00:22:19,100 >> אה. כי מסתבר ש-- כך השאלה, שהוא אחד גדול, 267 00:22:19,100 --> 00:22:27,800 לכן, כאשר אנו כותבים fclose, אנחנו כותבים משתנים fclose (קובץ) כוכב 268 00:22:27,800 --> 00:22:33,680 בניגוד לשם הקובץ, staff.csv? האם זה נכון? כן. 269 00:22:33,680 --> 00:22:39,570 אז בואו נסתכל. אם אני עובר בחזרה למחשב הנייד שלי, 270 00:22:39,570 --> 00:22:45,040 ובואו נסתכל על פונקצית fclose. 271 00:22:45,040 --> 00:22:51,460 אז פונקצית fclose סוגרת זרם וזה לוקח במצביע לזרם שאנחנו רוצים לסגור, 272 00:22:51,460 --> 00:22:57,010 בניגוד לשם הקובץ עצמו שאנחנו רוצים לסגור. 273 00:22:57,010 --> 00:23:01,620 וזה בגלל שמאחורי הקלעים, בעת ביצוע שיחה לfopen, 274 00:23:01,620 --> 00:23:12,020 כאשר אתה פותח את קובץ, אתם למעשה הקצאת זיכרון לאחסון מידע אודות הקובץ. 275 00:23:12,020 --> 00:23:16,380 אז יש לך מצביע קובץ המכיל מידע אודות הקובץ, 276 00:23:16,380 --> 00:23:23,080 כמו שזה פתוח, הגודל שלו, שבו אתה נמצא כעת בקובץ, 277 00:23:23,080 --> 00:23:29,100 כך שתוכל להפוך את הקריאה וכתיבה לשיחות שמקום מסוים בתוך הקובץ. 278 00:23:29,100 --> 00:23:38,060 בסוף אתה סוגר את המצביע במקום לסגור את שם הקובץ. 279 00:23:38,060 --> 00:23:48,990 >> כן? [דניאל] לכן, כדי להשתמש בהשכרה, היית אומר - איך זה לקבל קלט מהמשתמש? 280 00:23:48,990 --> 00:23:53,830 fprintf האם להתנהג כמו GetString במובן זה שהיא פשוט יחכה לקלט מהמשתמש 281 00:23:53,830 --> 00:23:57,180 ותשאל אותך לסוג זה - או לחכות לך להקליד שלושה הדברים האלה ב? 282 00:23:57,180 --> 00:24:00,480 או שאתה צריך להשתמש במשהו ליישם לשכור? 283 00:24:00,480 --> 00:24:04,100 >> כן. אז אנחנו לא - השאלה הייתה, איך אנחנו מקבלים את קלט המשתמש 284 00:24:04,100 --> 00:24:09,220 כדי ליישם לשכור? ומה יש לנו כאן הוא מתקשר מהשכרה, 285 00:24:09,220 --> 00:24:17,690 עבר בstruct צוות הזה עם כל נתונים המאוחסנים בstruct כבר. 286 00:24:17,690 --> 00:24:22,990 אז fprintf יכול פשוט לכתוב את הנתונים ישירות לקובץ. 287 00:24:22,990 --> 00:24:25,690 אין הצורך להמתין לקלט מהמשתמש. 288 00:24:25,690 --> 00:24:32,110 המשתמש כבר נתן קלט על ידי לשים את זה כמו שצריך בstruct צוות הזה. 289 00:24:32,110 --> 00:24:36,510 ודברים, כמובן, ישברו אם כל המצביעים האלה היו ריקים, 290 00:24:36,510 --> 00:24:40,370 לכן אנחנו לגלול חזרה לכאן, ואנחנו מסתכלים על struct שלנו. 291 00:24:40,370 --> 00:24:43,640 יש לנו מחרוזת האחרונה, מחרוזת הראשונה, דוא"ל מחרוזת. 292 00:24:43,640 --> 00:24:48,530 עכשיו אנחנו יודעים שכל אלה באמת, מתחת למכסת המנוע, משתנים * char. 293 00:24:48,530 --> 00:24:53,470 זה עשוי או לא עשוי להיות הצבעה על null. 294 00:24:53,470 --> 00:24:55,800 הם עשויים יצביעו לזיכרון על הערימה, 295 00:24:55,800 --> 00:24:59,650 אולי זיכרון על המחסנית. 296 00:24:59,650 --> 00:25:04,580 אנחנו לא באמת יודעים, אבל אם כל אחד מהמצביעים האלה הם אפס, או לא חוקיים, 297 00:25:04,580 --> 00:25:08,120 כי בהחלט לקרוס הפונקציה לשכור שלנו. 298 00:25:08,120 --> 00:25:11,050 זה היה משהו שהיה סוג של מעבר להיקף של הבחינה. 299 00:25:11,050 --> 00:25:16,440 אנחנו לא נצטרך לדאוג לזה. 300 00:25:16,440 --> 00:25:22,170 גדול. אוקיי. כל כך מרגש בחידון. 301 00:25:22,170 --> 00:25:25,760 >> בואו נסגור את הבחור הזה, ואנחנו הולכים להסתכל על pset 4. 302 00:25:25,760 --> 00:25:34,700 אז אם אתם מסתכלים על מפרט pset, ברגע שאתה יכול לגשת אליו, cs50.net/quizzes, 303 00:25:34,700 --> 00:25:42,730 אנחנו הולכים לעבור כמה מבעיות הסעיף היום. 304 00:25:42,730 --> 00:25:52,240 אני גלילה למטה - קטע של שאלות מתחיל בעמוד השלישי של מפרט pset. 305 00:25:52,240 --> 00:25:57,800 והחלק הראשון מבקש ממך ללכת ולצפות בהפניית הקצרה וצינורות. 306 00:25:57,800 --> 00:26:02,820 וזה היה סוג של קצר מגניב, מראה לך כמה טריקים חדשים, מגניבי שורת פקודה שאתה יכול להשתמש. 307 00:26:02,820 --> 00:26:06,050 ואז אנחנו צריכים גם לי כמה שאלות עבורך. 308 00:26:06,050 --> 00:26:10,860 זו שאלה ראשונה על זרמים, כדי שprintf כותב כברירת מחדל, 309 00:26:10,860 --> 00:26:15,920 אנחנו סוג של נגענו בקצת לפני רגע. 310 00:26:15,920 --> 00:26:22,380 זה fprintf שבדיוק דבר לוקח בזרם * קובץ כטענתה. 311 00:26:22,380 --> 00:26:26,580 fclose לוקח בזרם * קובץ, כמו גם, 312 00:26:26,580 --> 00:26:32,660 וערך ההחזרה של fopen נותן לך זרם * קובץ גם כן. 313 00:26:32,660 --> 00:26:36,060 הסיבה שלא ראתה אותם קודם לכן, כאשר יש לנו עסק עם printf 314 00:26:36,060 --> 00:26:39,450 בגלל printf יש זרם ברירת מחדל. 315 00:26:39,450 --> 00:26:41,810 וזרם ברירת המחדל שאליו הוא כותב 316 00:26:41,810 --> 00:26:45,190 תוכל לברר על בטווח הקצר. 317 00:26:45,190 --> 00:26:50,080 אז בהחלט תסתכל על זה. 318 00:26:50,080 --> 00:26:53,010 >> בסעיף של היום, אנחנו הולכים לדבר קצת על GDB, 319 00:26:53,010 --> 00:26:57,720 מאז מוכר יותר אתה עם זה, בפועל יותר אתה מקבל עם זה, 320 00:26:57,720 --> 00:27:01,390 היכולת טובה יותר אתה תהיה ממש לצוד באגים בקוד שלך. 321 00:27:01,390 --> 00:27:05,540 זה מאיץ את התהליך של ניפוי עד מאוד. 322 00:27:05,540 --> 00:27:09,230 זאת באמצעות printf, בכל פעם שאתה עושה כי יש לך להדר את הקוד שלך, 323 00:27:09,230 --> 00:27:13,000 אתה צריך להפעיל אותו שוב, לפעמים יש לך להעביר את שיחת printf מסביב, 324 00:27:13,000 --> 00:27:17,100 הערה את הקוד, זה פשוט לוקח זמן. 325 00:27:17,100 --> 00:27:20,850 המטרה שלנו היא לנסות ולשכנע אותך שעם GDB, אתה יכול למעשה 326 00:27:20,850 --> 00:27:26,810 דבר printf בכל נקודה בקוד שלך ואתה לא צריכים להדר מחדש את זה. 327 00:27:26,810 --> 00:27:35,120 אתה לא צריך להתחיל ולשמור מנחש איפה printf הבא. 328 00:27:35,120 --> 00:27:40,910 הדבר הראשון שצריך לעשות הוא להעתיק את הקו הזה ולקבל את קוד סעיף הנחה של האינטרנט. 329 00:27:40,910 --> 00:27:47,530 אני מעתיק את שורת הקוד שאומרת, "http://cdn.cs50.net wget". 330 00:27:47,530 --> 00:27:49,510 אני הולך להעתיק אותו. 331 00:27:49,510 --> 00:27:55,950 אני הולך לעבור למכשיר שלי, להקטין את התצוגה כך שתוכל לראות מה אני עושה, 332 00:27:55,950 --> 00:28:01,890 ההדבקה לשם, וכשאני מקיש Enter, פקודת wget זה ממש היא לקבל אינטרנט. 333 00:28:01,890 --> 00:28:06,210 זה הולך למשוך למטה את הקובץ הזה מהאינטרנט, 334 00:28:06,210 --> 00:28:11,790 וזה הולך לשמור אותו לספרייה הנוכחית. 335 00:28:11,790 --> 00:28:21,630 עכשיו, אם אני ברשימת הספרייה הנוכחית שלי אתה יכול לראות שיש לי קובץ section5.zip זה ממש שם. 336 00:28:21,630 --> 00:28:25,260 הדרך להתמודד עם הבחור הזה היא לפתוח את זה, 337 00:28:25,260 --> 00:28:27,650 שאתה יכול לעשות בשורת הפקודה, בדיוק כמו זה. 338 00:28:27,650 --> 00:28:31,880 Section5.zip. 339 00:28:31,880 --> 00:28:36,980 שתהיה לפתוח אותו, ליצור את התיקייה בשבילי, 340 00:28:36,980 --> 00:28:40,410 לנפח את כל התכולה, לשים אותם שם. 341 00:28:40,410 --> 00:28:47,410 אז עכשיו אני יכול ללכת לספריית סעיף 5 שלי באמצעות פקודת cd. 342 00:28:47,410 --> 00:28:58,310 נקה את המסך בעזרת ברור. אז לנקות את המסך. 343 00:28:58,310 --> 00:29:02,280 עכשיו יש לי מסוף נקי נחמד להתמודד איתו. 344 00:29:02,280 --> 00:29:06,200 >> עכשיו, אם אני ברשימה כל הקבצים שאני רואה במדריך זה, 345 00:29:06,200 --> 00:29:12,270 אתה רואה שיש לי ארבעה קבצים: buggy1, buggy2, buggy3 וbuggy4. 346 00:29:12,270 --> 00:29:16,180 יש לי גם קבצי ג המתאימים.. 347 00:29:16,180 --> 00:29:20,400 אנחנו לא הולכים להסתכל על הקבצים. ג לעת עתה. 348 00:29:20,400 --> 00:29:24,140 במקום זאת, אנחנו הולכים להשתמש בם כאשר אנו פותחים את GDB. 349 00:29:24,140 --> 00:29:28,220 שמרנו עליהם בסביבה כך שיש לנו גישה לקוד המקור הממשי כאשר אנו משתמשים GDB, 350 00:29:28,220 --> 00:29:32,740 אבל מטרתו של חלק זה של המדור היא להתעסק עם GDB 351 00:29:32,740 --> 00:29:40,370 ולראות איך אנחנו יכולים להשתמש בו כדי להבין מה השתבשנו עם כל אחת מארבע תוכניות כרכרה אלה. 352 00:29:40,370 --> 00:29:43,380 אז אנחנו פשוט הולכים סביב החדר ממש מהר, 353 00:29:43,380 --> 00:29:47,000 ואני הולך לשאול מישהו לרוץ אחת מתוכניות הכרכרה, 354 00:29:47,000 --> 00:29:54,730 ואחר כך תלכו כקבוצה דרך GDB, ונראה מה אנחנו יכולים לעשות כדי לתקן את התוכניות הללו, 355 00:29:54,730 --> 00:29:58,460 או לפחות לזהות מה השתבש בכל אחד מהם. 356 00:29:58,460 --> 00:30:04,760 בואו נתחיל כאן עם דניאל. האם אתה מפעיל buggy1? בואו לראות מה קורה. 357 00:30:04,760 --> 00:30:09,470 [דניאל] זה אומר שיש תקלת יישום. >> כן. בדיוק. 358 00:30:09,470 --> 00:30:12,460 אז אם אני מפעיל buggy1, אני מקבל את אשמת צינוק. 359 00:30:12,460 --> 00:30:16,210 בשלב זה, אני יכול ללכת ולפתוח buggy1.c, 360 00:30:16,210 --> 00:30:19,450 לנסות ולהבין מה השתבש, 361 00:30:19,450 --> 00:30:22,000 אבל אחד הדברים המעצבנים ביותר על שגיאת אשמת הצינוק הזה 362 00:30:22,000 --> 00:30:27,610 הוא שזה לא אומר לך באיזה שורה של הדברים שלמעשה התכנית השתבשה ונשברה. 363 00:30:27,610 --> 00:30:29,880 אתה סוג של צריך להסתכל על הקוד 364 00:30:29,880 --> 00:30:33,990 ולהבין באמצעות ניחוש ולבדוק או printf כדי לראות מה השתבש. 365 00:30:33,990 --> 00:30:37,840 אחד הדברים הכי המגניבים על GDB הוא שזה ממש ממש קל 366 00:30:37,840 --> 00:30:42,170 כדי להבין את הקו שבו תכנית הקריסות שלך. 367 00:30:42,170 --> 00:30:46,160 זה לגמרי שווה את זה כדי להשתמש בו, גם אם רק בשביל זה. 368 00:30:46,160 --> 00:30:56,190 אז לאתחל את GDB, אני מקליד GDB, ואז לתת לו את הנתיב אל קובץ ההפעלה שאני רוצה לרוץ. 369 00:30:56,190 --> 00:31:01,960 הנה אני מקליד gdb ./buggy1. 370 00:31:01,960 --> 00:31:06,600 על Enter. נותן לי את כל מידע על זכויות יוצרים זה, 371 00:31:06,600 --> 00:31:13,000 וכאן תוכל לראות את הקו הזה שאומר, "סמלי קריאה מהבית / / 372 00:31:13,000 --> 00:31:17,680 jharvard/section5/buggy1. " 373 00:31:17,680 --> 00:31:22,060 ואם הכל ילך כשורה, תראה אותו להדפיס את הודעה שנראית כך. 374 00:31:22,060 --> 00:31:25,500 זה יהיה לקרוא סמלים, הוא יגיד "אני קורא סמלים מקובץ ההפעלה שלך," 375 00:31:25,500 --> 00:31:29,900 ואז זה יהיה המסר הזה "עשה" כאן. 376 00:31:29,900 --> 00:31:35,410 אם אתה רואה איזו וריאציה אחרת של זה, או שאתה רואה זה לא הצליח למצוא את הסמלים 377 00:31:35,410 --> 00:31:41,460 או משהו כזה, מה שזה אומר זה שאתה פשוט לא חברת ההפעלה שלך כראוי. 378 00:31:41,460 --> 00:31:49,980 כאשר אנו עורכים תוכניות לשימוש עם GDB, אנחנו צריכים להשתמש בדגל מיוחד שגרם, 379 00:31:49,980 --> 00:31:54,540 וזה נעשה על ידי ברירת מחדל אם לקמפל את התוכניות שלך, פשוט על ידי ההקלדה להפוך 380 00:31:54,540 --> 00:31:59,320 או להפוך את המרכבה או להפוך להתאושש, אף אחד מאלה. 381 00:31:59,320 --> 00:32:07,800 אבל אם אתה קומפילציה ידנית עם קלאנג, אז אתה צריך ללכת ובכולל דגל ש- G. 382 00:32:07,800 --> 00:32:10,310 >> בשלב זה, עכשיו שיש לנו GDB הפקודה, 383 00:32:10,310 --> 00:32:12,310 זה די פשוט להפעלת התכנית. 384 00:32:12,310 --> 00:32:19,740 אנחנו יכולים להקליד ריצה, או שאנחנו יכולים פשוט להקליד r. 385 00:32:19,740 --> 00:32:22,820 רוב פקודות gdb יכולות להיות מצוינות. 386 00:32:22,820 --> 00:32:25,940 בדרך כלל רק לאחד או כמה אותיות, וזה די נחמד. 387 00:32:25,940 --> 00:32:30,980 אז סעד, אם תקליד r ועל Enter, מה קורה? 388 00:32:30,980 --> 00:32:39,390 [סעד] יש לי SIGSEGV, אשמת פילוח, ואז כל הקשקוש הזה. 389 00:32:39,390 --> 00:32:43,650 >> כן. 390 00:32:43,650 --> 00:32:47,990 כמו שאנחנו רואים על המסך כרגע, וכמו הסעד אמר, 391 00:32:47,990 --> 00:32:53,430 כאשר אנו מקלידים ריצה או r ועל Enter, אנחנו עדיין מקבלים את אותה אשמת צינוק. 392 00:32:53,430 --> 00:32:55,830 אז באמצעות GDB לא פותר את הבעיה שלנו. 393 00:32:55,830 --> 00:32:59,120 אבל זה נותן לנו קצת קשקושים, ומתברר שזה קשקוש 394 00:32:59,120 --> 00:33:03,080 בעצם אומר לנו איפה זה קורה. 395 00:33:03,080 --> 00:33:10,680 כדי לנתח קצת זה, קצת ראשון הוא הפונקציה שבה הכול משתבש. 396 00:33:10,680 --> 00:33:20,270 יש __ strcmp_sse4_2 הזה, וזה אומר לנו שזה קורה בקובץ זה 397 00:33:20,270 --> 00:33:29,450 קרא sysdeps/i386, כל זה, שוב, סוג של בלגן - אבל קו 254. 398 00:33:29,450 --> 00:33:31,670 זה קצת קשה לנתח. בדרך כלל כשאתה רואה דברים כאלה, 399 00:33:31,670 --> 00:33:38,770 זה אומר שזה שגיאה בצינוק באחת מספריות המערכת. 400 00:33:38,770 --> 00:33:43,220 אז משהו לעשות עם strcmp. אתם ראיתם strcmp לפני. 401 00:33:43,220 --> 00:33:52,730 לא משוגע מדי, אבל האם זה אומר שstrcmp שבור או שיש בעיה עם strcmp? 402 00:33:52,730 --> 00:33:57,110 מה אתה חושב, אלכסנדר? 403 00:33:57,110 --> 00:34:04,890 [אלכסנדר] האם זה - הוא 254 הקו? ו-- לא בינארי, אבל זה לא מתקרותיהם, 404 00:34:04,890 --> 00:34:10,590 ואז יש עוד שפה לכל פונקציה. האם זה 254 שבפונקציה או -? 405 00:34:10,590 --> 00:34:21,460 >> זה קו 254. זה נראה כמו ב. קובץ של זה, כך שזה קוד הרכבה של קרוב לוודאי. 406 00:34:21,460 --> 00:34:25,949 >> אבל, אני מניח שהדבר הדחוף יותר הוא, בגלל שאנחנו קבלנו אשמת צינוק, 407 00:34:25,949 --> 00:34:29,960 וזה נראה כאילו הוא בא מפונקצית strcmp, 408 00:34:29,960 --> 00:34:38,030 האם זה מרמז, אפוא, שstrcmp הוא שבור? 409 00:34:38,030 --> 00:34:42,290 זה לא אמור לפגוע, בתקווה. אז רק בגלל שיש לך תקלת פילוח 410 00:34:42,290 --> 00:34:49,480 באחד מתפקידיה של המערכת, בדרך כלל זה אומר שאתה פשוט לא קראת לזה בצורה נכונה. 411 00:34:49,480 --> 00:34:52,440 הדבר המהיר ביותר לעשות כדי להבין מה באמת קורה 412 00:34:52,440 --> 00:34:55,500 כשאתה רואה משהו מטורף כמו זה, בכל פעם שאתה רואה אשמת צינוק, 413 00:34:55,500 --> 00:34:59,800 במיוחד אם יש לך תכנית שמשתמשת ביותר מסתם ראשי, 414 00:34:59,800 --> 00:35:03,570 הוא להשתמש backtrace. 415 00:35:03,570 --> 00:35:13,080 אני לקצר backtrace באמצעות כתיבת BT, בניגוד למילת backtrace המלאה. 416 00:35:13,080 --> 00:35:16,510 אבל שרלוט, מה קורה כאשר אתה מקליד BT ולחץ על Enter? 417 00:35:16,510 --> 00:35:23,200 [שארלוט] זה מראה לי שני קווים, 0 קו וקו 1. 418 00:35:23,200 --> 00:35:26,150 >> כן. אז קו 0 וקו 1. 419 00:35:26,150 --> 00:35:34,560 אלו הן מסגרות מחסנית בפועל שהיו כרגע במשחק, כאשר התכנית שלך התרסקה. 420 00:35:34,560 --> 00:35:42,230 החל מהמסגרת העליונה, 0 המסגרת, והולך לתחתונים ביותר, שהוא 1 מסגרת. 421 00:35:42,230 --> 00:35:45,140 המסגרת העליונה ביותר שלנו היא מסגרת strcmp. 422 00:35:45,140 --> 00:35:50,080 אתה יכול לחשוב על זה כדומה לבעיה הזאת פשוט עשתה בחידון עם המצביעים, 423 00:35:50,080 --> 00:35:54,890 המקום ממנו להחליף מסגרת ערימה על גבי ערימת המסגרת ראשית, 424 00:35:54,890 --> 00:35:59,700 והיו לנו את המשתנים שההחלפה הייתה בשימוש על גבי המשתנים עיקריים שמשתמשים. 425 00:35:59,700 --> 00:36:08,440 כאן ההתרסקות שלנו קרתה בפונקציה שלנו strcmp, שנקרא על ידי הפונקציה העיקרית שלנו, 426 00:36:08,440 --> 00:36:14,370 וbacktrace הוא נותן לנו לא רק את הפונקציות שבו דברים כושלים, 427 00:36:14,370 --> 00:36:16,440 אבל זה גם אומר לנו שהכול בו התקשר מ. 428 00:36:16,440 --> 00:36:18,830 אז אם אני לגלול על קצת יותר ימינה, 429 00:36:18,830 --> 00:36:26,110 אנו יכולים לראות שכן, היינו על קו 254 של קובץ strcmp-sse4.s זה. 430 00:36:26,110 --> 00:36:32,540 אבל השיחה נעשתה בbuggy1.c, 6 בקו. 431 00:36:32,540 --> 00:36:35,960 אז זה אומר שאנחנו יכולים לעשות - הוא שאנחנו פשוט יכולים ללכת לבדוק ולראות מה קורה 432 00:36:35,960 --> 00:36:39,930 בbuggy1.c, 6 בקו. 433 00:36:39,930 --> 00:36:43,780 שוב, יש כמה דרכים לעשות זאת. אחת היא לצאת מGDB 434 00:36:43,780 --> 00:36:49,460 או שיש לך הקוד לפתוח בחלון אחר וקישור. 435 00:36:49,460 --> 00:36:54,740 זה, כשלעצמו, הוא די שימושי כי עכשיו אם אתה בשעתי עבודה 436 00:36:54,740 --> 00:36:57,220 ויש לך תקלת בידוד, וTF תוהה היכן הכל עומד להישבר 437 00:36:57,220 --> 00:36:59,710 אתה יכול פשוט לומר, "אה, קו 6. אני לא יודע מה קורה, 438 00:36:59,710 --> 00:37:03,670 אבל משהו בקו 6 גורם לתכנית שלי להישבר ". 439 00:37:03,670 --> 00:37:10,430 הדרך אחרת לעשות את זה היא שאתה יכול להשתמש בפקודה זו בשם רשימה בGDB. 440 00:37:10,430 --> 00:37:13,650 אתה יכול גם לקצר אותו באני. 441 00:37:13,650 --> 00:37:18,910 אז אם פגענו אני, מה שאנחנו מקבלים כאן? 442 00:37:18,910 --> 00:37:21,160 אנחנו מקבלים כל מיני דברים מוזרים. 443 00:37:21,160 --> 00:37:26,030 זהו קוד ההרכבה בפועל 444 00:37:26,030 --> 00:37:29,860 כי הוא בstrcmp_sse4_2. 445 00:37:29,860 --> 00:37:32,440 זה נראה סוג של פאנקי, 446 00:37:32,440 --> 00:37:36,520 והסיבה שאנחנו מקבלים זה בגלל שעכשיו, 447 00:37:36,520 --> 00:37:40,160 GDB יש לנו במסגרת 0. 448 00:37:40,160 --> 00:37:43,070 >> אז בכל פעם שאנחנו מסתכלים על משתנים, כל פעם שאנחנו מסתכלים על קוד מקור, 449 00:37:43,070 --> 00:37:50,530 אנחנו מסתכלים קוד מקור הנוגע למסגרת החבילה שאנו פנימה 450 00:37:50,530 --> 00:37:53,200 אז כדי לקבל שום דבר משמעותי, אנחנו צריכים 451 00:37:53,200 --> 00:37:57,070 לעבור למסגרת מחסנית שהגיונית יותר. 452 00:37:57,070 --> 00:38:00,180 במקרה זה, מסגרת המחסנית העיקרית תגרום מעט יותר, 453 00:38:00,180 --> 00:38:02,680 מכיוון שהיה למעשה קוד שאנחנו כתבנו. 454 00:38:02,680 --> 00:38:05,330 לא קוד strcmp. 455 00:38:05,330 --> 00:38:08,650 הדרך בה אתה יכול לנוע בין מסגרות, במקרה זה, כי יש לנו שתיים, 456 00:38:08,650 --> 00:38:10,430 יש לנו 0 ו 1, 457 00:38:10,430 --> 00:38:13,650 אתה עושה את זה עם פקודות ולמטה. 458 00:38:13,650 --> 00:38:18,480 אם אני מזיז את פריים אחד, 459 00:38:18,480 --> 00:38:21,770 עכשיו אני במסגרת המחסנית הראשית. 460 00:38:21,770 --> 00:38:24,330 אני יכול לנוע למטה כדי לחזור למקום שהייתי, 461 00:38:24,330 --> 00:38:32,830 לעלות שוב, לרדת שוב, ולעלות שוב. 462 00:38:32,830 --> 00:38:39,750 אם אי פעם תעשה את התכנית שלך בGDB, אתה מקבל התרסקות, אתה מקבל backtrace, 463 00:38:39,750 --> 00:38:42,380 ואתה רואה שזה בקובץ מסוים שאתה לא יודע מה קורה. 464 00:38:42,380 --> 00:38:45,460 אתה מנסה רשימה, הקוד לא נראה לך מוכר, 465 00:38:45,460 --> 00:38:48,150 יסתכל במסגרות שלך ולהבין איפה אתה נמצא. 466 00:38:48,150 --> 00:38:51,010 אתה כנראה במסגרת המחסנית הלא הנכונה. 467 00:38:51,010 --> 00:38:58,760 או לפחות אתה במסגרת חבילה שהוא לא אחד שאתה באמת יכול ניפוי. 468 00:38:58,760 --> 00:39:03,110 עכשיו שאנחנו במסגרת המחסנית המתאימה, אנחנו בראשיים, 469 00:39:03,110 --> 00:39:08,100 עכשיו אנחנו יכולים להשתמש בפקודת הרשימה כדי להבין מה היה הקו. 470 00:39:08,100 --> 00:39:13,590 ואתה יכול לראות את זה, זה הדפיס את זה בשבילנו ממש כאן. 471 00:39:13,590 --> 00:39:19,470 אבל אנחנו יכולים להכות את הרשימה כולה, ונותנת לנו רשימת תדפיס זה נחמד 472 00:39:19,470 --> 00:39:23,920 של קוד המקור הממשי שקורה כאן. 473 00:39:23,920 --> 00:39:26,420 >> בפרט, אנו יכולים להסתכל בקו 6. 474 00:39:26,420 --> 00:39:29,330 אנחנו יכולים לראות מה קורה כאן. 475 00:39:29,330 --> 00:39:31,250 וזה נראה כאילו אנחנו עושים את השוואת מחרוזת 476 00:39:31,250 --> 00:39:41,050 בין מייתרים "CS50 סלעים" וargv [1]. 477 00:39:41,050 --> 00:39:45,700 משהו בעניין הזה היה מתרסק. 478 00:39:45,700 --> 00:39:54,120 אז מסים, האם יש לך מחשבות על מה שאולי קרה כאן? 479 00:39:54,120 --> 00:39:59,400 [מסים] אני לא יודע למה היא מתרסקת. >> אתה לא יודע למה זה מתרסק? 480 00:39:59,400 --> 00:40:02,700 ג'ימי, כל מחשבות? 481 00:40:02,700 --> 00:40:06,240 [ג'ימי] אני לא לגמרי בטוח, אבל בפעם האחרונה שהשתמשנו במחרוזת להשוות, 482 00:40:06,240 --> 00:40:10,260 או strcmp, היו לנו כמו שלושה מקרים שונים תחתו. 483 00:40:10,260 --> 00:40:12,800 לא היה לנו ==, אני לא חושב, ממש שבשורה הראשונה. 484 00:40:12,800 --> 00:40:16,700 במקומו היה מופרד לשלוש, ואחד היה == 0, 485 00:40:16,700 --> 00:40:19,910 אחד היה <0, אני חושב, ואחד היה> 0. 486 00:40:19,910 --> 00:40:22,590 אז אולי משהו כזה? >> כן. אז יש את הבעיה 487 00:40:22,590 --> 00:40:27,200 מאנחנו עושים השוואה בצורה נכונה? 488 00:40:27,200 --> 00:40:31,660 סטלה? כל מחשבות? 489 00:40:31,660 --> 00:40:38,110 [סטלה] אני לא בטוח. >> לא בטוח. דניאל? מחשבות? אוקיי. 490 00:40:38,110 --> 00:40:44,770 מתברר מה שקורה כאן הוא כשנגמרנו התכנית 491 00:40:44,770 --> 00:40:48,370 ויש לנו אשמת הצינוק, כשנהל את התכנית בפעם הראשונה, דניאל, 492 00:40:48,370 --> 00:40:50,800 האם לתת לו את כל הארגומנטים בשורת פקודה? 493 00:40:50,800 --> 00:40:58,420 [דניאל] מס >> מס במקרה זה, מהו הערך של argv [1]? 494 00:40:58,420 --> 00:41:00,920 >> אין ערך. >> ימני. 495 00:41:00,920 --> 00:41:06,120 ובכן, אין שום ערך מחרוזת מתאימה. 496 00:41:06,120 --> 00:41:10,780 אבל יש איזה שהוא ערך. מהו הערך שמקבל מאוחסן שם? 497 00:41:10,780 --> 00:41:15,130 >> ערך זבל? >> זה או ערך אשפה או, במקרה זה, 498 00:41:15,130 --> 00:41:19,930 הסוף של מערך argv תמיד הסתיים עם אפס. 499 00:41:19,930 --> 00:41:26,050 אז מה בעצם קבל מאוחסנת שם הוא ריק. 500 00:41:26,050 --> 00:41:30,810 הדרך אחרת לפתור את זה, ולא לחשוב דרכו, 501 00:41:30,810 --> 00:41:33,420 הוא לנסות להדפיס אותו החוצה. 502 00:41:33,420 --> 00:41:35,880 זה המקום בו אני אומר שבאמצעות GDB הוא גדול, 503 00:41:35,880 --> 00:41:40,640 כי אתה יכול להדפיס את כל המשתנים, את כל הערכים שברצונך 504 00:41:40,640 --> 00:41:43,230 באמצעות פקודת p-הגנדרנית השימושית הזה. 505 00:41:43,230 --> 00:41:48,520 אז אם אני מקליד עמ 'ואז אני מקליד את הערך של משתנה או את שמו של משתנה, 506 00:41:48,520 --> 00:41:55,320 אומרים, argc, אני רואה שargc הוא 1. 507 00:41:55,320 --> 00:42:01,830 אם אני רוצה להדפיס argv [0], אני יכול לעשות זאת סתם כך. 508 00:42:01,830 --> 00:42:04,840 וכמו שראינו, argv [0] הוא תמיד את השם של התכנית שלך, 509 00:42:04,840 --> 00:42:06,910 תמיד את שמו של קובץ ההפעלה. 510 00:42:06,910 --> 00:42:09,740 כאן אתה רואה אותו יש לו את שם הנתיב המלא. 511 00:42:09,740 --> 00:42:15,920 אני יכול גם להדפיס את argv [1] ולראות מה קורה. 512 00:42:15,920 --> 00:42:20,890 >> יש לנו כאן סוג של ערך המיסטי. 513 00:42:20,890 --> 00:42:23,890 יש לנו 0x0 זה. 514 00:42:23,890 --> 00:42:27,850 זכור בתחילת הכהונה כשדברנו על מספרים הקסדצימליים? 515 00:42:27,850 --> 00:42:34,680 או שהשאלה הקטנה בסוף pset 0 על אופן מייצג 50 ב hex? 516 00:42:34,680 --> 00:42:39,410 הדרך בה אנו כותבים מספרי hex ב CS, רק כדי לא לבלבל את עצמנו 517 00:42:39,410 --> 00:42:46,080 עם מספרים עשרוניים, הוא תמיד להקדים אותם עם 0x. 518 00:42:46,080 --> 00:42:51,420 אז קידומת 0x זה תמיד רק אומרת לפרש את המספר הבא כמספר הקסדצימלי, 519 00:42:51,420 --> 00:42:57,400 לא כמחרוזת, ולא כמספר עשרוני, ולא כמספר בינארי. 520 00:42:57,400 --> 00:43:02,820 מאז המספר 5-0 הוא מספר חוקי בהקסדצימלי. 521 00:43:02,820 --> 00:43:06,240 וזה מספר עשרוני, 50. 522 00:43:06,240 --> 00:43:10,050 כך שזה רק איך אנחנו disambiguate. 523 00:43:10,050 --> 00:43:14,860 אז 0x0 אמצעי 0 הקסדצימלי, שהיא גם נקודה עשרונית 0, 0 בינאריים. 524 00:43:14,860 --> 00:43:17,030 זה רק ערך 0. 525 00:43:17,030 --> 00:43:22,630 מסתבר שזה מה שnull הוא, למעשה, לזכרו. 526 00:43:22,630 --> 00:43:25,940 ריק הוא בדיוק 0. 527 00:43:25,940 --> 00:43:37,010 כאן, אלמנט מאוחסן בargv [1] הוא ריק. 528 00:43:37,010 --> 00:43:45,220 אז אנחנו מנסים להשוות המחרוזת שלנו "CS50 הסלעים" למחרוזת ריקה. 529 00:43:45,220 --> 00:43:48,130 אז ביטול הפניה ריקה, מנסה לגשת לדברים בריק, 530 00:43:48,130 --> 00:43:55,050 אלה בדרך כלל הולכים לגרום לסוג מסוים של אשמת פילוח או דברים רעים אחרים לקרות. 531 00:43:55,050 --> 00:43:59,350 ומתברר שstrcmp לא בודק 532 00:43:59,350 --> 00:44:04,340 או אם אתה לא כבר עברת בערך זה ריק. 533 00:44:04,340 --> 00:44:06,370 במקום זאת, הוא פשוט הולכת קדימה, מנסה לעשות את שלו, 534 00:44:06,370 --> 00:44:14,640 ואם זה בחור, תקלות, זה צינוק תקלות, וזו הבעיה שלך. אתה צריך ללכת לתקן את זה. 535 00:44:14,640 --> 00:44:19,730 מהר מאוד, איך ניתן לפתור בעיה זו? שרלוט? 536 00:44:19,730 --> 00:44:23,540 [שארלוט] אתה יכול לבדוק אם שימוש. 537 00:44:23,540 --> 00:44:32,240 אז אם argv [1] הוא ריק, == 0, ואז לחזור 1, או משהו [לא מובן]. 538 00:44:32,240 --> 00:44:34,590 >> כן. אז זהו אחד דרך מצוינת לעשות את זה, כפי שאנו יכולים לבדוק, 539 00:44:34,590 --> 00:44:39,230 ערך שאנחנו עומדים לעבור לstrcmp, argv [1], הוא זה null? 540 00:44:39,230 --> 00:44:45,830 אם null זה, אז אנחנו יכולים לומר בסדר, להפיל. 541 00:44:45,830 --> 00:44:49,450 >> דרך נפוצה יותר לעשות זאת היא להשתמש בערך argc. 542 00:44:49,450 --> 00:44:52,040 אתה יכול לראות ממש כאן בתחילה ראשית, 543 00:44:52,040 --> 00:44:58,040 אנחנו השמטנו שהבדיקה הראשונה, כי בדרך כלל אנחנו עושים כאשר אנחנו משתמשים בטיעונים של שורת פקודה, 544 00:44:58,040 --> 00:45:05,240 אשר הוא לבדוק אם ערך argc שלנו הוא מה שאנחנו מצפים. 545 00:45:05,240 --> 00:45:10,290 במקרה זה, אנחנו מצפים לפחות שני טיעונים, 546 00:45:10,290 --> 00:45:13,660 השם של התכנית ועוד אחד אחר. 547 00:45:13,660 --> 00:45:17,140 מכיוון שאנחנו עומדים להשתמש בטיעון השני ממש כאן. 548 00:45:17,140 --> 00:45:21,350 כך שיש סוג מסוים של מבחן מראש, לפני שיחת strcmp 549 00:45:21,350 --> 00:45:37,390 כי בדיקות או לא argv הוא לפחות 2, היינו גם לעשות את אותו דבר. 550 00:45:37,390 --> 00:45:40,620 אנחנו יכולים לראות אם זה עובד על ידי הפעלת התכנית שוב. 551 00:45:40,620 --> 00:45:45,610 אתה תמיד יכול להפעיל מחדש את התכנית שלך בתוך GDB, שהוא ממש נחמד. 552 00:45:45,610 --> 00:45:49,310 אתה יכול לרוץ, וכשאתה עובר בטיעונים לתכנית שלך, 553 00:45:49,310 --> 00:45:53,060 שתעביר אותם בעת שיחה לרוץ, לא כאשר אתה לאתחל את GDB. 554 00:45:53,060 --> 00:45:57,120 כך תוכל לשמור על פניית התכנית שלך עם טיעונים שונים בכל פעם. 555 00:45:57,120 --> 00:46:08,080 אז לרוץ, או שוב, אני יכול להקליד r, ובואו נראים מה יקרה אם תקליד "שלום". 556 00:46:08,080 --> 00:46:11,140 תמיד ישאל אותך אם אתה רוצה להתחיל אותו מההתחלה שוב. 557 00:46:11,140 --> 00:46:17,490 בדרך כלל, אתה רוצה להתחיל אותו מההתחלה שוב. 558 00:46:17,490 --> 00:46:25,010 ובנקודה הזאת, זה מחדש את זה שוב, זה מדפיס את 559 00:46:25,010 --> 00:46:28,920 התכנית שאנחנו רצים, buggy1, בטענת שלום, 560 00:46:28,920 --> 00:46:32,720 וזה מדפיס את התקן זה, הוא אומר, "אתה מקבל D," פרצוף עצוב. 561 00:46:32,720 --> 00:46:37,610 אבל אנחנו לא אשמי צינוק. זה אומר תהליך שיצא באופן נורמלי. 562 00:46:37,610 --> 00:46:39,900 אז זה נראה די טוב. 563 00:46:39,900 --> 00:46:43,050 לא באשמה יותר צינוק, שעשינו את זה בעבר, 564 00:46:43,050 --> 00:46:48,190 כך זה נראה כמו שאכן היה באג אשמת הצינוק שאנחנו מקבלים. 565 00:46:48,190 --> 00:46:51,540 למרבה הצער, זה אומר לנו שאנחנו מקבלים ד 566 00:46:51,540 --> 00:46:54,090 >> אנחנו יכולים לחזור ולהסתכל על הקוד ולראות מה קורים שם 567 00:46:54,090 --> 00:46:57,980 כדי להבין מה היה - מדוע הוא אומר לנו שיש לנו ד 568 00:46:57,980 --> 00:47:03,690 בואו לראות, כאן היה זה printf אומר שיש לך ד ' 569 00:47:03,690 --> 00:47:08,540 אם תקלידו רשימה, כפי שאתה לשמור את רשימת הקלדה, זה שומר iterating למטה דרך התכנית שלך, 570 00:47:08,540 --> 00:47:10,940 כך יראו לך את השורות הראשונות של התכנית שלך. 571 00:47:10,940 --> 00:47:15,450 אז יראה לך את השורות הבאות, ואת הנתח הבא והנתח הבא. 572 00:47:15,450 --> 00:47:18,240 ואנסה שוב ושוב לרדת. 573 00:47:18,240 --> 00:47:21,180 ועכשיו אנחנו נתחיל את "קו המספר 16 הוא מחוץ לטווח." 574 00:47:21,180 --> 00:47:23,940 בגלל זה יש 15 קווים בלבד. 575 00:47:23,940 --> 00:47:30,310 אם להגיע לנקודה הזו ושלך תוהה, "מה עליי לעשות?" אתה יכול להשתמש בפקודת העזרה. 576 00:47:30,310 --> 00:47:34,340 השתמש בעזרה ואז לתת לו את השם של פקודה. 577 00:47:34,340 --> 00:47:36,460 ואתה רואה את GDB נותן לנו כל מיני דברים כאלו. 578 00:47:36,460 --> 00:47:43,870 זה אומר, "עם כל ויכוח, מפרט עוד עשר שורות אחרי או סביב הרישום הקודם. 579 00:47:43,870 --> 00:47:47,920 רשימה - מפרטת את העשר שורות לפני - " 580 00:47:47,920 --> 00:47:52,960 אז בואו נסו להשתמש מינוס רשימה. 581 00:47:52,960 --> 00:47:57,000 ושמפרט את 10 השורות קודמות, אתה יכול לשחק עם רשימה קצת. 582 00:47:57,000 --> 00:48:02,330 אתה יכול לעשות רשימה, רשימה -, אתה יכול אפילו לתת לי רשימת מספר, כמו רשימה 8, 583 00:48:02,330 --> 00:48:07,500 ואציין את 10 שורות סביב קו 8. 584 00:48:07,500 --> 00:48:10,290 ואתה יכול לראות מה קורה כאן הוא שיש לך פשוט אם אחר. 585 00:48:10,290 --> 00:48:13,980 אם תקליד בCS50 סלעים, זה מדפיס את "אתה מקבל א '" 586 00:48:13,980 --> 00:48:16,530 אחר זה מדפיס "אתה מקבל ד" 587 00:48:16,530 --> 00:48:23,770 עיירת באסה. בסדר. כן? 588 00:48:23,770 --> 00:48:26,730 >> [דניאל] אז כשניסיתי לעשות CS50 סלעים בלי המרכאות, 589 00:48:26,730 --> 00:48:29,290 זה אומר "אתה מקבל ד" 590 00:48:29,290 --> 00:48:32,560 אני צריך את הציטוטים כדי לקבל אותו לעבודה; מדוע זה כך? 591 00:48:32,560 --> 00:48:38,490 >> כן. מתברר שכאשר - זה עוד פרט קטן קצת כיף - 592 00:48:38,490 --> 00:48:47,900 כשאתה מפעיל את התכנית, אם אנחנו מפעילים את זה ואנחנו להקליד CS50 סלעים, 593 00:48:47,900 --> 00:48:50,800 בדיוק כמו שדניאל אומר שהוא עשה, ותקיש Enter, 594 00:48:50,800 --> 00:48:52,870 זה עדיין אומר שאנחנו מקבלים ד 595 00:48:52,870 --> 00:48:55,580 והשאלה היא, למה זה? 596 00:48:55,580 --> 00:49:02,120 ומתברר שגם המסוף וGDB לנתח אותם כשתי טענות נפרדות. 597 00:49:02,120 --> 00:49:04,800 כי כאשר יש מקום, זה משתמע כ 598 00:49:04,800 --> 00:49:08,730 הוויכוח הראשון הסתיים; הטיעון הבא הוא עומד להתחיל. 599 00:49:08,730 --> 00:49:13,260 דרך לשלב אותם לתוך שתיים, או מצטער, לטיעון אחד, 600 00:49:13,260 --> 00:49:18,510 הוא להשתמש בציטוטים. 601 00:49:18,510 --> 00:49:29,560 אז עכשיו, אם אנחנו שמים אותו במרכאות ולהפעיל אותו שוב, אנחנו מקבלים א 602 00:49:29,560 --> 00:49:38,780 אז רק כדי לסכם, ללא מרכאות, CS50 וסלעים מנותחים כשתי טענות נפרדות. 603 00:49:38,780 --> 00:49:45,320 עם ציטוטים, זה מנותח כטיעון אחד לגמרי. 604 00:49:45,320 --> 00:49:53,070 >> אנחנו יכולים לראות את זה בנקודת עצירה. 605 00:49:53,070 --> 00:49:54,920 עד כה אנו כבר מפעילים התכנית שלנו, וזה כבר פועל 606 00:49:54,920 --> 00:49:58,230 עד שאחד אותו הבחור, שגיאות או ליקויי להיטים 607 00:49:58,230 --> 00:50:05,930 או עד שהוא יצא והכל היה בסדר גמור. 608 00:50:05,930 --> 00:50:08,360 זה לא בהכרח הדבר המועיל ביותר, כי לפעמים 609 00:50:08,360 --> 00:50:11,840 יש לך שגיאה בתכנית שלך, אבל זה לא גורם לתקלות פילוח. 610 00:50:11,840 --> 00:50:16,950 זה לא גורם לתכנית שלך להפסיק או משהו כזה. 611 00:50:16,950 --> 00:50:20,730 הדרך להגיע GDB כדי להשהות את התכנית שלך בנקודה מסוימת 612 00:50:20,730 --> 00:50:23,260 הוא לקבוע נקודת עצירה. 613 00:50:23,260 --> 00:50:26,520 אתה יכול לעשות זאת על ידי קביעת נקודת עצירה בשם פונקציה 614 00:50:26,520 --> 00:50:30,770 או שאתה יכול להגדיר נקודת עצירה בקו מסוים של קוד. 615 00:50:30,770 --> 00:50:34,450 אני אוהב להגדיר נקודתי עצירה על שמות פונקציות, כי - קל לזכור, 616 00:50:34,450 --> 00:50:37,700 אם אתה באמת להיכנס ולשנות את קוד המקור שלך וקצת, 617 00:50:37,700 --> 00:50:42,020 אז נקודת העצירה שלך היא בעצם תישאר באותו המקום בתוך הקוד שלך. 618 00:50:42,020 --> 00:50:44,760 לעומת זאת, אם אתה משתמש במספרי שורות, ולשנות את מספרי השורות 619 00:50:44,760 --> 00:50:51,740 בגלל שאתה להוסיף או למחוק קצת קוד, ולאחר מכן נקודתי העצירה שלך דפוקות לחלוטין. 620 00:50:51,740 --> 00:50:58,590 אחד הדברים הנפוצים ביותר שאני עושה הוא להגדיר נקודת עצירה בפונקציה העיקרית. 621 00:50:58,590 --> 00:51:05,300 לעתים קרובות אני לאתחל את GDB, אני סוג B ראשי, על Enter, ושאקבע את נקודת עצירה 622 00:51:05,300 --> 00:51:10,630 על הפונקציה העיקרית שפשוט אומרת, "השהה את התכנית ברגע שאתה מתחיל לרוץ", 623 00:51:10,630 --> 00:51:17,960 וככה, כשאני מפעיל את התכנית שלי, למשל, CS50 סלעים כשני טיעונים 624 00:51:17,960 --> 00:51:24,830 והקש על Enter, הוא מגיע לתפקידו העיקרי והוא עוצר ממש בקו הראשון, 625 00:51:24,830 --> 00:51:30,620 ממש לפני שמעריך את תפקוד strcmp. 626 00:51:30,620 --> 00:51:34,940 >> מאז אני מושהה, עכשיו אני יכול להתחיל להתבטל ולראות מה קורה 627 00:51:34,940 --> 00:51:40,250 עם כל המשתנים השונים, כי הם עברו לתכנית שלי. 628 00:51:40,250 --> 00:51:43,670 כאן אני יכול להדפיס את argc ולראות מה קורה. 629 00:51:43,670 --> 00:51:50,030 ראה שargc הוא 3, כי יש בזה 3 ערכים שונים בו. 630 00:51:50,030 --> 00:51:54,060 יש לו את שמה של התכנית, יש לזה הנימוק הראשון והנימוק השני. 631 00:51:54,060 --> 00:52:09,330 אנחנו יכולים להדפיס את אלה מלהסתכל argv [0], argv [1], וargv [2]. 632 00:52:09,330 --> 00:52:12,030 אז עכשיו אתה יכול גם לראות מדוע שיחת strcmp זה הולך להיכשל, 633 00:52:12,030 --> 00:52:21,650 כי אתה רואה שזה לא נפרד CS50 והסלעים לשתי טענות נפרדות. 634 00:52:21,650 --> 00:52:27,250 בשלב זה, לאחר שפגעת בנקודת עצירה, אתה יכול להמשיך ולעבור דרך התכנית שלך 635 00:52:27,250 --> 00:52:32,920 שורה אחרת שורה, בניגוד לתכנית שלך מתחיל שוב. 636 00:52:32,920 --> 00:52:35,520 אז אם אתה לא רוצה להתחיל את התכנית שוב ופשוט להמשיך מכאן, 637 00:52:35,520 --> 00:52:41,970 אתה יכול להשתמש בפקודה תמשיך ותמשיך יהיה להפעיל את התכנית עד הסוף. 638 00:52:41,970 --> 00:52:45,010 בדיוק כמו שעשה כאן. 639 00:52:45,010 --> 00:52:54,880 עם זאת, אם אני מחדש את התכנית, CS50 סלעים, זה פוגע נקודת העצירה שלי שוב, 640 00:52:54,880 --> 00:52:59,670 והפעם, אם אני לא רוצה סתם ללכת כל הדרך עד סוף התכנית, 641 00:52:59,670 --> 00:53:08,040 אני יכול להשתמש בפקודה הבאה, שאני גם לקצר עם n. 642 00:53:08,040 --> 00:53:12,960 וזה יהיה צעד דרך קו התכנית על ידי קו. 643 00:53:12,960 --> 00:53:17,530 אז אתה יכול לראות איך דברים לבצע, כשינוי משתנה, כדברים להתעדכן. 644 00:53:17,530 --> 00:53:21,550 וזה די נחמד. 645 00:53:21,550 --> 00:53:26,570 הדבר המגניב האחר הוא לא חוזר על אותה הפקודה שוב ושוב ושוב, 646 00:53:26,570 --> 00:53:30,670 אם אתה רק על Enter - אז הנה אתה רואה אני לא הדפסתי משהו - 647 00:53:30,670 --> 00:53:33,780 אם אני רק Enter, היא עלולה לחזור על הפקודה הקודמת, 648 00:53:33,780 --> 00:53:36,900 או פקודת GDB הקודמת שאני פשוט מכניס פנימה 649 00:53:36,900 --> 00:53:56,000 אני יכול לשמור להכות זן והוא ימנע דריכה דרך שורת הקוד שלי בשורה. 650 00:53:56,000 --> 00:53:59,310 הייתי ממליץ לכם ללכת לבדוק את תוכניות כרכרה האחרות גם כן. 651 00:53:59,310 --> 00:54:01,330 אין לנו זמן לעבור את כולם היום בסעיף. 652 00:54:01,330 --> 00:54:05,890 קוד המקור הוא שם, כך שאתה יכול לראות סוג של מה קורה 653 00:54:05,890 --> 00:54:07,730 מאחורי הקלעים אם אתה מקבל באמת תקוע, 654 00:54:07,730 --> 00:54:11,940 אבל לכל הפחות, התאמן באתחול GDB, 655 00:54:11,940 --> 00:54:13,940 הפעלת התכנית עד שהוא נשבר עליך, 656 00:54:13,940 --> 00:54:18,260 מקבל backtrace, להבין מה פונקצית ההתרסקות הייתה ב, 657 00:54:18,260 --> 00:54:24,450 מה זה היה על קו, תוך הדפסה כמה ערכים משתנים, 658 00:54:24,450 --> 00:54:30,140 רק כדי שתקבל תחושה שלו, כי זה יהיה באמת לעזור לך בהמשך. 659 00:54:30,140 --> 00:54:36,340 בשלב זה, אנחנו הולכים לפרוש מGDB, שאתה משתמש לפרוש או רק ש. 660 00:54:36,340 --> 00:54:40,460 אם התכנית שלך היא באמצע הריצה עדיין, וזה לא יצא, 661 00:54:40,460 --> 00:54:43,510 תמיד ישאל אותך, "האם אתה בטוח שאתה באמת רוצה לפרוש?" 662 00:54:43,510 --> 00:54:48,770 אתה פשוט יכול להכות כן. 663 00:54:48,770 --> 00:54:55,250 >> עכשיו אנחנו הולכים להסתכל על הבעיה הבאה שיש לנו, שהיא התכנית לחתולים. 664 00:54:55,250 --> 00:54:59,880 אם אתם צופים בהפניית קצרה וצינורות, תראה שמשתמש טומי תכנית זו 665 00:54:59,880 --> 00:55:07,540 כי בעצם מדפיס את כל הפלט של קובץ על גבי המסך. 666 00:55:07,540 --> 00:55:12,660 אז אם אני מפעיל את החתול, זה הוא למעשה תכנית מובנית למכשיר, 667 00:55:12,660 --> 00:55:16,860 ואם יש לך מקינטוש אתה יכול לעשות את זה ב-Mac שלך יותר מדי, אם אתה פותח את המסוף. 668 00:55:16,860 --> 00:55:25,630 ואנחנו - חתול, יניח, cp.c, והקישו על Enter. 669 00:55:25,630 --> 00:55:29,640 מה זה עשה, אם אנחנו לגלול למעלה קצת ולראות איפה אנחנו רצנו קו, 670 00:55:29,640 --> 00:55:40,440 או שבו אנו רצים את פקודת החתול, זה ממש פשוט הדפיס את תוכן cp.c למסך שלנו. 671 00:55:40,440 --> 00:55:44,140 אנחנו יכולים להפעיל אותו שוב ואתה יכול לשים במספר קבצים יחד. 672 00:55:44,140 --> 00:55:49,880 אז אתה יכול לעשות cp.c חתול, ואז אנחנו גם יכולים לשרשר את קובץ cat.c, 673 00:55:49,880 --> 00:55:53,250 אשר היא התכנית שאנחנו עומדים לכתוב, 674 00:55:53,250 --> 00:55:58,140 וזה ידפיס את שני קבצי גב אל גב למסך שלנו. 675 00:55:58,140 --> 00:56:05,490 אז אם אנחנו לגלול למעלה קצת, אנו רואים שכאשר רצנו cp.c זה חתול, cat.c, 676 00:56:05,490 --> 00:56:17,110 ראשון זה הדפיס קובץ cp, ולאחר מכן בהמשכו, הוא הדפיס את קובץ cat.c כאן למטה. 677 00:56:17,110 --> 00:56:19,650 אנחנו הולכים להשתמש בזה רק כדי לקבל את רגלינו רטובות. 678 00:56:19,650 --> 00:56:25,930 שחק עם הדפסה פשוטה לטרמינל, לראות איך זה עובד. 679 00:56:25,930 --> 00:56:39,170 אם אתם פותחים עם gedit cat.c, Enter, 680 00:56:39,170 --> 00:56:43,760 אתה יכול לראות את התכנית שאנו עומדים לכתוב. 681 00:56:43,760 --> 00:56:48,980 צרפנו צלחת הדוד הנחמד הזה, ולכן אנחנו לא צריכים לבזבז זמן הקלדה את כל זה. 682 00:56:48,980 --> 00:56:52,310 גם אנחנו בודקים במספר הטיעונים עברנו פנימה 683 00:56:52,310 --> 00:56:56,910 אנחנו להדפיס הודעת שימוש נחמדה. 684 00:56:56,910 --> 00:57:00,950 >> זה מסוג הדברים ששוב, כמו שכבר דברו עליו, 685 00:57:00,950 --> 00:57:04,490 זה כמעט כמו זכרון שריר. 686 00:57:04,490 --> 00:57:07,190 רק תזכור להמשיך לעשות את אותו סוג של חומר 687 00:57:07,190 --> 00:57:11,310 ותמיד מדפיס על איזו הודעה מועילה 688 00:57:11,310 --> 00:57:17,670 כך שאנשים יודעים איך להפעיל את התכנית. 689 00:57:17,670 --> 00:57:21,630 עם חתול, זה די פשוט: הרי רק הולכים לעבור את כל הטענות השונות 690 00:57:21,630 --> 00:57:24,300 שהועברו לתכנית שלנו, ואנחנו הולכים להדפסה 691 00:57:24,300 --> 00:57:29,950 התכנים מתוכם למסך אחד בכל פעם. 692 00:57:29,950 --> 00:57:35,670 כדי להדפיס את קבצים על המסך, אנחנו הולכים לעשות משהו דומה מאוד 693 00:57:35,670 --> 00:57:38,120 למה שעשינו בסופו של החידון. 694 00:57:38,120 --> 00:57:45,350 בסופו של החידון, ששוכר תכנית, היו לנו לפתוח את קובץ, 695 00:57:45,350 --> 00:57:48,490 ואז היינו צריכים להדפיס אותו. 696 00:57:48,490 --> 00:57:54,660 במקרה זה, אנחנו הולכים לפתוח את קובץ, ואנחנו הולכים לקרוא ממנה במקום. 697 00:57:54,660 --> 00:58:00,630 ואז אנחנו הולכים להדפסה, במקום לקובץ, אנחנו הולכים להדפיס על גבי המסך. 698 00:58:00,630 --> 00:58:05,830 אז מדפיס על המסך כל מה שעשית בעבר עם printf. 699 00:58:05,830 --> 00:58:08,290 אז שלא משוגע מדי. 700 00:58:08,290 --> 00:58:12,190 אבל קריאת קובץ היא קצת מוזר. 701 00:58:12,190 --> 00:58:17,300 אנחנו נלך דרך שקצת בכל פעם. 702 00:58:17,300 --> 00:58:20,560 אם אתם חוזרים לאותו הבעיה האחרונה בחידון שלך, בעית 33, 703 00:58:20,560 --> 00:58:27,280 הקו הראשון שאנחנו הולכים לעשות כאן, פתיחת הקובץ, הוא מאוד דומה למה שעשינו שם. 704 00:58:27,280 --> 00:58:36,370 אז סטלה, מה שנראה כמו קו, כשפותחים את קובץ? 705 00:58:36,370 --> 00:58:47,510 [סטלה] * הון קובץ, קובץ - >> אוקיי. >> - שווה לfopen. >> כן. 706 00:58:47,510 --> 00:58:55,980 אשר במקרה זה הוא? זה בתגובה. 707 00:58:55,980 --> 00:59:06,930 >> זה בתגובה? argv [i] ו R? 708 00:59:06,930 --> 00:59:11,300 >> בדיוק. יפה מאוד. אז סטלה לגמרי נכונה. 709 00:59:11,300 --> 00:59:13,720 זה מה שנראה כמו הקו. 710 00:59:13,720 --> 00:59:19,670 אנחנו הולכים לקבל זרם משתנה קובץ, לאחסן אותו ב* קובץ, כך שכל הכובעים, 711 00:59:19,670 --> 00:59:25,720 קובץ, *, ושמו של משתנה זה יהיה קובץ. 712 00:59:25,720 --> 00:59:32,250 אנחנו יכולים לקרוא לזה איך שנרצה. יכולנו לקרוא לזה first_file, או file_i, כל מה שאנחנו רוצים. 713 00:59:32,250 --> 00:59:37,590 ולאחר מכן את השם של הקובץ הועבר בשורת הפקודה לתכנית זו. 714 00:59:37,590 --> 00:59:44,450 אז הוא מאוחסן בargv [i], ולאחר מכן אנחנו הולכים לפתוח קובץ זה במצב קריאה. 715 00:59:44,450 --> 00:59:48,100 עכשיו שאנחנו כבר פתחנו את הקובץ, מה הדבר שתמיד יש לנו לזכור לעשות 716 00:59:48,100 --> 00:59:52,230 בכל פעם שאנחנו פתחנו תיק? לסגור אותו. 717 00:59:52,230 --> 00:59:57,220 אז מסים, איך אנחנו לסגור תיק? 718 00:59:57,220 --> 01:00:01,020 [המסים] fclose (קובץ) >> fclose (קובץ). בדיוק. 719 01:00:01,020 --> 01:00:05,340 גדול. אוקיי. אם נסתכל על זה לעשות תגובה ממש כאן, 720 01:00:05,340 --> 01:00:11,940 הוא אומר, "פתח argv [i] ולהדפיס התוכן שלה ל stdout." 721 01:00:11,940 --> 01:00:15,460 >> מתוך סטנדרטי הוא שם מוזר. Stdout הוא פשוט הדרך שלנו לומר 722 01:00:15,460 --> 01:00:22,880 אנחנו רוצים להדפיס אותו למסוף, אנחנו רוצים להדפיס אותו אל זרם הפלט הסטנדרטי. 723 01:00:22,880 --> 01:00:26,450 אנחנו באמת יכולים להיפטר מהערה זו כאן. 724 01:00:26,450 --> 01:00:36,480 אני הולך להעתיק אותו ולהדביק אותו מכיוון שזה מה שעשינו. 725 01:00:36,480 --> 01:00:41,290 בשלב זה, עכשיו יש לנו לקרוא קצת על ידי הקובץ קצת. 726 01:00:41,290 --> 01:00:46,300 כבר דברנו על כמה דרכים של קבצי קריאה. 727 01:00:46,300 --> 01:00:51,830 אילו הם המועדפים שלך עד כה? 728 01:00:51,830 --> 01:00:57,960 איזה דרכים יש לך לראות או שאתה זוכר, לקרוא קבצים? 729 01:00:57,960 --> 01:01:04,870 [דניאל] fread? >> Fread? אז fread הוא אחד. ג'ימי, האם אתה מכיר אנשים אחרים? 730 01:01:04,870 --> 01:01:12,150 [ג'ימי] מס >> אוקיי. לא. שרלוט? אלכסנדר? עוד מישהו? אוקיי. 731 01:01:12,150 --> 01:01:20,740 אז האחרים הם fgetc, הוא אחד שאנחנו משתמשים בהרבה. 732 01:01:20,740 --> 01:01:26,410 יש גם fscanf; אתם רואים כאן דפוס? 733 01:01:26,410 --> 01:01:29,170 כולן מתחיל עם f. מה לעשות עם קובץ. 734 01:01:29,170 --> 01:01:35,260 יש fread, fgetc, fscanf. כל אלה הם מתפקידיו בקריאה. 735 01:01:35,260 --> 01:01:49,120 לכתיבה יש לנו fwrite, יש לנו fputc במקום fgetc. 736 01:01:49,120 --> 01:01:58,250 אנחנו גם fprintf לי אוהבים שראינו בחידון. 737 01:01:58,250 --> 01:02:01,680 מכיוון שמדובר בבעיה שכרוכה בקריאה מקובץ, 738 01:02:01,680 --> 01:02:04,940 אנחנו הולכים להשתמש באחד משלושת התפקידים האלה. 739 01:02:04,940 --> 01:02:10,890 אנחנו לא הולכים להשתמש בפונקציות אלו יורדות כאן. 740 01:02:10,890 --> 01:02:14,880 פונקציות אלה נמצאות כולם בספריית הקלט / פלט הסטנדרטית. 741 01:02:14,880 --> 01:02:17,510 אז אם אתה מסתכל על החלק העליון של תכנית זו, 742 01:02:17,510 --> 01:02:24,110 אתה יכול לראות שאנחנו כבר כללנו בקובץ הכותרת לספריית הקלט / פלט הסטנדרטית. 743 01:02:24,110 --> 01:02:27,120 אם ברצוננו להבין איזה מהם אנחנו רוצים להשתמש בו, 744 01:02:27,120 --> 01:02:29,690 אנחנו תמיד יכולים לפתוח את הדפים. 745 01:02:29,690 --> 01:02:34,350 אז אנחנו יכולים להקליד stdio אדם 746 01:02:34,350 --> 01:02:43,180 ולקרוא על כל קלט stdio ופונקציות פלט בג 747 01:02:43,180 --> 01:02:49,870 ואנו כבר רואים הו, נראים. זה להזכיר fgetc, זה להזכיר fputc. 748 01:02:49,870 --> 01:02:57,220 אז אתה יכול להסתעף קצת ומסתכל, אומר, fgetc 749 01:02:57,220 --> 01:03:00,060 ולהסתכל על דף האיש שלה. 750 01:03:00,060 --> 01:03:03,430 אתה יכול לראות שזה הולך יחד עם חבורה שלמה של פונקציות אחרות: 751 01:03:03,430 --> 01:03:12,640 fgetc, fgets, getc, getchar, מקבל, ungetc, והקלט של תווים ומחרוזות. 752 01:03:12,640 --> 01:03:19,180 אז ככה אנו קוראים בתווים ומחרוזות מקבצים מקלט סטנדרטי, 753 01:03:19,180 --> 01:03:21,990 שהוא למעשה ממשתמש. 754 01:03:21,990 --> 01:03:24,780 וזה איך אנחנו עושים את זה בג בפועל 755 01:03:24,780 --> 01:03:30,850 אז זה הוא לא משתמש GetString ופונקציות getchar 756 01:03:30,850 --> 01:03:36,840 שהיינו מCS50 הספרייה. 757 01:03:36,840 --> 01:03:39,710 אנחנו הולכים לעשות את הבעיה בכמה דרכים 758 01:03:39,710 --> 01:03:43,430 כך שאתה יכול לראות שתי דרכים שונות לעשות את זה. 759 01:03:43,430 --> 01:03:48,490 שניהם fread הפונקציה שדניאל ציין וfgetc דרכים טובות לעשות את זה. 760 01:03:48,490 --> 01:03:53,790 אני חושב fgetc הוא קצת יותר קל, כי יש לו רק, כפי שאתה רואה, 761 01:03:53,790 --> 01:03:59,660 טיעון אחד, * הקובץ שאנחנו מנסים לקרוא את התווים מ, 762 01:03:59,660 --> 01:04:02,740 וערך ההחזרה שלו הוא int. 763 01:04:02,740 --> 01:04:05,610 וזה קצת מבלבל, נכון? 764 01:04:05,610 --> 01:04:11,450 >> כי אנחנו מקבלים אופי, אז למה לא מחזיר את זה char? 765 01:04:11,450 --> 01:04:18,700 יש לכם רעיונות במה זה עלול לא לחזור char? 766 01:04:18,700 --> 01:04:25,510 [תשובות ילדונת, לא מובן] כן. >> אז המסים לגמרי נכונים. 767 01:04:25,510 --> 01:04:31,570 אם זה ASCII, אז מספר שלם זה יכול להיות ממופה לchar בפועל. 768 01:04:31,570 --> 01:04:33,520 יכול להיות תו ASCII, וזה נכון. 769 01:04:33,520 --> 01:04:36,220 זה בדיוק מה שקורה. 770 01:04:36,220 --> 01:04:39,190 אנחנו משתמשים int פשוט כי יש לו עוד דברים. 771 01:04:39,190 --> 01:04:44,750 זה יותר גדול מchar; char יש 8 סיביים בלבד, כי בית 1 על המכונות שלנו של 32-bit. 772 01:04:44,750 --> 01:04:48,520 ויש int שווי כל 4 הבתים של שטח. 773 01:04:48,520 --> 01:04:50,940 ומתברר שדרך fgetc עובדת, 774 01:04:50,940 --> 01:04:53,940 אם אנחנו לגלול למטה בתקציר שלנו בדף האיש הזה קצת, 775 01:04:53,940 --> 01:05:05,000 לגלול את כל הדרך למטה. מתבררים שהם משתמשים בערך המיוחד הזה שנקרא EOF. 776 01:05:05,000 --> 01:05:09,640 זה קבוע מיוחד כערך ההחזרה של פונקצית fgetc 777 01:05:09,640 --> 01:05:14,570 בכל פעם שאתה מכה את סוף הקובץ, או אם אתה מקבל הודעת שגיאה. 778 01:05:14,570 --> 01:05:18,170 ומתברר שכדי לעשות את ההשוואות האלה עם EOF כראוי, 779 01:05:18,170 --> 01:05:24,060 אתה רוצה להיות שסכום נוסף של מידע שיש לך בint 780 01:05:24,060 --> 01:05:28,420 בניגוד לשימוש במשתנת char. 781 01:05:28,420 --> 01:05:32,130 למרות יעילות fgetc הוא מקבל תו מתיק, 782 01:05:32,130 --> 01:05:38,450 אתה רוצה לזכור שהוא חוזר משהו שהוא של הסוג int אליך. 783 01:05:38,450 --> 01:05:41,360 עם זאת, זה די קל לשימוש. 784 01:05:41,360 --> 01:05:44,960 זה הולך לתת לנו אופי, ולכן כל שעלינו לעשות הוא להמשיך לשאול את הקובץ, 785 01:05:44,960 --> 01:05:48,440 "תן לי את התו הבא, תן לי את התו הבא, תן לי את התו הבא," 786 01:05:48,440 --> 01:05:51,400 עד שנגיע לסוף הקובץ. 787 01:05:51,400 --> 01:05:54,730 ושימשוך בתו אחד בכל זמן מהקובץ שלנו, 788 01:05:54,730 --> 01:05:56,250 ואז אנחנו יכולים לעשות מה שאנחנו אוהבים בו. 789 01:05:56,250 --> 01:06:00,160 אנחנו יכולים לאחסן אותו, אנחנו יכולים להוסיף אותו למחרוזת, אנחנו יכולים להדפיס אותו. 790 01:06:00,160 --> 01:06:04,630 האם משהו מכל זה. 791 01:06:04,630 --> 01:06:09,600 >> טסתי חזרה החוצה ולחזור לתכנית cat.c, 792 01:06:09,600 --> 01:06:16,170 אם אנחנו הולכים להשתמש fgetc, 793 01:06:16,170 --> 01:06:21,710 איך ייתכן שאנחנו מתקרבים השורה הבאה של קוד? 794 01:06:21,710 --> 01:06:26,020 אנחנו הולכים להשתמש - fread יעשה משהו שונה במקצת. 795 01:06:26,020 --> 01:06:32,600 והפעם, אנחנו פשוט הולכים להשתמש fgetc לקבל תו אחד בכל פעם. 796 01:06:32,600 --> 01:06:40,910 כדי לעבד את כל קובץ, מה שאולי יש לנו לעשות? 797 01:06:40,910 --> 01:06:44,030 כמה תווים יש בקובץ? 798 01:06:44,030 --> 01:06:47,390 יש הרבה. אז אתה בטח רוצה לקבל אחד 799 01:06:47,390 --> 01:06:49,860 ולאחר מכן לקבל עוד ולקבל עוד ולקבל עוד. 800 01:06:49,860 --> 01:06:53,330 איזה סוג של אלגוריתם אתה חושב שאולי אנחנו צריכים להשתמש כאן? 801 01:06:53,330 --> 01:06:55,470 איזה סוג של -? [אלכסנדר] ללולאה? >> בדיוק. 802 01:06:55,470 --> 01:06:57,500 איזה סוג של לולאה. 803 01:06:57,500 --> 01:07:03,380 ללולאה היא בעצם גדול, במקרה זה. 804 01:07:03,380 --> 01:07:08,620 וכמו שאמרתם, זה נשמע כאילו אתה רוצה לולאה על כל הקובץ, 805 01:07:08,620 --> 01:07:11,820 מקבל אופי בכל פעם. 806 01:07:11,820 --> 01:07:13,850 כל הצעה על מה שאולי ייראה כמו? 807 01:07:13,850 --> 01:07:22,090 [אלכסנדר, לא מובן] 808 01:07:22,090 --> 01:07:30,050 >> אוקיי, רק יגיד לי באנגלית מה אתה מנסה לעשות? [אלכסנדר, לא מובן] 809 01:07:30,050 --> 01:07:36,270 אז במקרה הזה, זה נשמע כאילו אנחנו רק מנסים לולאה על כל הקובץ. 810 01:07:36,270 --> 01:07:45,330 [אלכסנדר] אז אני <הגודל של int? >> הגודל של -? 811 01:07:45,330 --> 01:07:49,290 אני מניח שהגודל של הקובץ, נכון? הגודל - להכין מרק לכתוב את זה ככה. 812 01:07:49,290 --> 01:07:57,470 גודל קובץ לעת עתה, אני + +. 813 01:07:57,470 --> 01:08:04,610 אז מתברר כי הדרך בה אתה עושה זאת באמצעות fgetc, וזה חדש, 814 01:08:04,610 --> 01:08:10,460 הוא שאין דרך קלה, רק כדי לקבל את גודל קובץ 815 01:08:10,460 --> 01:08:16,979 עם סוג זה "sizeof" של בנייה שכבר ראה קודם. 816 01:08:16,979 --> 01:08:20,910 כאשר אנו משתמשים בפונקציה שfgetc, אנחנו משיקים כלשהו 817 01:08:20,910 --> 01:08:29,069 , תחביר חדש פאנקי לזה ללולאה, שבו במקום להשתמש רק דלפק בסיסי 818 01:08:29,069 --> 01:08:33,920 ללכת תו אחר תו, אנחנו הולכים להוציא תו אחד בכל פעם, 819 01:08:33,920 --> 01:08:37,120 תו אחד בכל פעם, והדרך בה אנו יודעים שאנחנו בסוף 820 01:08:37,120 --> 01:08:41,290 לא כשהתחלנו לספור את מספר מסוים של תווים, 821 01:08:41,290 --> 01:08:49,939 אבל כאשר אנו שולפים את האופי הוא שסוף מיוחד של דמות קובץ. 822 01:08:49,939 --> 01:08:58,689 אז אנחנו יכולים לעשות את זה על ידי - אני קורא פרק זה, ואנחנו הולכים לאתחל אותו 823 01:08:58,689 --> 01:09:08,050 בשיחה הראשונה שלנו כדי לקבל את התו הראשון מתוך הקובץ. 824 01:09:08,050 --> 01:09:14,979 אז את החלק הזה ממש כאן, זה הולך כדי לקבל תו מתוך הקובץ 825 01:09:14,979 --> 01:09:20,840 ולאחסן אותו לפרק משתנה. 826 01:09:20,840 --> 01:09:25,420 אנחנו הולכים להמשיך לעשות את זה עד שנגיע לסוף הקובץ, 827 01:09:25,420 --> 01:09:41,170 שאנחנו עושים על ידי בדיקה לתו שלא להיות שווה לזה אופי EOF מיוחד. 828 01:09:41,170 --> 01:09:48,750 ואז במקום לעשות CH + +, שהיה פשוט להגדיל את הערך, 829 01:09:48,750 --> 01:09:52,710 כך שאם אנו קוראים מתוך הקובץ, הון, אומר, 830 01:09:52,710 --> 01:09:56,810 ch + + היה נותן לנו ב ', ואז הייתי בא ג ד ולאחר מכן. 831 01:09:56,810 --> 01:09:59,310 זה בבירור לא מה שאנחנו רוצים. מה שאנחנו רוצים כאן 832 01:09:59,310 --> 01:10:05,830 בחלק אחרון זה שאנחנו רוצים לקבל את התו הבא מהקובץ. 833 01:10:05,830 --> 01:10:09,500 >> אז איך ייתכן שאנחנו מקבלים את התו הבא מהקובץ? 834 01:10:09,500 --> 01:10:13,470 איך אנחנו מקבלים את התו הראשון מהקובץ? 835 01:10:13,470 --> 01:10:17,200 [סטודנטים] fgetfile? >> Fgetc, או, סליחה, היית לגמרי נכון. 836 01:10:17,200 --> 01:10:20,470 שגיתי באיות זה ממש שם. אז כן. 837 01:10:20,470 --> 01:10:26,240 כאן במקום לעשות CH + +, 838 01:10:26,240 --> 01:10:29,560 אנחנו רק הולכים לקרוא fgetc (קובץ) שוב 839 01:10:29,560 --> 01:10:39,180 ולאחסן את התוצאה באותו משתנה הפרק שלנו. 840 01:10:39,180 --> 01:10:43,730 [שאלת סטודנט, לא מובן] 841 01:10:43,730 --> 01:10:52,390 >> זה המקום בו חבר 'ה * הקבצים אלה מיוחדים. 842 01:10:52,390 --> 01:10:59,070 הדרך בה הם עובדים היא שהם - בעת הפתיחה ראשונה - כשאתה עושה ששיחת fopen הראשון, 843 01:10:59,070 --> 01:11:04,260 * הקובץ ביעילות משמש כמצביע לתחילת הקובץ. 844 01:11:04,260 --> 01:11:12,830 ואז כל פעם שאתה קורא fgetc, זה עובר דמות אחת בתיק. 845 01:11:12,830 --> 01:11:23,280 אז כל פעם שאתה קורא לזה, אתה הגדלת מצביע הקובץ על ידי תו אחד. 846 01:11:23,280 --> 01:11:26,210 וכשאתה fgetc שוב, אתה מזיז אותה דמות אחרת 847 01:11:26,210 --> 01:11:28,910 ועוד דמות ודמות אחרת ואופי אחר. 848 01:11:28,910 --> 01:11:32,030 [שאלת סטודנט, לא מובן] ו>> כלומר - כן. 849 01:11:32,030 --> 01:11:34,810 זה סוג של הקסם הזה מתחת למכסת המנוע. 850 01:11:34,810 --> 01:11:37,930 אתה פשוט להגדיל כל דרך. 851 01:11:37,930 --> 01:11:46,510 בשלב זה, אתה יכול ממש לעבוד עם אופי. 852 01:11:46,510 --> 01:11:52,150 אז איך ניתן להדפיס את זה על המסך, עכשיו? 853 01:11:52,150 --> 01:11:58,340 אנחנו יכולים להשתמש באותו הדבר printf שהשתמשנו בעבר. 854 01:11:58,340 --> 01:12:00,330 כי אנחנו כבר משתמשים בכל הסמסטר. 855 01:12:00,330 --> 01:12:05,450 אנחנו יכולים לקרוא printf, 856 01:12:05,450 --> 01:12:21,300 ואנחנו יכולים לעבור עליו בתו סתם ככה. 857 01:12:21,300 --> 01:12:27,430 דרך נוספת לעשות את זה היא לא באמצעות printf והצורך לעשות מחרוזת תבנית זו, 858 01:12:27,430 --> 01:12:29,490 אנחנו יכולים גם להשתמש באחת מהפונקציות האחרות. 859 01:12:29,490 --> 01:12:40,090 אנחנו יכולים להשתמש בfputc, שמדפיס דמות על המסך, 860 01:12:40,090 --> 01:12:52,580 אלא אם אנחנו מסתכלים על fputc - תנו לי להתרחק קצת. 861 01:12:52,580 --> 01:12:56,430 אנחנו רואים מה שיפים הוא שלוקח באופי שאנו קוראים את שימוש fgetc, 862 01:12:56,430 --> 01:13:05,100 אבל אז אנחנו צריכים לתת לו זרם להדפיס ל. 863 01:13:05,100 --> 01:13:11,850 אנחנו יכולים גם להשתמש בפונקצית putchar, שלשים ישירות לפלט סטנדרטי. 864 01:13:11,850 --> 01:13:16,070 אז יש חבורה שלמה של אפשרויות שונות שאנחנו יכולים להשתמש להדפסה. 865 01:13:16,070 --> 01:13:19,580 הם כולם בספריית הקלט / פלט הסטנדרטית. 866 01:13:19,580 --> 01:13:25,150 כל פעם שאתה רוצה להדפיס - כך printf, כברירת מחדל, ידפיס לתקן המיוחד החוצה את הזרם, 867 01:13:25,150 --> 01:13:27,910 אשר stdout ש. 868 01:13:27,910 --> 01:13:41,300 אז אנחנו פשוט יכולים להתייחס אליו כסוג של ערך זה קסם, stdout כאן. 869 01:13:41,300 --> 01:13:48,410 אופס. שים פסיק בחוץ. 870 01:13:48,410 --> 01:13:52,790 >> זה הרבה מידע חדש, פאנקי בפה. 871 01:13:52,790 --> 01:13:58,600 הרבה זה מאוד האידיומטיים, במובן זה שזה קוד 872 01:13:58,600 --> 01:14:05,700 שנכתב בדרך זו רק משום שהיא נקיה לקריאה, קל לקריאה. 873 01:14:05,700 --> 01:14:11,520 ישנן דרכים רבות ושונות כדי לעשות את זה, הרבה פונקציות שונות בן ניתן להשתמש, 874 01:14:11,520 --> 01:14:14,680 אבל אנחנו נוטים פשוט בצעו את אותם הדפוסים הללו שוב ושוב. 875 01:14:14,680 --> 01:14:20,180 אז אל תתפלא אם אתה רואה קוד כזה עולה שוב ושוב. 876 01:14:20,180 --> 01:14:25,690 בסדר. בשלב זה, אנו זקוקים להפסקה ליום. 877 01:14:25,690 --> 01:14:31,300 תודה שבאתם. תודה שצפה, אם אתה במצב מקוון. ונתראה בשבוע הבא. 878 01:14:31,300 --> 01:14:33,890 [CS50.TV]