Bachelor of Computer Application

Year: 1st Semester: 1st

Subject Code: BCA-103 N

Subject Title: Programming with C

Course Outcomes

Course Details

Credits: 4 | Core Compulsory

Max. Marks: 30 + 70 | Min. Passing Marks: 40

Total No. of Lectures-Tutorials-Practical (in hours per week): 4-0-0

Unit I

Unit II

Unit III

Unit IV

Unit V

Explanations

Evolution of C

The C programming language was developed in the early 1970s at Bell Labs by Dennis Ritchie. It was originally created for developing the UNIX operating system. C evolved from an earlier language called B, which was developed by Ken Thompson. Over the years, C has influenced many programming languages, such as C++, C#, and Java, and remains widely used due to its efficiency and control over system resources.

Programming Languages

Programming languages are formal languages comprising a set of instructions that can be used to produce various kinds of output, such as software applications or algorithms. They can be categorized into:

Structure of a C program

A C program consists of various components, including:

Example:

                    
                    #include <stdio.h>
        
                    int main() {
                        printf("Hello, World!\n");
                        return 0;
                    }
                    
                

Compiling a C program

Compiling is the process of translating the C source code into machine code that the computer can execute. This is typically done using a compiler like GCC. The compilation process involves several steps:

Example Command:

                    
                    gcc -o hello hello.c
                    
                

Character set in C

The character set in C includes:

C is case-sensitive, meaning 'A' and 'a' are treated as different characters.

Keywords in C

Keywords are reserved words that have special meaning in C. They cannot be used as identifiers. Some common keywords include:

Example:

                    
                    int main() {
                        return 0; // 'return' is a keyword
                    }
                    
                

Hierarchy of operators

Operators in C have a defined precedence, which determines the order in which operations are performed. The hierarchy from highest to lowest precedence is:

Example:

                    
                    int a = 5, b = 10;
                    int c = a + b * 2; // b is multiplied by 2 first, then added to a
                    
                

Basic data types

C has several basic data types:

Example:

                    
                    int age = 20;
                    float salary = 3000.50;
                    char grade = 'A';
                    
                

Qualifiers used with basic data types

Qualifiers modify the basic data types in C to provide more precision and control:

Example:

                    
                    unsigned int count = 100;
                    long int distance = 1000000;
                    
                

Variables in C

Variables are used to store data that can be modified during program execution. Each variable has a type that determines what kind of data it can hold.

Rules for declaring variables:

Example:

                    
                    int score = 100;
                    float temperature = 36.6;
                    
                

Type declaration

Type declaration is the process of specifying the type of a variable when it is defined. This informs the compiler about the kind of data the variable will hold and how much memory to allocate for it.

Example:

                    
                    int num; // Declares an integer variable
                    float price; // Declares a float variable
                    char letter; // Declares a character variable
                    
                

Output function

The primary output function in C is printf(). It is used to display data on the standard output (usually the console).

Example:

                    
                    #include <stdio.h>
        
                    int main() {
                        int num = 10;
                        printf("The number is: %d\n", num);
                        return 0;
                    }
                    
                

Input function and format specifiers

The primary input function in C is scanf(), used to read formatted input from the user. It requires format specifiers to identify the type of data being read.

Common format specifiers:

  • %d - for integers
  • %f - for floats
  • %c - for characters
  • %s - for strings

Example:

                    
                    #include <stdio.h>
        
                    int main() {
                        int age;
                        printf("Enter your age: ");
                        scanf("%d", &age);
                        printf("Your age is: %d\n", age);
                        return 0;
                    }
                    
                

Arithmetic operators

Arithmetic operators are used to perform mathematical calculations in C. The main arithmetic operators include:

  • + - Addition
  • - - Subtraction
  • * - Multiplication
  • / - Division
  • % - Modulus (remainder)

Example:

                    
                    #include <stdio.h>
        
                    int main() {
                        int a = 10, b = 5;
                        printf("Addition: %d\n", a + b);
                        printf("Subtraction: %d\n", a - b);
                        printf("Multiplication: %d\n", a * b);
                        printf("Division: %d\n", a / b);
                        printf("Modulus: %d\n", a % b);
                        return 0;
                    }
                    
                

Unary Operators

