C Programming Overview
C is a general-purpose, procedural, and mid-level
programming language. It was developed by Dennis M. Ritchie at
AT&T’s Bell Laboratories in 1972. C was initially used for
developing the UNIX operating system, which was later entirely
re-written in C.
Key Features of C:
• It can be used to develop system software (like operating
systems) as well as application software.
• It is portable, meaning programs written in C can be easily
moved to different platforms.
• It supports a variety of data types, such as int and float.
• It is a procedure-oriented programming language and
provides built-in functions.
• C programs generally have faster execution compared to
other high-level language programs.
• It is considered a middle-level language, offering low-level
memory access while maintaining high-level language
features.
General Structure of a C Program: A typical C program includes
several sections:
1. Documentation Section: Contains information about the
program, such as its purpose, author, date, etc., enclosed
within comments and ignored by the compiler.
2. Link Section: Involves the inclusion of header files, which
contain predefined functions for standard input and output
(e.g., <stdio.h>).
3. Definition Section: Consists of macro definitions and
constant definitions (e.g., #define PI 3.14).
4. Global Declaration Section: Any variables declared here
are accessible throughout the entire program and to all
functions.
5. main() Function: Mandatory for every C program, it serves
as the entry point where program execution begins. It
contains a declaration part and an executable part within
curly braces {}.
6. Sub-program Section: Optional, used for user-defined
functions.
Compilation Process: The process of converting C source code
(written in a high-level language) into machine code
(understandable by the computer, i.e., 0s and 1s) is called
compiling. This process typically involves several phases:
1. Preprocessor: Processes source code before compilation,
handling directives starting with # (e.g., #include, #define).
2. Compiler: Compiles the expanded source code into
assembly source code, checking for syntax or semantic
errors. If successful, it creates an object code file with a
.obj extension.
3. Linker: Connects the object code with necessary library
modules (from header files) to create an executable
program file with an .exe extension.
4. Loader: Transfers the executable program from secondary
storage to main memory for execution.
5. Execution: The program's instructions run, and the output is
displayed.
C Tokens: Tokens are the smallest individual units in a C program
that have meaningful representations and are the building blocks
recognized by the C compiler. There are six types of tokens:
1. Identifiers: User-defined names for variables, constants,
functions, and arrays. Rules for naming include using
alphanumeric characters and underscores, starting with an
alphabet or underscore, being case-sensitive, and not being
keywords.
2. Keywords: Reserved words with predefined meanings
that cannot be changed or used as identifiers. C has 32
keywords.
3. Constants: Fixed values that do not change during program
execution, also called literals.
4. Strings: Sequences of characters terminated by a null
character \0.
5. Special Symbols: Characters like ;, ,, :, {, /, \, ^, #, @.
6. Operators: Symbols that perform specific operations on
values and variables (operands).
Variables and Data Types
Variables: A variable in C is a named memory location used to
store data and access it when needed. Its value can change
during program execution.
• Declaration: Associates an identifier with a specific data
type, informing the compiler about its characteristics.
o Syntax: data_type variable-1, variable-2, ..., variable-
n;.
o Example: int age;.
• Initialization: Storing a value in a variable. This can be done
along with declaration (e.g., int age = 22;) or later using an
assignment statement (e.g., age = 22;). Uninitialized
variables can lead to unpredictable results.
• Types of Variables: C supports various types including
local, global, and static variables, each with specific scope
and lifetime properties.
Constants: Constants are read-only values that remain fixed
throughout the program's execution. They can be integer, floating-
point, character, or string types.
• Integer Constants: Numeric constants without fractional or
exponential parts (e.g., 32727, 021 (octal), 0x7f
(hexadecimal)).
• Floating Point Constants: Numeric constants with a
fractional or exponential form (e.g., 2.58, -0.22E-5).
• Character Constants: Single characters enclosed in single
quotes (e.g., 'A').
• String Constants: Sequences of characters enclosed in
double quotes (e.g., "Rama").
• Symbolic Constants: Names associated with a constant
value, defined using #define (e.g., #define MAX 100).
• const Keyword: Used to define a constant variable whose
value cannot be changed after initialization (e.g., const float
PI = 3.14;).
Data Types: Data types in C define the kind of data a variable can
store, how much storage it occupies, and how its bit pattern is
interpreted. C is a statically typed language.
Classification of Data Types:
1. Basic Types (Primary Data Types): Arithmetic types
including integer and floating-point types.
o Integer Types: char, int, short, long, and their unsigned
and signed variants. Their storage size and value range
can vary (e.g., int can be 2 or 4 bytes).
▪ char: 1 byte, range -128 to 127 or 0 to 255.
▪ int: 2 or 4 bytes, ranges from -32,768 to 32,767 or -
2,147,483,648 to 2,147,483,647.
o Floating-Point Types: float, double, long double. They
store real numbers with varying precision.
▪ float: 4 bytes, 6 decimal places precision.
▪ double: 8 bytes, 15 decimal places precision.
▪ long double: 10 bytes, 19 decimal places
precision.
2. Enumerated Types (enum): Arithmetic types used to define
variables that can only be assigned certain discrete integer
values (e.g., enum week {sun, mon, ...};).
3. The void Type: Specifies that no value is available. It is
used in three situations:
o Function returns as void: Functions that do not return
a value (e.g., void main()).
o Function arguments as void: Functions that do not
accept any parameters (e.g., int rand(void);).
o Pointers to void: A void * pointer represents the
address of an object without knowing its specific type.
It can be cast to any data type.
4. Derived Types: Include Pointer types, Array types,
Structure types, and Union types, as well as Function
types.
Type Conversion/Casting:
• Implicit Type Conversion: Automatically performed by the
compiler without programmer intervention (e.g., assigning
an int to a float).
• Explicit Type Conversion (Type Casting): Manually done by
the programmer to convert one data type to another using
the cast operator (new_type) operand; (e.g., (float)x /
(float)y;).
I/O Operations
In C programming, input and output (I/O) operations involve
reading data from external sources (like the user) and writing data
to external destinations (like the screen or files). These operations
enable communication between the user and the program. C
provides a standard set of functions for this purpose, found in the
standard input/output library <stdio.h>.
I/O functions are generally categorized into two types:
1. Formatted I/O Functions: These functions handle data in a
specific, predefined format using format specifiers (e.g.,
%d for integer, %c for character, %f for float, %s for string).
o printf() Function:
▪ Used to print formatted output to the standard
output (stdout), typically the console screen.
▪ Syntax: printf("formatted_string",
variables/values);.
▪ The formatted_string defines the output structure
and includes format specifiers (placeholders).
▪ Examples:
▪ Printing Text: printf("First Print"); outputs
"First Print". The text inside double quotes is
a string.
▪ Printing Variables: printf("%d\n", age);
outputs the value of the age variable. %d is
the format specifier for an integer. \n is an
escape sequence for a newline character.
▪ Printing Variables with Strings: printf("The
value of the variable age is %d\n", age);
outputs a formatted string with the variable's
value embedded.
o scanf() Function:
▪ Used to read user input from the console
(stdin).
▪ It takes a format string and the addresses of the
variables where the input will be stored.
▪ Syntax: scanf("formatted_string",
address_of_variables/values);.
▪ Important: This function requires the address
operator (&) before variable names (e.g., &age) to
store the input value directly into the memory
location of the variable.
▪ Examples:
▪ Reading an Integer: scanf("%d", &age);
reads an integer from the user.
▪ Reading a Character: scanf("%c", &ch);
reads a single character.
▪ Reading a String: scanf("%s", str); can read
string input, but only reads single words (it
stops at the first space or newline).
2. Unformatted I/O Functions: These functions read or write
character or string data without using format specifiers.
o fputs(): Used to output strings to files, but can also
print strings to the console using stdout (e.g.,
fputs("your text here", stdout);).
o fgets(): A better alternative to scanf() for reading strings
as it can handle spaces and prevent buffer overflow. It
reads a specified number of characters from input into
a string.
▪ Syntax: fgets(str, n, stdin); where str is the buffer,
n is max characters to read, and stdin specifies
keyboard input.
o Character I/O:
▪ getchar(): Reads a single character from
standard input; waits for Enter key press.
▪ putchar(): Writes a single character to the
standard output screen.
▪ getch(): Reads a single character directly from the
keyboard without echoing it to the screen.
▪ getche(): Reads a single character from the
keyboard and echoes it to the screen.
o String I/O:
▪ gets(): Reads an entire line of text (string)
including spaces from the user and stores it into
a character array.
▪ puts(): Writes an entire string (sentence) to the
screen and automatically adds a newline
character at the end.
Operators and Expressions
Operators in C are symbols that represent specific operations
to be performed on values and variables called operands. They
are fundamental components of C programming.
Types of Operators Based on Operands:
• Unary Operators: Work on a single operand (e.g., a++, !a,
sizeof(a)).
• Binary Operators: Work on two operands (e.g., a + b, a > b).
• Ternary Operators: Work on three operands. The
conditional operator (?:) is the only ternary operator in C.
Classification of Operators by Functionality:
1. Arithmetic Operators: Used for mathematical
calculations.
o + (Addition), - (Subtraction), * (Multiplication), /
(Division), % (Modulus - returns remainder for integers).
o ++ (Increment - increases operand by 1), -- (Decrement
- decreases operand by 1).
▪ Pre-increment/decrement (++a, --a):
Increments/decrements first, then uses the new
value.
▪ Post-increment/decrement (a++, a--): Uses the
current value first, then increments/decrements.
2. Relational Operators: Used to compare two operands and
return a Boolean result (1 for true, 0 for false).
o < (Less than), > (Greater than), <= (Less than or equal
to), >= (Greater than or equal to), == (Equal to), != (Not
equal to).
3. Logical Operators: Used to combine two or more
conditions or to complement a condition, returning true (1)
or false (0).
o && (Logical AND): Returns true if both operands are
true.
o || (Logical OR): Returns true if at least one operand is
true.
o ! (Logical NOT): Reverses the Boolean value of its
operand.
4. Assignment Operators: Used to assign a value to a
variable. The left operand must be a variable.
o = (Simple assignment): Assigns the value of the right
operand to the left operand (e.g., x = 10;).
o Compound Assignment Operators: Combine an
arithmetic or bitwise operation with assignment (e.g.,
+=, -=, *=, /=, %=, &=, |=, ^=, >>=, <<=). Example: x += y
is equivalent to x = x + y.
5. Bitwise Operators: Perform operations directly on the
binary representations (individual bits) of numbers. They
only work with integer data types.
o & (Bitwise AND), | (Bitwise OR), ^ (Bitwise XOR).
o ~ (Bitwise First Complement): Flips all bits.
o << (Bitwise Left Shift): Shifts bits to the left, equivalent
to multiplication by powers of 2.
o >> (Bitwise Right Shift): Shifts bits to the right,
equivalent to division by powers of 2.
6. Other/Special Operators:
o sizeof Operator: A compile-time unary operator that
computes the size of its operand in bytes. The result
is of size_t type.
o Comma Operator (,): A binary operator that evaluates
its first operand, discards the result, then evaluates the
second operand and returns its value. It has the lowest
precedence.
o Conditional Operator (?:): The only ternary operator,
used as a shorthand for if...else statements. Syntax:
expression1 ? Expression2 : Expression3; If
Expression1 (condition) is true, Expression2 is
executed; otherwise, Expression3 is executed.
o Dot (.) and Arrow (->) Operators: Used to access
members of structures and unions.
▪ . is used with the actual object/variable.
▪ -> is used with a pointer to an object.
o Address-of (&) and Dereference (*) Operators:
▪ & (Address-of Operator): Returns the memory
address of a variable.
▪ * (Dereference/Indirection Operator): Accesses
the value stored at the memory address held by a
pointer.
Expressions: An expression is a line of code consisting of
operators and operands that typically returns a value as a result
of its evaluation (e.g., 2 + 3, (a - b) * 2).
Operator Precedence and Associativity: These rules determine
the order in which operators are evaluated in an expression
containing multiple operators.
• Precedence: Defines which operators are evaluated first
(e.g., multiplication has higher precedence than addition).
• Associativity: Determines the direction of evaluation (left-
to-right or right-to-left) for operators with the same
precedence. For example, arithmetic operators *, /, %, +, -
are left-to-right associative. The assignment operator = is
right-to-left associative.
Control Flow Statements
Control flow statements in C programming are used to alter the
normal sequential execution of a program, allowing it to make
decisions, repeat actions, or jump to different parts of the code.
They are generally categorized into three types: Selection (or
Decision/Branch), Loop (or Iteration/Repetition), and Jump
statements.
• Selection/Decision/Branch Statements: These
statements allow a program to choose which part of the
code to execute based on certain conditions.
o if statement: This is the simplest decision-making
statement. Its body executes only if the given test
condition is true (non-zero); otherwise, it is skipped.
▪ Syntax: if (condition) { true statement; }.
▪ Example: if (number < 0) { printf("You entered
%d.\n", number); }.
▪ If there is only one statement in the if block,
braces {} are optional, but for multiple
statements, they are compulsory.
o if-else statement: An extension of the if statement, it
executes one block of code if the condition is true and
a different block if the condition is false.
▪ Syntax: if (condition) { true statement; } else { false
statement; }.
o nested if-else statement: An if-else statement placed
inside another if or else block.
o else if ladder: Used to test a series of conditions
sequentially, executing the code for the first true
condition. Only if all previous conditions are false is a
condition checked.
▪ Syntax: if (condition-1) { ... } else if (condition-2) {
... } else { default-statement; }.
o switch statement: Allows execution of different code
blocks based on the value of an integer expression. It's
often used as an alternative to a long if-else if ladder
when there are multiple discrete options.
▪ Syntax: switch(expression) { case value-1: ...
break; default: ... }.
▪ Rules: The expression must yield an integer value,
case constants must be integers or characters
and unique, default is optional and can be placed
anywhere, and case labels must end with a colon.
▪ break statements are typically used to exit the
switch block after a match; without them,
execution "falls through" to subsequent cases.
• Loop/Iteration/Repetition Statements: These statements
are used to execute a block of code multiple times until a
specified condition becomes false. Every loop typically
requires three parts: initialization of a control variable, a
condition based on this variable, and modification
(increment/decrement) of the control variable within the
loop body.
o while loop: An entry-controlled loop that repeatedly
executes a block of code as long as a given condition
remains true. The condition is evaluated before each
execution of the loop body.
▪ Syntax: while (test condition) { body_of_the_loop;
}.
o do-while loop: An exit-controlled loop that executes
the code block at least once before evaluating the
condition. After the first execution, it continues to
repeat as long as the condition remains true.
▪ Syntax: do { body_of_the_loop; } while
(condition);.
o for loop: An entry-controlled loop that is often used
when the number of repetitions is fixed. It simplifies the
syntax by including initialization, condition, and
modification steps in its header.
▪ Syntax: for (initialization; condition; modification)
{ Statements; }.
o Nested for loop: One for loop placed inside another
for loop, commonly used for multidimensional arrays.
• Jump Statements: These control statements transfer the
program's execution control from one place to another.
o break statement: Terminates the innermost loop (or
switch statement) immediately when encountered,
transferring control to the statement following the
loop/switch.
▪ Syntax: break;.
o continue statement: Skips the current iteration of a
loop and proceeds to the next iteration. It does not
terminate the loop entirely.
▪ Syntax: continue;.
o goto statement: Transfers the control of execution to a
specified label within the program. While it offers
control, it's generally not recommended as it can make
code harder to read and maintain.
▪ Syntax: goto label; ... label: statements;.
Functions
A function in C is a block of logically connected executable
statements that performs a specific task when called. Functions
are fundamental building blocks that provide modularity and
code reusability to a C program. They are also known as
subroutines or procedures in other languages.
• Advantages of Functions:
o Code Reusability: Functions can be called multiple
times, avoiding repetitive code.
o Code Optimization: Reduces the amount of code
needed.
o Improved Readability: Makes the main program easier
to understand.
o Easier Debugging: Isolates logic into smaller units,
making it simpler to find and fix errors.
• Types of Functions:
o Library Functions (Built-in/Pre-defined): These
functions are already declared in standard C header
files (e.g., stdio.h for printf() and scanf(), string.h for
string functions, math.h for mathematical operations)
and their definitions are implemented in .dll files. You
include the appropriate header file to use them.
o User-defined Functions: These are functions created
by the programmer to perform specific tasks as per the
program's requirements. They help reduce program
complexity and optimize code.
• Elements of User-Defined Functions:
o Function Declaration (Function Prototype): Informs
the compiler about the function's name, its return type,
and the number and data types of its parameters. It
helps the compiler cross-check function calls and
definitions.
▪ Syntax: return_type
function_name(parameter/argument);.
o Function Call (Invocation): The act of executing a
function. When a function is called, program control
transfers to the function's definition, executes its code,
and then returns to the caller function.
▪ Syntax: function_name(); or
function_name(arguments);.
o Function Definition: Contains the actual executable
logic or "body" of the function. It consists of a header
(specifying attributes) and a body (containing
executable logic).
▪ Syntax: return_type function_name(parameter
list) { ... function body ... }.
• void Keyword:
o Used as a return type (void func()) to indicate that a
function does not return any value.
o Used in the parameter list (func(void)) to indicate that a
function does not accept any arguments.
• return Statement:
o Used to terminate the execution of a function and
return control (and optionally a value) to the calling
function.
o Syntax: return; (no value) or return expression; (returns
value).
• Types of Function Definitions (based on arguments and
return values):
o No arguments and No return value: No data transfer
between caller and called function, only control flow.
o No arguments but with return value: Data transfer
from called function to caller.
o With arguments and no return value: Data transfer
from caller to called function.
o With arguments and with return value: Data transfer
in both directions.
• Parameters:
o Actual Parameters: Values or variables passed from
the calling function during a function call.
o Formal Parameters: Variables defined in the function's
parameter list that receive values from the actual
parameters.
• Parameter Passing Techniques:
o Call by Value: The values of actual parameters are
copied into the formal parameters. Changes to formal
parameters within the function do not affect the
original actual parameters.
o Call by Reference: The addresses of actual
parameters are passed to the formal parameters
(which are pointer variables). This allows the function
to directly access and modify the original values of the
actual parameters.
• Inter-Function Communication: The process of exchanging
information between calling and called functions.
o Downward Communication: Data transferred from
calling to called function (functions with parameters,
no return value).
o Upward Communication: Data transferred from called
to calling function (functions without parameters, with
return value).
o Bi-directional Communication: Data transferred in
both directions (functions with parameters and return
value).
• Recursion: A function calling itself within its own body. A
recursive function requires a terminating condition to
prevent an infinite loop.
Arrays
An array in C is a fixed-size collection of similar data items
stored in contiguous memory locations. All elements of an
array share the same name and are distinguished by an index.
• Advantages:
o Easy Data Sorting: Requires few lines of code to sort
elements.
o Random Access: Any element can be accessed
directly using its index.
• Disadvantage: Arrays have a fixed size determined at
compile time, meaning their size cannot be dynamically
changed during program execution.
• Declaration:
o Syntax: data_type array_name[size];.
o The size specifies the number of elements the array
can hold.
o Array indices start from 0 and go up to size-1.
• Initialization: An array can be initialized to prevent garbage
values.
o Compile-time Initialization: Values are assigned
when the array is declared.
▪ Example: int age = {22, 25, 30, 32, 35};.
▪ For string initialization, the null terminator \0 is
automatically added by the compiler if space
permits.
o Runtime Initialization: Values are assigned during
program execution, typically using input functions like
scanf().
• Multidimensional Arrays: Arrays with more than one
dimension.
o Two-Dimensional (2D) Arrays: Represented in rows
and columns, similar to a matrix. Also known as "array
of arrays".
▪ Declaration: data_type array_name[size1][size2];.
▪ Elements can be accessed using two subscripts
(array[row][column]) or pointer notation (*(*(arr +
i) + j)).
o Three-Dimensional (3D) Arrays: Arrays with three
dimensions.
• Passing Arrays to Functions: In C, arrays are always
passed to functions using pointers. This means that
modifications to array elements inside a function will affect
the original array in the calling function. This behavior is
sometimes referred to as "array decay".
Pointers
A pointer is a variable that stores the memory address of
another variable. Instead of holding a direct value, it holds the
address where the value is stored in memory, making it the
backbone of low-level memory manipulation in C.
• Benefits of using pointers:
o Efficient Handling: Improves efficiency when working
with arrays and structures.
o Function References: Allows functions to be passed
as arguments to other functions.
o Reduced Program Length and Execution Time.
o Dynamic Memory Management: Enables C to support
dynamic memory allocation.
• Declaration:
o Syntax: data_type* pointer_variable_name;.
o The asterisk * indicates that it's a pointer variable.
o The data_type specifies the type of the variable whose
address the pointer can store.
• Initialization: The process of assigning the address of a
variable to a pointer variable.
o Example: int num = 10; int *ptr; ptr = #.
• Address-of Operator (&) and Indirection/Dereference
Operator (*):
o & (Address-of): Returns the memory address of a
variable. Example: &qty gives the address of qty.
o * (Indirection/Dereference): Returns the value stored
at the memory address held by the pointer. Example:
*ptr gives the value pointed to by ptr.
• Key Points about Pointers:
o Pointers store whole numbers (memory addresses).
o A pointer is typically initialized to NULL if it doesn't
point to a valid memory location; the value of a NULL
pointer is 0.
o Pointer arithmetic (increment, decrement, addition,
subtraction of integers) is allowed to move between
array elements.
o Pointer addition, multiplication, or division are
generally not allowed.
• NULL Pointer: A pointer that is not assigned any value but
NULL (or 0) is a NULL pointer, meaning it points to nothing.
• Pointers to Pointers (Double Pointers): A pointer that
stores the address of another pointer.
o Syntax: int **pii;.
• Relationship with Arrays: In C, an array name itself acts
like a pointer constant that points to the address of the first
element of the array.
o arr is equivalent to &arr.
o *(arr + i) is equivalent to arr[i] (value of the i-th
element).
o (arr + i) is equivalent to &arr[i] (address of the i-th
element).
• Pointer Arithmetic: Operations on pointer variables
calculate new memory addresses.
o new_address = current_address + i * size_of(data type).
o Incrementing/decrementing a pointer moves it by the
size of the data type it points to (e.g., an int*
increments by 2 or 4 bytes depending on system
architecture).
• Pointers to void (void *):
o A "general purpose" pointer that has no associated
data type.
o It can hold the address of any data type and can be
typecasted to any type.
o Functions like malloc() and calloc() (for dynamic
memory allocation) return void * pointers, allowing
them to allocate memory for any data type.
• Pointers to Functions (Function Pointers):
o A pointer that stores the address of a function's
executable code.
o Allows functions to be called dynamically or passed as
arguments to other functions.
o Cannot perform pointer arithmetic on them.
o Declaration syntax requires the pointer name to be in
parentheses: return_type
(*pointer_name)(argument_list);.
• Dynamic Memory Allocation (stdlib.h functions): These
functions allow memory to be allocated and freed during
program execution (at runtime) from the Heap memory area.
o malloc(): Allocates a single block of requested
memory. The allocated memory is not initialized and
contains garbage values.
▪ Syntax: ptr = (cast_type*) malloc(size_in_bytes);.
o calloc(): Allocates multiple blocks of requested
memory and initializes all bytes to zero.
▪ Syntax: ptr = (cast_type*) calloc(num_elements,
element_size);.
o realloc(): Resizes (reallocates) a previously allocated
memory block.
o free(): Deallocates (frees) the dynamically allocated
memory.
String Handling
A String in C programming is a sequence of characters
terminated with a null character ('\0'). The null character signals
the end of the string.
• Difference from Character Arrays: The key difference is the
'\0' terminator. A character array is just a group of
characters, while a string must be null-terminated to be
treated as a string by C's string functions.
• Declaration: C does not have a built-in string data type.
Strings are represented as character arrays.
o Syntax: char string_name[size]; The size must be
specified and must include space for the '\0'
terminator.
• Initialization:
o Character by character: char city1={'R','J','Y'};.
o Using a string literal (double quotes): char
city3[]="RJY"; The compiler automatically adds the '\0'
terminator.
• Reading and Writing Strings:
o Formatted I/O:
▪ printf("%s", ...): Used to print strings.
▪ scanf("%s", ...): Used to read single words from
input, as it stops reading at the first whitespace.
o Unformatted I/O: These functions are often better for
string handling than scanf() as they can handle spaces.
▪ gets(): Reads a line of characters (string) from
standard input until a newline character is
encountered. It can read multiple words. Note:
The gets() function is considered unsafe because
it doesn't perform bounds checking, leading to
potential buffer overflows. (This is an important
safety consideration, although not explicitly
stated in your provided sources, it's a common C
programming best practice. The sources do
mention fgets() as a better alternative to scanf()
because it prevents buffer overflow.)
▪ puts(): Writes a string to the standard output,
automatically adding a newline character at the
end.
▪ fgets(): Reads a specified number of characters
from a line of input and stores them in a string,
capable of handling spaces and preventing buffer
overflow.
▪ getchar(): Reads a single character from standard
input; waits for Enter key.
▪ putchar(): Writes a single character to standard
output.
▪ getch(): Reads a single character directly from the
keyboard without echoing it to the screen.
▪ getche(): Reads a single character from the
keyboard and echoes it to the screen.
• String Manipulation Functions (string.h header file):
o strlen(str): Returns the length of the string (number of
characters before the '\0').
o strcpy(destination, source): Copies the source string
to the destination string. You cannot directly assign one
character array to another.
o strcat(destination, source): Appends the source
string to the end of the destination string.
o strcmp(str1, str2): Compares two strings
lexicographically. Returns 0 if equal, a negative value if
str1 is less than str2, and a positive value if str1 is
greater than str2.
o strlwr(str): Converts uppercase characters in str to
lowercase.
o strupr(str): Converts lowercase characters in str to
uppercase.
o strrev(str): Reverses the given string.
o strdup(str): Allocates sufficient memory for a copy of
str, performs the copy, and returns a pointer to it. The
allocated memory must be free()d later.
o strncpy(dst, src, len): Copies len characters from src
to dst. It will pad with \0 if src is shorter than len but will
not null-terminate dst if src is len or longer.
o strncat(s, append, count): Appends append to s,
adding a \0. Appends not more than count characters.
o memset(b, c, len): Writes len bytes of value c to string
b.
o strlcpy(dst, src, size) and strlcat(dst, src, size): Safer
alternatives to strncpy and strncat that take the full
buffer size and guarantee null-termination as long as
size > 0 (for strlcpy) or there is at least one byte free (for
strlcat).
o strchr(s, c): Locates the first occurrence of character c
in string s.
o strrchr(s, c): Locates the last occurrence of character
c in string s.
o strstr(big, little): Locates the first occurrence of
substring little in string big.
o snprintf(): Acts like printf() but stores the formatted
output into a string buffer.
o atoi(), atol(), atof(): Convert a string to an integer, long
integer, or double-precision floating-point number,
respectively.
Structures and Unions
Both structures and unions are user-defined data types in C
used to group different types of data under a single name. The
main difference lies in how they allocate and use memory.
• Structures:
o Definition: A structure is a collection of variables,
possibly of different data types, grouped under a single
name.
o Memory Allocation: Each member within a structure
is allocated its own unique storage area in memory.
The size of the structure is the sum of the sizes of all
its members, potentially with padding. This means no
data overlap.
o Keyword: Defined using the struct keyword.
o Syntax:
o struct structName {
o DataType Member1;
o DataType Member2;
o // ...
o };
.
o Declaration of Variables: Variables of a structure type
can be declared after the definition or as part of the
definition.
o Accessing Members: Individual members are
accessed using the dot (.) operator for structure
variables or the arrow (->) operator for structure
pointers.
o Initialization: Structures can be initialized at the time
of declaration.
o Array of Structures: An array where each element is a
structure variable, allowing storage of multiple records
of the same structure type.
o Structures as Function Arguments: Structures can be
passed to functions either by value (a copy is passed)
or by address (reference) using pointers.
o Structure Pointers: A pointer can be created to point
to a variable of a structure type. Members are accessed
using the -> operator.
o Nested Structures: A structure can contain another
structure as a member.
o Self-referential Structures: A structure containing a
pointer member that points to another structure of the
same type. These are used to create data structures
like linked lists.
• Unions:
o Definition: A special data type that allows different
data types to be stored in the same memory
location.
o Memory Allocation: All members of a union share the
same memory location. The size of the union is
equal to the size of its largest member. This results in
full data overlap.
o Keyword: Defined using the union keyword.
o Syntax:
o union unionName {
o DataType Member1;
o DataType Member2;
o // ...
o };
.
o Accessing Members: Only one member can be
accessed at a time in a union, as changing the value of
one member will overwrite the values of other
members (due to shared memory).
o Initialization: Only the first member of a union can be
initialized.
• Similarities Between Structures and Unions:
o Both are user-defined data types.
o Both group different data types into a single unit.
o Their members can be of any type, including other
structures, unions, arrays, or bit fields.
o Both support only the assignment (=) and sizeof
operators.
o Both can be passed by value to functions and returned
by value by functions.
o The dot (.) operator is used for accessing member
variables.
• typedef: A keyword that allows the programmer to create a
new alias (data type name) for an existing data type.
o Syntax: typedef datatype alias_name;.
o Advantages: Provides a more meaningful way of
declaring variables and increases program readability.
Can be used for basic data types, structures, and
pointers.
• Enumerations (enum):
o A user-defined data type that behaves like an integer
type.
o Used to create a sequence of integer constant values.
o By default, the first identifier in the enum list is
assigned 0, and subsequent identifiers are
incremented by 1.
o Syntax: enum tagname {value1, value2, value3, ...};.
Files Handling
In C programming, input and output (I/O) operations involve
reading data from external sources and writing data to external
destinations outside the program. When data is stored using
variables, it is typically lost when the program terminates. Files
are needed for permanent storage of data, ensuring that data
persists even after the program exits. They also facilitate entering
large amounts of data and moving data between computers.
A file in C is viewed as a sequential stream of bytes and is a
collection of bytes stored on secondary storage devices like a
hard disk. All file-related functions are available in the <stdio.h>
header file.
Types of Files: There are two primary types of files in C:
• Text files: These are standard .txt files that store content as
plain text. They are easily readable and editable, require
minimal maintenance, but offer less security and occupy
more storage space. For example, an integer 54 would be
stored as a 3-byte string "54\0" in a text file.
• Binary files: These files store data in binary form (0s and 1s).
They can hold larger amounts of data, are not easily
readable by humans, and provide better security than text
files. For instance, the integer 1245 would be stored in 2
bytes internally in memory, but would require 5 bytes in a
text file.
File Operations: In C, you can perform four major operations on
files:
1. Creation/Naming: Creating a new file.
2. Opening: Opening an existing file.
3. Reading: Reading data from the file.
4. Writing: Writing data into the file.
5. Closing: Closing a file.
Steps for Processing a File: The general steps for file processing
are:
1. Declare a file pointer: This pointer, of type FILE*, is
necessary for communication between the program and the
file. It is declared as FILE *fp;.
2. Open a file: The fopen() function is used to create a new file
or open an existing one. Its syntax is FILE *fopen(char
*filename, mode);.
o File Opening Modes specify how the file will be
accessed:
▪ r / rt: Opens a text file for read-only access.
▪ w / wt: Opens a text file for write-only access. If
the file exists, its content is truncated; otherwise,
a new file is created.
▪ a / at: Opens a text file in append mode. Data is
added to the end of the existing content; if the file
doesn't exist, a new one is created.
▪ r+ / r+t: Opens a text file for both read and write
access.
▪ w+ / w+t: Creates a text file for read and write
access. Existing content is truncated.
▪ a+ / a+t: Creates a text file for read and write
access in append mode. Data is added to the end.
▪ Binary modes include rb, wb, ab, rb+, wb+, ab+.
3. Process the file: Use suitable file functions for reading or
writing.
4. Close the file: The fclose() function closes an opened file.
Its syntax is int fclose(FILE *fptr);. It returns 0 on success
and EOF on error.
Formatted File I/O Functions: These functions operate on
various types of data and use format specifiers:
• fprintf(): Used to print formatted output to a file (stream).
Syntax: fprintf(fp, "control string", list);.
• fscanf(): Used to read formatted input from a file (stream).
Syntax: fscanf(fp, "control string", list);.
Unformatted File I/O Functions: These functions typically do not
use format specifiers and are often used for single character or
string operations:
• fputc(): Writes a single character to a file. Example: fputc('a',
fp);.
• fgetc(): Reads a single character from a file. It returns EOF
(End of File) at the end of the file.
• fputs(): Writes a line of characters (string) to a file. Example:
fputs("hello c programming", fp);.
• fgets(): Reads a line of characters (string) from a file. It is a
better alternative to scanf() for strings as it can handle
spaces and prevent buffer overflow. Syntax: fgets(str, n,
stdin); where str is the string, n is max characters to read,
and stdin represents keyboard input.
• putw(): Writes an integer value to a file.
• getw(): Reads an integer value from a file.
File Positioning Functions: These functions allow control over
the file pointer's position:
• fseek(): Sets the file pointer to a specified offset from a given
position (SEEK_SET for beginning, SEEK_CUR for current,
SEEK_END for end). Syntax: fseek(FILE *stream, long int
offset, int whence).
• rewind(): Places the file pointer at the beginning of the file.
Syntax: rewind(fp);.
• ftell(): Returns the current file position (offset in bytes).
Standard I/O Library Functions (from <stdio.h>) related to
files: Beyond file-specific functions, standard I/O functions like
printf() and scanf() can also interact with files via stdin, stdout,
and stderr streams.
• Input Functions: scanf(), getc(), getchar(), gets(), getch(),
getche(), fgetc(), fgets(), fscanf(), getw().
• Output Functions: printf(), putc(), putchar(), puts(), putch(),
fprintf(), fputc(), fputs(), putw().
Pre-Processor Directives
The preprocessor is a program that processes the source code
before the actual compilation begins. It uses preprocessor
directives, which are commands that instruct the preprocessor
to perform specific actions. These directives always start with the
# symbol. The preprocessor is a text substitution tool; it modifies
the code before compilation.
List of Commonly Used Preprocessor Directives:
• #define: Used to define a macro or symbolic constant.
• #undef: Used to undefine a macro.
• #include: Used to include the contents of a specified file
into the source code.
• #ifdef: Includes a section of code if a certain macro is
defined.
• #ifndef: Includes a section of code if a certain macro is not
defined.
• #if: Checks for a specified condition; code executes if the
condition is true.
• #else: Provides an alternative code block to execute when
#if, #elif, #ifdef, or #ifndef conditions are false.
• #elif: An "else if" for preprocessor directives, checking
additional conditions.
• #endif: Marks the end of #if, #ifdef, #ifndef conditional
blocks.
• #error: Generates a compilation error message and
terminates compilation.
• #line: Modifies line number and filename information for
debugging.
• #pragma: A special purpose directive that provides
additional information or instructions to the compiler, or
turns features on/off. It is compiler-specific. Common uses
include #pragma message (print custom messages during
compilation), #pragma once (include header file only once),
and #pragma warning (enable/disable warnings).
Details on Key Directives:
• #define (Macro Substitution):
o Object-like Macros: An identifier replaced by a value
(e.g., #define PI 3.14159).
o Function-like Macros: Resemble function calls but
perform text substitution (e.g., #define MIN(a,b)
((a)<(b)?(a):(b))).
• #include (File Inclusion):
o #include <filename>: Tells the compiler to search for
the header file in system directories (e.g., <stdio.h>).
o #include "filename": Tells the compiler to look in the
current directory (where the source file is).
• Conditional Compilation: These directives allow selecting
specific code segments for compilation based on
conditions.
o Example with #if, #elif, #else, #endif: Allows compiling
different code blocks based on chained conditions.
o #ifdef DEBUG: Compiles code if DEBUG macro is
defined.
o #ifndef DEBUG: Compiles code if DEBUG macro is not
defined.
Predefined Macros: C provides several predefined macros, such
as _DATE_ (current date), _TIME_ (current time), _FILE_ (current
file name), _LINE_ (current line number), and _STDC_ (1 if
compiler complies with ANSI standard).
Command Line Arguments
Command-line arguments are values that can be passed to a C
program from the command line when it is executed. They allow
external control over the program without hardcoding values.
Handling in main() Function: Command-line arguments are
handled by the main() function, which can be declared with two
parameters to receive them: int main (int argc, char *argv[]) { /*
program here ... */ }
• argc (argument count): This integer parameter specifies the
number of words on the command line, including the
name of the program itself. Thus, argc is always at least one.
• argv[] (argument vector): This is an array of C strings (char
*[]) that stores all the words from the command line.
o argv always contains the name of the program that
was executed.
o Subsequent elements, argv up to argv[argc-1], store the
actual command-line arguments provided by the
user.
Important Considerations:
• Names of parameters: While argc and argv are
conventional names, they are not mandatory and can be
changed, although it is considered poor programming style.
• Checking argc: It is crucial to check if the expected
number of arguments was provided by the user using argc.
Failing to do so can lead to attempts to access non-existent
locations in the argv array, causing errors.
• Arguments with spaces: If arguments contain spaces, they
must be enclosed in double quotes on the command line,
otherwise, they will be treated as multiple separate
arguments. For example, ./program "hello c how r u" treats
"hello c how r u" as a single argument.
• Execution environment: Programs that process command-
line arguments cannot always be run directly from an
Integrated Development Environment (IDE) like Turbo C IDE
because the arguments cannot be passed in that
environment. They typically need to be run from a command
prompt or terminal.
Example of Usage: If you compile a program named mycmd and
run it as mycmd 10 20:
• argc will be 3 (program name + two arguments).
• argv will be mycmd.exe (or similar, depending on system).
• argv will be "10".
• argv will be "20".
You can also use string manipulation functions like strrchr() to
extract just the program name from argv by finding the last
occurrence of a path separator (/). This involves pointer
arithmetic to adjust argv to point past the last slash.