C PDF

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 45

Introduction to C Programming

C is a powerful and general-purpose programming language developed in 1972 by Dennis


Ritchie at Bell Labs. It was originally created to develop the UNIX operating system and has
since become a cornerstone of system programming, embedded systems development, and
various other applications.

Overview of C

● Procedural: C follows a procedural programming paradigm, where programs are structured


as a sequence of procedures (functions) that perform specific tasks.
● Mid-Level: C bridges the gap between high-level languages (like Python or Java) that
provide abstractions and low-level languages (like assembly) that directly interact with
hardware. It offers more control over memory management compared to high-level
languages.
● Compiled: C code is compiled into machine code that can be directly executed by the
computer's processor, making it efficient and fast.

Importance of C

● Foundation for Other Languages: Understanding C is essential for learning many other
programming languages, as C's syntax and concepts form the basis for languages like
C++, Java, and C#.
● System Programming: C remains the go-to language for developing operating systems,
device drivers, and other system-level software due to its direct hardware interaction
capabilities.
● Efficiency: C programs can be highly optimized for performance, making them ideal for
applications where speed is critical, such as embedded systems and graphics
programming.

Advantages of C Programming

● Speed and Performance: C code often executes faster than code written in higher-level
languages due to its compiled nature and direct memory access.
● Portable: C code can be easily ported (adapted) to different platforms with minimal changes
because it's standardized (ANSI C) and less reliant on machine-specific features.
● Memory Management: C provides fine-grained control over memory allocation and
deallocation, allowing for efficient memory usage in resource-constrained environments.
● Large Community and Resources: C has a vast community of developers and a wealth of
learning materials, libraries, and tools available.
Getting Started with C Programming

Add Headings (Format > Paragraph styles) and they will appear in your table of contents.

Here are some steps to get you started with learning C:

1. Choose a C compiler: Popular options include GCC (GNU Compiler Collection) and
Clang.
2. Set up a development environment: You can use a simple text editor or an Integrated
Development Environment (IDE) that provides features like code completion, debugging,
and project management.
3. Learn the basics: Start with fundamental concepts like variables, data types, operators,
control flow statements (if, else, for, while), and functions.
4. Practice and experiment: Write small programs to solidify your understanding and
explore different functionalities.
5. Explore resources: Refer to online tutorials, books, and C programming communities for
further guidance and in-depth learning.

Structure of C
The structure of a C program typically consists of six main sections:

1. Documentation Section (Optional):


○ Contains comments that provide information about the program's purpose, author, date
of creation, and any other relevant details.
○ These comments are ignored by the compiler but enhance code readability and
maintainability.
2. Preprocessor Section:
○ Uses directives (lines starting with #) to instruct the compiler to perform specific actions
before compilation.
○ Common directives include:
■ #include <stdio.h>: Includes the standard input/output library for functions like
printf and scanf.
■ #define SYMBOL value: Defines a constant symbol (SYMBOL) with a fixed value.
3. Definition Section:
○ Declares functions (reusable blocks of code) that perform specific tasks.
○ Function prototypes (declarations without the function body) can be placed here to
ensure functions are called correctly.
4. Global Declaration Section:
○ Declares variables that can be accessed by any part of the program.
○ It's generally recommended to minimize global variables to improve code modularity
and avoid naming conflicts.
5. Main Function:
○ The mandatory entry point of the program execution.
○ It has the signature int main(void) { ... }.
○ The code within main is where your program's logic and instructions reside.
6. Subprograms (Optional):
○ Contains function definitions that implement the functionalities declared earlier.
○ Functions can call other functions to break down the program into smaller, reusable
components.

Here's a breakdown of these sections in a basic C program example:

// Documentation (Optional)
// This program calculates the area of a rectangle

#include <stdio.h> // Preprocessor directive

// Function prototypes (Optional)


double calculate_area(double length, double width);

int main() { // Main function


double length, width, area;

// Get input from the user


printf("Enter the length: ");
scanf("%lf", &length);

printf("Enter the width: ");


scanf("%lf", &width);

// Call the calculate_area function


area = calculate_area(length, width);

// Print the result


printf("Area of the rectangle: %.2lf\n", area);

return 0; // Indicate successful program termination


}
// Function definition (Optional)
double calculate_area(double length, double width) {
return length * width;
}

Character Set
In C, the character set refers to the collection of all valid characters that can be used to create
programs. These characters include:

● Alphanumeric characters: Lowercase letters (a-z), uppercase letters (A-Z), and digits
(0-9). These are used to form identifiers, keywords, and constants.
● Special characters: Symbols like +, -, *, /, %, =, !, @, #, $, &, ^, *, (, ),
[, ], {, }, ;, :, ', ", ~, \, ?, |, and whitespace characters (space, tab,
newline). These have specific meanings in C.
● Control characters: Non-printable characters like carriage return, backspace, and form
feed, often used for formatting or controlling program behavior (typically not used directly in
code).

C Tokens
Tokens are the basic building blocks that the C compiler recognizes to construct programs.
They fall into several categories:

1. Keywords:
○ Reserved words with predefined meanings in C. You cannot use them as variable or
function names.
○ Examples: int, float, char, if, else, for, while, do, switch, case, return, void, static, auto,
register, extern, sizeof, typedef, enum, struct, union, volatile (32 keywords in total).
2. Identifiers:
○ User-defined names given to variables, functions, constants, structures, and unions.
○ Rules:
■ Must start with a letter (a-z, A-Z) or underscore (_).
■ Subsequent characters can be letters, digits, or underscores.
■ Cannot be the same as a keyword.
○ Examples: age, calculateArea, PI, student, myStructure.
3. Constants:
○ Fixed values that cannot be changed during program execution.
○ Types:
■ Integer constants: Whole numbers, positive, negative, or zero (e.g., 10, -25, 0).
■ Floating-point constants: Numbers with decimal points (e.g., 3.14-1.23e-5).
■ Character constants: Enclosed in single quotes (e.g., 'a', 'Z', '\n').
■ String literals: Sequences of characters enclosed in double quotes (e.g., "Hello,
world!", "This is a string").
4. Operators:
○ Symbols that perform operations on data (e.g., +, -, *, /, %, =, ++, --, ==,
!=, <, >, <=, >=, &&, ||, !).
5. Punctuators:
○ Special characters that separate tokens or have specific meanings (e.g., (, ), {, },
[, ], ?, :, ;, ,, ., ->, *).

Understanding Examples:

int x = 10; // 'int' is a keyword, 'x' is an identifier, '10' is an


integer constant, '=' is an assignment operator
float area = 3.14159 * radius * radius; // 'float', 'area', 'radius' are
identifiers, '3.14159' is a floating-point constant, '*' is a
multiplication operator
if (age >= 18) { // 'if', '(', ')', '{', '}', 'age', '18', '>=' are
keywords, operators, and identifiers

printf("You are eligible to vote.\n"); // 'printf' is an identifier


(function name), '(' and ')' are punctuators
}

Variables
● In C programming, variables are named memory locations that store data during program
execution. They act as containers for values that your code can manipulate.
● To use a variable effectively, you need to follow these steps:
○ Declaration: This step informs the compiler about the name of the variable, its data type
(the kind of data it can hold), and optionally, its initial value. Declaration allocates the
necessary memory space for the variable.
○ Initialization (optional): During declaration, you can assign a starting value to the
variable using the assignment operator (=). This is helpful for setting initial conditions or
ensuring the variable is in a known state when the program starts.

Syntax:

data_type variable_name [= initial_value];

Examples:

int age = 25; // Integer variable named 'age' with initial value 25
float pi = 3.14159; // Floating-point variable named 'pi' with initial
value for pi
char initial = 'A'; // Character variable named 'initial' with initial
value 'A'

Data Types
● Data types are essential in C because they define the type of data a variable can hold and
the operations that can be performed on it. They determine the size of memory allocated to
the variable, the range of values it can represent, and the set of valid operations (like
addition, subtraction, etc.) that can be applied to it.
● C provides several fundamental data types, each with its own characteristics:
1. Integer Types:
○ Represent whole numbers, positive, negative, or zero.
○ Types:
■ int: The most common integer type, its size varies depending on the system
architecture (typically 4 bytes on modern systems). Use this for general-purpose
integer calculations.
■ short int: Smaller integer type, often 2 bytes. Useful for conserving memory when you
know the values will be within a limited range.
■ long int: Larger integer type, often 4 or 8 bytes. Suitable for storing larger integer
values.
■ unsigned int: Stores only non-negative integers, often used in conjunction with bitwise
operations.
2. Floating-Point Types:
○ Represent numbers with decimal points for more precise calculations.
○ Types:
■ float: Single-precision floating-point type, typically 4 bytes. Provides a balance
between precision and memory usage.
■ double: Double-precision floating-point type, usually 8 bytes. Offers greater precision
but requires more memory.
3. Character Type:
○ Stores a single character, usually represented using ASCII or Unicode encoding.
○ Type:
■ char: Stores a single character, often 1 byte. Use this for storing individual characters
or short text strings.
4. Void Type:
○ A special type that doesn't hold any value.
○ Used to indicate that a function doesn't return a value (e.g., a function that only prints
output to the console).

Choosing Data Types Effectively


● Selection of an appropriate data type is crucial for writing efficient and accurate C
programs. Here are some guidelines to consider:
○ Match the data type to the intended values: Choose a data type that can
accommodate the entire range of values you plan to store in the variable. For example,
use int for storing ages (positive whole numbers) but consider long int if you need to
handle very large numbers.
○ Optimize memory usage: If memory is a constraint, consider using smaller data types
like short int or char when you know the values will be within a limited range. This can be
particularly important when dealing with large arrays or many variables.
○ Balance precision and memory: For floating-point types, float provides a good balance
between precision and memory usage for most calculations. Use double if you require
very high precision or are working with scientific computations.

Example:

int numPeople = 100; // Use int for whole numbers like people count
float interestRate = 0.05; // float for decimal values like interest rates
char initial = 'C'; // char for single characters
module -2

Operators
C operators are symbols that perform specific operations on variables, constants, and
expressions. They play a vital role in manipulating data and controlling program flow. Here's a
breakdown of the main C operators with examples:

1. Arithmetic Operators:

● Perform basic mathematical calculations.


● Operators: + (addition), - (subtraction), * (multiplication), / (division), % (modulo - remainder
after division).

Examples:

int x = 10, y = 5;
int sum = x + y; // sum will be 15
int difference = x - y; // difference will be 5
int product = x * y; // product will be 50
int quotient = x / y; // quotient will be 2 (integer division truncates
decimals)
int remainder = x % y; // remainder will be 0

2. Assignment Operators:

● Assign a value to a variable.


● Operators: = (simple assignment), +=, -=, *=, /=, %= (compound assignment -
perform operation and assign result).

Examples:

int count = 0;
count += 5; // Equivalent to count = count + 5; (count becomes 5)
float price = 10.5;
price *= 1.1; // Equivalent to price = price * 1.1; (price becomes 11.55)

3. Comparison Operators:

● Compare values and return true (1) or false (0) based on the condition.
● Operators: == (equal to), != (not equal to), < (less than), > (greater than), <= (less than or
equal to), >= (greater than or equal to).
Examples:

int age = 21;


bool isAdult = age >= 18; // isAdult will be true (1)
char initial = 'A';
bool isFirstLetter = initial == 'A'; // isFirstLetter will be true (1)

4. Logical Operators:

● Combine Boolean expressions (true or false).


● Operators: && (AND), || (OR), ! (NOT).
● AND: Both conditions must be true for the expression to be true.
● OR: At least one condition must be true for the expression to be true.
● NOT: Inverts the truth value of the expression.

Examples:

int score = 85, attendance = 90;


bool passed = score >= 70 && attendance >= 80; // passed will be true (1)
char grade = 'A';
bool isExcellent = grade == 'A' || grade == 'B'; // isExcellent will be
true (1)
bool notFailing = !(score < 50); // notFailing will be true (1)

5. Bitwise Operators:

● Perform operations on individual bits within a variable (often used for low-level
programming).
● Operators: & (bitwise AND), | (bitwise OR), ^ (bitwise XOR), ~ (bitwise NOT), << (left shift),
>> (right shift).

Example:

int flags = 0x0F; // Hexadecimal representation of binary 00001111