Unary operators are operators that operate on a single operand. They can perform various operations, such as incrementing, decrementing, negating, or logical complementing a variable. Common unary operators include:

  • + (Unary plus): Indicates a positive value.
  • - (Unary minus): Negates a value.
  • ++ (Increment): Increases the value of a variable by one.
  • -- (Decrement): Decreases the value of a variable by one.

Example:


        #include <stdio.h>
        
        int main() {
            int a = 5;
            printf("Original: %d\n", a);
            printf("Incremented: %d\n", ++a); // Pre-increment
            printf("Decremented: %d\n", --a); // Pre-decrement
            return 0;
        }
            

Relational and Logical Operators

Relational operators are used to compare two values, and they return a boolean value (true or false). Common relational operators include:

  • ==: Equal to
  • !=: Not equal to
  • >: Greater than
  • <: Less than
  • >=: Greater than or equal to
  • <=: Less than or equal to

Logical operators combine multiple relational expressions. They include:

  • && (Logical AND)
  • || (Logical OR)
  • ! (Logical NOT)

Example:


        #include <stdio.h>
        
        int main() {
            int x = 10, y = 20;
            if (x < y) {
                printf("x is less than y\n");
            }
            if (x >= 5 && y <= 20) {
                printf("x is greater than or equal to 5 AND y is less than or equal to 20\n");
            }
            return 0;
        }
            

If Statement

The if statement is a control structure that executes a block of code if the specified condition is true. It allows for conditional execution in programs.

Example:


        #include <stdio.h>
        
        int main() {
            int num = 10;
            if (num > 0) {
                printf("The number is positive.\n");
            }
            return 0;
        }
            

If-Else Statement

The if-else statement extends the if statement by providing an alternative block of code that executes if the condition is false.

Example:


        #include <stdio.h>
        
        int main() {
            int num = -5;
            if (num > 0) {
                printf("The number is positive.\n");
            } else {
                printf("The number is not positive.\n");
            }
            return 0;
        }
            

For Statement

The for statement is used to execute a block of code a specific number of times. It is often used for iterating over arrays or executing a loop a predetermined number of times.

Example:


        #include <stdio.h>
        
        int main() {
            for (int i = 1; i <= 5; i++) {
                printf("Iteration %d\n", i);
            }
            return 0;
        }
            

While Loop

The while loop repeatedly executes a block of code as long as a specified condition is true. It is often used when the number of iterations is not known in advance.

Example:


        #include <stdio.h>
        
        int main() {
            int i = 1;
            while (i <= 5) {
                printf("Iteration %d\n", i);
                i++;
            }
            return 0;
        }
            

Do-While Statement

The do-while statement is similar to the while loop, but it guarantees that the block of code will execute at least once before checking the condition.

Example:


        #include <stdio.h>
        
        int main() {
            int i = 1;
            do {
                printf("Iteration %d\n", i);
                i++;
            } while (i <= 5);
            return 0;
        }
            

Break Statement

The break statement is used to exit a loop or switch statement prematurely. It terminates the nearest enclosing loop or switch.

Example:


        #include <stdio.h>
        
        int main() {
            for (int i = 1; i <= 10; i++) {
                if (i == 5) {
                    break; // Exit the loop when i equals 5
                }
                printf("%d\n", i);
            }
            return 0;
        }
            

Continue Statement

The continue statement skips the current iteration of a loop and proceeds to the next iteration. It is often used to avoid executing certain code under specific conditions.

Example:


        #include <stdio.h>
        
        int main() {
            for (int i = 1; i <= 10; i++) {
                if (i % 2 == 0) {
                    continue; // Skip even numbers
                }
                printf("%d\n", i);
            }
            return 0;
        }
            

Switch Statement

The switch statement allows for multi-way branching based on the value of a variable. It provides a cleaner syntax than multiple if-else statements.

Example:


        #include <stdio.h>
        
        int main() {
            int day = 3;
            switch (day) {
                case 1:
                    printf("Monday\n");
                    break;
                case 2:
                    printf("Tuesday\n");
                    break;
                case 3:
                    printf("Wednesday\n");
                    break;
                default:
                    printf("Invalid day\n");
            }
            return 0;
        }
            

Goto Statement

The goto statement allows for an unconditional jump to another point in the program. It is generally discouraged in modern programming due to potential for creating complex, unstructured code.

