Menu
CoddyTech

دالة لعرض جهة اتصال

جزء من قسم المنطق وتدفق التنفيذ في رحلة C على Coddy. الدرس 53 من 63.

challenge icon

التحدي

سهل

استنادًا إلى نظام إدارة جهات الاتصال الذي أنشأته في الدروس السابقة، أنشئ دالة تعرض معلومات جهة الاتصال بتنسيق منظّم. يقدم هذا الدرس ثلاث دوال سلاسل نصية جديدة ستحتاج إليها: 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 إذا لم يُعثر عليه.

ينبغي أن ينفذ برنامجك ما يلي:

  1. استخدم تعريف البنية Contact نفسه من الدروس السابقة، مع الأعضاء التالية:
    • مصفوفة أحرف name بحجم 50
    • مصفوفة أحرف phone بحجم 20
    • مصفوفة أحرف email بحجم 40
    • عدد صحيح age
  2. استخدم دالة createContact نفسها من الدروس السابقة، والتي:
    • تخصص ذاكرة ديناميكيًا لبنية Contact
    • تهيئ جميع الأعضاء بالقيم الافتراضية
    • تعيد مؤشرًا إلى جهة الاتصال
  3. اكتب دالة populateContact التي:
    • تأخذ مؤشرًا إلى بنية Contact كمعامل لها
    • تستخدم fgets() لقراءة كل حقل نصي (الاسم والهاتف والبريد الإلكتروني) بحيث تُقبل الأسماء التي تحتوي على مسافات
    • تستخدم strcspn() لإزالة حرف السطر الجديد من نهاية كل حقل نصي بعد قراءته
    • تستخدم scanf("%d", ...) لقراءة حقل العمر ذي العدد الصحيح
    • قبل قراءة كل حقل، تطبع موجّهه كما هو تمامًا، من دون حرف سطر جديد بعده: Enter name: وEnter phone: وEnter email: وEnter age: (لذا يظهر === CONTACT DETAILS === بعد Enter age: في السطر نفسه)
    • ملاحظة: لا يتضمن هذا الإصدار من populateContact التحقق من طول رقم الهاتف: لا تضف هذا التحقق، إذ تستخدم مدخلات الاختبار أرقام هواتف قصيرة مثل 555-1234
  4. اكتب دالة باسم 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
      • تتحقق مما إذا كان البريد الإلكتروني يحتوي على الحرف '@' باستخدام strchr() وتطبع:
        • إذا عُثر على '@': Email format: Valid
        • إذا لم يُعثر على '@': Email format: Invalid
  5. في الدالة الرئيسية:
    • أنشئ جهة اتصال باستخدام الدالة 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;
}

جميع دروس المنطق وتدفق التنفيذ

تدرّب بنفسك: مترجم C عبر الإنترنت