int mask = 0x03; // Hexadecimal representation of binary 00000011
int result = flags & mask; // result will be 0x03 (binary 00000011 - AND
each bit)

6. Increment/Decrement Operators:
● Increase or decrease the value of a variable by 1.
● Operators: ++ (increment), -- (decrement).
● Pre-increment (++x) increments the value and then uses it in the expression.
● Post-increment (x++) uses the current value and then increments it. Similar logic applies for
decrement.

Example:

int count = 0;
count++; // count becomes 1 (post-increment)
int value = count++; // value becomes 1 (uses current value of count, then
increments)
count = ++count

Special operators
1. Comma Operator (,):

● Evaluates multiple expressions from left to right, but returns the value of the rightmost
expression.
● Often used for side effects (e.g., incrementing a counter while assigning another value).

Example:

int x = 5, y = 10;
int result = (x++, y = 20); // result becomes 20 (y is assigned 20, then
the expression returns 20)

2. Sizeof Operator (sizeof):

● Returns the size (in bytes) of a variable or data type.

Example:

int num = 10;


int size_of_num = sizeof(num); // size_of_num will likely be 4 (assuming
a 32-bit system)

3. Scope Resolution Operator (::):


● Used to access global or static variables/functions within a specific namespace (particularly
useful when dealing with multiple files or namespaces).
// In a header file:
extern int global_var; // Declared as global

// In a source file:
int main() {
printf("Global variable value: %d\n", ::global_var); // Accessing
global_var using scope resolution
}
4. Conditional (Ternary) Operator (?:):
● Provides a concise way to write an if-else statement in a single expression.
● Syntax: condition ? expression_if_true : expression_if_false

Example:

int age = 20;


bool canVote = (age >= 18) ? true : false; // canVote becomes true

int grade = 88;


char letterGrade = (grade >= 90) ? 'A' : (grade >= 80) ? 'B' : 'C'; //
letterGrade becomes 'B'
5. Cast Operator ((type))

● Explicitly converts a value from one data type to another. Useful for type coercion when
necessary.

Example:

double pi = 3.14159;
int int_pi = (int)pi; // int_pi will become 3 (truncating decimal part)
Remember:
● Special operators might have specific precedence rules compared to other operator types.
Consult a C operator precedence table when necessary.
● Use casting operators with caution, as incorrect casting can lead to unexpected behavior or
data loss.

Arithmetic Expressions
In C programming, arithmetic expressions are combinations of variables, constants,
operators, and function calls that evaluate to a numerical value. They form the building blocks
for performing calculations within your programs.

Components of Arithmetic Expressions

● Variables: Named memory locations that store numerical data.


● Constants: Fixed values (e.g., integers, floating-point numbers) that don't change during
program execution.
● Operators: Symbols that perform specific mathematical or logical operations on operands
(variables or constants).
○ Arithmetic operators: + (addition), - (subtraction), * (multiplication), / (division), %
(modulo - remainder after division).
● Function calls: Functions that might return numerical values.

Expression Evaluation

C follows a specific set of rules to evaluate arithmetic expressions, ensuring consistent


results:

1. Precedence: Operators have a defined order of operations. Higher precedence operators


are evaluated first. The common precedence order (from highest to lowest) is:
○ Parentheses (())
○ Exponentiation (^)
○ Multiplication (*) and Division (/) (left to right)
○ Modulus (%) (left to right)
○ Addition (+) and Subtraction (-) (left to right)
2. Associativity: If operators have the same precedence, the associativity determines the
evaluation order.
○ Left-to-right associativity: Operators are evaluated from left to right (e.g., +, -, *, /, %).
○ Right-to-left associativity: Operators are evaluated from right to left (e.g., exponentiation
^).
3. Parentheses: Parentheses can be used to override the default order of operations and
group expressions for evaluation within them first.

Examples:

1. x + y * z
○ Evaluated as x + (y * z) because * has higher precedence than +.
2. (x + y) * z
○ Parentheses force x + y to be evaluated first, then the result is multiplied by z.
3. x * y ^ 2
○ Right-to-left associativity: y ^ 2 is evaluated first, then x is multiplied by the result.

Importance of Evaluation Order:

Understanding expression evaluation is crucial for writing correct and predictable C programs.
Incorrect evaluation can lead to unexpected results, so it's essential to use parentheses or
choose expressions with clear precedence when necessary.

Additional Notes:

● C performs integer division by default. When dividing integers, the result is truncated
(decimal part discarded). To perform floating-point division, use floating-point operands
(e.g., 3.0 / 2).
● Be mindful of data type mixing and potential overflows/underflows when performing
calculations. Consider casting or using appropriate data types to avoid unexpected
behavior.

Operator Precedence and Associativity in C

In C programming, operator precedence and associativity are fundamental concepts that


dictate how expressions containing multiple operators are evaluated. Mastering these rules is
essential for writing C code that produces the intended results and avoids unexpected
behavior.

Operator Precedence
Operator precedence defines the order of operations within an expression. Operators with
higher precedence are evaluated first. If no parentheses are used, the compiler adheres to a
predefined hierarchy, ensuring consistent evaluation across your code. Here's a breakdown of
operator precedence in C (from highest to lowest):

Associativity
Associativity comes into play when multiple operators of the same precedence level appear in
an expression. It specifies the direction (left to right or right to left) in which these operators
are evaluated.

Left-to-Right Associativity: Operators like multiplication, division, modulus, addition,


subtraction, shift, relational, equality, bitwise AND, bitwise XOR, and bitwise OR are
left-to-right associative. For example, in x * y / z, x * y is computed first, and the result is
divided by z.

Right-to-Left Associativity: Unary operators, the conditional (ternary) operator, and


assignment operators are right-to-left associative. This means, in expressions like ++x or x =
y = z, the operand is evaluated first, followed by the operator.

Operator Group Operators Description Precedence Associativity Example (Result)

Increment/decr
ement after the x++ (post-increment, x is used
Postfix ++ -- operand Highest Right to left first, then incremented)

Plus/minus,
logical NOT,
+, -, !, ~, (type bitwise NOT,
Unary cast) type casting High Right to left -x (unary minus, x is negated)
Multiplication,
division,
Multiplicative *, /, % modulo Medium Left to right x * y / z ((x * y) / z)
Addition,
Additive +, - subtraction Low Left to right x + y - z ((x + y) - z)

