Course Topics
C Basics Introduction and Setup Syntax and Program Structure Comments and Documentation Compiling and Running C Programs Exercise Variables and Data Types Variables and Declaration Data Types (int, float, char, double) Constants and Literals Type Conversion and Casting Exercise Operators Arithmetic Operators Comparison Operators Logical Operators Assignment Operators Bitwise Operators Exercise Input and Output Standard Input/Output (scanf, printf) Format Specifiers File Input/Output Exercise Control Flow - Conditionals If Statements If-Else Statements Switch Statements Nested Conditionals Exercise Control Flow - Loops For Loops While Loops Do-While Loops Loop Control (break, continue) Nested Loops Exercise Functions Defining Functions Function Parameters and Arguments Return Statements Scope and Variables Recursion Exercise Arrays One-Dimensional Arrays Multi-Dimensional Arrays Array Operations Strings as Character Arrays Exercise Pointers Introduction to Pointers Pointer Arithmetic Pointers and Arrays Pointers and Functions Dynamic Memory Allocation Exercise Strings String Handling String Functions (strlen, strcpy, strcmp) String Manipulation Exercise Structures Defining Structures Structure Members Arrays of Structures Pointers to Structures Exercise File Handling Opening and Closing Files Reading from Files Writing to Files File Positioning Exercise Memory Management Static vs Dynamic Memory malloc() and free() Memory Leaks Best Practices Exercise Advanced Topics Preprocessor Directives Macros Header Files Modular Programming Exercise Final Project Project Planning Building Complete Application Code Organization Testing and Debugging Exercise

Defining Structures

Introduction

  • Structures are user-defined data types in C that allow you to combine data items of different kinds into a single entity. This topic matters because it enables you to organize complex data more effectively and write cleaner, more efficient code.
  • In this lesson, we will learn how to define structures, access their components, and handle arrays of structures. By the end of this tutorial, you'll be able to create your own custom data types and manipulate them with ease.

Core Concepts

  • A structure is declared using the struct keyword followed by a name for the new data type. Inside the curly braces {}, you can define various fields of different data types, separated by commas. For example:

C struct Student { char name[50]; int age; float gpa; };
Here we've created a Student structure with three fields: name, age, and gpa.

  • To create an instance of the structure, use the keyword struct followed by the structure name. Assign values to each field using the dot notation:

C struct Student student1; strcpy(student1.name, "John Doe"); student1.age = 20; student1.gpa = 3.5;
- To print the values of a structure instance, use the printf function and the dot notation:

C printf("Student Name: %s\n", student1.name); printf("Age: %d\n", student1.age); printf("GPA: %.2f\n", student1.gpa);
- You can also declare multiple instances of a structure in a single line, like this:

C struct Student students[10]; // Declares an array of 10 Student structures

Practical Examples

Example 1 - Creating and Printing Structures

#include <stdio.h>
#include <string.h>

struct Student {
    char name[50];
    int age;
    float gpa;
};

int main() {
    struct Student student1 = {"John Doe", 20, 3.5}; // Initializing structure with values
    struct Student student2 = {"Jane Smith", 22, 3.7};

    printf("Student 1:\n");
    printf("Name: %s\n", student1.name);
    printf("Age: %d\n", student1.age);
    printf("GPA: %.2f\n", student1.gpa);

    printf("\nStudent 2:\n");
    printf("Name: %s\n", student2.name);
    printf("Age: %d\n", student2.age);
    printf("GPA: %.2f\n", student2.gpa);

    return 0;
}

Output:

Student 1:
Name: John Doe
Age: 20
GPA: 3.50

Student 2:
Name: Jane Smith
Age: 22
GPA: 3.70

Example 2 - Accessing Structures in Loops

#include <stdio.h>
#include <string.h>

struct Student {
    char name[50];
    int age;
    float gpa;
};

void printStudents(struct Student students[], int size) {
    for (int i = 0; i < size; i++) {
        printf("\nStudent %d:\n", i+1);
        printf("Name: %s\n", students[i].name);
        printf("Age: %d\n", students[i].age);
        printf("GPA: %.2f\n", students[i].gpa);
    }
}

int main() {
    struct Student students[3] = {{"John Doe", 20, 3.5}, {"Jane Smith", 22, 3.7}, {"Mary Johnson", 21, 3.8}};
    printStudents(students, 3); // Calling the function to display students

    return 0;
}

Output:

Student 1:
Name: John Doe
Age: 20
GPA: 3.50

Student 2:
Name: Jane Smith
Age: 22
GPA: 3.70

Student 3:
Name: Mary Johnson
Age: 21
GPA: 3.80

Common Issues and Solutions (CRITICAL SECTION)

NameError

What causes it: Failing to include the header file <stdio.h>.

#include <stdlib.h> // Incorrect header file
struct Student { ... }; // Structure declaration

Error message:

error: 'printf' undeclared (first use in this function)
printf("Student Name: %s\n", student1.name);
                         ^

Solution: Include the correct header file: <stdio.h>.

#include <stdio.h>
struct Student { ... }; // Structure declaration

Why it happens: The printf function is declared in the stdio.h header file, but not in stdlib.h.

How to prevent it: Include the correct header file at the beginning of your code.

TypeError

What causes it: Attempting to assign an incompatible data type to a structure field.

struct Student {
    char name[50];
    int age;
    float gpa; // Incorrect data type for average_score (int expected)
};

Error message:

error: incompatible types when assigning to type 'float' from type 'int'
student1.average_score = 85; // Assigning an integer to a float field
                            ^

Solution: Use the appropriate data type for each structure field.

struct Student {
    char name[50];
    int age;
    float gpa, average_score; // Correct data types
};

Why it happens: The average_score variable was declared as a float, but an integer was being assigned to it.

How to prevent it: Ensure that the correct data type is used for each structure field and avoid mixing incompatible data types when assigning values.

Best Practices

  • Use meaningful names for your structures and their fields.
  • Keep related data together within a single structure.
  • Use functions to work with structures, such as reading input, performing calculations, and displaying output. This helps maintain modularity and makes the code easier to read and understand.
  • Be aware of potential memory issues when working with large structures or arrays of structures. Allocate memory carefully, and consider using dynamic memory allocation techniques like malloc() and calloc() when necessary.

Key Takeaways

  • Structures are user-defined data types in C that allow you to organize complex data effectively.
  • To create a structure, use the struct keyword followed by a name and define fields inside curly braces.
  • To access the fields of a structure, use the dot notation.
  • You can declare arrays of structures and work with them using loops and functions for better organization and efficiency.
  • Be cautious when working with structures to avoid common issues like NameError and TypeError.

Next steps for learning: Learn about pointer arithmetic, dynamic memory allocation, and structure pointers to further enhance your understanding and skills in working with structures in C.