C Programming
Deep Understanding: 70 hours
Community
C Programming
2078 Boards
Section A
Answer any two questions.
A jump statement unconditionally transfers the program control from one point to another within the program. These statements alter the normal sequential flow of execution and are primarily used for controlling loops, functions, and specific execution paths.
Types of Jump Statements
-
breakStatement:- Purpose: Terminates the execution of the innermost
for,while,do-while, orswitchstatement in which it appears. Program control resumes at the statement immediately following the terminated construct. - Example:
Output:#include <stdio.h> int main() { int i; for (i = 1; i <= 10; i++) { if (i == 5) { break; // Exit the loop when i is 5 } printf("%d ", i); } printf("\nLoop terminated at i = 5.\n"); return 0; }
1 2 3 4
Loop terminated at i = 5.
- Purpose: Terminates the execution of the innermost
-
continueStatement:- Purpose: Skips the rest of the current iteration of the innermost
for,while, ordo-whileloop and proceeds to the next iteration. In aforloop, it jumps to the update expression; inwhile/do-whileloops, it jumps to the test condition. - Example:
Output:#include <stdio.h> int main() { int i; for (i = 1; i <= 5; i++) { if (i == 3) { continue; // Skip printing 3 } printf("%d ", i); } printf("\n"); return 0; }
1 2 4 5
- Purpose: Skips the rest of the current iteration of the innermost
-
returnStatement:- Purpose: Terminates the execution of the current function and returns control to the calling function. If a
returnstatement has an expression, the value of that expression is returned to the caller. - Example:
Output:#include <stdio.h> int add(int a, int b) { return a + b; // Returns the sum of a and b } int main() { int result = add(10, 20); printf("Sum: %d\n", result); return 0; // Exits main function }
Sum: 30
- Purpose: Terminates the execution of the current function and returns control to the calling function. If a
-
gotoStatement:- Purpose: Transfers control unconditionally to a labeled statement within the same function. While it provides powerful jump capabilities, its unrestricted use can lead to unstructured and hard-to-read code ("spaghetti code") and is generally discouraged in modern programming.
- Syntax:
goto label;followed bylabel:elsewhere in the function. - Example:
Output:#include <stdio.h> int main() { int a = 10; if (a > 5) { goto print_message; } printf("This line will not be executed.\n"); print_message: // Label definition printf("Value of a is greater than 5.\n"); return 0; }
Value of a is greater than 5.
Program to Check Whether a Number Entered is Prime or Not
A prime number is a natural number greater than 1 that has no positive divisors other than 1 and itself.
#include <stdio.h>
#include <stdbool.h> // For bool type
#include <math.h> // For sqrt()
int main() {
int num;
bool is_prime = true; // Assume the number is prime initially
// Get input from the user
printf("Enter a positive integer: ");
scanf("%d", &num);
// Handle special cases
if (num <= 1) {
is_prime = false; // Numbers less than or equal to 1 are not prime
} else if (num == 2) {
is_prime = true; // 2 is the only even prime number
} else if (num % 2 == 0) {
is_prime = false; // Other even numbers are not prime
} else {
// Check for divisibility from 3 up to sqrt(num), only odd numbers
// We increment by 2 (i+=2) because even divisors have already been excluded.
for (int i = 3; i * i <= num; i += 2) {
if (num % i == 0) {
is_prime = false; // Found a divisor, so it's not prime
break; // Exit the loop early (jump statement)
}
}
}
// Print the result
if (is_prime) {
printf("%d is a prime number.\n", num);
} else {
printf("%d is not a prime number.\n", num);
}
return 0;
}
String Functions
String functions are pre-defined routines in programming libraries (e.g., <string.h> in C/C++) that perform common operations on strings, such as calculating length, copying, concatenating, or comparing them.
-
strlen()(String Length)- Purpose: This function calculates the length of a given string. The length is determined by counting the number of characters until the null terminator (
\0) is encountered. The null terminator itself is not included in the count. - Syntax (C/C++):
size_t strlen(const char *str); - Example:
char myString[] = "Programming"; int length = strlen(myString); // 'length' will be 11
- Purpose: This function calculates the length of a given string. The length is determined by counting the number of characters until the null terminator (
-
strcpy()(String Copy)- Purpose: This function copies the contents of a source string to a destination string buffer. It copies characters including the null terminator from the source to the destination.
- Syntax (C/C++):
char *strcpy(char *destination, const char *source); - Important Note: The destination buffer must have sufficient space to accommodate the entire source string, including the null terminator, to prevent buffer overflow vulnerabilities.
- Example:
char sourceString[] = "Hello World"; char destinationBuffer[20]; // Ensure enough space strcpy(destinationBuffer, sourceString); // 'destinationBuffer' now contains "Hello World"
-
strcmp()(String Compare)- Purpose: This function compares two strings lexicographically (based on the ASCII values of their characters). It returns an integer value indicating the relationship between the two strings.
- Syntax (C/C++):
int strcmp(const char *str1, const char *str2); - Return Value:
- A negative value if
str1is lexicographically less thanstr2. 0ifstr1is identical tostr2.- A positive value if
str1is lexicographically greater thanstr2.
- A negative value if
- Example:
char string1[] = "apple"; char string2[] = "banana"; char string3[] = "apple"; int result1 = strcmp(string1, string2); // result1 will be < 0 int result2 = strcmp(string1, string3); // result2 will be 0 int result3 = strcmp(string2, string1); // result3 will be > 0
Program to Check if Two Matrices are Identical
To determine if two matrices are identical, they must satisfy two conditions:
- They must have the same dimensions (same number of rows and same number of columns).
- All corresponding elements at the same positions (i, j) in both matrices must be equal.
The following Python program implements this logic:
def are_matrices_identical(matrix1, matrix2):
"""
Checks if two matrices are identical.
Args:
matrix1 (list of lists): The first matrix.
matrix2 (list of lists): The second matrix.
Returns:
bool: True if matrices are identical, False otherwise.
"""
# Step 1: Check if the number of rows is the same
rows1 = len(matrix1)
rows2 = len(matrix2)
if rows1 != rows2:
return False
# Handle empty matrices case: two empty matrices are identical
if rows1 == 0:
return True
# Step 2: Check if the number of columns is the same for all rows and between matrices
# Assumes rectangular matrices for simplicity.
cols1 = len(matrix1[0]) if rows1 > 0 else 0
cols2 = len(matrix2[0]) if rows2 > 0 else 0
if cols1 != cols2:
return False
# Optional: Robust check for non-rectangular input matrices
# for r in range(rows1):
# if len(matrix1[r]) != cols1 or len(matrix2[r]) != cols2:
# return False
# Step 3: Compare elements at each corresponding position
for i in range(rows1):
for j in range(cols1):
if matrix1[i][j] != matrix2[i][j]:
return False # Found a differing element, so matrices are not identical
# Step 4: If all checks pass and no differing elements were found
return True # Matrices are identical
# --- Example Usage ---
# Identical matrices
matrix_A = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
matrix_B = [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
# Matrices with different elements
matrix_C = [[1, 2, 3],
[4, 5, 0], # Different element here
[7, 8, 9]]
# Matrices with different dimensions (rows)
matrix_D = [[1, 2, 3],
[4, 5, 6]]
# Matrices with different dimensions (columns)
matrix_E = [[1, 2],
[3, 4],
[5, 6]]
print(f"Matrix A and B are identical: {are_matrices_identical(matrix_A, matrix_B)}")
print(f"Matrix A and C are identical: {are_matrices_identical(matrix_A, matrix_C)}")
print(f"Matrix A and D are identical: {are_matrices_identical(matrix_A, matrix_D)}")
print(f"Matrix A and E are identical: {are_matrices_identical(matrix_A, matrix_E)}")
matrix_empty_1 = []
matrix_empty_2 = []
print(f"Empty matrices are identical: {are_matrices_identical(matrix_empty_1, matrix_empty_2)}")
matrix_one_row_1 = [[1, 2, 3]]
matrix_one_row_2 = [[1, 2, 3]]
matrix_one_row_3 = [[1, 2, 4]]
print(f"Single row matrices identical: {are_matrices_identical(matrix_one_row_1, matrix_one_row_2)}")
print(f"Single row matrices different: {are_matrices_identical(matrix_one_row_1, matrix_one_row_3)}")
A structure in C is a user-defined data type that allows grouping of different data types under a single name. It provides a way to combine related data items of varying types into a single unit, enhancing data organization and readability. Each data item within a structure is called a member.
A nested structure is a structure that is a member of another structure. This allows for hierarchical organization of data, where a complex entity can be represented by combining simpler, related entities.
Example of a Nested Structure:
#include <stdio.h>
// Inner structure: date
struct date {
int day;
int month;
int year;
};
// Outer structure: employee, which includes a 'date' structure
struct employee {
int id;
char name[50];
struct date dob; // Nested structure member
};
int main() {
struct employee emp1;
emp1.id = 101;
strcpy(emp1.name, "Alice Smith");
emp1.dob.day = 15;
emp1.dob.month = 6;
emp1.dob.year = 1990;
printf("Employee ID: %d\n", emp1.id);
printf("Employee Name: %s\n", emp1.name);
printf("Date of Birth: %d/%d/%d\n", emp1.dob.day, emp1.dob.month, emp1.dob.year);
return 0;
}
Structure book Definition:
struct book {
char name[100];
char author[100];
char publisher[100];
};
Program to Read Book Data and Display Names from "XYZ" Publisher:
#include <stdio.h>
#include <string.h> // Required for strcmp() and strcspn()
#define MAX_BOOKS 50
#define NAME_LEN 100
#define AUTHOR_LEN 100
#define PUBLISHER_LEN 100
// Structure definition for book
struct book {
char name[NAME_LEN];
char author[AUTHOR_LEN];
char publisher[PUBLISHER_LEN];
};
int main() {
struct book books[MAX_BOOKS]; // Array of 50 book structures
int i;
// Read data for 50 books
printf("Enter details for %d books:\n", MAX_BOOKS);
for (i = 0; i < MAX_BOOKS; i++) {
printf("\n--- Book %d ---\n", i + 1);
printf("Enter book name: ");
fgets(books[i].name, sizeof(books[i].name), stdin);
// Remove trailing newline character
books[i].name[strcspn(books[i].name, "\n")] = 0;
printf("Enter author name: ");
fgets(books[i].author, sizeof(books[i].author), stdin);
books[i].author[strcspn(books[i].author, "\n")] = 0;
printf("Enter publisher name: ");
fgets(books[i].publisher, sizeof(books[i].publisher), stdin);
books[i].publisher[strcspn(books[i].publisher, "\n")] = 0;
}
// Display names of books published by "XYZ"
printf("\n--- Books published by \"XYZ\" ---\n");
int found_books = 0;
for (i = 0; i < MAX_BOOKS; i++) {
// Compare publisher string (case-sensitive)
if (strcmp(books[i].publisher, "XYZ") == 0) {
printf("- %s\n", books[i].name);
found_books++;
}
}
if (found_books == 0) {
printf("No books found from publisher \"XYZ\".\n");
}
return 0;
}
Section B
Answer any two questions.
A C program typically follows a well-defined structure, comprising several logical sections that organize the code effectively.
- Preprocessing Directives: These are instructions for the C preprocessor, which processes the source code before actual compilation. Common directives include
#includefor incorporating header files (e.g.,stdio.hfor standard input/output functions) and#definefor defining macros. - Global Declarations: This section includes declarations of variables, functions, or data structures that are accessible throughout the entire program. These are declared outside any function.
main()Function: This is the essential entry point of every C program. Execution always begins from within themain()function. It defines the primary flow of the program and typically returns an integer value (0 for successful execution).- User-defined Functions: Beyond
main(), programmers can define their own functions to perform specific tasks. These functions enhance modularity, reusability, and readability of the code. They are called frommain()or other functions within the program. - Comments: While not executable code, comments (single-line
//or multi-line/* ... */) are crucial for documenting the code, explaining its logic, and improving maintainability.
Example:
// Preprocessing Directive
#include <stdio.h> // Includes standard input/output library
// Global Declaration (optional for this simple example, but shown for structure)
int global_data = 10;
// User-defined Function Declaration (Prototype)
void greet_user(void);
// main() Function - Program entry point
int main() {
// Local variable declaration
int local_var = 5;
printf("Welcome to C programming!\n"); // Statement
printf("Global data: %d\n", global_data);
printf("Local variable: %d\n", local_var);
greet_user(); // Calling a user-defined function
return 0; // Indicates successful program execution
}
// User-defined Function Definition
void greet_user() {
printf("Hello from greet_user function!\n");
}
Variable
A variable is a named storage location in memory used to hold data. Its value can change during the execution of a program. Each variable has a specific data type, which determines the type of data it can store (e.g., integer, character, float) and the amount of memory it occupies.
Difference from Constant
- Variable: A variable's value can be modified or reassigned at any point after its declaration and initialization during program execution.
- Constant: A constant's value is fixed after its initialization and cannot be changed throughout the program's execution. Constants are typically declared using the
constkeyword or defined using the preprocessor directive#define.
Comments in C
Comments in C are explanatory notes within the source code that are ignored by the compiler. They are used to make the code more readable and understandable.
There are two ways to write comments in C:
- Single-line comments: These begin with
//and extend to the end of the line.// This is a single-line comment int x = 10; // Variable x initialized to 10 - Multi-line comments: These begin with
/*and end with*/. They can span multiple lines./* * This is a multi-line comment. * It can describe complex logic * or provide function documentation. */ float pi = 3.14;
Formatted I/O functions facilitate the reading and writing of data in a specified format between a program and a peripheral device, typically the console or a file. They allow for the conversion of internal data representations (e.g., binary integers, floating-point numbers) into human-readable text and vice-versa.
Key aspects:
- Format Specifiers: These functions utilize format specifiers (e.g.,
%dfor integer,%ffor float,%sfor string,%cfor character) within a format string to indicate the type and desired presentation of the data being input or output. - Data Conversion: During output, data is converted from its internal binary representation to character sequences based on the format string. During input, character sequences are parsed and converted back into internal binary representations.
- Common Functions:
printf(): Writes formatted output to the standard output device (console).scanf(): Reads formatted input from the standard input device (console).fprintf(): Writes formatted output to a specified file stream.fscanf(): Reads formatted input from a specified file stream.sprintf(): Writes formatted output to a character array (string).sscanf(): Reads formatted input from a character array (string).
These functions provide powerful control over data representation, making program interaction with users and files more flexible and user-friendly.
def add_numbers(num1, num2):
"""
Calculates the sum of two numbers.
Parameters:
num1 (float or int): The first number.
num2 (float or int): The second number.
Returns:
float or int: The sum of num1 and num2.
"""
return num1 + num2
# Main part of the program
if __name__ == "__main__":
try:
# Get input from the user
number1 = float(input("Enter the first number: "))
number2 = float(input("Enter the second number: "))
# Call the custom function to find the sum
result_sum = add_numbers(number1, number2)
# Display the result
print(f"The sum of {number1} and {number2} is: {result_sum}")
except ValueError:
print("Invalid input. Please enter valid numbers.")
# Program to print the largest among three numbers
# Get input from the user
num1 = float(input("Enter the first number: "))
num2 = float(input("Enter the second number: "))
num3 = float(input("Enter the third number: "))
# Determine the largest number
if (num1 >= num2) and (num1 >= num3):
largest = num1
elif (num2 >= num1) and (num2 >= num3):
largest = num2
else:
largest = num3
# Print the result
print("The largest number is:", largest)
Dynamic memory allocation is a programming technique that allows a program to request memory space at runtime (during program execution) instead of compile time. This memory is typically allocated from the heap segment.
Key aspects:
- Flexibility: It enables programs to handle varying amounts of data without predefined memory limits, making memory usage more efficient and adaptable to different input sizes.
- Runtime Control: Memory is requested and released by the programmer explicitly, offering greater control over memory resources.
- Standard Library Functions (C/C++): Common functions for dynamic memory management include:
malloc(): Allocates a specified number of bytes and returns a void pointer to the beginning of the allocated block.calloc(): Allocates space for an array of elements, initializes all bits to zero, and returns a void pointer.realloc(): Changes the size of a previously allocated memory block.free(): Deallocates the memory block pointed to by a pointer, returning it to the system.
Example (Conceptual C-like):
#include <stdio.h>
#include <stdlib.h> // Required for malloc and free
int main() {
int *arr; // Pointer to an integer
int n = 5; // Number of elements
// Allocate memory for 5 integers dynamically
arr = (int *) malloc(n * sizeof(int));
// Check if malloc was successful
if (arr == NULL) {
printf("Memory allocation failed!\n");
return 1;
}
// Use the allocated memory
for (int i = 0; i < n; i++) {
arr[i] = i + 1;
printf("%d ", arr[i]);
}
printf("\n");
// Deallocate the memory
free(arr);
arr = NULL; // Good practice to set pointer to NULL after freeing
return 0;
}
# Program to read data from a file
# Define the name of the file to be read
file_name = "input_data.txt"
try:
# Open the file in read mode ('r')
# The 'with' statement ensures the file is automatically closed after its block
with open(file_name, 'r') as file:
print(f"--- Content of '{file_name}' ---")
# Iterate through each line in the file
for line in file:
# Print the line, removing the trailing newline character
print(line.strip())
print(f"--- End of '{file_name}' ---")
except FileNotFoundError:
# Handle the case where the specified file does not exist
print(f"Error: The file '{file_name}' was not found.")
print("Please ensure the file exists in the same directory as the script.")
except Exception as e:
# Handle any other unexpected errors during file operation
print(f"An unexpected error occurred: {e}")
#include <graphics.h> // Required for graphics functions
#include <conio.h> // Required for getch()
void main() {
int gd = DETECT, gm; // gd = graphics driver, gm = graphics mode
int x1 = 100, y1 = 100; // Starting coordinates of the line
int x2 = 400, y2 = 200; // Ending coordinates of the line
// Initialize graphics mode
initgraph(&gd, &gm, "C:\\TURBOC3\\BGI"); // Adjust path to BGI folder if necessary
// Draw a line from (x1, y1) to (x2, y2)
line(x1, y1, x2, y2);
getch(); // Wait for a key press
closegraph(); // Close graphics mode
}
History of C
- Developed at Bell Labs in the early 1970s by Dennis Ritchie.
- Evolved from earlier languages such as ALGOL, BCPL, and B. The 'B' language was created by Ken Thompson.
- Initially designed to develop the UNIX operating system, making it a powerful system programming language.
- Gained popularity due to its efficiency, low-level memory access, and high portability across various hardware platforms.
- Standardized by the American National Standards Institute (ANSI) in 1989, leading to ANSI C (C89/C90), which ensured consistent behavior across different compilers.
- Subsequent standards include C99, C11, C17, and C23, introducing new features and improvements.
Bitwise Operator
Bitwise operators manipulate data at the individual bit level. They treat their operands as sequences of bits rather than as decimal, octal, or hexadecimal numbers.
-
Types of Bitwise Operators:
- AND (
&): Sets each bit to 1 if both corresponding bits are 1. - OR (
|): Sets each bit to 1 if at least one of the corresponding bits is 1. - XOR (
^): Sets each bit to 1 if only one of the corresponding bits is 1 (exclusive OR). - NOT (
~): Inverts all bits of the operand (unary operator, one's complement). - Left Shift (
<<): Shifts bits to the left, filling vacated positions with zeros. Equivalent to multiplying by powers of 2. - Right Shift (
>>): Shifts bits to the right. For unsigned types, vacated positions are filled with zeros. For signed types, it depends on the implementation (arithmetic vs. logical shift). Equivalent to dividing by powers of 2.
- AND (
-
Common Applications:
- Masking: Extracting specific bits from a value.
- Setting/Clearing Bits: Turning specific bits on or off.
- Checking Bits: Determining if a specific bit is set or clear.
- Efficient Arithmetic: Fast multiplication or division by powers of 2 using shift operators.