Menu
Coddy logo textTech

מצביעים כערכים במפה

חלק מהיחידה לוגיקה וזרימת התוכנית במסלול ה-GO של Coddy. שיעור 27 מתוך 68.

אף ששמירת מבנים ישירות במפות היא שימושית, שמירת מצביעים למבנים פותחת אפשרות רבת־עוצמה: לשנות את נתוני המבנה המקורי ישירות דרך המפה. גישה זו חיונית כשצריך לעדכן את הנתונים לאחר ששמרת אותם.

כשמאחסנים מצביע למבנה כערך במפה, מאחסנים את כתובת הזיכרון של המבנה, ולא עותק שלו. כך מצהירים על מפה כזו ומשתמשים בה:

type Product struct {
    Price    float64
    Quantity int
}

products := map[string]*Product{
    "laptop": &Product{Price: 999.99, Quantity: 5},
    "mouse":  &Product{Price: 25.50, Quantity: 20},
}

היתרון המרכזי מתברר כשצריך לשנות את הנתונים. מכיוון שעובדים עם מצביעים, שינויים שנעשים דרך המפה משפיעים על המבנה המקורי:

// עדכנו את מחיר המחשב הנייד ישירות דרך המפה
products["laptop"].Price = 899.99
fmt.Println(products["laptop"].Price) // מדפיס: 899.99

התבנית הזאת שימושית במיוחד ביישומים שבהם צריך לעדכן לעיתים קרובות נתונים מאוחסנים, כמו מערכות מלאי, פרופילי משתמשים או כל תרחיש שבו המפה משמשת כמאגר הנתונים הראשי שלך והשינויים צריכים להישמר.

challenge icon

אתגר

קל

בנו מערכת פשוטה לניהול מלאי שמדגימה את העוצמה של שימוש במצביעים למבנים כערכים במפה. האתגר הזה מראה כיצד מפות המבוססות על מצביעים מאפשרות לשנות ישירות את הנתונים המאוחסנים, וכך להפוך את מערכת המלאי שלכם ליעילה ומגיבה לעדכונים.

תקבלו שלוש קלטים:

  • מחרוזת שמייצגת את מספר המוצרים (למשל, "4")
  • מחרוזת שמכילה נתוני מוצרים בפורמט: "name1:price1:quantity1,name2:price2:quantity2,name3:price3:quantity3" (למשל, "laptop:999.99:5,mouse:25.50:20,keyboard:75.00:15,monitor:299.99:8")
  • מחרוזת שמכילה פעולות עדכון בפורמט: "operation1:product1:value1,operation2:product2:value2", כאשר הפעולות הן "price" או "quantity" (למשל, "price:laptop:899.99,quantity:mouse:25,price:keyboard:65.00")

המשימה שלכם היא:

  1. להגדיר מבנה Product עם השדות הבאים:
    • Price (float64) - מחיר המוצר
    • Quantity (int) - כמות המוצר במלאי
  2. ליצור מפה שבה המפתחות הם שמות המוצרים (מחרוזות) והערכים הם מצביעים למבני Product
  3. לנתח את נתוני המוצרים מהקלט השני:
    • לפצל את הקלט לפי פסיקים כדי לקבל רשומות של מוצרים בודדים
    • עבור כל רשומה, לפצל לפי נקודתיים כדי להפריד בין השם, המחיר והכמות
    • להמיר את מחרוזת המחיר ל-float64 ואת מחרוזת הכמות למספר שלם
    • ליצור מבנה Product ולאחסן מצביע אליו במפה
  4. לשמור את שמות המוצרים בפרוסה נפרדת במהלך הניתוח, לפי הסדר שבו הם מופיעים בקלט. מעבר על מפה ב-Go מבקר במפתחות בסדר אקראי, ולכן הפרוסה היא זו ששומרת על הסדר המקורי של כל הרשימות.
  5. להציג את המלאי הראשוני עם הכותרת "Initial Inventory:"
  6. להציג כל מוצר בפורמט: "[name]: $[price] (Stock: [quantity])"
  7. לנתח ולהחיל את פעולות העדכון מהקלט השלישי:
    • לפצל את הקלט לפי פסיקים כדי לקבל פעולות בודדות
    • עבור כל פעולה, לפצל לפי נקודתיים כדי לקבל את סוג הפעולה, שם המוצר והערך החדש
    • לעדכן את השדה המתאים ישירות דרך המצביע שבמפה
    • להדפיס כל עדכון בפורמט: "Updated [product]: [field] changed to [new_value]"
  8. להציג את המלאי המעודכן עם הכותרת "Updated Inventory:"
  9. להציג שוב כל מוצר באותו פורמט כמו בתצוגה הראשונית
  10. לחשב ולהציג את הערך הכולל של המלאי: "Total Inventory Value: $[total_value]"

השתמשו בחבילה strconv כדי להמיר את מחרוזות המחיר והכמות לסוגים המספריים המתאימים. הציגו את כל המחירים עם 2 ספרות אחרי הנקודה העשרונית. האתגר הזה מדגים כיצד אחסון מצביעים במפות מאפשר לשנות ישירות את נתוני המבנה המקורי, וכך לעדכן את המלאי באופן מיידי ומתמשך, בלי צורך להקצות מחדש ערכים במפה.

נסו בעצמכם

package main

import (
	"fmt"
	"strconv"
	"strings"
)

func main() {
	// קראו את הקלט
	var numProductsStr string
	var productDataStr string
	var operationsStr string
	
	fmt.Scanln(&numProductsStr)
	fmt.Scanln(&productDataStr)
	fmt.Scanln(&operationsStr)
	
	// TODO: הגדירו כאן את ה-struct ‏Product
	
	// TODO: צרו map לאחסון מצביעים למוצרים
	
	// TODO: צרו slice לשמירה על סדר המוצרים (כדי להבטיח פלט עקבי)
	
	// TODO: נתחו את נתוני המוצרים ומלאו את ה-map
	// זכרו:
	// - פצלו את productDataStr לפי פסיקים כדי לקבל רשומות נפרדות
	// - עבור כל רשומה, פצלו לפי נקודתיים כדי לקבל שם, מחיר וכמות
	// - המירו את המחרוזות של המחיר והכמות לטיפוסים המתאימים
	// - אחסנו מצביע ל-struct ‏Product ב-map
	// - הוסיפו את שם המוצר ל-slice של הסדר
	
	// TODO: הציגו את המלאי ההתחלתי
	// השתמשו ב-slice של הסדר כדי לעבור על המוצרים באופן עקבי
	// פורמט: "[name]: $[price] (Stock: [quantity])"
	
	// TODO: נתחו והחילו את פעולות העדכון
	// זכרו:
	// - פצלו את operationsStr לפי פסיקים כדי לקבל פעולות נפרדות
	// - לכל פעולה, פצלו לפי נקודתיים כדי לקבל סוג, שם וערך
	// - עדכנו את השדה המתאים ישירות דרך המצביע שב-map
	// - הדפיסו הודעת עדכון לכל פעולה
	
	// TODO: הציגו את המלאי המעודכן
	// שוב, השתמשו ב-slice של הסדר כדי להפיק פלט עקבי
	// חשבו את הערך הכולל בזמן ההצגה
	
	// TODO: חשבו והציגו את הערך הכולל של המלאי
	// פורמט: "Total Inventory Value: $[total_value]"
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה לוגיקה וזרימת התוכנית

תרגלו בעצמכם: קומפיילר Go אונליין