Example:


        #include <stdio.h>
        
        int main() {
            int num = 0;
            start:
            printf("Number: %d\n", num);
            num++;
            if (num < 5) goto start; // Jump to the 'start' label
            return 0;
        }
            

Ternary Operators

The ternary operator is a shorthand for the if-else statement and takes three operands. It is commonly used for simple conditional assignments.

Syntax:

condition ? expression1 : expression2

If the condition is true, expression1 is executed; otherwise, expression2 is executed.

Example:


        #include <stdio.h>
        
        int main() {
            int a = 5, b = 10;
            int max = (a > b) ? a : b; // Ternary operator
            printf("Maximum value: %d\n", max);
            return 0;
        }
            

Definition of Array

An array is a collection of elements of the same type, stored in contiguous memory locations. It allows you to store multiple values in a single variable and is accessed using indices.

Types of Arrays

There are several types of arrays in C:

  • One-Dimensional Arrays: A linear list of elements.
  • Two-Dimensional Arrays: A matrix (table) of elements.
  • Multi-Dimensional Arrays: Arrays with more than two dimensions.

Array Declaration

To declare an array, specify the data type followed by the array name and size. The syntax is:

data_type array_name[size];

Example:


        #include <stdio.h>
        
        int main() {
            int arr[5]; // Declaration of an integer array of size 5
            return 0;
        }
            

Array Initialization

Arrays can be initialized at the time of declaration. The syntax is:

data_type array_name[size] = {value1, value2, ...};

Example:


        #include <stdio.h>
        
        int main() {
            int arr[5] = {1, 2, 3, 4, 5}; // Initialization of an integer array
            for (int i = 0; i < 5; i++) {
                printf("%d ", arr[i]); // Accessing array elements
            }
            return 0;
        }
            

Advantages of Arrays

Arrays allow you to store multiple values of the same type in a single variable. This simplifies the management of data as it can be accessed using an index. Here are some advantages:

  • Efficient Memory Use: Arrays use contiguous memory locations which can reduce the overhead of memory management.
  • Fast Access: Elements in an array can be accessed directly using their index, making retrieval fast.
  • Data Organization: Arrays help in organizing related data elements logically.

Example:


        #include <stdio.h>
        
        int main() {
            int arr[5] = {10, 20, 30, 40, 50};
            printf("First element: %d\n", arr[0]);
            printf("Second element: %d\n", arr[1]);
            return 0;
        }
            

Accessing Data from Array

Accessing data from an array is done using the index of the elements. The index starts from 0, meaning the first element is at index 0, the second at index 1, and so on.

Example:


        #include <stdio.h>
        
        int main() {
            int arr[5] = {1, 2, 3, 4, 5};
            for(int i = 0; i < 5; i++) {
                printf("Element at index %d: %d\n", i, arr[i]);
            }
            return 0;
        }
            

Array Inside the Memory

Arrays are stored in contiguous memory locations, which allows the program to calculate the address of each element. The base address is the address of the first element.

Example:


        #include <stdio.h>
        
        int main() {
            int arr[3] = {10, 20, 30};
            printf("Address of arr: %p\n", (void*)arr);
            printf("Address of arr[0]: %p\n", (void*)&arr[0]);
            printf("Address of arr[1]: %p\n", (void*)&arr[1]);
            return 0;
        }
            

Multi-dimensional Arrays

Multi-dimensional arrays are arrays of arrays. They can be used to represent matrices and higher-dimensional data.

Example:


        #include <stdio.h>
        
        int main() {
            int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
            for(int i = 0; i < 2; i++) {
                for(int j = 0; j < 3; j++) {
                    printf("%d ", matrix[i][j]);
                }
                printf("\n");
            }
            return 0;
        }
            

Character Arrays

Character arrays are used to store strings in C. They are essentially arrays of characters terminated by a null character ('\\0').

Example:


        #include <stdio.h>
        
        int main() {
            char name[20] = "John Doe";
            printf("Name: %s\n", name);
            return 0;
        }
            

Array Overflow

Array overflow occurs when you try to access an index outside the bounds of the array. This can lead to undefined behavior and memory corruption.