Shift <<, >> Left/right shift Low Left to left x << 2 (x is shifted left by 2 bits)
Less than,
greater than,
less than or
equal to,
greater than or x < y (evaluates to 1 if true, 0 if
Relational <, >, <=, >= equal to Low Left to right false)

Equal to, not x == y (evaluates to 1 if equal, 0 if


Equality ==, != equal to Low Left to right not)

x && y (evaluates to 1 if both x


Logical AND && Logical AND Low Left to right and y are true, 0 otherwise)
Logical OR Left to right ` Logical OR

Ternary Conditional x ? y : z (if x is true, evaluate y,


(Conditional) ?: expression ` Right to left otherwise evaluate z)
Comma
operator
(evaluation
from left to
right, only used x, y = 10, 20 (evaluates x, then
Comma , for side effects) Low Left to right assigns 10 to y)

=, +=, -=, *=, /=, Assignment and compound


Assignment %=, &=, ^=, Right to left Lowest =, <<=, >>= assignment

type conversion within expressions


In C programming, type conversion within expressions, also known as implicit conversion or
coercion, refers to the automatic conversion of a value from one data type to another during
the evaluation of an expression. C performs these conversions to ensure compatibility
between operands (variables or constants) involved in an operation.

Understanding Type Conversion

● When it Happens: Type conversion occurs when:


○ An operator requires operands of different data types.
○ A value is assigned to a variable of a different type.
○ A function is called with arguments of different types than expected.
● Conversion Rules: C follows specific rules to determine the resulting data type:
○ Promotion: Smaller data types are converted (promoted) to larger types to avoid data
loss. For example, an int is converted to a float when involved with a float in an
operation.
○ Truncation: If a larger data type is assigned to a smaller one, the value might be
truncated (excess bits removed) to fit the smaller type, potentially leading to data loss.

Common Conversion Scenarios

Here are some examples of type conversion in expressions:

1. Mixing Integers and Floats:


○ In x = 10 + 3.14, the integer 10 is promoted to a float (typically) before addition,
resulting in x having a floating-point value.
2. Assigning a Float to an Integer:
○ In int result = 10.5;, the decimal part of 10.5 is truncated (discarded), and result will
become 10.
3. Character Constants in Arithmetic Expressions:
○ Character constants are treated as integer codes (e.g., 'A' might have a code of 65).
So, 'A' + 2 would evaluate to 67 (integer addition).

Potential Issues with Type Conversion

● Data Loss: Truncation during conversion from larger to smaller types can lead to
unexpected results. Be cautious when assigning values that might overflow the target data
type's range.
● Loss of Precision: When converting from floating-point to integer, precision is lost due to
truncation. Consider using appropriate data types if high precision is crucial.

Controlling Type Conversion

● Explicit Casting: You can explicitly cast a value to a specific data type using the (type)
operator. This can be useful to force the conversion and potentially avoid unintended
consequences.

Example:

float pi = 3.14159;
int int_pi = (int)pi; // Explicitly cast pi (float) to int_pi (int),
potentially losing precision

Best Practices

● Choose Appropriate Data Types: Select data types that can accommodate the expected
range and precision of values to minimize the need for conversion.
● Be Mindful of Truncation: When mixing different data types, be aware of the possibility of
data loss and take steps to mitigate it if necessary.
● Use Explicit Casting Cautiously: While casting offers control, use it judiciously to avoid
unintended side effects.

predefined functions
In C programming, leveraging library functions is essential for building efficient and versatile
programs. These predefined functions, grouped in header files, provide a rich set of
functionalities to perform various tasks without reinventing the wheel. Here's a breakdown of
some commonly used library functions in C:

1. Mathematical Functions (math.h header):

