העברת מצביעים למבנים
חלק מהיחידה לוגיקה וזרימת תוכנית במסלול ה-C של Coddy. שיעור 47 מתוך 63.
בעוד שהעברת מבנים לפי ערך מתאימה לקריאת נתונים, היא נעשית לא יעילה כשמדובר במבנים גדולים, משום שכל המבנה מועתק. חשוב מכך, אי אפשר לשנות את המבנה המקורי מתוך הפונקציה. כאן נעשית חיונית העברת מצביעים למבנים.
כשמעבירים מצביע למבנה במקום את המבנה עצמו, הפונקציה מקבלת את כתובת הזיכרון של המבנה המקורי. לגישה הזאת יש שני יתרונות מרכזיים: היא יעילה יותר (אין העתקה) ומאפשרת לפונקציה לשנות את הנתונים המקוריים.
התחביר של פונקציה שמקבלת מצביע למבנה הוא:
void functionName(struct StructureName *ptr) {
// גוף הפונקציה המשתמש ב-ptr->member
}בתוך הפונקציה, משתמשים באופרטור החץ כדי לגשת לחברי המבנה ולשנות אותם. כל שינוי שנעשה דרך המצביע ישפיע ישירות על המבנה המקורי בפונקציה הקוראת, ולכן הגישה הזאת מושלמת לפונקציות שצריכות לעדכן או לשנות נתונים במבנה.
הטכניקה הזו חיונית לבניית תוכניות C יעילות שעובדות עם מבני נתונים מורכבים, מכיוון שהיא משלבת את העוצמה של מצביעים עם הארגון של מבני struct.
אתגר
קלצרו תוכנית C שמדגימה העברת מצביעים למבנים לפונקציות כדי לשנות נתונים ביעילות. התוכנית שלכם צריכה:
- להגדיר
structבשםBankAccountעם השדות הבאים:- מספר שלם
accountNumberלאחסון מספר החשבון - מערך תווים
ownerNameבגודל 30 לאחסון שם בעל החשבון - מספר ממשי מסוג float בשם
balanceלאחסון יתרת החשבון - מספר שלם
transactionCountלאחסון מספר העסקאות
- מספר שלם
- לכתוב פונקציה בשם
depositMoneyש:- מקבלת פרמטרים של מצביע למבנה
BankAccountוסכום מסוג float - מוסיפה את הסכום ליתרת החשבון באמצעות אופרטור החץ
- מגדילה את מספר העסקאות ב-1
- מדפיסה
Deposit successful. New balance: [balance]
- מקבלת פרמטרים של מצביע למבנה
- לכתוב פונקציה בשם
withdrawMoneyש:- מקבלת פרמטרים של מצביע למבנה
BankAccountוסכום מסוג float - בודקת אם סכום המשיכה גדול מהיתרה הנוכחית
- אם אין מספיק כספים, מדפיסה
Insufficient funds. Current balance: [balance] - אם יש מספיק כספים, מחסירה את הסכום מהיתרה, מגדילה את מספר העסקאות ומדפיסה
Withdrawal successful. New balance: [balance]
- מקבלת פרמטרים של מצביע למבנה
- לכתוב פונקציה בשם
displayAccountש:- מקבלת פרמטר של מצביע למבנה
BankAccount - מדפיסה את פרטי החשבון בדיוק בפורמט הבא:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- מקבלת פרמטר של מצביע למבנה
- בפונקציה main:
- ליצור משתנה מסוג
BankAccountבשםaccount - לקרוא מהקלט את מספר החשבון, שם הבעלים והיתרה ההתחלתית
- להגדיר את מספר העסקאות ל-0
- לקרוא ל-
displayAccountכדי להציג את מצב החשבון ההתחלתי - לקרוא סכום הפקדה ולקרוא ל-
depositMoney - לקרוא סכום משיכה ולקרוא ל-
withdrawMoney - לקרוא ל-
displayAccountכדי להציג את מצב החשבון הסופי
- ליצור משתנה מסוג
האתגר הזה מדגים את העוצמה שבהעברת מצביעים למבנים לפונקציות. בניגוד להעברה לפי ערך, הפונקציות מקבלות את כתובת הזיכרון של המבנה המקורי, וכך יכולות לשנות ישירות את הנתונים המקוריים. הגישה הזאת יעילה יותר (אין העתקה) ומאפשרת לפונקציות לשנות לצמיתות את ערכי המבנה בפונקציה הקוראת.
נסו בעצמכם
#include <stdio.h>
#include <string.h>
// TODO: הגדירו כאן את המבנה BankAccount
// TODO: כתבו כאן את הפונקציה depositMoney
// TODO: כתבו כאן את הפונקציה withdrawMoney
// TODO: כתבו כאן את הפונקציה displayAccount
int main() {
// קראו קלט
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// TODO: צרו משתנה מסוג BankAccount ואתחלו אותו
// TODO: קראו ל-displayAccount כדי להציג את המצב ההתחלתי
// TODO: קראו ל-depositMoney עם סכום ההפקדה
// TODO: קראו ל-withdrawMoney עם סכום המשיכה
// TODO: קראו ל-displayAccount כדי להציג את המצב הסופי
return 0;
}השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה לוגיקה וזרימת תוכנית
1יסודות המצביעים
מהו מצביע?הכרזה על מצביעיםאופרטור לקיחת הכתובת (&)אופרטור ביטול ההפניה (*)מצביעי NULLסיכום: יסודות המצביעים2מצביעים ומערכים
שמות מערכים כמצביעיםאיברי מערך ומצביעיםאריתמטיקה של מצביעיםהשוואת מצביעיםסיכום: מעבר על מערך באמצעות מצביעים5מצביעים ופונקציות
העברה לפי ערךהעברת מצביעים לפונקציותשינוי משתנים באמצעות מצביעיםדוגמה קלאסית: החלפההעברת מערכים לפונקציותחזרה: ארגומנטים של מצביעי פונקציה8מבנים ומצביעים
מצביעים למבניםאופרטור החץ (->)העברת מבנים לפי ערךהעברת מצביעים למבניםהקצאה דינמית של מבניםסיכום: שינוי מבנה באמצעות מצביע3מערכי תווים ומחרוזות
מחרוזות כמערכי charתו הסיום nullקלט מחרוזת באמצעות scanfשימוש ב־strlen()שימוש ב־strcpy()שימוש ב־strcat()שימוש ב־strcmp()סיכום: פונקציות מחרוזת בסיסיותתרגלו בעצמכם: קומפיילר C אונליין