Example:


        #include <stdio.h>
        
        int main() {
            int arr[3] = {1, 2, 3};
            // Uncommenting the following line will cause overflow
            // printf("%d\n", arr[5]);
            return 0;
        }
            

String Variables

Strings in C are represented as arrays of characters. A string variable is simply an array of characters that ends with a null terminator.

Example:


        #include <stdio.h>
        
        int main() {
            char str[50] = "Hello, World!";
            printf("%s\n", str);
            return 0;
        }
            

Reading & Writing Strings

You can read and write strings using standard input/output functions like scanf and printf.

Example:


        #include <stdio.h>
        
        int main() {
            char str[50];
            printf("Enter a string: ");
            scanf("%49s", str); // Limit input to prevent overflow
            printf("You entered: %s\n", str);
            return 0;
        }
            

String Handling Functions

C provides several functions to manipulate strings, such as strlen, strcpy, strcat, and strcmp.

Example:


        #include <stdio.h>
        #include <string.h>
        
        int main() {
            char str1[20] = "Hello";
            char str2[20] = "World";
            strcat(str1, str2); // Concatenates str2 to str1
            printf("Concatenated string: %s\n", str1);
            return 0;
        }
            

Declaring a Function

Functions are declared using a specific syntax that includes the return type, function name, and parameters.

Example:


        #include <stdio.h>
        
        // Function declaration
        int add(int a, int b);
        
        int main() {
            int result = add(5, 10);
            printf("Sum: %d\n", result);
            return 0;
        }
        
        int add(int a, int b) {
            return a + b;
        }
            

Calling a Function

A function is called by its name followed by parentheses containing any arguments.

Example:


        #include <stdio.h>
        
        // Function declaration
        void greet();
        
        int main() {
            greet(); // Calling the function
            return 0;
        }
        
        void greet() {
            printf("Hello, World!\n");
        }
            

Advantages of Functions

Functions provide several benefits including:

  • Code Reusability: Functions allow you to reuse code without rewriting it.
  • Modularity: Breaking down a program into functions makes it easier to understand and maintain.
  • Ease of Debugging: Functions help isolate problems in specific areas of code.

Variables in Functions

Variables declared within a function are local to that function and cannot be accessed outside it. They are created when the function is called and destroyed when it exits.

Example:


        #include <stdio.h>
        
        void demo() {
            int localVar = 5; // Local variable
            printf("Local variable: %d\n", localVar);
        }
        
        int main() {
            demo();
            // printf("%d", localVar); // Error: localVar not accessible here
            return 0;
        }
            

Passing Arguments to a Function

You can pass arguments to functions either by value or by reference. Passing by value means a copy of the variable is sent, while passing by reference means the function can modify the original variable.

Example:


        #include <stdio.h>
        
        void byValue(int x) {
            x = x + 10; // Modifies local copy
        }
        
        void byReference(int *x) {
            *x = *x + 10; // Modifies original value
        }
        
        int main() {
            int a = 5;
            byValue(a);
            printf("By value: %d\n", a); // Output: 5
            byReference(&a);
            printf("By reference: %d\n", a); // Output: 15
            return 0;
        }
            

Nested Functions

Functions can be called from within other functions, creating a nested structure. However, C does not support function nesting directly; you must define functions separately.

Example:


        #include <stdio.h>
        
        void functionA() {
            printf("Function A called\n");
        }
        
        void functionB() {
            printf("Function B called\n");
            functionA(); // Calling function A from B
        }
        
        int main() {
            functionB();
            return 0;
        }
            

Passing Array to Functions

Arrays can be passed to functions by providing the array name. Inside the function, the array can be accessed as a pointer.

Example:


        #include <stdio.h>
        
        void printArray(int arr[], int size) {
            for(int i = 0; i < size; i++) {
                printf("%d ", arr[i]);
            }
            printf("\n");
        }
        
        int main() {
            int numbers[] = {1, 2, 3, 4, 5};
            printArray(numbers, 5);
            return 0;
        }
            

Recursion in Functions

Recursion is a programming technique where a function calls itself to solve a problem. It consists of a base case that stops the recursion and a recursive case that continues the recursion.

