Menu
CoddyTech

連絡先を表示する関数

CoddyのCジャーニー「論理と制御フロー」セクションの一部。レッスン 53/63。

challenge icon

チャレンジ

簡単

前のレッスンで作成した連絡先管理システムを発展させ、連絡先情報を整形して表示する関数を作成しましょう。このレッスンでは、新たに必要となる3つの文字列関数、fgets()、strcspn()、strchr()を紹介します。要件の前に、それぞれについて以下で説明します。

このレッスンで使用する新しい関数:

  • fgets(buffer, size, stdin): 空白を含む入力行を読み取ります(空白で読み取りを停止するscanfとは異なります)。入力をbufferに格納し、最大でsize - 1文字を読み取ります。また、末尾に改行文字'\n'も格納します。
  • strcspn(str, "\n"): str内で最初に'\n'が出現する位置のインデックスを返します。fgetsが残す末尾の改行を削除するために使用します: str[strcspn(str, "\n")] = '\0';
  • strchr(str, ch): str内で文字chを検索し、その位置へのポインターを返します。見つからない場合はNULLを返します。

プログラムは次の要件を満たす必要があります:

  1. 前のレッスンと同じContact構造体の定義を使用し、次のメンバーを含めます:
    • サイズ50の文字配列name
    • サイズ20の文字配列phone
    • サイズ40の文字配列email
    • 整数age
  2. 前のレッスンと同じcreateContact関数を使用します。この関数は次の処理を行います:
    • Contact構造体用のメモリを動的に確保する
    • すべてのメンバーをデフォルト値で初期化する
    • 連絡先へのポインターを返す
  3. 次の処理を行うpopulateContact関数を作成します:
    • Contact構造体へのポインターをパラメーターとして受け取る
    • 各文字列フィールド(name、phone、email)の読み取りに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. main関数では:
    • 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オンラインコンパイラ