[Powered by Google Translate] בואו נדבר על structs.
Structs לספק לנו את הדרך לקבוצה את החבורה של משתנים יחד
לתוך חבילה יפה.
זה כנראה הכי קל לראות דוגמה מייד,
כך אנו אומרים struct,
לאחר מכן לפתוח סד מתולתל,
ובstruct זה, יהיה לנו גיל int,
שם * char,
וזהו זה.
זה אולי נראה מוזר עם פסיק לאחר סד מתולתל,
אבל זה למעשה צורך בstructs.
כל סוג תקף יכול ללכת בתוך הגדרת struct.
הנה, יש לנו בשימוש int ו* char,
אבל אתה יכול גם להשתמש במערך, של לומר, 100 אלמנטים
או אפילו struct אחר.
כאשר אתה משתמש structs ב-C,
אתה יוצר סוגים חדשים
מתוך אוסף של סוגים אחרים.
הנה, אנחנו עושים סוג חדש
מתוך שלם ו* char.
כפי שנראים מאוחר יותר, סוג struct
הוא בהרבה מובנים שווים ערך לכל סוג אחר שאתם רגילים אליו.
בדרך כלל, אני אהיה השוואה בין אופן סוג struct
דומה לסוג מספר שלם.
אף שהקוד שכתבנו הוא C התקפה,
זה לא מאוד שימושי,
וצלצולים, ינתנו לנו אזהרה.
זוכר איך structs ודומים?
ובכן, אנחנו בעצם רק אמרנו
int,
שהוא לא קו מאוד מועיל.
אז בואו בעצם מצהירים על משתנה מסוג זה
על ידי מתן שם לפני הפסיק.
אנחנו קוראים לתלמיד משתנה.
עכשיו אנחנו כבר הכרזנו תלמיד נקרא משתנה
עם הסוג שניתן על ידי struct.
איך אנחנו מגיעים למשתנים בתוך struct?
מבחינה הטכנית, שמות למשתנים אלו
הם חברים.
כדי לגשת לכל חבר בפרט בstruct סטודנט,
אתה מצרף לנקודת השם המשתנה,
ואחריו השם של החבר שאתה רוצה.
אז הנה, את 2 אפשרויות חוקיות בלבד
הם student.age
וstudent.name.
ואנחנו יכולים לעשות משהו כזה
student.age = 12
וstudent.name = תלמיד.
עכשיו מה אם אנחנו רוצים להפוך תלמיד שני?
אתה חושב שאולי כדי להעתיק ולהדביק את השורות האלה
ולשנות את התלמיד לתלמיד 2 או משהו,
ושיעבוד,
אבל מבחינה טכנית, סטודנט ותלמיד 2
אין לו סוג.
ראה, אתה לא תוכל להקצות אותם אחד לשני.
הסיבה לכך היא, עד כה,
struct שלך כבר בעילום שם.
אנחנו צריכים לתת לו שם.
כדי לעשות זאת, אנו מוסיפים את שמו של struct
אחרי המילה struct.
סטודנט,
אחרי ההגדרה.
אנחנו עדיין יכולים להצהיר על משתנים מהסוג מייד
struct תלמיד, כמו שעשינו בעבר.
אנחנו קוראים לזה S1
על ידי מתן struct שם,
עכשיו אנחנו יכולים להשתמש בתלמיד struct
כמעט באותו אופן בדיוק שהיינו משתמש int.
אז אנחנו יכולים להצהיר על משתנים מסוג struct סטודנט,
כמו
struct תלמיד S2.
כמו מערכים, structs לספק תחביר אתחול קיצור,
כך אנו יכולים לומר, struct התלמיד S2
שווה
מתולתל שמאל 3 סד, S2.
כאן, S2.age יהיה 3,
וS2.name יצביע על S2.
תחשוב על כל הדברים שאתה יכול לעשות עם סוג int
ורובם אתה יכול לעשות עם סוג תלמיד struct.
אנחנו יכולים להשתמש בתלמיד struct כסוג של פונקצית פרמטר.
אנחנו יכולים להשתמש בתלמיד struct בתוך struct חדש.
יכול להיות לנו מצביע לתלמיד struct.
אנחנו יכולים לעשות את הגודל של תלמיד struct.
Struct הסטודנט הוא סוג
בדיוק כמו int הוא סוג.
אנחנו גם יכולים להקצות לS1 S2
מאז שניהם מאותו הסוג, ולכן אנחנו יכולים לעשות
S1 = S2.
מה קורה אם אנחנו עושים
S1.age = 10?
האם שינוי S2 בכלל?
שוב, חושב על structs רק כמספרים שלמים רגילה.
אם אנחנו להקצות חלק X int לכמה int Y,
כמו X = Y
ולאחר מכן לשנות את X,
כמו בX + +,
אין Y ישתנה בכלל?
Y לא ישתנה כאן, וכך גם לא S2 לעיל.
S2.age הוא עדיין 3.
אבל שים לב שכאשר הקצאת struct אחד למשנו,
כל המצביעים עדיין מצביעים על אותו הדבר,
מאז הם פשוט הועתקו.
אם אתה לא רוצה את המצביעים להיות משותפים,
תצטרך להתמודד עם זה באופן ידני,
אולי על ידי malicking בלוק אחד של זיכרון לאחד מהמצביעים להצביע
ולהעתיק את הנתונים מחדש.
זה יכול להיות מעצבן לתלמיד צריך לכתוב struct בכל מקום.
שימוש def סוג, אנחנו יכולים לעשות
הסוג def
struct
ואנחנו קוראים לזה תלמיד.
עכשיו, אנחנו יכולים להשתמש בכל מקום תלמיד
שנהגנו להשתמש תלמיד struct.
סוג זה של def struct אנונימי
וממכן אותו התלמיד.
אבל אם יש לנו גם לשמור על זיהוי הסטודנט
ליד המילה struct, כמו בתלמיד struct typedef,
אנו יכולים להשתמש בשני תלמיד ותלמיד struct לסירוגין עכשיו.
הם אפילו לא צריכים שיהיו לו שם.
אנחנו יכולים להקליד תלמיד struct def לבוב
ולאחר מכן struct תלמיד ובוב
יהיו סוגים להחלפה.
ללא קשר לסוג def,
אנחנו צריכים את המזהה ליד struct
אם ההגדרה של struct
הוא רקורסיבי.
לדוגמה,
סוג def struct צומת
וזה יוגדר כval int
ויהיה לו מצביע שמצביע לצומת struct אחר.,
כמו בצומת * struct הבאה.
ואז אנחנו קוראים לזה צומת.
struct זה רקורסיבית,
מאז ההגדרה של צומת struct מכילה בתוכו
מצביע לצומת struct.
שים לב שיש לנו לומר struct * צומת הבאה
בתוך ההגדרה של צומת struct,
מאז הסוג def טרם הסתיים כדי לאפשר לנו לפשט את זה
* לצומת ממש ליד.
תוכל ללמוד עוד על structs דומה לזה
בעת התמודדות עם רשימות ועצים מקושרים.
מה לגבי structs בתפקוד?
זה גם תקף לחלוטין.
יכל להיות לנו
לבטל את הפונקציה
אשר לוקח כטיעון,
סטודנט של
ועושה משהו עם תלמיד.
ואז אנחנו יכולים לעבור אותו כתלמיד struct כמו אז.
Func של S1 מקודם.
Struct מתנהג
בדיוק כפי שהייתי כששלם עבר לפונקציה.
Func מקבל עותק של S1
ולכן לא ניתן לשנות S1;
לייתר דיוק, רק את העותק שלו, ששומר בס
אם אתה רוצה את הפונקציה כדי להיות מסוגלת לשנות S1,
התפקוד יצטרך לקחת * סטודנט S,
ואתה צריך לעבור S1 לפי כתובת, כמו אז.
סטודנטים * S, פונקציה & S1.
יש עוד סיבה לעבור על ידי כתובת כאן.
מה אם struct שלנו הכיל 100 שדות?
בכל פעם שאנו עוברים תלמיד לתפקוד,
התכנית שלנו צריכה להעתיק את כל 100 שדות אלה לS הטיעון של התפקוד,
גם אם הוא לא משתמש ברובם גדולים.
אז גם אם תפקוד אינו מתכנן שינוי הסטודנט,
אם עדיין יכול להיות בעל ערך רב לעובר כתובת.
בסדר, מה אם אנחנו רוצים ליצור מצביעים ל struct?
אנחנו יכולים לעשות משהו כמו
התלמיד * S
שווה malloc
גודלו של תלמיד.
שים לב שהגודל של עדיין עובד כאן.
אז איך אנחנו עכשיו לגשת לחבר הגיל
של הבלוק שמצביע לS?
אתה עשוי לחשוב ראשון לעשות
* S.age = 4,
אבל זה לא ממש עובד.
מכיוון שזו תהיה באמת להתפרש כ
* S.age בסוגריים = 4,
שאפילו לא לקמפל,
מאז S הוא לא struct או לייתר הדיוק מצביע ל struct,
ולכן הנקודה לא תעבוד כאן.
אנחנו יכולים לעשות
(* S). גיל = 4
אבל הסוגריים יכולים לקבל מעצבן ומבלבל.
למרבה המזל, יש לנו מפעיל חץ מיוחד
זה נראה משהו כזה
S-> גיל = 4.
2 דרכים אלה של התייחסות גיל
שווים
ואנחנו לא באמת אי פעם נצטרך מפעיל החץ,
אבל הוא עושה את הדברים נראים יותר נחמדים.
מאז S הוא מצביע לגוש חלק מזיכרון המכיל struct,
אתה יכול לחשוב על הגיל> כמו בצע חץ המצביע
ולתפוס את חבר הגיל.
אז למה אנחנו צריכים פעם להשתמש structs?
זה בהחלט אפשרי כדי לברוח רק עם המספרים השלמים פרימיטיביים,
תווים, מצביעים וכדומה
שאנחנו רגילים;
במקום S1 ו S2 לפני,
היינו יכול age1, age2, name1, וname2
כל במשתנים נפרדים.
זה בסדר רק עם 2 תלמידים,
אבל מה אם היו לנו 10 מהם?
ומה אם במקום רק 2 שדות,
struct התלמיד היה 100 שדות?
ממוצע ציונים, קורסים, צבע שיער, מין, וכן הלאה.
במקום רק 10 structs, אנחנו צריכים 1,000 משתנים נפרדים.
כמו כן, שקלו פונקציה
שלוקח struct שעם 100 שדות עם הטיעון היחיד שלה
ומדפיס את כל השדות.
אם לא הייתי משתמש בstruct,
בכל פעם שאנו קוראים פונקציה ש,
אנחנו צריכים לעבור בכל 100 המשתנים,
אם יש לנו 100 משתנה לסטודנט 1 ו,
ו100 משתנה לסטודנט 2,
אנחנו צריכים להיות בטוחים שאנחנו לא עוברים בטעות כמה משתנים מתלמיד 1
וכמה משתנים מתלמיד 2.
זה בלתי אפשרי לעשות את טעות עם struct,
מכיוון שכל 100 המשתנים כלולים בחבילה אחת.
רק כמה הערות אחרונות:
אם הבנת את הכל עד לנקודה זו, גדול.
שאר הווידאו הוא רק למען השלמות ".
בגלל structs יכול להחזיק כל סוג של מצביע,
הם יכולים גם להחזיק מצביעי פונקציות.
אם אתה מכיר עם תכנות מונחה עצמים,
זה מספק דרך להשתמש structs לתכנית בסגנון מונחה עצמים.
עוד על מצביעי פונקציות במועד אחר.
כמו כן, לפעמים אתה יכול להיות 2 structs
הגדרות שתלויות בזה.
לדוגמה,
שנהיה לנו struct,
אשר מוגדר כ
מצביע לB struct,
struct B * X,
ועכשיו אנחנו יכולים להיות B struct
אשר מוגדר כמצביע
ל struct,
struct * י
אבל זה לא הידור,
מאז struct ב 'לא היה קיים בזמן שstruct הוא להיות הידור.
ואם להחליף struct וstruct B,
אז הייתי פשוט אשאר עם אותה הבעיה;
הפעם, עם struct לא קיים.
כדי לפתור את זה, אנחנו יכולים לכתוב
struct B;
לפני הגדרת struct א
זה נקרא הכרזה קדימה.
זה פשוט מאפשר למהדר יודע ש
struct B הוא סוג חוקי שיוגדר באופן מלא מאוחר יותר או במקום אחר.
השם שלי הוא רוב אודן, וזה CS50.
[CS50.TV]