Example: Factorial Calculation


        #include <stdio.h>
        
        // Recursive function to calculate factorial
        int factorial(int n) {
            if (n == 0) // Base case
                return 1;
            else // Recursive case
                return n * factorial(n - 1);
        }
        
        int main() {
            int num = 5;
            printf("Factorial of %d is %d\n", num, factorial(num));
            return 0;
        }
            

Call by Value and Call by Reference

In C, functions can receive parameters by value or by reference. In "call by value," a copy of the actual parameter is passed to the function. In "call by reference," the address of the actual parameter is passed, allowing the function to modify the original value.

Example: Call by Value


        #include <stdio.h>
        
        // Function that demonstrates call by value
        void increment(int x) {
            x++;
            printf("Inside increment (call by value): %d\n", x);
        }
        
        int main() {
            int num = 10;
            increment(num);
            printf("After increment (in main): %d\n", num);
            return 0;
        }
            

Example: Call by Reference


        #include <stdio.h>
        
        // Function that demonstrates call by reference
        void increment(int *x) {
            (*x)++;
            printf("Inside increment (call by reference): %d\n", *x);
        }
        
        int main() {
            int num = 10;
            increment(&num);
            printf("After increment (in main): %d\n", num);
            return 0;
        }
            

Pointers and Functions

Pointers can be passed to functions, allowing the function to modify the original data. This is particularly useful for working with large data structures without making copies.

Example: Modifying Values with Pointers


        #include <stdio.h>
        
        // Function that modifies the value using a pointer
        void modifyValue(int *x) {
            *x = 20;
        }
        
        int main() {
            int num = 10;
            modifyValue(&num);
            printf("Modified value: %d\n", num);
            return 0;
        }
            

Array of Pointers

An array of pointers is an array where each element is a pointer. This can be useful for dynamic memory allocation and managing arrays of strings.

Example: Array of String Pointers


        #include <stdio.h>
        
        int main() {
            const char *fruits[] = {"Apple", "Banana", "Cherry"}; // Array of pointers
            for (int i = 0; i < 3; i++) {
                printf("%s\n", fruits[i]); // Accessing strings via pointers
            }
            return 0;
        }
            

Pointer and Strings

Strings in C are represented as arrays of characters terminated by a null character (`'\0'`). A pointer can be used to manipulate strings efficiently.

Example: Using Pointers with Strings


        #include <stdio.h>
        
        int main() {
            char str[] = "Hello, World!";
            char *ptr = str; // Pointer to the string
        
            while (*ptr) { // Iterate through the string
                putchar(*ptr++);
            }
            putchar('\n');
            return 0;
        }
            

Pointer to Structure

Structures in C allow you to group related variables. A pointer to a structure can be used to access and modify the structure's members.

Example: Pointer to Structure


        #include <stdio.h>
        
        struct Student {
            char name[50];
            int age;
        };
        
        int main() {
            struct Student student = {"Alice", 20};
            struct Student *ptr = &student; // Pointer to structure
        
            printf("Name: %s, Age: %d\n", ptr->name, ptr->age);
            return 0;
        }
            

Pointers within Structure

Structures can contain pointers as members. This allows for dynamic data structures such as linked lists.

Example: Pointers within Structure


        #include <stdio.h>
        
        struct Node {
            int data;
            struct Node *next; // Pointer to the next node
        };
        
        int main() {
            struct Node node1;
            struct Node node2;
            node1.data = 10;
            node1.next = &node2; // Linking nodes
            node2.data = 20;
            node2.next = NULL;
        
            printf("Node1: %d, Node2: %d\n", node1.data, node1.next->data);
            return 0;
        }
            

Introduction to Static and Dynamic Memory Allocation

Static memory allocation is done at compile time, while dynamic memory allocation is done at runtime using functions like `malloc`, `calloc`, `realloc`, and `free`.

Static Memory Allocation Example


        #include <stdio.h>
        
        int main() {
            int arr[5]; // Static allocation
            for (int i = 0; i < 5; i++) {
                arr[i] = i + 1;
                printf("%d ", arr[i]);
            }
            printf("\n");
            return 0;
        }
            

Dynamic Memory Allocation (DMA)

DMA allows you to allocate memory at runtime. It is particularly useful when the size of data is not known at compile time. `malloc` allocates uninitialized memory, while `calloc` allocates memory and initializes it to zero.