● Trigonometric Functions:
○ sin(x): Sine of angle x (in radians).
○ cos(x): Cosine of angle x (in radians).
○ tan(x): Tangent of angle x (in radians).
○ asin(x): Arcsine (inverse sine) of x.
○ acos(x): Arccosine (inverse cosine) of x.
○ atan(x): Arctangent (inverse tangent) of x.
● Exponential and Logarithmic Functions:
○ exp(x): Raises e (Euler's number) to the power of x.
○ log(x): Natural logarithm (base-e) of x.
○ log10(x): Base-10 logarithm of x.
● Power Function:
○ pow(x, y): Raises x to the power of y.
● Rounding and Absolute Value Functions:
○ ceil(x): Returns the smallest integer greater than or equal to x.
○ floor(x): Returns the largest integer less than or equal to x.
○ round(x): Rounds x to the nearest integer.
○ abs(x): Returns the absolute value (non-negative) of x.
● Square Root:
○ sqrt(x): Square root of x.
● Other Functions:
○ fmod(x, y): Remainder of floating-point division x / y.
○ remainder(x, y): Integer remainder of division x / y.

2. Input/Output (I/O) Operations (stdio.h header):

● Formatted Input/Output:
○ printf(format, ...): Prints formatted output to the console or a file. The format string
specifies placeholders for arguments (...) that are inserted during printing.
○ scanf(format, ...): Reads formatted input from the console or a file. The format string
specifies the expected format of input, and arguments (...) store the read values.
● Character I/O:
○ getchar(): Reads a single character from the console.
○ putchar(c): Writes a single character c to the console.
● File I/O:
○ fopen(filename, mode): Opens a file named filename in the specified mode (e.g., "r" for
reading, "w" for writing). Returns a file pointer if successful.
○ fclose(fp): Closes the file pointed to by fp.
○ fscanf(fp, format, ...): Reads formatted data from a file pointed to by fp.
○ fprintf(fp, format, ...): Writes formatted data to a file pointed to by fp.

3. String Manipulation (string.h header):

● strlen(str): Returns the length (number of characters) of the string str (excluding the null
terminator).
● strcpy(dest, src): Copies the string src (including the null terminator) to dest. (Caution:
potential buffer overflow if dest is too small)
● strcat(dest, src): Appends the string src to the end of dest. (Caution: potential buffer
overflow)
● strcmp(str1, str2): Compares strings str1 and str2. Returns 0 if equal, negative if str1 is less
than str2, positive if str1 is greater than str2.
● strstr(haystack, needle): Searches for the first occurrence of the string needle within
haystack. Returns a pointer to the beginning of the substring if found, or NULL if not found.
● strncpy(dest, src, num): Copies at most num characters from src to dest, padding with null
characters if src is shorter.
Module 3

basic c programs
1. Hello World Program

#include <stdio.h>

int main() {
printf("Hello, World!\n");
return 0;
}
1. Program to Add Two Integers

#include <stdio.h>

int main() {
int number1, number2, sum;

printf("Enter two integers: ");


scanf("%d %d", &number1, &number2);

sum = number1 + number2;


printf("Sum = %d\n", sum);

return 0;
}
1. Program to Check if a Number is Even or Odd

#include <stdio.h>

int main() {
int number;

printf("Enter an integer: ");


scanf("%d", &number);

if (number % 2 == 0)
printf("%d is even.\n", number);
else
printf("%d is odd.\n", number);

return 0;
}

flow of control in c program


In C programming, the flow of control determines how the program's
instructions are executed. Here's a brief overview:

1. Sequential Execution: By default, statements in C are executed


sequentially from top to bottom in the order they appear.
2. Selection Statements: These alter the flow based on conditions. The if, else
if, else, and switch statements are used for selection.
3. Iteration Statements: These are used for looping and include while,
do-while, and for loops.
4. Jump Statements: These include break, continue, return, and goto, which
transfer control to another part of the program.
5. Function Calls: When a function is called, control is transferred to that
function. After the function executes, control returns to the point
immediately after where the function was called.

decisions making statements in c


Decision-making statements in C allow you to control the flow of your
program based on certain conditions. Here's a brief explanation:

1. if statement: It is used to execute a block of code only if a specified


condition is true.
if (condition) {
// code to be executed if condition is true
}

2. if-else statement: It adds an alternative path; the else block is executed if


the condition is false.
if (condition) {
// code to be executed if condition is true
} else {
// code to be executed if condition is false
}
3. else-if ladder: It is used when you need to test multiple conditions. Only
the block of code where the condition is true will execute.
if (a > b) {
printf("a is greater than b");
} else if (a < b) {
printf("a is less than b");
} else {
printf("a is equal to b");
}

4. switch statement: It allows you to select one of many code blocks to be


executed.

switch (expression) {
case constant1:
// code to be executed if expression equals constant1
break;
case constant2:
// code to be executed if expression equals constant2
break;
// ...
default:
// code to be executed if expression doesn't match any case
}

The break keyword exits the switch block. The default case is optional and can
appear anywhere in the switch block; it's executed only if none of the cases are
true.

nested if
A nested if is an if statement that appears inside another if or else block. It allows
you to test multiple conditions in a sequence or hierarchy. Here's an example:

#include <stdio.h>
int main() {
int num;
printf("Enter an integer: ");
scanf("%d", &num);

if (num >= 0) {
if (num == 0) {
printf("The number is zero.\n");
} else {
printf("The number is positive.\n");
}
} else {
printf("The number is negative.\n");
}

return 0;
}
In this program, the outer if checks if the number is non-negative. If it's true, the
nested if then checks if the number is zero or positive. If the outer if condition is
false, it means the number is negative, and the corresponding message is printed.

Conditional Operator Example:The conditional operator, also known as the


ternary operator, is used in C to make a decision between two values based on a
condition. It's a shorthand for the if-else statement. The syntax is:

#include <stdio.h>

int main() {
int a = 10, b = 20;
int max;

// Using conditional operator to find the maximum number


max = (a > b) ? a : b;

printf("The maximum number is %d\n", max);

return 0;
}
In this example, if a is greater than b, max will be assigned the value of a;
otherwise, max will be assigned the value of b.

Goto Operator Example:The goto statement allows you to make an


unconditional jump to another part of your program. The syntax is:

#include <stdio.h>

int main() {
int num = 0;

start:
num++;
if (num < 5) {
printf("num is %d\n", num);
goto start; // Jumps back to the label "start"
}

printf("Finished counting.\n");

return 0;
}
In this example, the program will print numbers from 1 to 4. When num is less
than 5, it jumps back to the label start and continues incrementing and printing
num.

Remember that using goto can make your code hard to follow and is generally
discouraged in modern programming practices.

loops
For Loop:Used when the number of iterations is known beforehand.

for (initialization; condition; increment) {


// code to be executed
}
Example:

for (int i = 0; i < 5; i++) {


printf("%d ", i);
}
While Loop:Executes the code block as long as the condition is true.

while (condition) {
// code to be executed
}
Example:

int i = 0;
while (i < 5) {
printf("%d ", i);
i++;
}
Do-While Loop:Similar to the while loop, but the code block is executed at least
once.

do {
// code to be executed
} while (condition);
Example:

int i = 0;
do {
printf("%d ", i);
i++;
} while (i < 5);
Nested Loop:A loop inside another loop.

for (int i = 0; i < 3; i++) {


for (int j = 0; j < 3; j++) {
printf("(%d,%d) ", i, j);
}
}
Skipping Loop Iteration (continue):Skips the current iteration and continues
with the next one.

for (int i = 0; i < 5; i++) {


if (i == 2) continue;
printf("%d ", i);
}
Jumping Out of Loop (break):Exits the loop immediately.
for (int i = 0; i < 5; i++) {
if (i == 3) break;
printf("%d ", i);
}
These are basic examples to illustrate each type of loop and control statement.
Would you like more detailed examples or explanations on any of these?
module 4

arrays and strings


Certainly! In C programming, an array is a collection of elements of the same
type stored in contiguous memory locations. Here's a brief overview:

● One-dimensional array: It's like a list of elements. You can declare it as int
arr[5]; which creates an array arr that can hold 5 integers.

int arr[5] = {1, 2, 3, 4, 5}; // Initializing an array with 5 elements


● Two-dimensional array: It's similar to a matrix or table with rows and
columns. Declare it as int arr[2][3]; which creates a 2x3 matrix.

int arr[2][3] = {
{1, 2, 3},
{4, 5, 6}
}; // A 2x3 array
● Multi-dimensional array: This extends the concept to more dimensions. A
three-dimensional array can be thought of as an array of arrays of arrays.

int arr[2][3][2] = {
{
{1, 2},
{3, 4},
{5, 6}
},
{
{7, 8},
{9, 10},
{11, 12}
}
}; // A 2x3x2 array
You access elements using indices that start from 0. For example, arr[0][1]
accesses the second element in the first row of a two-dimensional array.

Remember that in C, the size of the arrays must be known at compile time if they
are declared statically. For dynamic sizes, you'd use pointers and memory
allocation functions like malloc().
string manipulation functions in c program
In C, a string is an array of characters terminated by a null character '\0'. Here's
how you can declare and initialize a string:

char str[] = "Hello, World!";


For string manipulation, C provides several functions in the <string.h> library.
Here are a few examples:

● strlen(): Returns the length of the string.


● strcpy(): Copies one string to another.
● strcat(): Concatenates two strings.
● strcmp(): Compares two strings.

Here's some code that uses these functions:

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

int main() {
char str1[20] = "Hello";
char str2[] = "World";

// Concatenate str2 to str1


strcat(str1, ", ");
strcat(str1, str2);

// Output the concatenated string


printf("%s\n", str1); // Prints "Hello, World"

// Compare two strings


if(strcmp(str1, "Hello, World") == 0) {
printf("The strings are equal.\n");
}

return 0;
}
Remember to include the <string.h> header at the top of your program to use
these functions.
concept of modularization in c
Modularization in C programming is the process of dividing a program into
separate modules or functions that can be developed, tested, and maintained
independently. This approach enhances readability, reusability, and
manageability of code.

Here's how you can achieve modularization:

● Functions: Break down tasks into functions. Each function should perform
a specific task and can be called from other parts of the program.

#include <stdio.h>

// Function declaration
int add(int a, int b);

int main() {
int result = add(5, 3);
printf("The sum is: %d\n", result);
return 0;
}

// Function definition
int add(int a, int b) {
return a + b;
}
● Separate Files: For larger projects, you can split your code into multiple
files. For example, you can have main.c for the main program,
math_functions.c for math-related functions, and utility.c for utility
functions. You include them in your main file using header files (.h).

This way, each part of your program has a clear purpose, making it easier to
understand and maintain.

user defined functions


User-defined functions in C are functions that you create to perform specific
tasks. Here's how they work:

● Passing Arguments: You can pass data to functions using arguments.


These can be passed by value or by reference.
// Passing by value
void printNumber(int num) {
printf("%d\n", num);
}

// Passing by reference
void increment(int *num) {
(*num)++;
}
● Calling Functions: You call a function by using its name followed by
parentheses containing any arguments.

int main() {
int number = 5;
printNumber(number); // Call by value
increment(&number); // Call by reference
printNumber(number); // Now prints 6
return 0;
}

● Categories of Functions:
○ Functions with no arguments and no return value.
○ Functions with arguments and no return value.
○ Functions with arguments and a return value.
○ Functions that return pointers or arrays.

Each category serves different purposes depending on what you need the
function to do. Remember to declare your functions before calling them or
provide a function prototype at the beginning of your file.

multifunction program and prototypes in c


In a multi-function program in C, you have several functions working
together to perform the program's tasks. A function prototype is a declaration of
a function that specifies the function's name, return type, and parameters
without the body. It informs the compiler about the function before its actual
definition.

Here's an example of a multi-function program with prototypes:

#include <stdio.h>

// Function prototypes
void greet();
int add(int a, int b);

int main() {
greet(); // Call greet function
int sum = add(10, 20); // Call add function
printf("Sum is: %d\n", sum);
return 0;
}

// Function definitions
void greet() {
printf("Hello, World!\n");
}

int add(int a, int b) {


return a + b;
}
In this example, greet and add are two separate functions with their prototypes
declared before main(). The actual definitions are provided after main(). This
structure allows main() to call these functions even though their definitions
appear later in the code.

Nesting of functions? and recursion


In C programming, nesting of functions is not allowed, which means you
cannot define a function inside another function. However, you can call a
function from within another function.

Recursion
is a technique where a function calls itself directly or indirectly. Here's a simple
example of a recursive function that calculates the factorial of a number:

int factorial(int n) {
if (n <= 1)
return 1;
else
return n * factorial(n - 1);
}
For functions and arrays, you can pass an array to a function as an argument.
Here's how you can pass an array to a function that calculates the sum of its
elements:

int sumArray(int arr[], int size) {


int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}

// Usage
int main() {
int myArray[] = {1, 2, 3, 4, 5};
int result = sumArray(myArray, 5);
printf("Sum is: %d", result);
return 0;
}
Remember that when arrays are passed to functions, they are passed by
reference, meaning the function can modify the original array elements.

scope
In C, the scope of a variable determines where it can be accessed:

● Local variables have a block scope, accessible only within the function or
block where they're defined.
● Global variables have a file scope, accessible from any function within the
same file.

The lifetime of a variable refers to when it is created and destroyed:

● Local variables have an automatic lifetime; they are created when the
function is called and destroyed when the function exits.
● Global variables and static local variables have a static lifetime; they are
created when the program starts and destroyed when the program ends.

In multi-file programs, global variables can be shared across files using the
extern keyword to declare them in other files.

Here's an example to illustrate:


// File1.c
int globalVar = 10; // Global variable

void function1() {
int localVar = 20; // Local variable
}

// File2.c
extern int globalVar; // Accessing globalVar from File1.c

void function2() {
static int staticVar = 30; // Static local variable
}

Structures & Union structur


In C programming, a structure is a user-defined data type that allows you to
combine data items of different kinds. Structures are used to represent a record.
Here's an example of how you can define a structure:

struct Person {
char name[50];
int age;
float salary;
};
To use it, you would create a variable of the structure type and access
its members using the dot operator:
struct Person person1;
person1.age = 30;
strcpy(person1.name, "Alice");
person1.salary = 25000.50;

Union
A union is similar to a structure because it's also a user-defined data type that
allows you to store different data types in the same memory location. However,
you can only use one field at a time. Here's an example of a union:

union Data {
int i;
float f;
char str[20];
};
When you use a union, you can store data in one member at a time:

union Data data;


data.i = 10;
data.f = 220.5; // This will overwrite the previous value stored in 'i'
strcpy(data.str, "C Programming"); // This will overwrite 'f'
Remember, since all members of a union share the same memory location,
changing one will affect the others.

Initialization:You can initialize a structure in C by assigning values to its


members at the time of declaration:

struct Person {
char name[50];
int age;
float salary;
};

struct Person person1 = {"Alice", 30, 25000.50};


Assigning Values:To assign values to the members of a structure after it has
been declared, you can do the following:

strcpy(person1.name, "Bob");
person1.age = 25;
person1.salary = 30000.75;
Comparison:To compare two structure variables, you need to compare each
member individually because C does not support operator overloading:

struct Person person2 = {"Charlie", 25, 30000.75};

if (person1.age == person2.age && person1.salary == person2.salary &&


strcmp(person1.name, person2.name) == 0) {
printf("person1 and person2 are the same.\n");
} else {
printf("person1 and person2 are different.\n");
}
This code compares the age, salary, and name members of person1 and person2.
If all members are equal, it considers the two structures to be the same.

Arrays of Structures:You can create an array of structures to store multiple


records of the same type. Here's an example:

struct Person {
char name[50];
int age;
float salary;
};

struct Person employees[5]; // Array of 5 structure variables


Arrays Within Structures:A structure can contain arrays as members. Here's
how you can define and use it:

struct Student {
char name[50];
int marks[5]; // Array within a structure
};

struct Student student1;


strcpy(student1.name, "John");
student1.marks[0] = 85; // Assigning values to array elements
student1.marks[1] = 90;
// ...and so on for the rest of the marks
Structures Within Arrays:You can also have structures within arrays. This is
essentially the same as an array of structures, but you might be referring to
having an array where each element is a structure that contains an array. Here's
an example:

struct Classroom {
struct Student students[30]; // Structures within an array
};

struct Classroom class1;


strcpy(class1.students[0].name, "Alice");
class1.students[0].marks[0] = 95; // Assigning values to the nested array
elements
// ...and so on for the rest of the students and their marks
In this example, class1 is a variable of type Classroom, which contains an array
of Student structures.

Structures and Functions:You can pass structures to functions by value or by


reference. Here's an example of passing a structure to a function by reference:

void printPerson(struct Person *p) {


printf("Name: %s\nAge: %d\nSalary: %.2f\n", p->name, p->age,
p->salary);
}

// Usage
struct Person person1 = {"Alice", 30, 25000.50};
printPerson(&person1);
Unions:As mentioned earlier, unions allow you to store different data types in
the same memory location. Here's an example of using unions with functions:

void printData(union Data *data) {


printf("Int: %d\n", data->i);
printf("Float: %f\n", data->f);
printf("String: %s\n", data->str);
}

// Usage
union Data data;
data.i = 10;
printData(&data); // Only 'i' has a meaningful value here
Bit Fields:Bit fields allow you to use less than an integer's worth of memory to
store a value. They are defined inside structures. Here's an example:

struct Bits {
unsigned int a : 1;
unsigned int b : 3;
unsigned int c : 4;
};

struct Bits myBits;


myBits.a = 1; // Only one bit is used, so the value can be 0 or 1
myBits.b = 7; // Can store values from 0 to 7 (3 bits)
myBits.c = 15; // Can store values from 0 to 15 (4 bits)
In this example, myBits is a structure with bit fields a, b, and c that use 1, 3, and 4
bits respectively.
Module 5

pointers

Pointers in C
Pointers are a fundamental concept in C programming that enable you to work with memory
addresses. They act as variables that store memory locations rather than data values
themselves. This indirection through pointers offers several advantages:
● Memory Efficiency: Pointers can be used to pass references to variables to functions,
reducing the need for copying large data structures.
● Dynamic Memory Allocation: Pointers allow you to allocate memory at runtime using
functions like malloc and free, providing flexibility for managing memory as your
program's needs evolve.
● Array Manipulation: Pointers and arrays are closely linked in C. Array names
essentially behave like constant pointers to the first element's address, enabling efficient
array traversal and modification.

Accessing Variable Addresses (Address-of Operator '&')


The address-of operator (&) in C retrieves the memory address of a variable. Here's the
syntax:
address = &variable;
For instance:
int num = 42;
int *ptr = &num; // ptr now holds the memory address of num

Declaring and Initializing Pointers


To declare a pointer variable, you precede its name with an asterisk (*) to indicate it stores an
address. Here's the general form:
data_type *pointer_name;

You can initialize a pointer in two ways:


1. Null Pointer: Assigning a null pointer (NULL) signifies the pointer doesn't point to any
valid memory location.
data_type *pointer_name;

2. Address of a Variable: Using the address-of operator to store the memory address of
another variable.
int num = 25;
int *ptr = &num; // ptr now points to the memory address of num

Code Examples
1. Basic Pointer Example:
#include <stdio.h>

int main() {
int age = 30;
int *ptr = &age;
printf("Value of age: %d\n", age);
printf("Address of age: %p\n", &age);
printf("Value stored at the address pointed to by ptr: %d\n",
*ptr);

return 0;
}
This code outputs:

Value of age: 30
Address of age: 0x7ffe5... // Memory address will vary
Value stored at the address pointed to by ptr: 30

2. Swapping Values Using Pointers:


#include <stdio.h>

void swap(int *x, int *y) {


int temp = *x;
*x = *y;
*y = temp;
}

int main() {
int a = 10, b = 20;

printf("Before swapping: a = %d, b = %d\n", a, b);


swap(&a, &b);
printf("After swapping: a = %d, b = %d\n", a, b);

return 0;
}
This code outputs:
Before swapping: a = 10, b = 20
After swapping: a = 20, b = 10

By understanding pointers, you unlock a powerful mechanism for memory management and
manipulating data in C programs.

Accessing Variables through Pointers


Once a pointer points to a valid memory location, you can access the value stored at that
address using the dereference operator (*). The syntax is:
value = *pointer_variable;

Consider this example:


int num = 42;
int *ptr = &num;

int retrieved_value = *ptr; // retrieved_value will now contain 42

Pointer Expressions
Pointer expressions involve arithmetic operations on pointers. However, these operations
have specific rules:
● Addition/Subtraction: You can only add/subtract integers to/from pointers if they point
to elements of the same array. The amount added/subtracted depends on the data type
the pointer points to (e.g., adding 1 to an integer pointer moves it to the next integer
location).
int numbers[5] = {1, 2, 3, 4, 5};
int *ptr1 = numbers;
int *ptr2 = ptr1 + 2; // ptr2 now points to the third element (index 2)

printf("Value at ptr1: %d\n", *ptr1); // Output: 1


printf("Value at ptr2: %d\n", *ptr2); // Output: 3

● Comparison: You can compare pointers to see if they point to the same memory
location (using == or !=) or compare their relative order within the same array (using <,
>, <=, or >=).
int num1 = 10;
int num2 = 20;
int *ptr1 = &num1;
int *ptr2 = &num2;

if (ptr1 < ptr2) {


printf("ptr1 points to a memory location before ptr2\n");
}

Pointers and Arrays


In C, array names behave like constant pointers to the array's first element. This implies:
● array_name[index] is equivalent to *(array_name + index).
● You can use pointer arithmetic to traverse arrays.
int numbers[5] = {10, 20, 30, 40, 50};

for (int i = 0; i < 5; i++) {


printf("%d ", numbers[i]); // Accessing using array indexing
}

printf("\n");

for (int *ptr = numbers; ptr < numbers + 5; ptr++) {


printf("%d ", *ptr); // Accessing using pointer arithmetic
}

By effectively using pointers, you can achieve efficient memory management and array
manipulation in C programs.

Pointers and Character Strings


In C, strings are essentially character arrays terminated by a null character (\0). Pointers can
be used to manipulate these strings. Here's a common approach:
1. Declare a character pointer (char *ptr).
2. Initialize the pointer to point to the first character of the string. This can be done in two
ways:
○ By assigning the string literal directly (assuming the string is stored in a constant
memory location).
○ By using the address-of operator (&) to get the address of the first character of an
existing character array.
Code Example:
#include <stdio.h>
int main() {
char str[] = "Hello, world!";

// Option 1: Pointing to a string literal


char *ptr1 = str;

// Option 2: Pointing to an existing character array


char message[] = "Welcome";
char *ptr2 = &message[0]; // ptr2 points to the first character of
message

printf("ptr1 points to: %s\n", ptr1);


printf("ptr2 points to: %s\n", ptr2);

return 0;
}

Pointers and Functionsṣ


Pointers can be passed to functions as arguments, allowing you to modify the data pointed to
by the pointer within the function. Here's a general structure:
void function_name(data_type *ptr) {
// Access and modify data using the pointer
}

Code Example (Swapping Characters in a String)


#include <stdio.h>

void swap_characters(char *a, char *b) {


char temp = *a;
*a = *b;
*b = temp;
}

int main() {
char str[] = "Geeks";

printf("Original string: %s\n", str);


swap_characters(&str[0], &str[2]); // Swap first and third characters

printf("String after swapping: %s\n", str);

return 0;
}

Remember that pointers are a powerful tool in C, but they require careful handling to avoid
memory-related errors. Ensure proper initialization and memory management when using
pointers.

Pointer to Pointer () for Dynamic Memory Allocation**


In C, you can use a pointer to a pointer to allocate memory dynamically at runtime.
This technique provides an extra layer of indirection and flexibility for memory
management.
1. Declare a pointer to a pointer:
data_type **ptr_ptr;
This creates a pointer variable (ptr_ptr) that will store the address of another
pointer variable.
2. Allocate memory:

ptr_ptr = (data_type **)malloc(sizeof(data_type *));

○ malloc allocates memory to hold a single pointer address.


○ We cast the return value to data_type ** to match the pointer-to-pointer type.
3. Allocate memory for the actual data:

*ptr_ptr = (data_type *)malloc(sizeof(data_type) * num_elements);

○ We dereference ptr_ptr to get the pointer it points to.


○ We allocate memory using malloc for the desired number of elements
(num_elements).
○ We cast the return value to data_type * to match the pointer type for the data.
Code Example
#include <stdio.h>
#malloc

int main() {
int rows = 3, cols = 4;
int **matrix;

// Allocate memory for the row pointers


matrix = (int **)malloc(rows * sizeof(int *));

// Allocate memory for each row


for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
}

// Access and modify elements


for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
}
}

