Implementing a Contact Management System in C

Building a Small Address Book in C

Mini Project: Address Book System

Menu screenshot

Requirements: Store contact information:
Name, Gender, Phone
Maximum capacity: 50 contacts
Functional requirements:

  1. Add a contact
  2. Delete a contact by name
  3. Modify a contact by name
  4. Search contacts by name or phone (supports fuzzy search)
  5. Display all contacts
  6. Exit the system

This address book stores data in a file, so even after closing the program, the information persists for the next session.

Without further ado, here is the code.

main.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "contact.h"
#include "utils.h"
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_INPUT_LENGTH 100

main.c

Contains the main menu code.

#include "main.h"

int main() {
   Contact phonebook[MAX_CONTACTS];
   initialize_contacts(phonebook);
   int count = 0;

   // Load contacts from file into array
   load_contacts(phonebook, &count);

   int choice;
   char input[MAX_INPUT_LENGTH];

   do {
       printf("\n===== Contact Management System =====\n");
       printf("1. Add Contact\n");
       printf("2. Delete Contact\n");
       printf("3. Modify Contact\n");
       printf("4. Search Contact\n");
       printf("5. Display All Contacts\n");
       printf("6. Exit\n");
       printf("Enter your choice: ");
       scanf("%d", &choice);

       switch (choice) {
           case 1: {
               system("clear"); // Use "cls" on Windows
               load_contacts(phonebook, &count);
               Contact new_entry;
               printf("Enter name: ");
               scanf("%s", new_entry.name);
               printf("Enter gender (M/F): ");
               scanf(" %s", new_entry.gender);
               printf("Enter phone number: ");
               scanf("%s", new_entry.phone);
               if (is_valid_name(new_entry.name) && is_valid_phone(new_entry.phone)) {
                   if (add_contact(phonebook, &count, &new_entry)) {
                       save_contacts(phonebook, count);
                       printf("Contact added successfully.\n");
                   } else {
                       printf("Failed to add contact.\n");
                   }
               } else {
                   printf("Invalid name or phone number.\n");
               }
               break;
           }
           case 2: {
               system("clear");
               load_contacts(phonebook, &count);
               char target_name[MAX_NAME_LENGTH];
               printf("Enter the name of the contact to delete: ");
               scanf("%s", target_name);
               if (delete_contact(phonebook, &count, target_name)) {
                   save_contacts(phonebook, count);
                   printf("Contact deleted successfully.\n");
               }
               break;
           }
           case 3: {
               system("clear");
               char target_name[MAX_NAME_LENGTH];
               Contact updated_info;
               load_contacts(phonebook, &count);
               printf("Enter the name of the contact to modify: ");
               scanf("%s", target_name);
               printf("Enter new name: ");
               scanf("%s", updated_info.name);
               printf("Enter new gender (M/F): ");
               scanf(" %s", updated_info.gender);
               printf("Enter new phone number: ");
               scanf("%s", updated_info.phone);
               if (is_valid_name(updated_info.name) && is_valid_phone(updated_info.phone)) {
                   if (modify_contact(phonebook, count, target_name, &updated_info)) {
                       save_contacts(phonebook, count);
                       printf("Contact modified successfully.\n");
                   }
               } else {
                   printf("Invalid name or phone number.\n");
               }
               break;
           }
           case 4: {
               system("clear");
               load_contacts(phonebook, &count);
               char query[MAX_INPUT_LENGTH];
               printf("Enter search keyword: ");
               scanf("%s", query);
               search_contact(phonebook, count, query);
               break;
           }
           case 5:
               system("clear");
               load_contacts(phonebook, &count);
               display_contacts(phonebook, count);
               break;
           case 6:
               printf("Exiting program...\n");
               exit(0);
           default:
               printf("Invalid choice, please try again!\n");
       }
   } while (choice != 6);

   return 0;
}

contact.h
#ifndef CONTACT_H
#define CONTACT_H

#define MAX_CONTACTS 50
#define MAX_NAME_LENGTH 50
#define MAX_PHONE_LENGTH 20

typedef struct {
   char name[MAX_NAME_LENGTH];
   char gender[10];
   char phone[MAX_PHONE_LENGTH];
} Contact;

void initialize_contacts(Contact contacts[]);
int add_contact(Contact contacts[], int* num_contacts, const Contact* new_contact);
int delete_contact(Contact contacts[], int* num_contacts, const char* name);
int modify_contact(Contact contacts[], int num_contacts, const char* name, const Contact* new_contact);
void search_contact(Contact contacts[], int num_contacts, const char* query);
void display_contacts(Contact contacts[], int num_contacts);

int load_contacts(Contact contacts[], int* num_contacts);
void save_contacts(Contact contacts[], int num_contacts);

#endif /* CONTACT_H */

contact.c

Contains CRUD functions.

#include "main.h"