Example: Using malloc


        #include <stdio.h>
        #include <stdlib.h>
        
        int main() {
            int *arr = (int *)malloc(5 * sizeof(int)); // Allocate memory
            if (arr == NULL) {
                printf("Memory allocation failed!\n");
                return 1;
            }
            for (int i = 0; i < 5; i++) {
                arr[i] = i + 1;
                printf("%d ", arr[i]);
            }
            free(arr); // Free allocated memory
            printf("\n");
            return 0;
        }
            

DMA Functions

The most common DMA functions in C are:

  • malloc(size_t size): Allocates a specified number of bytes.
  • calloc(size_t num, size_t size): Allocates memory for an array of elements, initializes all bytes to zero.
  • realloc(void *ptr, size_t size): Changes the size of previously allocated memory.
  • free(void *ptr): Deallocates previously allocated memory.

Example: Using realloc


        #include <stdio.h>
        #include <stdlib.h>
        
        int main() {
            int *arr = (int *)malloc(5 * sizeof(int));
            for (int i = 0; i < 5; i++) {
                arr[i] = i + 1;
            }
        
            // Reallocate memory to hold 10 integers
            arr = (int *)realloc(arr, 10 * sizeof(int));
            for (int i = 5; i < 10; i++) {
                arr[i] = i + 1;
            }
        
            for (int i = 0; i < 10; i++) {
                printf("%d ", arr[i]);
            }
            free(arr);
            printf("\n");
            return 0;
        }
            

malloc() function

The malloc() function is used to allocate a specified amount of memory at runtime. It returns a pointer to the beginning of the allocated memory block. If the allocation fails, it returns NULL.


        #include 
        #include 
        
        int main() {
            int *arr;
            int n = 5;
        
            arr = (int *)malloc(n * sizeof(int)); // Allocating memory for 5 integers
        
            if (arr == NULL) {
                printf("Memory allocation failed\n");
                return 1;
            }
        
            for (int i = 0; i < n; i++) {
                arr[i] = i + 1; // Initializing array elements
            }
        
            for (int i = 0; i < n; i++) {
                printf("%d ", arr[i]);
            }
        
            free(arr); // Freeing allocated memory
            return 0;
        }
            

Sizeof() operator

The sizeof operator is used to determine the size, in bytes, of a data type or a variable. It can be used with both built-in and user-defined data types.


        #include 
        
        struct MyStruct {
            int a;
            double b;
        };
        
        int main() {
            printf("Size of int: %zu bytes\n", sizeof(int));
            printf("Size of double: %zu bytes\n", sizeof(double));
            printf("Size of MyStruct: %zu bytes\n", sizeof(struct MyStruct));
            return 0;
        }
            

Definition of Structure

A structure in C is a user-defined data type that allows the grouping of variables of different data types under a single name. Structures are defined using the struct keyword.


        #include 
        
        struct Student {
            char name[50];
            int roll_no;
            float marks;
        };
            

Structure declaration

After defining a structure, you can declare variables of that structure type. This is done after the structure definition.


        #include 
        
        struct Student {
            char name[50];
            int roll_no;
            float marks;
        };
        
        int main() {
            struct Student s1; // Declaration of a structure variable
            return 0;
        }
            

Structure initialization

Structures can be initialized at the time of declaration using an initializer list. This sets the values of the structure members.


        #include 
        
        struct Student {
            char name[50];
            int roll_no;
            float marks;
        };
        
        int main() {
            struct Student s1 = {"Alice", 101, 89.5}; // Initialization
            printf("Name: %s, Roll No: %d, Marks: %.2f\n", s1.name, s1.roll_no, s1.marks);
            return 0;
        }
            

Accessing structure members

Structure members can be accessed using the dot operator (.) for structure variables and the arrow operator (->) for pointers to structures.


        #include 
        
        struct Student {
            char name[50];
            int roll_no;
            float marks;
        };
        
        int main() {
            struct Student s1 = {"Bob", 102, 76.5};
            printf("Name: %s\n", s1.name); // Accessing member using dot operator
        
            struct Student *ptr = &s1;
            printf("Roll No: %d\n", ptr->roll_no); // Accessing member using arrow operator
            return 0;
        }
            

Nested structures