// Print the matrix


for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}

// Free memory
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);

return 0;
}

This code dynamically allocates a 2D array using pointer to pointer. Remember to free
the allocated memory using free to prevent memory leaks.
Creating and Processing a Data File
1. Include header:
#include <stdio.h>

2. Open the file in write mode ("w") using fopen:

FILE *fp = fopen("data.txt", "w");

if (fp == NULL) {
printf("Error opening file!\n");
return 1;
}

○ Replace "data.txt" with your desired filename.


○ The if statement checks for errors during opening.
3. Write data to the file using fprintf:

fprintf(fp, "This is some data to write to the file.\n");

○ Use appropriate format specifiers (%d for integers, %f for floats, etc.) based
on your data types.
4. Close the file using fclose:
fclose(fp);

Opening an Existing File


1. Use fopen with "r" mode for reading:

FILE *fp = fopen("data.txt", "r");

if (fp == NULL) {
printf("Error opening file!\n");
return 1;
}

2. Read data from the file using fscanf or fgets (for strings):
int value;
fscanf(fp, "%d", &value); // Read an integer

char buffer[100];
fgets(buffer, 100, fp); // Read a line of text into a buffer

3. Close the file using fclose.

Command-Line Arguments
C programs can access command-line arguments passed during execution. You can
use these arguments to specify filenames or other parameters.
1. Include header:
#include <stdio.h>

2. In main function, access arguments using argc (argument count) and argv
(argument vector):

int main(int argc, char *argv[]) {


if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}

// Process the file specified in argv[1]


...
}

○ This code checks if exactly one argument (the filename) is provided.


Code Example (Creating and Reading a File)
#include <stdio.h>

int main() {
FILE *fp = fopen("data.txt", "w");

if (fp == NULL) {
printf("Error opening file!\n");
return 1;
}

fprintf(fp, "Hello from C program!\n");


fclose(fp);

// Open the file for reading


fp = fopen("data.txt", "r");

if (fp == NULL) {
printf("Error opening file!\n");
return 1;
}

char buffer[100];
fgets(buffer, 100, fp);
printf("Read from file: %s", buffer);

fclose(fp);

return 0;

Remember to error handle file operations and close files to avoid resource leaks.

You might also like