void initialize_contacts(Contact list[]) {
   for (int i = 0; i < MAX_CONTACTS; ++i) {
       list[i].name[0] = '\0';
   }
}

int add_contact(Contact list[], int* count, const Contact* new_entry) {
   if (*count >= MAX_CONTACTS) {
       printf("Address book is full. Cannot add contact.\n");
       return 0;
   }
   list[*count] = *new_entry;
   (*count)++;
   save_contacts(list, *count);
   printf("Contact %s added successfully.\n", new_entry->name);
   return 1;
}

int delete_contact(Contact list[], int* count, const char* name) {
   int found = 0;
   FILE* fp = fopen("contacts.txt", "w");
   if (fp == NULL) {
       perror("Failed to open contacts.txt");
       return 0;
   }
   for (int i = 0; i < *count; ++i) {
       if (strcmp(list[i].name, name) == 0) {
           found = 1;
       } else {
           fprintf(fp, "%s %s %s\n", list[i].name, list[i].gender, list[i].phone);
       }
   }
   fclose(fp);
   if (found) {
       (*count)--;
       printf("Contact %s deleted successfully.\n", name);
       return 1;
   } else {
       printf("Contact with name %s not found.\n", name);
       return 0;
   }
}

int modify_contact(Contact list[], int count, const char* name, const Contact* updated) {
   int found = 0;
   for (int i = 0; i < count; ++i) {
       if (strcmp(list[i].name, name) == 0) {
           list[i] = *updated;
           found = 1;
           printf("Contact %s updated successfully.\n", name);
           break;
       }
   }
   if (!found) {
       printf("Contact with name %s not found.\n", name);
   } else {
       save_contacts(list, count);
   }
   return found;
}

void display_contacts(Contact list[], int count) {
   printf("All contacts:\n");
   for (int i = 0; i < count; i++) {
       printf("Name: %s  Gender: %s  Phone: %s\n", list[i].name, list[i].gender, list[i].phone);
   }
}

void search_contact(Contact list[], int count, const char* query) {
   int found = 0;
   printf("Search results:\n");
   printf("%-6s %-10s %-10s\n", "Name", "Gender", "Phone");
   for (int i = 0; i < count; i++) {
       if (strstr(list[i].name, query) != NULL || strstr(list[i].phone, query) != NULL) {
           printf("%-6s %-10s %-10s\n", list[i].name, list[i].gender, list[i].phone);
           found = 1;
       }
   }
   if (!found) {
       printf("No contacts found matching '%s'.\n", query);
   }
}

int load_contacts(Contact list[], int* count) {
   FILE* fp = fopen("contacts.txt", "r");
   if (fp == NULL) {
       perror("Failed to open contacts.txt");
       return 0;
   }
   *count = 0;
   char line[100];
   while (fgets(line, sizeof(line), fp) != NULL) {
       if (sscanf(line, "%s %s %s", list[*count].name, list[*count].gender, list[*count].phone) == 3) {
           (*count)++;
       }
   }
   fclose(fp);
   return *count;
}

void save_contacts(Contact list[], int count) {
   FILE* fp = fopen("contacts.txt", "w");
   if (fp == NULL) {
       perror("Failed to open contacts.txt");
       return;
   }
   for (int i = 0; i < count; ++i) {
       fprintf(fp, "%s %s %s\n", list[i].name, list[i].gender, list[i].phone);
   }
   fclose(fp);
}

utils.h
#ifndef UTILS_H
#define UTILS_H

int is_valid_name(const char *name);
int is_valid_phone(const char *phone);
int string_starts_with(const char *str, const char *prefix);
void load_num_contacts(int* num_contacts);

#endif /* UTILS_H */

utils.c

Contains utility functoins for validation and file operations.

#include "main.h"

int is_valid_name(const char* name) {
   if (name == NULL || strlen(name) == 0) {
       return 0;
   }
   return 1;
}

int is_valid_phone(const char* phone) {
   if (phone == NULL || strlen(phone) == 0) {
       return 0;
   }
   for (int i = 0; phone[i] != '\0'; i++) {
       if (!isdigit(phone[i])) {
           return 0;
       }
   }
   return 1;
}

int string_starts_with(const char* str, const char* prefix) {
   if (str == NULL || prefix == NULL) {
       return 0;
   }
   size_t len_str = strlen(str);
   size_t len_prefix = strlen(prefix);
   if (len_str < len_prefix) {
       return 0;
   }
   return strncmp(str, prefix, len_prefix) == 0;
}

void load_num_contacts(int* num_contacts) {
   FILE* fp = fopen("num_contacts.txt", "r");
   if (fp == NULL) {
       perror("Failed to open num_contacts.txt");
       return;
   }
   fscanf(fp, "%d", num_contacts);
   fclose(fp);
}

Tags: C contact management File I/O Data Structures Address Book

Posted on Sun, 02 Aug 2026 16:21:01 +0000 by benjy