A structure can contain another structure as a member. This is called a nested structure.


        #include 
        
        struct Address {
            char street[100];
            char city[50];
        };
        
        struct Student {
            char name[50];
            int roll_no;
            struct Address addr; // Nested structure
        };
        
        int main() {
            struct Student s1 = {"Charlie", 103, {"123 Main St", "Springfield"}};
            printf("Name: %s, City: %s\n", s1.name, s1.addr.city);
            return 0;
        }
            

Arrays in structures

Structures can contain arrays as members, allowing for the storage of multiple values of the same type.


        #include 
        
        struct Student {
            char name[50];
            int grades[5]; // Array of grades
        };
        
        int main() {
            struct Student s1 = {"David", {85, 90, 78, 92, 88}};
            printf("Grades of %s: ", s1.name);
            for (int i = 0; i < 5; i++) {
                printf("%d ", s1.grades[i]);
            }
            return 0;
        }
            

Pointers in structures

Structures can have pointer members, allowing for dynamic memory allocation and efficient data management.


        #include 
        #include 
        
        struct Student {
            char *name; // Pointer to char
            int roll_no;
        };
        
        int main() {
            struct Student s1;
            s1.name = (char *)malloc(50 * sizeof(char)); // Dynamic allocation for name
            snprintf(s1.name, 50, "Eve");
            s1.roll_no = 104;
        
            printf("Name: %s, Roll No: %d\n", s1.name, s1.roll_no);
            free(s1.name); // Free allocated memory
            return 0;
        }
            

Definition of Union

A union is a user-defined data type that allows storing different data types in the same memory location. Only one member can store a value at any time.


        #include 
        
        union Data {
            int intVal;
            float floatVal;
            char charVal;
        };
            

Union declaration

After defining a union, you can declare variables of that union type similarly to structures.


        #include 
        
        union Data {
            int intVal;
            float floatVal;
            char charVal;
        };
        
        int main() {
            union Data data; // Declaration of a union variable
            return 0;
        }
            

Union initialization

Unions can be initialized at the time of declaration using an initializer list, similar to structures.


        #include 
        
        union Data {
            int intVal;
            float floatVal;
            char charVal;
        };
        
        int main() {
            union Data data = {10}; // Initialization
            printf("Integer: %d\n", data.intVal);
            return 0;
        }
            

Accessing union members

Union members can be accessed using the dot operator (.). However, only one member can be used at a time, as they share the same memory location.


        #include 
        
        union Data {
            int intVal;
            float floatVal;
            char charVal;
        };
        
        int main() {
            union Data data;
            data.intVal = 10;
            printf("Integer: %d\n", data.intVal);
        
            data.floatVal = 15.5; // Assigning to another member
            printf("Float: %.2f\n", data.floatVal); // Previous value is overwritten
            return 0;
        }
            

Difference between Structure and Union

The primary difference between structures and unions is that in a structure, each member has its own memory, while in a union, all members share the same memory. Thus, a structure can store multiple values simultaneously, whereas a union can only store one value at a time.


        #include 
        
        struct MyStruct {
            int a;
            float b;
        };
        
        union MyUnion {
            int a;
            float b;
        };
        
        int main() {
            printf("Size of MyStruct: %zu bytes\n", sizeof(struct MyStruct)); // Outputs size of struct
            printf("Size of MyUnion: %zu bytes\n", sizeof(union MyUnion)); // Outputs size of union
            return 0;
        }
            

File Structure

In C, file structure refers to the organization of data in files. C provides functions for file handling through the FILE structure. You can open, read, write, and close files using these functions.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("example.txt", "w"); // Opening a file in write mode
        
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
        
            fprintf(file, "Hello, World!\n"); // Writing to the file
            fclose(file); // Closing the file
        
            return 0;
        }
            

File Mode

In C, file mode refers to the way a file is opened and how the data in it will be accessed. There are several modes available for opening files:

  • "r": Open a file for reading. The file must exist.
  • "w": Open a file for writing. If the file exists, it is truncated. If not, a new file is created.
  • "a": Open a file for appending. Data is written at the end of the file. If the file does not exist, it is created.
  • "rb", "wb", "ab": Open a file in binary mode for reading, writing, or appending respectively.

File Opening

To open a file, you use the fopen() function, which takes two arguments: the filename and the mode. It returns a pointer to a FILE object.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("example.txt", "r"); // Open for reading
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
            fclose(file); // Close the file
            return 0;
        }
            

