• Labs icon Lab
  • Core Tech
Labs

Guided: Arrays, Strings, and Basic String Manipulation in C

Master arrays and string manipulation in C with this hands-on Code Lab. Build a functional Contact Management Application to store, search, delete, and list contacts using arrays and strings. Debug common issues and explore string handling techniques. By the end of this lab, you'll have the skills to solve real-world problems using arrays and strings in C.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 43m
Published
Clock icon Feb 11, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    In this lab, you will learn how to manipulate arrays and strings in C by implementing operations such as adding, searching, deleting, and listing contacts in a simple contact management app. You will also practice debugging common array and string issues, sorting, and searching data effectively.


    Learning Objectives:

    • Handle arrays and strings effectively in C.
    • Perform basic string manipulation tasks.
    • Debug common issues with arrays and strings.

    Use Case:

    You will build a contact management app that stores names and phone numbers in an array, allowing users to:

    • Add contacts.
    • Display contacts.
    • Search for contacts.
    • Delete contact

    Before you begin, here are some key points:

    1. You will implement code in the contact_management.c file.
    2. If you face any challenges, refer to the solution directory for guidance.
    3. To help you locate changes easily, comments indicate required modifications for each task, e.g., // Task 2.1.
    4. You can execute the program using the Run button or by running the following commands in the Terminal.
    Compile the code and generate the output a.exe:
    g++ contact_management.c
    
    Run the generated a.exe:
    ./a.out
    

    Let's get started !

  2. Challenge

    Strings and Arrays

    In this step, you will understand about strings and arrays in C.


    String (One Dimentional Arrays)

    In C, a string is essentially a one-dimensional array of characters, terminated by a special null character (\0). This null character marks the end of the string and is critical for string manipulation.

    Declaring and Initializing Strings

    1. Declaration with size

    char str[10];
    

    This reserves space for a string of up to 9 characters (plus the null terminator \0).

    2. With size and initial value

    char str[10] = "Hello";
    

    Here, the array str has space for 10 characters, but only 6 (including \0) are used.

    3. Without specifying size

    char str[] = "World";
    

    The compiler automatically allocates enough space for the string, i.e., 6 characters (5 for "World" + \0).


    Two-Dimensional Arrays

    A two-dimensional array is a table (matrix) of elements, where each element is accessed using two indices:

    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    
    // Access element in the second row, third column
    printf("%d\n", matrix[1][2]); // Output: 6
    
    

    You can also extend this concept to multi-dimensional arrays, with additional dimensions added as needed.


    Great! Now that you understand arrays and strings, you’ll use this knowledge to declare the names and phones arrays for your contact management system.

    These arrays will store the names and phone numbers of your contacts, using strings for both. Similarly you'll also declare the phones array. Now that you’ve learned how to declare and initialize arrays, the next step is to implement the add_contacts function and store the contacts in the array.

  3. Challenge

    Storing Contacts

    In this step, you will learn how to add items to the array. You will then use this knowledge to add contacts to the array.

    Before you get started, you'll understand some of the string fucntions.


    strcpy

    strcpy copies one string into another.

    The content of the destination is replaced with the source content.

    Syntax:

    strcpy(destination, source);
    

    Example

    char str1[10] = "ABC";
    char str2[10] = "123";
        
    // Copy the contents of str2 into str1
    strcpy(str1, str2); 
    
    // Output: 123    
    printf("str1 after strcpy: %s\n", str1); 
    

    Key Points

    • The destination array (str1) must have enough space to hold the source string (str2) and the null terminator.

    strcat

    strcat appends one string to the end of another.

    The content of the source string is added to the end of the destination string.

    Syntax:

    strcat(destination, source);
    

    Example:

    // Ensure enough space for concatenation
    char str1[20] = "Hello";  
    char str2[] = " World!";
    
    // Append the contents of str2 to str1
    strcat(str1, str2);
    
    // Output: HelloWorld!
    printf("str1 after strcat: %s\n", str1);
    

    Key Points

    • The destination array (str1) must have enough space to hold both its original content, the source string (str2), and the null terminator.
    • A null terminator is automatically added at the end of the concatenated string.

    Now, you will use these utility functions to complete the add_contact function, where you will concatenate the first name, then " " space and last name to create the full name. Great ! Now that you've successfully implemented the add_contact function. It's time to test it.

    When you test the code, you'll find that the following scenario works as expected:

    Enter First Name: John
    Enter Last Name: Doe
    [Full Name] : John Doe
    Enter Phone Number: 122456
    Contact added successfully!
    

    However, when there is a space in the First Name, the program behaves unexpectedly and skips the Last Name input altogether:

    Enter First Name: John Thomas
    Enter Last Name:
    [Full Name] : John Thomas
    Enter Phone Number: 122456
    Contact added successfully!
    

    This issue occurs because of how scanf handles input when a space is included in the user's input.

    Now you'll understand more about it and how to fix it.

    ---- #### Why the Problem Occurs with Spaces in Input

    When you use scanf("%s", ...), it stops reading at the first space or newline. For example:

    • If you input John Thomas for the first name, scanf reads John and leaves Thomas and the newline (\n) in the input buffer.
    • The next scanf for the last name or phone number doesn't work properly due to the leftover newline or space.

    Why getchar() is Needed

    The leftover newline or space in the input buffer interferes with subsequent scanf calls. Using getchar() clears this, ensuring the program works as expected.

    Fix:

    1. Use scanf("%[^\n]s", ...) to read the full line, including spaces.
    2. After each scanf, use getchar() to clear any leftover characters (like \n).

    This ensures the program handles spaces in input correctly and maintains smooth input flow. In this step, you learned how to use string functions like strcpy and strcat to manage names, as well as how to read and store phone numbers.

    You also explored how to handle text input with spaces.

    Currently, even though you've set a maximum input length, users can still enter larger text, causing a buffer overflow. In the next step, you'll learn more about buffer overflow and how to prevent it.

  4. Challenge

    Understanding Buffer Overflow

    What is Buffer Overflow?

    In C, arrays have fixed sizes, and when you use functions like strcpy, strncpy, and strncat, it's important to ensure that the input does not exceed the array's allocated space. If the input data is larger than the buffer size, it will overwrite adjacent memory, causing a buffer overflow. Buffer overflow is a common source of security vulnerabilities and program crashes.


    Example:

    char name[10];
    scanf("%s", name);  
    // User inputs 'ThisIsAVeryLongName'
    
    

    Buffer overflow occurs when more data is written to a buffer than it can hold. This can lead to:

    1. Data corruption: Overwriting memory that the program did not intend to change, leading to incorrect results or program malfunction.

    2. Security risks: Malicious input could exploit a buffer overflow to inject and execute arbitrary code, potentially allowing attackers to take control of the system.

    3. Program crashes: The program may crash unexpectedly if it writes past the end of an array, potentially corrupting the memory structure.


    How Size Limitations Prevent Buffer Overflow:

    By using functions like strncpy or strncat with size restrictions you ensure that:

    • Only the allowed number of characters are copied into the buffer.
    • Any additional input is discarded, preventing it from overwriting other data in memory.

    example

    char source[] = "Hello!";
    char dest1[5];
    char dest2[5];
    
    // Using strcpy
    strcpy(dest1, source);
    printf("strcpy result: %s\n", dest1);  
    // Output: Hello!
    
    // Using strncpy
    strncpy(dest2, source, 4);  // Copy only the first 4 characters
    dest2[4] = '\0';  // Ensure null termination
    printf("strncpy result: %s\n", dest2);  
    // Output: Hell
    
    

    Output

    strcpy result: Hello!
    strncpy result: Hell
    
    

    In the above example

    1. strcpy: Copies the entire string from source to dest1.
    2. strncpy: Copies only the first 4 characters from source to dest2, and manually null terminator to dest2.

    info> strncpy does not automatically null-terminate the destination string if the source string is longer than the specified length. Therefore, you need to manually ensure null termination after using strncpy.

    Similarly, strncat concatenates a specified number of characters from one string to another, preventing buffer overflow.

    info> strncat automatically null-terminates the resulting string, but you need to ensure that the destination string has enough space to accommodate the concatenated result.


    The strlen function in C is used to determine the length of a null-terminated string.

    Example :

    char str[] = "Hello";
    printf("Length of the string: %zu\n", strlen(str));
    // Output : Length of the string: 5
    

    Now you'll replace strcpy with strncpy to limit the number of characters copied. Next, update the strcat to strncat, which appends only the specified number of characters. For safety, explicitly add a null terminator at the end of the array to ensure the string is properly null-terminated, even if the length approaches NAME_LENGTH. Alternatively, you can specify the maximum number of characters to be read from the input.

    To read only a two-digit ISO country code:

    scanf("%2[^\n]", country_code);
    

    Similarly, you can use this approach to read a maximum of 14 characters for the phone number. In this step, you learned about buffer overflow and how to prevent it by using functions like strncpy and strncat with size limitations. You also updated the scanf format specifiers to restrict input length, ensuring safe copying and proper null termination. These changes help prevent data corruption, security risks, and program crashes.

    In the next step, you will implement the display_contacts function to display all stored contacts.

  5. Challenge

    List All Contacts

    In this step, you will implement the display_contact function to ensure that the contacts are displayed in ascending order based on their names.

    Before implementing the function, you'll first learn how the strcmp function works. This will help you compare strings to determine their order.

    --- #### strcmp

    The strcmp function in C compares two strings lexicographically. It returns:

    • 0 if the strings are identical.
    • A negative value if the first string is lexicographically smaller.
    • A positive value if the first string is lexicographically greater.

    Example with three cases:

    char str1[] = "apple";
    char str2[] = "banana";
    char str3[] = "apple";
        
    printf("Case 1 (apple vs banana): %d\n", 
      strcmp(str1, str2));
    // Negative (apple < banana)
    
    printf("Case 2 (apple vs apple): %d\n", 
      strcmp(str1, str3));
    // 0 (apple == apple)
    
    printf("Case 3 (banana vs apple): %d\n",
      strcmp(str2, str1));
    // Positive (banana > apple)
    

    Output:

    Comparison 1 (apple vs banana): -1
    Comparison 2 (apple vs apple): 0
    Comparison 3 (banana vs apple): 1
    

    In this example:

    • "apple" is less than "banana" (negative result).
    • "apple" is equal to "apple" (zero result).
    • "banana" is greater than "apple" (positive result). In the display_contact function you will use the bubble sort to sort contacts by name.

    Next, if the current contact is greater than the next, swap the contact names.

    --

    For instance, to swap the values of A and B, you would use a temporary variable to temporarily store one of the values.

    // Swap the following values
    A = 1, B = 2
    
    X = A;
    A = B;
    B = X;
    

    Output:

    A = 2, B = 1
    

    Now you will swap the contact name using strcpy. Good job ! Now similarly swap the phone numbers. It's time to test!

    Run the application, add a few contacts, and then select the Display Contacts option. The contacts should now appear in sorted order.

    In this step, you learned how to use strcmp and successfully implemented Bubble Sort to sort contacts by name.

  6. Challenge

    Searching for Contacts

    In this step, you will implement the contact search functionality within the search_contact function.

    You will also learn about the strstr and toLower function, which will be essential for the implementation.


    Substring - strstr

    The strstr function in C is used to find the first occurrence of a substring within a string. It returns a pointer to the beginning of the substring if found, or NULL if the substring is not present.

    Example:

    char *result = strstr("Hello, world!", "world");
    
    • If "world" is found, result will point to "world" in "Hello, world!".
    • If not found, result will be NULL.

    info> strstr performs a case-sensitive search.


    tolower

    The tolower function in C is used to convert a character to its lowercase equivalent. If the character is already lowercase or is not a letter, it returns the character unchanged.

    char ch = 'A';
    char lowerCh = tolower(ch);
    printf("Lowercase: %c\n", lowerCh);  // Output: a
    

    Output:

    Lowercase: a
    

    While searching for contacts you need a case-insensitive search to match any text within the contact names.

    Example: Contact Names

    • John Barclay
    • Carry Bob
    • Justin John

    Search for: john

    Expected Result:

    The list should display the following matching names:

    • John Barclay
    • Justin John

    Next you will update the to_lowercase funtion so that it correctly returns string in lowercase format. Now, use strstr to check if the entered search name matches any names in the contact array. Good work!

    Now it's time to test the solution by adding some contacts and searching for a contact using either the first or last name. The search feature will be especially useful as the contact list grows.

    In this step, you implemented the Search Contact functionality using strstr and tolower for case-insensitive substring matching within the contact names. In the next step, you will implement the Delete Contact functionality.

  7. Challenge

    Deleting Contacts

    The delete_contact function allows the user to delete a contact from the contact list by searching for the contact's name.

    You are going to use the strcmp function to compare if the match is found. If both strings are same then strcmp will return 0.

    info> strcmp is case-sensitive and compares strings character by character, and it considers uppercase and lowercase letters as different.


    Next, implement logic to overwrite the deleted contact by shifting all subsequent contacts one position to the left. It's time to test the Contact Management Application!

    Press the Run button on the bottom right of the Terminal window to test.

    In this step, you implemented the Delete Contact functionality, ensuring that contacts you no longer need are successfully removed.

    You can also explore the strcasecmp function, which performs a case-insensitive comparison.

  8. Challenge

    Conclusion and Next Steps

    Congratulations on completing this lab!

    This lab provided a solid foundation in handling arrays and strings in C, allowing you to build basic contact management functionality. You’ve learned how to add, delete, and search contacts while manipulating strings effectively.


    You can further enhance your learning by adding the following features:

    Handling Duplicates

    • Implement checks to prevent adding duplicate contacts by name or phone number.

    Update Contact

    • Allow updating a contact’s information (e.g., phone number) by searching for the contact’s name.

    Enhance Sorting

    • Implement advanced sorting algorithms like QuickSort or MergeSort to organize contacts more efficiently.

    Introduce Dynamic Memory

    • Use dynamically allocated memory for contact storage to allow greater flexibility.

    Explore Other String Functions in string.h

    • Learn about strcasecmp, strncasecmp, and other string utility functions like strtok and strchr.

    File I/O

    • Extend the app to save and retrieve contacts from a file, making it persistent across sessions.
    Error Handling
    • Add error handling for edge cases like invalid input, exceeding array limits, and file I/O errors.

    Exploring these areas will strengthen your C skills and help you build more efficient applications.

    Continue your learning journey by exploring the C path on Pluralsight:

    C Development Fundamentals

    Happy coding !

Amar Sonwani is a software architect with more than twelve years of experience. He has worked extensively in the financial industry and has expertise in building scalable applications.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.