פונקציה להצגת איש קשר
חלק מהיחידה לוגיקה וזרימת תוכנית במסלול ה-C של Coddy. שיעור 53 מתוך 63.
אתגר
קלבהסתמך על מערכת ניהול אנשי הקשר שבנית בשיעורים הקודמים, צרו פונקציה שמציגה פרטי איש קשר בצורה מעוצבת. בשיעור הזה נכיר שלוש פונקציות מחרוזת חדשות שתזדקקו להן: fgets(), strcspn() ו־strchr(): כל אחת מהן מוסברת בהמשך, לפני הדרישות.
פונקציות חדשות שבהן משתמשים בשיעור הזה:
fgets(buffer, size, stdin): קוראת שורת קלט, כולל רווחים (בניגוד ל־scanf, שעוצרת בתו רווח). היא שומרת את הקלט ב־buffer, וקוראת לכל היותרsize - 1תווים. היא גם שומרת את תו ירידת השורה'\n'בסוף.strcspn(str, "\n"): מחזירה את האינדקס של ההופעה הראשונה של'\n'בתוךstr. משתמשים בה כדי להסיר את תו ירידת השורה שנשאר בסוף בעקבותfgets:str[strcspn(str, "\n")] = '\0';strchr(str, ch): מחפשת את התוchבתוךstrומחזירה מצביע למיקומו, אוNULLאם הוא לא נמצא.
התוכנית שלכם צריכה:
- להשתמש בהגדרה של המבנה
Contactמהשיעורים הקודמים, עם השדות:- מערך תווים בשם
nameבגודל 50 - מערך תווים בשם
phoneבגודל 20 - מערך תווים בשם
emailבגודל 40 - מספר שלם בשם
age
- מערך תווים בשם
- להשתמש באותה פונקציה
createContactמהשיעורים הקודמים, אשר:- מקצה באופן דינמי זיכרון עבור מבנה
Contact - מאתחלת את כל השדות לערכי ברירת מחדל
- מחזירה מצביע לאיש הקשר
- מקצה באופן דינמי זיכרון עבור מבנה
- לכתוב פונקציה בשם
populateContact, אשר:- מקבלת כפרמטר מצביע למבנה
Contact - משתמשת ב־
fgets()כדי לקרוא כל שדה מחרוזת (שם, טלפון, דוא"ל), כך שאפשר יהיה להזין שמות עם רווחים - משתמשת ב־
strcspn()כדי להסיר את תו ירידת השורה שבסוף כל שדה מחרוזת לאחר קריאתו - משתמשת ב־
scanf("%d", ...)כדי לקרוא את שדה הגיל, שהוא מספר שלם - לפני קריאת כל שדה, מדפיסה בדיוק את ההנחיה המתאימה, ללא ירידת שורה אחריה:
Enter name:,Enter phone:,Enter email:,Enter age:(כך ש־=== CONTACT DETAILS ===מופיע באותה שורה מיד אחריEnter age:) - הערה: גרסה זו של
populateContactאינה כוללת בדיקת אורך של מספר הטלפון: אל תוסיפו אותה, כי בקלטי הבדיקה נעשה שימוש במספרי טלפון קצרים כמו555-1234
- מקבלת כפרמטר מצביע למבנה
- לכתוב פונקציה בשם
displayContact, אשר:- מקבלת כפרמטר מצביע קבוע למבנה
Contact:const struct Contact *contactPtr - לא מחזירה ערך (void)
- מדפיסה את פרטי איש הקשר בדיוק בתבנית הבאה:
=== CONTACT DETAILS ===Name: [name]Phone: [phone]Email: [email]Age: [age] years old========================
- לאחר הצגת הפרטים הבסיסיים, מחשבת ומציגה פרטים נוספים:
- מחשבת את אורך השם באמצעות
strlen()ומדפיסה:Name length: [length] characters - קובעת את קטגוריית הדור לפי הגיל ומדפיסה:
- אם הגיל בין 0 ל־12:
Generation: Child - אם הגיל בין 13 ל־19:
Generation: Teenager - אם הגיל בין 20 ל־39:
Generation: Young Adult - אם הגיל בין 40 ל־59:
Generation: Middle-aged Adult - אם הגיל הוא 60 ומעלה:
Generation: Senior
- אם הגיל בין 0 ל־12:
- בודקת אם כתובת הדוא"ל מכילה את התו
'@'באמצעותstrchr()ומדפיסה:- אם
'@'נמצא:Email format: Valid - אם
'@'לא נמצא:Email format: Invalid
- אם
- מחשבת את אורך השם באמצעות
- מקבלת כפרמטר מצביע קבוע למבנה
- בפונקציה הראשית:
- יוצרת איש קשר באמצעות הפונקציה
createContact - בודקת אם יצירת איש הקשר הצליחה
- קוראת לפונקציה
populateContactכדי למלא את פרטי איש הקשר - קוראת לפונקציה
displayContactכדי להציג את פרטי איש הקשר בתבנית המעוצבת - משחררת את הזיכרון שהוקצה באופן דינמי
- מדפיסה
Program completed successfully
- יוצרת איש קשר באמצעות הפונקציה
האתגר הזה מדגים כיצד ליצור פונקציית תצוגה שמקבלת מצביע קבוע למבנה, ובכך מבטיחה שהפונקציה לא תוכל לשנות את הנתונים המקוריים. תתרגלו שימוש ב־fgets() לקריאת מחרוזות שמכילות רווחים, ב־strcspn() להסרת תווי ירידת שורה בסוף מחרוזת, באופרטור החץ כדי לגשת לשדות של מבנה דרך מצביע, ב־strchr() לחיפוש תווים, ובלוגיקה מותנית לסיווג נתונים. השימוש ב־const בהצהרת הפרמטר הוא נוהג מומלץ שמונע שינויים מקריים בפרטי איש הקשר בתוך פונקציית התצוגה.
נסו בעצמכם
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[50];
char phone[20];
char email[40];
int age;
} Contact;
Contact* createContact() {
Contact* contact = (Contact*)malloc(sizeof(Contact));
if (contact == NULL) {
return NULL;
}
strcpy(contact->name, "");
strcpy(contact->phone, "");
strcpy(contact->email, "");
contact->age = 0;
return contact;
}
void populateContact(Contact* contactPtr) {
printf("Enter name: ");
scanf("%s", contactPtr->name);
printf("Enter phone: ");
scanf("%s", contactPtr->phone);
printf("Enter email: ");
scanf("%s", contactPtr->email);
printf("Enter age: ");
scanf("%d", &contactPtr->age);
if (contactPtr->age < 0 || contactPtr->age > 120) {
printf("Invalid age entered\n");
} else if (strlen(contactPtr->phone) < 10) {
printf("Invalid phone number\n");
} else {
printf("Contact populated successfully\n");
}
}
int main() {
Contact* contact = createContact();
if (contact == NULL) {
return 1;
}
populateContact(contact);
printf("Contact Information:\n");
printf("Name: %s\n", contact->name);
printf("Phone: %s\n", contact->phone);
printf("Email: %s\n", contact->email);
printf("Age: %d\n", contact->age);
free(contact);
printf("Contact deleted successfully\n");
return 0;
}כל השיעורים ביחידה לוגיקה וזרימת תוכנית
1יסודות המצביעים
מהו מצביע?הכרזה על מצביעיםאופרטור לקיחת הכתובת (&)אופרטור ביטול ההפניה (*)מצביעי NULLסיכום: יסודות המצביעים2מצביעים ומערכים
שמות מערכים כמצביעיםאיברי מערך ומצביעיםאריתמטיקה של מצביעיםהשוואת מצביעיםסיכום: מעבר על מערך באמצעות מצביעים5מצביעים ופונקציות
העברה לפי ערךהעברת מצביעים לפונקציותשינוי משתנים באמצעות מצביעיםדוגמה קלאסית: החלפההעברת מערכים לפונקציותחזרה: ארגומנטים של מצביעי פונקציה3מערכי תווים ומחרוזות
מחרוזות כמערכי charתו הסיום nullקלט מחרוזת באמצעות scanfשימוש ב־strlen()שימוש ב־strcpy()שימוש ב־strcat()שימוש ב־strcmp()סיכום: פונקציות מחרוזת בסיסיות6ניהול זיכרון
זיכרון מחסנית לעומת ערימההקצאה דינמית - malloc()שימוש ב-sizeof() להקצאהבדיקת כישלון בהקצאהשחרור זיכרון באמצעות free()הקצאה באמצעות calloc()סיכום: מערך דינמי9פרויקט: רישום איש קשר פשוט
פרויקט: הגדרת מבנה איש קשרפונקציה ליצירת איש קשרתרגלו בעצמכם: קומפיילר C אונליין