File Creation

You can create a new file or overwrite an existing file by using the w mode with fopen(). If the file already exists, its contents will be erased.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("newfile.txt", "w"); // Create or overwrite a file
            if (file == NULL) {
                printf("Error creating file\n");
                return 1;
            }
            fprintf(file, "This is a new file.\n");
            fclose(file); // Close the file
            return 0;
        }
            

File Reading

To read from a file, use fgets() for strings or fscanf() for formatted input. Remember to check for errors.


        #include 
        
        int main() {
            FILE *file;
            char buffer[100];
            
            file = fopen("example.txt", "r"); // Open for reading
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
            
            while (fgets(buffer, sizeof(buffer), file) != NULL) {
                printf("%s", buffer); // Print each line
            }
            
            fclose(file); // Close the file
            return 0;
        }
            

File Writing

To write to a file, you can use fprintf() for formatted output or fputs() for strings. Ensure the file is opened in a mode that allows writing.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("output.txt", "w"); // Open for writing
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
            
            fprintf(file, "Hello, World!\n"); // Write formatted text
            fputs("Writing to a file using fputs.\n", file); // Write string
            
            fclose(file); // Close the file
            return 0;
        }
            

File Closure

After finishing file operations, it is crucial to close the file using fclose(). This flushes buffers and frees up resources.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("example.txt", "w");
            
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
            
            // File operations here...
            
            fclose(file); // Close the file
            printf("File closed successfully.\n");
            return 0;
        }
            

Random Access File

To perform random access in files, use fseek() to move the file pointer to a specific location. This allows you to read/write data at any position in the file.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("random_access.txt", "w+"); // Open for read/write
            
            if (file == NULL) {
                printf("Error opening file\n");
                return 1;
            }
            
            fprintf(file, "Hello, Random Access!\n");
            fseek(file, 0, SEEK_SET); // Move to the beginning
            char buffer[50];
            fgets(buffer, sizeof(buffer), file); // Read from the file
            printf("%s", buffer); // Print content
            
            fclose(file); // Close the file
            return 0;
        }
            

Copying File

You can copy the contents of one file to another by reading from the source file and writing to the destination file.


        #include 
        
        int main() {
            FILE *source, *dest;
            char buffer[100];
            
            source = fopen("source.txt", "r");
            dest = fopen("copy.txt", "w");
            
            if (source == NULL || dest == NULL) {
                printf("Error opening files\n");
                return 1;
            }
            
            while (fgets(buffer, sizeof(buffer), source) != NULL) {
                fputs(buffer, dest); // Write to destination file
            }
            
            fclose(source);
            fclose(dest);
            printf("File copied successfully.\n");
            return 0;
        }
            

Error Handling

Proper error handling is essential when working with files. Check the return value of fopen(), fgets(), etc., to ensure operations succeed.


        #include 
        
        int main() {
            FILE *file;
            file = fopen("nonexistent.txt", "r"); // Attempt to open a non-existent file
            
            if (file == NULL) {
                perror("Error opening file"); // Print error message
                return 1;
            }
            
            fclose(file); // Close the file if opened successfully
            return 0;
        }
            

Command Line Arguments

C programs can accept command line arguments which are passed when executing the program. They are accessible via argc (argument count) and argv (argument vector).


        #include 
        
        int main(int argc, char *argv[]) {
            printf("Number of arguments: %d\n", argc);
            for (int i = 0; i < argc; i++) {
                printf("Argument %d: %s\n", i, argv[i]);
            }
            return 0;
        }
            

Preprocessor Directives

Preprocessor directives are instructions processed before compilation. They begin with a # and are used for including files, defining macros, and conditional compilation.


        #include 
        
        #define PI 3.14 // Define a macro
        
        int main() {
            printf("Value of PI: %f\n", PI);
            return 0;
        }
            

Macros in C

Macros are a way to define constants or functions that are expanded at compile time. They can improve code readability and reduce redundancy.


        #include 
        
        #define SQUARE(x) ((x) * (x)) // Macro for square
        
        int main() {
            int num = 5;
            printf("Square of %d: %d\n", num, SQUARE(num));
            return 0;
        }
            
Go Back to Main Menu