[Powered by Google Translate] [סעיף 6] [יותר נוח]
[רוב אודן] [אוניברסיטת הרווארד]
[זה CS50.] [CS50.TV]
>> אנחנו יכולים ראש לקטע של שאלות שלנו.
אני שלחתי את כתובת האתר למקום קודם לכן.
תחילת הקטע של השאלות אומרות-
כנראה אני לא לגמרי unsick-הוא שאלה מאוד קלה
ולא רק את מה שvalgrind?
מה valgrind עושה?
כל מי שרוצה להגיד מה valgrind עושה?
[סטודנטים] צקי זכרון הדלפות.
כן, valgrind הוא בודק זיכרון כללי.
זה, בסופו של דבר, אומר לך אם יש לך דליפות זיכרון,
וזה בעיקר מה שאנחנו משתמשים בו לכי אם אתה רוצה
טוב תעשה בקבוצת הבעיה או אם אתה רוצה
לעלות על הלוח הגדול, אתה צריך אין לי דליפות זיכרון שהיא,
ובמקרה שיש לך דליפת זיכרון שאתה לא יכול למצוא,
גם לזכור כי בכל פעם שאתה פותח קובץ
ואם אתה לא סוגר אותו, זה דליפת זיכרון.
>> הרבה אנשים מחפשים צומת מסוימת שהם לא משחררים
כאשר באמת, הם לא סגרו את המילון בצעד הראשון.
זה גם אומר לך אם יש לך לא חוקי קורא או כותב,
מה שאומר שאם אתה מנסה להגדיר ערך
זה מעבר לתום הגל וזה לא קורה לאשמת seg
אבל valgrind תופס אותו, כמו שאתה לא צריך להיות ממש כותב שם,
ואז אתה בהחלט לא צריך את כל אלה גם.
כיצד אתם משתמשים valgrind?
>> זו שאלה כללית של
סוג של להריץ אותו ולהסתכל על הפלט.
הפלט מציף הרבה פעמים.
יש גם שגיאות כיף שבו אם יש לך משהו מאוד לא בסדר
קורה בלולאה, ואז זה יהיה הסוף של דבר אומר, "הרבה יותר מדי טעויות.
אני הולך להפסיק לספור עכשיו. "
זה בעצם פלט טקסטואלי שיש לך לנתח.
בסוף, זה יגיד לך כל דליפות זיכרון שיש לך,
כמה רחובות משם, מה שיכול להיות שימושי כי
אם זה unfreed בלוק אחד, אז זה בדרך כלל קל יותר למצוא
מ -1,000 קוביות unfreed.
1000 לוקים unfreed כנראה אומרים שאתה לא משחרר
הרשימות המקושרות שלך כראוי או משהו.
זה valgrind.
>> עכשיו יש לנו הקטע מהשאלות שלנו,
שאתה לא צריך להוריד.
אתה יכול ללחוץ על השם שלי ומושך אותם בחלל.
כעת לחץ עליי.
גרסה 1 תהיה ערימה, שאנחנו עושים ראשונים.
הגרסה 2 תהיה התור, והגרסה 3 תהיה הרשימה המקושרת ביחידים.
להתחיל עם המחסנית שלנו.
כמו שנאמר כאן, מחסנית היא אחד הבסיסי ביותר,
מבני נתונים בסיסיים של מדעי מחשב.
הדוגמא הטיפוסית היא מאוד
את ערימת המגשים בחדר האוכל.
זה בעצם כל פעם שהם מונהגים על ערימה,
מישהו הולך לומר, "אה, כמו ערימה של מגשים."
אתה מחסנית את המגשים.
ואז כשאתה הולך למשוך את מגש,
המגש הראשון המקבל משך הוא האחרון שהונח על הערימה.
המחסנית גם כמו שהוא אומר, כאן
יש לנו את הקטע של זיכרון נקרא המחסנית.
ולמה זה נקרא המחסנית?
>> כי כמו מבנה נתוני מחסנית,
הוא דוחף וקופץ מסגרות מחסנית במחסנית,
בי מסגרות מחסנית הן כמו שיחה ספציפית של תפקוד.
וכמו ערימה, אתה תמיד צריך לחזור
מקריאה לפונקציה לפני שתוכל לרדת לתוך מסגרות מחסנית נמוכות שוב.
אתה לא יכול להיות בר מרכזי שיחת foo שיחה ולחזור לבר ישירות ראשי.
זה תמיד יש לעקוב אחרי הערימה הנכונה דוחפת ומכניסה.
שתי הפעולות, כמו שאמרתי, הן דחיפה ופופ.
אלה מושגים אוניברסליים.
אתה צריך לדעת לדחוף ופופ במונחים של ערימות לא משנים מה.
נצטרך לראות תורים הם קצת שונה.
זה לא ממש יש מושג בינלאומי, אבל הדחיפה ופופ הם אוניברסליות לערימות.
דחיפה פשוט לשים בערימה.
פופ הוא לקחת את הערימה.
ואנחנו רואים כאן שיש לנו מחסנית struct typedef שלנו,
לכן יש לנו מחרוזות char **.
אל תיבהל על ידי כל. **
זה הולך להיות בסופו מערך של מחרוזות
או מערך של מצביעים לתווים, שבי
מצביעים לדמויות נוטים להיות מחרוזות.
זה לא חייב להיות מחרוזות, אבל הנה, הם הולכים עליו מגבלות.
>> יש לנו מערך של מחרוזות.
יש לנו גודל, המייצג כמה אלמנטים כרגע על הערימה,
ולאחר מכן יש לנו את היכולת, שהוא כמה אלמנטים יכול להיות במחסנית.
הקיבולת צריכה להתחיל כמשהו גדול מ 1,
אבל את הגודל עומד להתחיל את דרכו כ0.
עכשיו, יש בעצם שלוש דרכים שונות אתה יכול לחשוב עליו מחסנית.
ובכן, יש כנראה יותר, אבל שתי הדרכים העיקריות הן
אתה יכול ליישם אותו באמצעות מערך, או שאתה יכול ליישם אותו באמצעות רשימה מקושרת.
רשימות מקושרות הן סוג של מה בכך כדי להפוך את ערימות מ.
זה מאוד קל לעשות את מחסנית תוך שימוש ברשימות מקושרות,
אז הנה, אנחנו הולכים להפוך את ערימה באמצעות מערכים,
ולאחר מכן שימוש במערכים, יש גם שתי דרכים שאתה יכול לחשוב על זה.
קודם, כשאמרתי שיש לנו יכולת לערימה,
כדי שנוכל להתאים את רכיב במחסנית.
>> הדרך אחת היא שזה יכול לקרות ברגע שאתה מכה 10 אלמנטים, אז תסיים.
אתה אולי יודע שיש גבול עליון של 10 דברים בעולם
שלעולם לא יצטרכו יותר מ 10 דברים על הערימה שלך,
בכל מקרה אתה יכול להיות חסם עליון על גודל הערימה שלך.
או שאתה יכול להיות יש לך ערימה בלתי מוגבלת,
אבל אם אתה עושה מערך, זה אומר שכל פעם שאתה מכה 10 אלמנטים,
ואז אתה הולך לצריך לגדול ל 20 אלמנטים, וכאשר אתה מכה 20 אלמנטים,
אתה הולך צריך לגדול מערכך עד 30 או 40 אלמנטי אלמנטים.
אתה הולך צריך להגדיל את הקיבולת, וזה מה שאנחנו הולכים לעשות כאן.
בכל פעם שאנחנו מגיעים לגודל המרבי של המחסנית שלנו,
כאשר אנחנו דוחפים משהו אחר, אנחנו הולכים לצורך להגדיל את הקיבולת.
הנה, יש לנו דחיפה הכריז כדחיפת bool (char * str).
* char str הוא המחרוזת שאנחנו דוחפים על המחסנית,
וbool פשוט אומר אם הצלחנו או נכשלנו.
>> איך אפשר להיכשל?
מה הן הנסיבות היחידות שאתה יכול לחשוב על
שבו היינו צריך לחזור שווא?
כן.
[סטודנטים] אם זה מלא ואנחנו משתמשים ביישום מתוחם.
כן, אז איך אנחנו מגדירים-ענינו
אם הוא יהיה מלא ואנחנו משתמשים ביישום מוגבל.
אז אנחנו בהחלט נחזור שווא.
ברגע שפגענו 10 דברים במערך, אנחנו לא יכולים להתאים 11, ואנחנו חוזרים שווא.
מה אם זה בלתי מוגבל? כן.
אם אתה לא יכול להרחיב את המערך מסיבה כלשהי.
כן, אז זיכרון הוא משאב מוגבל,
וסופו של דבר, אם אנו שומרים על דברים שדוחפים על המחסנית שוב ושוב,
אנחנו הולכים לנסות ולהקצות מערך גדול יותר שיתאימו
הקיבולת הגדולה יותר, וmalloc או מה שאנו משתמשים הולכים לחזור שווא.
ובכן, malloc תחזיר null.
>> זכור, בכל פעם שהתקשרת פעם malloc, אתה צריך להיות בדיקה כדי לראות אם הוא
חוזרים ריק או אחר שנמצא תקינות ניכוי.
מכיוון שאנחנו רוצים שנהיה לי ערימה חסרת גבולות,
המקרה היחיד שאנחנו הולכים נחזור שווא הוא אם ננסה
להגדיל את הקיבולת וmalloc או מה שמחזיר שקר.
אז פופ לוקח בלי ויכוחים,
וזה מחזיר את המחרוזת שנמצאה בראש הערימה.
מה לאחרונה נדחף על המחסנית היא מה אבא חוזר,
וזה גם מסיר אותו מהערימה.
ושים לב שהיא מחזירה null אם אין שום דבר בערימה.
תמיד אפשר שהמחסנית ריקה.
ב-Java, אם אתה כבר רגיל לזה, או בשפות אחרות,
מנסה לקפוץ ממחסנית ריקה עלול לגרום לחריגה או משהו.
>> אבל ב-C, null הוא סוג של הרבה מהמקרים כיצד אנו מטפלים בבעיות אלה.
חוזר null הוא איך אנחנו הולכים כדי לסמן שהמחסנית הייתה ריקה.
אנו מספקים קוד שיהיה מבחן הפונקציונלי של הערימה שלך,
ליישם לדחוף ופופ.
זה לא יהיה הרבה קוד.
כך יקר, למעשה, לפני שאנחנו עושים את זה, רמז, רמז,
אם לא ראה את זה, malloc אינו הפונקציה רק
שמקצה זיכרון על הערימה בשבילך.
יש משפחה של פונקציות alloc.
הראשון הוא malloc, שאתה רגיל.
אז יש calloc, שעושה את אותו דבר כמו malloc,
אבל זה יהיה לאפס את הכל בשבילך.
אם אי פעם רצית להגדיר הכל כדי null לאחר mallocing משהו
אתה צריך רק להשתמש calloc במקום הראשון במקום לכתוב
עבור לולאה כדי לאפס את כל הבלוק של זיכרון.
>> Realloc הוא כמו malloc ויש הרבה מקרים מיוחדים,
אבל בעצם מה שעושה הוא realloc
זה לוקח מצביע שכבר הוקצה.
Realloc היא הפונקציה שאתה רוצה לשים לב לכאן.
זה לוקח מצביע שכבר חזר מmalloc.
בואו נגיד שאתה מבקש מmalloc מצביע של 10 בתים.
ואז מאוחר יותר אתה מבין שאתה רוצה 20 בתים,
כך שאתה קורא על realloc שמצביע עם 20 בתים,
וrealloc יעתיק אוטומטית מעל הכל בשבילך.
אם אתה רק בשם malloc שוב, כאילו יש לי גוש של 10 בתים.
עכשיו אני צריך בלוק של 20 בתים,
כך שאם אני malloc 20 בתים, אז יש לי לשם העתקה ידנית על פני 10 בתים מהדבר הראשון
לדבר השני ולאחר מכן חופשי הדבר הראשון.
Realloc יהיה להתמודד עם זה בשבילך.
>> שים לב לחתימה הולכת להיות * מבוטל,
שרק חוזר מצביע לבלוק של זיכרון,
אז void * ptr.
אתה יכול לחשוב על החלל * כמצביע גנרי.
באופן כללי, אתה אף פעם לא להתמודד עם החלל *,
אבל malloc חוזר * מבוטל, ואז זה בדיוק כמו בשימוש
זה בעצם הולך להיות * char.
* החלל הקודם, שהוחזרו על ידי malloc
עכשיו הוא הולך להיות מועבר לrealloc, ולאחר מכן גודל
הוא המספר החדש של בתים שאתה רוצה להקצות, כך היכולת החדשה שלך.
אני אתן לך כמה דקות, ולעשות את זה בשטח שלנו.
התחל עם 1 גרסות.
אני אפסיק אותך אחרי בתקווה על מספיק זמן כדי ליישם את הדחיפה,
ואז אני אתן לך עוד הפסקה לעשות פופ.
אבל זה באמת לא כל כך הרבה קוד בכלל.
רוב הקוד הוא כנראה חומר מתרחב, הרחבת הכושר.
אוקיי, אין לחץ לעשות לחלוטין,
אבל כל עוד אתה מרגיש שאתה בדרך הנכונה, זה טוב.
>> יש למישהו איזה קוד הם מרגישים בנוח איתי מושכים את?
כן, אני אעשה את זה, אבל למישהו יש קוד שאני יכול לרוץ?
אוקיי, אתה יכול להתחיל, לשמור אותו, מה שזה לא?
אני תמיד שוכח צעד זה.
אוקיי, מביט בדחיפה,
אתה רוצה להסביר את הקוד שלך?
[סטודנטים] קודם כל, אני הגדלתי את הגודל.
אני מניח שאולי כדאי לי בכל אופן, אני הגדלתי את הגודל,
ואני רואה אם ​​זה פחות מהיכולת.
ואם זה פחות מהיכולת, אני מוסיף למערך שכבר יש לנו.
ואם זה לא, אני מכפיל את הקיבולת של 2,
ואני להקצות מחדש את מערך מחרוזות למשהו עם גודל קיבולת גדולה יותר כעת.
ואז, אם זה לא יצליח, אני אומר לי המשתמש ותמורת שווא,
ואם זה בסדר, ואז אני מחזיר את המחרוזת במקום החדש.
>> [רוב ב] גם שמנו לב שהייתי מפעיל סיבי האופרטור נחמד כאן
להכפיל אותו ב 2.
זכור, משמרת השמאל תמיד הולכת להיות מוכפלת ב 2.
Shift הימני מחולק על ידי 2, כל עוד אתה זוכר שזה אומר
חלק 2 כמו במספר שלם חלק 2.
זה יכול לחתוך 1 כאן או לשם.
אבל השינוי שהשאיר 1 תמיד הולך להיות מוכפל ב 2,
אלא אם כן אתה הצפת הגבולות השלמים, ואז זה לא יהיה.
הערת צד.
אני אוהב לעשות, זה לא הולך לשנות את הקידוד כל דרך שהיא,
אבל אני רוצה לעשות משהו כזה.
זה באמת הולך לעשות את זה קצת יותר ארוך.
אולי זה לא מקרה המושלם כדי להראות את זה,
אבל אני אוהב אותו הקטע לגושים האלה של
אוקיי, אם זה אם קורה, אז אני הולך לעשות משהו,
ואז הפונקציה נעשתה.
אני לא צריך אז כדי לגלול את עיניי כל הדרך למטה הפונקציה
כדי לראות מה קורה לאחר אחר.
זה אם זה אם קורה, אז אני פשוט אחזור.
יש לו גם הערך המוסף הנחמד של כל דבר מעבר לזה
כעת העביר עזב פעם אחת.
אני כבר לא צריך, אם אי פעם ליד גיחוך התורים ארוכים,
אז 4 הבתים האלה יכולים לעזור, וגם משהו השמאלי יותר הוא,
פחות רגש אותך, אם תרצה להרגיש-בסדר, אני צריך לזכור
אני כרגע בלולאה בתוך בפנים אחר של ללולאה.
בכל מקום שאתה יכול לעשות זה לחזור באופן מיידי, אני די אוהב.
זה לגמרי לא חובה ולא צפוי בכל דרך.
>> [סטודנטים] האם צריך להיות בגודל - במצב להיכשל?
המצב להיכשל כאן הוא שלא הצליח realloc, אז כן.
שים לב איך במצב להיכשל, ככל הנראה,
אלא אם כן דברים בחינם מאוחר יותר, אנחנו תמיד הולכים להיכשל
לא משנה כמה פעמים אנחנו מנסים לדחוף משהו.
אם תמשיכו לדחוף, אנחנו שומרים על גודל הגדלה,
למרות שאנחנו לא לשים שום דבר על המחסנית.
בדרך כלל אנחנו לא להגדיל את הגודל עד
אחרי שהכנסנו אותו בהצלחה במחסנית.
אנחנו נעשה את זה, למשל, או כאן וכאן.
ואז במקום לומר s.size ≤ קיבולת, זה פחות מיכולת,
רק בגלל שאנחנו עברנו בה הכול.
>> ואזכור, המקום היחיד שאנחנו יכולים אולי בתמורת שווא
הוא כאן, שם realloc חזר ריק,
אם אתה זוכר במקרה שגיאה סטנדרטית ו,
אולי אתם יכולים לשקול מקרה זה שבו אתה רוצה להדפיס שגיאה סטנדרטית,
stderr כך fprintf במקום רק להדפיס ישירות לפלט סטנדרטי.
שוב, זה לא ציפייה, אבל אם זה טעות,
הקלד printf, אז אולי כדאי לך לעשות את זה כדי להדפיס שגיאה סטנדרטית במקום פלט סטנדרטי.
>> למישהו יש משהו אחר לשים לב? כן.
[סטודנטים] האם אתה יכול לעבור על [לא ברור]?
[רוב ב '] כן, binariness הממשי שלו או מה זה בדיוק?
[סטודנטים] אז אתה מכפיל אותו ב 2?
[רוב ב '] כן, בעצם.
בארץ בינארי, תמיד יש לנו הסדרה של ספרות שלנו.
הסטה שמאלית זו עד ליום 1 בעצם מוסיפה אותו כאן על צד ימין.
חזור לזה, רק לזכור שכל הדבר בינארי
הוא כוח של 2, כך שזה מייצג 2 ל 0,
זה 2 ל1, 2 לזה 2.
על ידי הוספת 0 לצד ימין עכשיו, אנחנו פשוט לעבור על הכול.
מה הייתה אמור להיות 2 ל 0 הוא עכשיו 2 ל 1, הוא 2 עד 2.
בצד ימין שהוכנסנו
בהכרח הולך להיות 0,
וזה הגיוני.
אם אי פעם להכפיל מספר ב 2, זה לא הולך בסופו מוזר,
כך 2 עד 0 המקום צריכים להיות 0,
וזה מה שאני חצי הזהרתי לפני הוא אם קורה להסיט
מעבר למספר הביטים במספר שלם,
אז 1 זה הולך בסופו נוסע.
זה דאגה רק אם קורה לך להיות התמודדות עם קיבולות גדולות באמת.
אבל בנקודה הזאת, אז יש לך עסק עם מערך של מליארד דברים,
אשר עשוי שלא להתאים לזיכרון בכל מקרה.
>> עכשיו אנחנו יכולים להגיע לפופ, וזה אפילו יותר קל.
אתה יכול לעשות את זה כמו שאם קורה לך לקפוץ כל חבורה,
ועכשיו אתה במחצית הקיבולת שוב.
אתה יכול realloc לכווץ את כמות הזיכרון שיש לך,
אבל אתה לא צריך לדאוג בקשר לזה, ולכן במקרה realloc רק הולך להיות
גדל זיכרון, לא מתכווץ זיכרון,
שהוא הולך לעשות סופר פופ קל.
עכשיו תורים, שהם הולכים להיות כמו ערימות,
אבל כדי שאתה מוציא את הדברים החוצה הוא הפוך.
הדוגמא הטיפוסית של תור היא קו,
אז אני מניח שאם היית אנגלי, הייתי אומר
דוגמה טיפוסית של תור היא תור.
אז כמו קו, אם אתה האדם הראשון בשורה,
אתה מצפה להיות האדם הראשון מחוץ לקו.
אם אתה האדם האחרון בשורה, אתה הולך להיות האדם האחרון לתיקון.
אנו קוראים כי דפוס FIFO, בעוד שמחסנית הייתה דפוס LIFO.
המילים האלה הן די אוניברסליות.
>> כמו ערימות ולא כמו מערכים, תורים אינם מאפשרים בדרך כלל גישה לאלמנטים באמצע.
כאן, מחסנית, יש לנו דחיפה ופופ.
כאן, אנו קורים שקראנו להם וEnqueue dequeue.
שמעתי גם קראו משמרת וunshift.
שמעתי אנשים אומרים דחיפה ופופ לחלים גם על תורים.
שמעתי להוסיף, להסיר,
אז דחף ופופ, אם אתה מדבר על ערימות, אתה דוחף ומכניס.
אם אתה מדבר על תורים, אתה יכול לבחור את המילים שברצונך להשתמש
להכנסה והוצאה, ואין הסכמה על מה שהיא צריכה להיקרא.
אבל הנה, יש לנו Enqueue וdequeue.
עכשיו, struct נראה כמעט זהה לstruct המחסנית.
אבל אנחנו צריכים לעקוב אחר הראש.
אני מניח שזה אומר כאן, אבל למה אנחנו צריכים את הראש?
אבות הטיפוס הוא בעצם זהה ללדחוף ופופ.
אתה יכול לחשוב על זה כעל דחיפה ופופ.
ההבדל היחיד הוא הפופ חוזר-במקום שעבר הוא חזרה הראשונה.
2, 1, 3, 4, או משהו.
והנה ההתחלה.
התור שלנו הוא מלא לחלוטין, כך שיש ארבעה יסודות שבו.
סוף התור שלנו הוא כרגע 2,
ועכשיו אנחנו הולכים להכניס משהו אחר.
>> כאשר אנו רוצים להוסיף משהו אחר, מה שעשינו לגרסת המחסנית
הוא הרחבנו את הבלוק של זיכרון שלנו.
מה הבעיה עם זה?
[סטודנטים] אתה מעביר את 2.
מה שאמרתי קודם על סוף התור,
זה לא הגיוני שאנחנו מתחילים ב1,
אז אנחנו רוצים dequeue 1, אז dequeue 3, אז dequeue 4,
אז dequeue 2, אז dequeue זה.
אנחנו לא יכולים להשתמש realloc עכשיו,
או לכל הפחות, יש לך להשתמש realloc בדרך אחרת.
אבל כנראה שאתה לא צריך רק להשתמש realloc.
אתה הולך באופן ידני להעתיק את הזיכרון שלך.
>> ישנן שתי פונקציות להעתקת זיכרון.
יש memcopy וmemmove.
אני כרגע קורא את הדפים כדי לראות איזה מהם אתה הולך רוצה להשתמש.
אוקיי, memcopy, ההבדל הוא
שmemcopy וmemmove, אחד מטפל במקרה בצורה נכונה
לאן אתה מעתיק לתוך אזור שקורה לחפיפת האזור
אתה מעתיק מ.
Memcopy לא להתמודד עם זה. Memmove עושה.
אתה יכול לחשוב על הבעיה כ-
נניח שאני רוצה להעתיק את הבחור הזה,
אלה ארבעה לבחור הזה.
בסוף, מה המערך צריך להיראות
לאחר ההעתקה היא 2, 1, 2, 1, 3, 4, ולאחר מכן כמה דברים בסוף.
אבל זה תלוי בהסדר שבו אנחנו בעצם להעתיק,
שהרים אם אנחנו לא מחשיבים את העובדה שהאזור שאנו מעתיקים אל
חופף אחד אנחנו מעתיקים מ,
אז אנחנו יכולים לעשות כמו התחלה כאן, להעתיק את 2 למקום שאנחנו רוצים ללכת,
לאחר מכן להעביר את המצביעים שלנו קדימה.
>> עכשיו אנחנו הולכים להיות כאן וכאן, ועכשיו אנחנו רוצים להעתיק
הבחור הזה על הבחור הזה ולהעביר את המצביעים שלנו קדימה.
מה שאנחנו הולכים בסופו של דבר מקבלים הוא 2, 1, 2, 1, 2, 1
במקום 2 המתאימים, 1, 2, 1, 3, 4, כי
2, 1 הגיע לקיצת 3 המקוריים, 4.
Memmove ידיות בצורה נכונה.
במקרה זה, בעצם רק משתמש תמיד memmove
משום שהוא מטפל בזה בצורה נכונה.
זה בדרך כלל לא לבצע כל רע.
הרעיון הוא במקום להתחיל מההתחלה וההעתקה בדרך זו
כמו שאנחנו כאן, זה מתחיל מהסוף ומעתיק ב,
ובמקרה כזה, אתה לא יכול יש לי בעיה.
לא ביצועים יש לאיבוד.
השתמש תמיד memmove. לא לדאוג memcopy.
וזה מקום שאתה הולך להיות בנפרד לmemmove
עטוף סביב חלק מהתור שלך.
אל דאגה, אם לא נעשתה לחלוטין.
זה קשה יותר ממחסנית, לדחוף, ופופ.
>> מישהו יש לך קוד שנוכל לעבוד איתו?
גם אם לחלוטין לא שלם?
[סטודנטים] כן, זה לחלוטין לא מושלם, אם כי.
לחלוטין לא שלם הוא בסדר, כל עוד אנחנו יכולים, שתשמרו את העדכון?
אני שוכח שכל פעם אחת.
אוקיי, מתעלם ממה שקורה כאשר אנחנו צריכים לשנות את גודל דברים.
לחלוטין להתעלם מגודל.
הסבר את הקוד הזה.
אני בודק קודם כל אם הגודל הוא פחות מהעותק הראשון של כל
ואז אחרי זה, אני מכניס, אני לוקח את הראש + גודל,
ואני מקפיד שעוטף את הקיבולת של המערך,
ואני מכניס את המחרוזת החדשה במיקום זה.
ואז אני מגדיל את הגודל והחזר אמיתי.
>> [רוב ב] זה בהחלט אחד מאותם מקרים שבו אתה הולך רוצה להיות באמצעות משרד ביטחון.
כל סוג של מקרה שבו יש לך עוטף מסביב, אם אתה חושב שעוטף מסביב,
המחשבה המיידית צריכה להיות אופנתית.
כאופטימיזציה מהירה / להפוך את שורת הקוד האחת שלך קצרה יותר,
אתה שם לב שהשורה הבאה זה אחד מייד
הוא בדיוק גודל + +, אז לך למזג את זה לתוך הקו הזה, גודל + +.
עכשיו כאן למטה, יש לנו מקרה
שם אין לנו מספיק זיכרון,
כך אנו מגדילים את היכולת שלנו על ידי 2.
אני מניח שאפשר לה בעיה כאן, אבל אנחנו יכולים להתעלם מזה עכשיו,
בו אם אתה לא להגדיל את הקיבולת שלך,
ואז אתה הולך לרוצה להפחית את היכולת שלך על ידי 2 שוב.
הערה קצרה נוספת היא בדיוק כמו שאתה יכול לעשות + =,
אתה יכול גם לעשות << =.
כמעט כל דבר יכול לעבור לפני שווים, + =, | =, & =, << =.
Char * החדש הוא הבלוק החדש שלנו בזיכרון.
הו, כאן.
>> מה אנשים חושבים על הסוג של הבלוק החדש שלנו בזיכרון?
[סטודנטים] זה צריך להיות char **.
מחשבה לאחור לstruct שלנו כאן,
מייתרים הם מה שאנחנו הקצאה מחדש.
אנחנו עושים אחסון דינמי חדש לחלוטין עבור האלמנטים בתור.
מה שאנחנו הולכים להיות הקצאה למייתרים שלך הוא מה שאנחנו mallocing עכשיו,
וכל כך חדש היא הולך להיות char **.
זה הולך להיות מערך של מחרוזות.
אז מה שקורה תחתו אנחנו הולכים בתמורת שווא?
[סטודנטים] האם עלינו לעשות * char?
[רוב ב '] כן, שיחה טובה.
[סטודנטים] מה זה היה?
[רוב ב '] רצינו לעשות גודל של * char בגלל שאנחנו כבר לא,
זה הייתי למעשה להיות בעיה גדולה מאוד, כי sizeof (char) יהיה 1.
* Char sizeof הולך להיות 4,
כל כך הרבה פעמים כשאתה עוסק בints,
אתם נוטים לצאת מזה בגלל גודל של int וגודל של int *
על מערכה 32-bit הולכים להיות אותו הדבר.
אבל כאן, sizeof (char) וsizeof (char *) עכשיו הולכים להיות אותו הדבר.
>> מה הן הנסיבות שבו אנחנו בתמורת שווא?
[סטודנטים] חדש הוא ריק.
כן, אם חדש הוא ריק, אנחנו חוזרים שקר,
ואני הולך לזרוק כאן למטה-
[סטודנטים] [לא ברור]
[רוב ב '] כן, זה בסדר.
אתה יכול גם לעשות 2 פעמים קיבולת או שינוי קיבולת 1 ואז רק הניח אותו כאן או משהו כזה.
אנחנו נעשה את זה כמו שהיינו לנו את זה.
קיבולת >> = 1.
ואתה לעולם לא צריך לדאוג לאבד את מקומו של 1
בגלל שעזבת מוזז על ידי 1, כך המקום של 1 הוא בהכרח 0,
כל כך נכון הסטה של ​​1, אתה עדיין הולך להיות בסדר.
[סטודנטים] האם אתה צריך לעשות את זה לפני התמורה?
[רוב ב '] כן, זה כבר ממש לא הגיוני.
>> כעת אניח שאנחנו הולכים בסופו חוזר אמיתי עד הסוף.
הדרך שאנחנו הולכים לעשות memmoves אלה,
אנחנו צריכים להיות זהירים עם איך אנחנו עושים אותם.
למישהו יש הצעות לאופן בו אנו עושים אותם?
הנה ההתחלה שלנו.
באופן בלתי נמנע, אנחנו רוצים להתחיל בתחילה שוב
ודברים בהעתקה משם, 1, 3, 4, 2.
איך אתה עושה את זה?
ראשית, יש לי להסתכל על דף האדם לmemmove שוב.
Memmove, סדר של טענות הוא תמיד חשוב.
אנחנו רוצים לייעדנו ראשונים, שניים מקור שלישי בגודל.
יש הרבה פונקציות שאשיבנו מקור ויעד.
יעד, מקור נוטה להיות עקבי במידה מה.
מהלך, מה שהוא חוזר?
זה מחזיר את מצביע ליעד, מכל סיבה שייתכן שתרצה את זה.
אני יכול לקרוא אותו תמונה, אבל אנחנו רוצים לעבור ליעד שלנו.
>> מה היעד שלנו הולך להיות?
[סטודנטים] חדש.
[רוב ב '] כן, ושבו אנחנו מעתיקים?
הדבר הראשון שאנחנו מעתיקים זה 1, 3, 4.
מה זה, 1, 3, 4.
מה הכתובת של זה 1?
מה הכתובת של 1?
[סטודנטים] [לא ברור]
[רוב ב] ראש + הכתובת של האלמנט הראשון.
איך אנחנו מגיעים לאלמנט הראשון במערך?
[סטודנטים] תור.
[רוב ב '] כן, q.strings.
זכור, כאן, הראש שלנו הוא 1.
לעזאזל. אני פשוט חושב שזה קסם,
הנה, הראש שלנו הוא 1. אני הולך לשנות את הצבע שלי יותר מדי.
וכאן הוא מחרוזות.
זה, אנחנו יכולים גם לכתוב אותו כמו שעשינו כאן
עם ראשים + q.strings.
הרבה אנשים גם לכתוב את זה וq.strings [ראש].
זה לא באמת פחות יעיל.
אתה יכול לחשוב על זה כאתם ביטול ההפניה ולאחר מכן מקבלים את הכתובת של,
אבל המהדר הולך לתרגם את זה למה שהיינו לפני מקרה, q.strings + ראש.
כך או כך אתה רוצה לחשוב על זה.
>> וכמה בתים שאנחנו רוצים להעתיק?
[סטודנטים] קיבולת - ראש.
קיבולת - ראש.
ואז אתה תמיד יכול לכתוב את דוגמה
כדי להבין אם זה נכון.
זה [סטודנטים] צריכים להיות מחולקים על ידי 2 אז.
כן, אז אני מניח שאנחנו יכולים להשתמש בגודל.
עדיין יש לנו גודל רווחת
באמצעות גודל, יש לנו גודל שווה ל 4.
הגודל שלנו הוא 4. הראש שלנו הוא 1.
אנחנו רוצים להעתיק 3 האלמנטים הללו.
זה השפיות לבדוק גודל ש-- הראש הוא נכון 3.
ואחזור לכאן, כמו שאמרנו קודם,
אם אשתמש בקיבולת, אז הייתי צריך לחלק ב 2
כי אנחנו כבר גדלנו היכולת שלנו, אז במקום זה, אנחנו הולכים להשתמש בגודל.
כי עותקים שמנה.
עכשיו, אנחנו צריכים להעתיק את החלק השני, החלק שנותר מההתחלה.
>> זה הולך memmove לאיזה תפקיד?
[סטודנטים] גודל פלוס - ראש.
כן, אז יש לנו כבר העתיקו בגודל - בתי ראש,
ואז שבו אנחנו רוצים להעתיק את הבתים שנותרו הוא חדש
ולאחר מכן גודל מינוס היטב, את מספר הבתים שכבר להעתיק פנימה
ואז שבו אנחנו מעתיקים?
[סטודנטים] Q.strings [0].
[רוב ב '] כן, q.strings.
אנחנו יכולים גם לעשות וq.strings [0].
זה הרבה פחות נפוץ מאשר זה.
אם זה רק הולך להיות 0, אז אתה נוטה לראות q.strings.
זה המקום שבי אנו מעתיקים מ.
כמה בתים נשארו לנו להעתיק? >> [סטודנטים] 10.
נכון.
[סטודנטים] האם יש לנו להכפיל 5-10 פעמים את הגודל של הבתים או משהו?
כן, אז זה המקום שבי-מה בדיוק אנחנו מעתיקים?
[סטודנטים] [לא ברור]
מהו הסוג של הדבר שאנו מעתיקים?
[סטודנטים] [לא ברור]
כן, אז * של char שאנו מעתיקים, אנחנו לא יודעים איפה אלה מגיעים.
ובכן, שבו הם מצביעים, כמו מייתרים, אנחנו בסופו מעלה אותה על התור
או enqueuing על התור.
איפה אלה שבאים, אין לנו מושג.
אנחנו פשוט צריכים לעקוב אחר * char של עצמם.
אנחנו לא רוצים להעתיק גודל - בתי ראש.
אנחנו רוצים להעתיק גודל - ראש char * s,
כך אנחנו הולכים להכפיל את זה על ידי sizeof (char *).
כאן למטה, ראש * sizeof (char *).
>> [סטודנטים] מה [לא ברור]?
זה ממש כאן?
[סטודנטים] לא, מתחת לזה, גודל - ראש.
[רוב ב] זכות זו כאן?
פעולות אריתמטיות על מצביעים.
איך פעולות אריתמטיות על מצביעים הולכות לעבוד הוא
זה באופן אוטומטי על ידי מכפיל את הגודל מהסוג שיש לנו עסק איתו.
בדיוק כמו כאן, חדש + (גודל - ראש)
זה בדיוק שווה ערך ל [גודל - הראש] וחדש
עד שאנחנו מצפים שנפעל כהלכה,
שכן אם יש לנו עסק עם מערך int, אז אנחנו לא אינדקס על ידי-int
או אם זה בגודל של 5 ואתה רוצה אלמנט 4, אז אנחנו אינדקס לתוך
מערך int [4].
אתה אל, [4] * גודל של int.
שמטפל בו באופן אוטומטי, ומקרה זה
פשוטו כמשמעו, הוא שווה ערך, כך תחביר הסוגר
פשוט הולך להיות מומר לזה ברגע שאתה לקמפל.
זה משהו שאתה צריך להיות זהיר של
כשאתה מוסיף גודל - ראש
אתה מוסיף לא בייט אחד.
אתה מוסיף * char אחד, שיכול להיות אחד בתים או משהו כזה.
>> שאלות אחרות?
אוקיי, dequeue הולך להיות קל יותר.
אני אתן לך דקה ליישום.
אה, ואני מניח שזה אותו המצב שבו
מה מקרה Enqueue, אם אנחנו enqueuing ריק,
אולי אנחנו רוצים לטפל בזה, אולי לא.
אנחנו לא נעשינו את זה שוב כאן, אבל כמו מקרה המחסנית שלנו.
אם אנחנו Enqueue ריק, יתכן שעלינו להתעלם ממנו.
למישהו יש איזה קוד שאני יכול לרוץ?
[סטודנטים] יש לי רק dequeue.
גרסה 2 היא ש- בסדר.
אתה רוצה להסביר?
[סטודנטים] ראשית, לך לוודא שיש משהו בתור
ושהגודל הוא יורד ב 1.
אתה צריך לעשות את זה, ואז אתה מחזיר את הראש
ואז להזיז את הראש למעלה 1.
אוקיי, אז יש פינת מקרה אנחנו צריכים לשקול. כן.
[סטודנטים] אם הראש שלך הוא באלמנט האחרון,
אז אתה לא רוצה את הראש להצביע מחוץ למערך.
>> כן, אז ברגע שראש פוגע בסופו של המערך שלנו,
כאשר אנו dequeue, הראש שלנו צריך להיות חזרה לmodded 0.
למרבה הצער, אנחנו לא יכולים לעשות את זה בצעד אחד.
אני מניח שהייתי כנראה הדרך לתקן את זה הוא
זה הולך להיות * char, מה שאנחנו חוזרים,
מה השם המשתנה שלך רוצה להיות.
אז אנחנו רוצים mod הראש ביכולת שלנו
ואז לחזור להשרות.
הרבה אנשים כאן שהם עלולים לעשות-
זה מקרה של את תראה שאנשים עושים אם ראש
גדול מקיבולת, לעשות את הראש - קיבולת.
וזה פשוט עובד סביב מה mod הוא.
ראש mod = קיבולת היא הרבה יותר נקיה
מעטיפה סביב מאשר אם הראש גדול יותר מראש הקיבולת - קיבולת.
>> שאלות?
אוקיי, הדבר האחרון שנשארנו לנו הוא הרשימה המקושרת שלנו.
אתה עשוי לשמש לחלק מהתנהגות הרשימה המקושרת אם עשה
רשימות מקושרות בטבלאות hash שלך, אם אתה עשית שולחן חשיש.
אני ממליץ בחום לעשות שולחן חשיש.
ייתכן שכבר עשה trie,
אבל ניסיונות קשים יותר.
בתאוריה, הם asymptotically טובים יותר.
אבל רק להסתכל על הלוח הגדול,
ומנסה לא לעשות יותר טוב, והם תופסים יותר זיכרון.
הכל על מנסה סופו להיות יותר גרוע ליותר עבודה.
זה מה שהפתרון של דוד מלאן תמיד הוא
האם הוא תמיד פתרון trie הודעות שלו, ובואו נראים שם הוא משמש כיום.
מה הוא היה תחת, הדוד J?
הוא # 18, ככה שזה לא נורא רע,
וזה הולך להיות אחד מהטובים מנסה אתה יכול לחשוב על
או אחד מהטובים מנסה של trie.
האם זה גם לא הפתרון המקורי שלו?
אני מרגיש כמו פתרוני trie נוטים להיות יותר בטווח זה של שימוש בזכרון RAM.
>> לרדת אל חלקו העליון, ושימוש בזכרון RAM הוא בחד הספרתיה.
יורדים לכיוון התחתי, ואז אתה מתחיל לראות מנסה
איפה אתה מקבל את השימוש בזכרון RAM בהחלט מסיבי,
והניסיונות קשים יותר.
לא לגמרי שווה את זה, אבל חוויה חינוכית אם עשה את אחד.
הדבר האחרון הוא הרשימה המקושרת שלנו,
ושלושת הדברים האלה, מחסניות, התורים, ורשימות מקושרות,
כל דבר שאי פעם בעתיד לעשות במדעי מחשב
יניח שיש לך היכרות עם הדברים האלה.
הם פשוט כל כך בסיסיים לכל דבר.
>> מקושרי רשימות, והנה יש לנו רשימה מקושרת ביחידים הולכת להיות היישום שלנו.
מה קשור singly אומרים כניגוד למקושר doubly? כן.
[סטודנטים] זה רק מצביע למצביע הבא ולאו דווקא למצביעים,
כמו זו שקדם לה וזה שאחריו.
כן, אז בפורמט תמונה, מה אני בדיוק עושה?
יש לי שני דברים. יש לי תמונה ותמונה.
בפורמט תמונה, הרשימות שלנו ביחידות המקושרות,
בהכרח, יש לנו סוג של מצביע לראש הרשימה שלנו,
ולאחר מכן ברשימה שלנו, אנחנו רק צריכים מצביעים,
ואולי זה נקודות לnull.
זה הולך להיות הציור הטיפוסי שלך מרשימה מקושרת ביחידים.
רשימה מקושרת כפול, אתה יכול ללכת אחורה.
אם אני אתן לך בכל צומת ברשימה, אז אתה יכול להגיע לבהכרח
כל צומת אחר ברשימה, אם זה רשימה מקושרת כפליים.
אבל אם אני מקבל אותך בצומת השלישית ברשימה וזה רשימה מקושרת ביחידים,
אין דרך שאתה אי פעם הולך לקבל לבלוטות הראשונות ושניות.
ויש יתרונות וdetriments, ואחד אחד ברור
אתה תופס יותר גודל, ויש לך לעקוב אחר שבו הדברים האלה מצביעים עכשיו.
אבל אנחנו רק אכפת קשורי ביחידים.
>> כמה דברים שאנחנו הולכים יש ליישם.
node typedef struct, אני int: struct node * הבא; הצומת.
That typedef צריך ייצרב מוחכם.
1 חידון צריך להיות כמו לתת typedef של צומת רשימה מקושרת,
ואתה צריך להיות מסוגל לשרבט מייד שלמטה
אפילו בלי לחשוב על זה.
אני מניח שכמה שאלות, למה אנחנו צריכים את struct כאן?
למה לא יכולים להגיד * node?
[סטודנטים] [לא ברור]
כן.
הדבר היחיד שמגדיר את צומת כדבר
הוא typedef עצמו.
אבל כמו בנקודה זו, כאשר אנחנו סוג של ניתוח באמצעות הגדרת node struct זה,
אנחנו עדיין לא סיימנו typedef עדיין, מה גם שtypedef לא סיים,
node לא קיים.
אבל struct node עושה, ואת הצומת הזה בפה,
זה גם יכול להיות משהו אחר.
זה יכול להיקרא n.
אפשר לקרוא node רשימה מקושרת.
אפשר לקרוא שום דבר.
אבל node struct הזה צריך להיקרא אותו הדבר כמו node struct זה.
מה אתה קורא לזה יש גם כדי להיות כאן,
וכדי שגם עונה על הנקודה השנייה של השאלה
ולכן, הרבה פעמים כשאתה רואה structs וtypedefs של structs,
תראה structs אנונימיים שבו אתה פשוט רואה struct typedef,
יישום של struct, מילון, או משהו כזה.
>> למה כאן אנחנו צריכים לומר node?
למה זה לא יכול להיות struct אנונימי?
זה כמעט את אותה התשובה.
[סטודנטים] אתה צריך להתייחס אליו בתוך struct.
כן, בתוך struct, אתה צריך להפנות לstruct עצמו.
אם אתה לא נותן struct שם, אם זה struct בעילום שם, אתה לא יכול להתייחס לזה.
ואחרון אך לא פחות חשוב, אלה צריכים להיות במידה מסוימת כל פשוט,
והם צריכים לעזור לך לממש אם אתה רושם את זה
שאתה עושה משהו לא בסדר אם הדברים כאלה לא הגיוניים.
אחרון חביב, למה זה צריך להיות * struct node?
למה זה לא יכול פשוט להיות struct node הבא?
[סטודנטים] מצביעים לstruct הבא.
זה בהכרח מה שאנחנו רוצים.
למה זה יכול להיות לא node struct הבא?
למה זה צריך להיות struct node * הבא? כן.
[סטודנטים] זה כמו לולאה אינסופית.
כן.
[סטודנטים] הכול היה יכול להיות באחד.
כן, רק לחשוב על איך אנחנו נעשה גודל או משהו.
גודל של struct הוא בעצם + או - איזה דפוס כאן או שם.
זה בעצם הולך להיות סכום הגדלים של הדברים בstruct.
זכות זו כאן, מבלי לשנות שום דבר, את הגודל הולכת להיות קל.
גודלו של צומת struct הולך להיות גודל של אני + הגודל הבא.
הגודל שלי הולך להיות 4. הגודל הבא הולך להיות 4.
הגודל של צומת struct הולך להיות 8.
אם אין לך את *, וחשב על sizeof,
אז sizeof (אני) הולך להיות 4.
גודלו של צומת struct הבא הולך להיות בגודל של i + גודל של צומת struct הבאה
+ גודל אני + הגודל של struct צומת הבאה.
זה יהיה רקורסיה אינסופית של צמתים.
זו הסיבה מדוע זה איך דברים צריכים להיות.
>> שוב, בהחלט לשנן את זה,
או לפחות מבין את זה מספיק כדי שתוכל להיות מסוגל
סיבה דרך מה זה אמור להיראות.
הדברים שאנחנו הולכים רוצים ליישם.
אם אורכה של הרשימה
אתה יכול לרמות ולשמור על הסביבה
אורך גלובלי או משהו, אבל אנחנו לא הולכים לעשות את זה.
אנחנו הולכים לספור את אורכה של הרשימה.
יש לנו מכיל, כך שבעצם כמו חיפוש,
אז יש לנו רשימה מקושרת של מספרים שלמים כדי לראות אם מספר שלם זה ברשימה המקושרת.
הקדם זיהוי הולך להכניס בתחילת הרשימה.
הצרף הולך להכניס בסוף.
Insert_sorted הולך להכניס לתוך העמדה מסודרת ברשימה.
סוג של Insert_sorted מניח שאתה מעולם לא השתמשת בהקדם זיהוי או לצרף בדרכים רעות.
>> Insert_sorted כשאתה מיישם insert_sorted-
נניח שיש לנו הרשימה המקושרת שלנו.
זה מה שהוא כרגע נראה, 2, 4, 5.
אני רוצה להכניס 3, ולכן כל עוד הרשימה עצם כבר ממוינת,
זה קל למצוא בו 3 שייכים.
אני מתחיל בשעת 2.
אוקיי, 3 גדולים מ 2, אז אני רוצה להמשיך.
אה, 4 הם גדולים מדי, ולכן אני יודע 3 הוא הולכים להיכנס בו בין 2 ל 4,
ואני חייב לתקן את מצביעים וכל הדברים האלה.
אבל אם אנחנו לא בהחלט להשתמש insert_sorted,
אוהבים בואו רק נאמרתי שאני הקדם זיהוי 6,
אז הרשימה המקושרת שלי הולכת להיות זה.
עכשיו זה לא הגיוני, ולכן לinsert_sorted, אתה יכול פשוט להניח
שהרשימה ממוינת, למרות שקיימות פעולות
מה שיכול לגרום לו לא להיות מסודר, וזהו זה.
מצא מועיל להוסיף כל כך אלה הם הדברים העיקריים שאתה הולך צריך ליישם.
>> לעת עתה, לקחת רגע כדי לעשות אורך ומכיל,
ואלה צריכים להיות מהירים יחסית.
מתקרב לשעת סגירה, כך שכל אחד יש משהו לאורכו או מכיל?
הם הולכים להיות כמעט זהים.
[סטודנטים] זמן.
בואו נראים, מהדורה.
אוקיי.
אתה רוצה להסביר?
[סטודנטים] אני פשוט ליצור צומת מצביע ולאתחל אותו לראשון, שהוא משתנה הגלובלי שלנו,
ואז אני בודק אם זה null אז אני לא אקבל אשמת בידוד, ולהחזיר 0 אם זה המקרה.
אחרת, אני לולאה דרך, תוך שמירה על מסלול של מספר שלם
כמה פעמים אני קבלתי גישה לאלמנט הבא ברשימה
ובאותה הפעולה גם לגשת תוספת אלמנט שבפועל,
ואז אני עושה ברציפות הבדיקה כדי לראות אם זה ריק,
ואם זה אפס, אז זה מבטל ופשוט מחזיר את מספר האלמנטים שגישה.
>> [רוב ב '] למישהו יש הערות על כל דבר?
זה נראה בסדר תקינות חכמה.
[סטודנטים] אני לא חושב שאתה צריך את צומת == null.
כן, כך שאם צומת == 0 החזר null.
אבל אם == null צומת אז זה-הו, יש בעית תקינות.
זה היה רק ​​אתה חוזר אני, אבל זה לא בהיקפה ברגע זה.
אתה פשוט צריך int i, אז אני = 0.
אבל אם הצומת היא ריקה, אז אני עדיין הולך להיות 0,
ואנחנו הולכים להחזיר 0, ולכן מקרה זה הוא זהה.
דבר משותף נוסף הוא לשמור על ההצהרה
בבתוך צומת של ללולאה.
אפשר לומר, הו, לא.
בואו נשאיר את זה כמו זה.
אני כנראה יהיה שם אני int = 0 כאן,
אז צומת * צומת = 1 כאן.
וזה, מן הסתם, מקבל-להיפטר מזה עכשיו.
זה כנראה מה שאני הייתי כותב את זה.
אתה יכול גם להסתכל על זה, כמו זה.
זה למבנה לולאה כאן
צריך להיות כמעט טבעי לך כפי שלint i = 0
אני הוא פחות מאורכו של מערך i + +.
אם זה מה שאתה לחזר על מערך, זה איך אתה לחזר על רשימה מקושרת.
>> זה צריך להיות טבע שני בשלב מסוים.
עם זה בחשבון, זה הולך להיות כמעט אותו הדבר.
אתה הולך רוצה לחזר על רשימה מקושרת.
אם צומת אין לי מושג מה ערכו נקרא.
צומת i.
אם הערך שבצומת = אני חוזר נכון, וזהו.
שים לב שהדרך היחידה שבה בתמורת שווא
הוא אם לחזר על הרשימה המקושרת כולו ולא לחזור לנכון,
אז זה מה שזה עושה.
כצד הערות שסביר להניח שלא יגיעו לצירוף או הקדם זיהוי.
>> הפתק אחרון מהיר.
אם אתה רואה את מילת מפתח סטטי, אז נגיד שint ספירת סטטי = 0,
אז אנחנו עושים ספירה + +, אתה יכול בעצם לחשוב על זה כמשתנה גלובלי,
למרות שאני רק אמרתי שזה לא איך אנחנו מתכוונים ליישם את האורך.
אני עושה את זה כאן, ואז לספור + +.
יש לנו אפשרות להיכנס לתוך צומת הרשימה המקושרת שלנו אנחנו הגדלת הספירה שלנו.
הנקודה זו היא מה משמעות מילת מפתח סטטי.
אם רק הייתי ספירת int = 0 שיהיו משתנים גלובלי ישן רגיל.
מה זה אומר הספירה int סטטי הוא שזה משתנה גלובלי עבור קובץ זה.
זה בלתי אפשרי עבור קובץ אחר,
אוהבים לחשוב על pset 5, אם יש לך החל.
יש לך גם speller.c, ויש לך dictionary.c,
ואם אתה רק מצהיר דבר עולמי, אז הכל בspeller.c
ניתן לגשת בdictionary.c ולהיפך.
משתנים גלובליים נגישים על ידי. כל קובץ c,
אבל משתנה סטטיים נגישים רק מתוך הקובץ עצמו,
כך פנימי של בודקת איות או בתוך dictionary.c,
זה סוג של איך הייתי להכריז משתנה לגודל של מערכי
או בגודל של מספר המילים במילון שלי.
מאז אני לא רוצה להכריז על משתנה גלובלי שכל אחד יש גישה ל,
אכפת לי באמת על זה רק למטרות שלי.
>> דבר טוב בזה גם דברי התנגשות השם השלמים.
אם קובץ אחר מנסה להשתמש במשתנה גלובלית הנקראת ספירה, דברים הולכים מאוד מאוד לא בסדר,
אז זה יפה שומר על דברים בטוחים, ורק אתה יכול לגשת אליו,
ואף אחד אחר לא יכול, ואם מישהו אחר מצהיר משתנה גלובלי הנקרא ספירה,
אז זה לא מפריע למשתנת סטטי נקראת ספירה.
זה מה שהוא סטטי. זה משתנה קובץ גלובלי.
>> שאלות על כל דבר?
כל הקבוצה. ביי.
[CS50.TV]