C Notes Final
C Notes Final
Contents
- BASICS OF C LANGUAGE: ............................................................................................... 4
EXERCISES: ......................................................................................................................... 20
Why It Works:................................................................................................................ 43
How It Works: ............................................................................................................... 45
Example: Setting Specific Bits ....................................................................................... 45
LOOP CONTROL INSTRUCTIONS:......................................................................................... 52
INCREMENT DECREMENT OPERATORS:............................................................................ 54
FOR LOOP:....................................................................................................................... 57
BREAK & CONTINUE: ........................................................................................................ 60
FUNCTIONS:........................................................................................................................ 70
- How to Change the Original Variable: .................................................................... 77
- RECURSION: ................................................................................................................ 79
- EXERCISE:................................................................................................................ 80
- ARRAYS: ....................................................................................................................... 82
- STRINGS:...................................................................................................................... 88
- EXTRACTING CHARACTERS IN 1D ARRAY: ..................................................................... 95
- SORTING THE 1D ARRAY: .............................................................................................. 96
- TRANPOSE 2D MATRIX: ................................................................................................. 97
- RANDOM NUMBERS :.................................................................................................... 98
Understanding fgets(str, sizeof(str), stdin):............................................................................ 99
Why Include the Newline? ........................................................................................... 100
Removing the Newline:................................................................................................ 100
Here’s what happens with fgets(): .......................................................................... 100
What fgets() Does: ............................................................................................................. 102
REMOVING NEW LINE CHARACTER: ................................................................................... 107
- 2D ARRAY QUESTIONS: ............................................................................................... 117
BINARY TO DECIMAL .......................................................................................................... 127
DECIMAL TO BINARY : ........................................................................................................ 127
DECIMAL TO HEXADECIMAL:.............................................................................................. 129
- HEXADECIMAL TO DECIMAL: ...................................................................................... 131
- HEXADECIMAL TO BINARY: ......................................................................................... 133
- BINARY TO DECIMAL: .................................................................................................. 134
POINTERS:......................................................................................................................... 141
POINTER TO ARRAY: ....................................................................................................... 144
Why Increment p and ptr? ........................................................................................... 147
FUNCTION POINTERS:.................................................................................................... 152
- PASSING POINTERS: .............................................................................................. 154
PATTERN PRINTING: .......................................................................................................... 162
RECURSION: ..................................................................................................................... 178
HOW TO WRITE RECURSIVE FUNCTIONS: ....................................................................... 190
TYPES OF RECURSION: .................................................................................................. 195
TAIL & NON TAIL RECURSION: ..................................................................................... 200
PRACTISE QUESTIONS: .................................................................................................. 207
STATIC VARIABLES: ............................................................................................................ 210
ADVANTAGES & DISADVANTAGES OF RECURSION: ........................................................ 211
STRUCTURES:.................................................................................................................... 213
STRUCURE VARIABLES (DEC , INT , ACCESS): ................................................................. 215
TYPEDEF: ....................................................................................................................... 221
ARRAY OF STRUCTURES: ................................................................................................ 227
FEATURES OF STRUCTURE: ............................................................................................ 235
ASSIGNING VALUE OF ONE VARIABLE TO ANOTHER: ................................................... 235
NESTING OF STRUCTURES: ......................................................................................... 239
PASSING OF STRUCTURE TO FUNCTION ..................................................................... 244
STRUCTURE POINTERS: .............................................................................................. 252
ACCESSING STRUCTURE VARIABLES USING POINTERS: ................................................. 254
STRUCURES VS UNION: ................................................................................................. 261
FILE HANDLING: ................................................................................................................ 265
QUESTIONS: ...................................................................................................................... 272
FILING CRUD OPERATIONS: ........................................................................................... 283
DYNAMIC MEMORY ALLOCATION: ..................................................................................... 298
POINTERS RECAP ........................................................................................................... 298
C MALLOC(): .................................................................................................................. 304
What Happens During malloc? ................................................................................ 304
EXIT(0) EXPLANATION: ................................................................................................ 306
C CALLOC() : .................................................................................................................. 310
Free(): ............................................................................................................................ 313
REALLOC(): .................................................................................................................... 318
DANGLING POINTERS: ................................................................................................... 323
DMA and Array: ................................................................................................................. 328
3D ARRAY:...................................................................................................................... 333
3D ARRAY MEMORY ALLOCATION:.................................................................................. 335
DMA AND POINTERS PRACTISE: ......................................................................................... 338
PROJECT NOTES: ............................................................................................................... 354
FPUTS VS FPRINTF: ........................................................................................................ 366
GETCHAR AND FGETS INPUT HANDLING: ....................................................................... 372
DIFFERENCE BETWEEN PRINTF AND FPRINTF ................................................................. 380
ASSIGNMENT QUERIES: ..................................................................................................... 382
MACRO FUNCTIONS: ......................................................................................................... 384
- BASICS OF C LANGUAGE:
• Use when you're working with large numbers that exceed the range of a regular
int.
• Often used in situations where precision for large values is required, such as
financial calculations, scientific computations, or file offsets in large files.
•
•
•
•
•
•
•
•
•
•
•
• Modulous operator gives us the remainder while division operator gives us the
quotient .
•
• Pre-Increment (++a):
• First, the value of a is incremented, then it is used in the expression.
• Example: b = ++a increments a before assigning it to b.
• Post-Increment (a++):
• First, the value of a is used in the expression, and then a is incremented.
• Example: b = a++ assigns the current value of a to b, and then increments a.
• Pre-Decrement (--a):
• First, the value of a is decremented, then it is used in the expression.
• Example: b = --a decrements a before assigning it to b.
• Post-Decrement (a--):
• First, the value of a is used in the expression, and then a is decremented.
• Example: b = a-- assigns the current value of a to b, and then decrements a.
• #include <stdio.h>
• DEMONSTRATION OF POST AND PRE :
• int main() {
• int a = 5, b;
• return 0;
• }
• HOW TO FIND SIZE OF DATATYPES IN C USING SIZEOF():
•
•
•
•
- EXERCISES :
-
5.
6.
7.
EXERCISES:
•
• To convert from m to km : multiply by 1000
• To convert from m to cm : multiply by 100
• To convert from cm to inch : cm /2.54
• To convert from inch to feet : divide by 12
•
•
• TO FIND THE FIRST DIGIT FROM 4 DIGIT NUMBER DIRECTLY , MULTIPLY THE
NUMBER WITH 3 ZEROES THOUSAND. IT WILL HELP US GET THE FIRST
NUMBER.
• TO GET THE LAST DIGIT DIRECTLY , DIRECTLY MODULUS THE NUMBER BY 10.
• NUM % 10
•
•
•
•
•
•
• #include <stdio.h>
•
• int main() {
• int matchsticks = 21; // Initial number of matchsticks
• int player_pick, computer_pick;
•
• printf("Welcome to the Matchstick Game!\n");
• printf("Rules: You can pick 1, 2, 3, or 4 matchsticks.\n");
• printf("Whoever is forced to pick up the last matchstick loses the game.\n");
•
• while (matchsticks > 1) {
• // Player's turn
• printf("\nThere are %d matchsticks left.\n", matchsticks);
• printf("Pick 1, 2, 3, or 4 matchsticks: ");
• scanf("%d", &player_pick);
•
• // Validate player input
• if (player_pick < 1 || player_pick > 4) {
• printf("Invalid input! Please pick between 1 and 4 matchsticks.\n");
• continue;
• }
•
• // Subtract player's pick from the total number of matchsticks
• matchsticks -= player_pick;
•
• // If after player's pick, 1 matchstick is left, player loses
• if (matchsticks == 1) {
• printf("You picked the second last matchstick. You lose!\n");
• break;
• }
•
• // Computer's turn - computer will always pick in such a way that total picks
=5
• computer_pick = 5 - player_pick;
• printf("Computer picks %d matchsticks.\n", computer_pick);
•
• // Subtract computer's pick from the total number of matchsticks
• matchsticks -= computer_pick;
•
• // If after computer's pick, 1 matchstick is left, player loses
• if (matchsticks == 1) {
• printf("Computer forced you to pick the last matchstick. You lose!\n");
• break;
• }
• }
•
• printf("Game over.\n");
• return 0;
• }
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
• When you XOR two numbers, the result holds information about both numbers.
• By XORing the result with one of the original numbers again, you can "recover"
the other number.
Why It Works:
To check if a number is even or odd using the AND operator, you can use the fact that
the least significant bit (LSB) of a binary number determines whether it is even or odd:
• Odd numbers always have their least significant bit (LSB) set to 1.
• Even numbers always have their LSB set to 0
• Example:
• Input: 5 (binary 101)
• 5 & 1 = 1 → Odd
• Input: 8 (binary 1000)
• 8 & 1 = 0 → Even
• This method is very efficient because it checks only the least significant bit,
making it faster than performing a full division (%) operation for large numbers.
The bitwise OR operation is often used to set specific bits in a number. You can "turn
on" particular bits by ORing a number with a bitmask. The OR operation results in 1 if
either of the corresponding bits is 1.
How It Works:
• You create a bitmask where the bits you want to set are 1, and the rest are 0.
• ORing a number with this bitmask ensures that the desired bits are set to 1, while the
other bits remain unchanged.
Let’s say you want to set the second and third bits of a number num (considering bit
positions start from 0, i.e., the least significant bit is bit 0).
• If num = 4 (binary 0100), and you want to set the second and third bits, you would use a
mask 0110 (binary for 6).
•
• Explanation:
• num: 0100 (this is 4 in decimal)
• mask: 0110 (this is 6 in decimal)
• Result: After num | mask, the result is 0110 (which is 6 in decimal).
• Why It Works:
• In the OR operation:
• If either of the bits is 1, the result will be 1.
• For example, in this case:
• 0100 (num)
• 0110 (mask)
• -------- 0110 (result)
• Thus, OR ensures that specific bits are set to 1 without altering the other bits.
• The NOT operator flips all the bits of a number. It changes every 1 to 0 and every 0
to 1. This is often called the bitwise complement.
• How It Works:
• If you apply the ~ operator to a number, it returns the inverse of the number's
binary representation.
•
• Explanation:
• 5 in binary (32-bit): 00000000 00000000 00000000 00000101
• ~5: 11111111 11111111 11111111 11111010
• In two's complement representation (which is used by most systems for signed
integers), the flipped bits represent -6.
• This is because in two's complement:
• The leftmost bit (1) indicates that the number is negative.
• The negative number is obtained by inverting all the bits and adding 1.
• Use Case:
• The NOT operator is often used when you want to flip bits in certain binary
operations, such as when you need to perform bitwise negation.
• The left shift operator (<<) shifts the bits of a number to the left by a specified
number of positions, filling the empty right bits with 0. Each left shift is
equivalent to multiplying the number by 2^n (where n is the number of shift
positions).
• How It Works:
• When you left shift a number, its binary representation moves left, and new
zeros fill the rightmost positions.
•
• Explanation:
• 3 in binary: 00000011
• 3 << 2: 00001100 (which is 12 in decimal)
• Shifting left by 2 positions is equivalent to multiplying 3 by 2^2 = 4, resulting in
12.
• Use Case:
• The left shift is commonly used to multiply numbers by powers of 2. It's an
efficient way to perform multiplication when you know the factor is a power of 2.
• For example, instead of num * 4, you can use num <<
• The right shift operator (>>) shifts the bits of a number to the right by a specified
number of positions. Depending on the system and the data type, it may perform
logical shift or arithmetic shift.
• When you right shift a number, its binary representation moves right, and the
leftmost bits are either filled with 0 (for unsigned numbers) or the sign bit (for
signed numbers).
• Explanation:
• 16 in binary: 00010000
• 16 >> 2: 00000100 (which is 4 in decimal)
• Shifting right by 2 positions is equivalent to dividing 16 by 2^2 = 4, resulting in 4.
• Use Case:
• The right shift is commonly used to divide numbers by powers of 2. It's an
efficient way to perform division when you know the divisor is a power of 2.
• For example, instead of num / 4, you can use num >> 2.
• Arithmetic vs Logical Right Shift:
• Logical Shift (>> for unsigned integers): Fills the leftmost bits with 0.
• Arithmetic Shift (>> for signed integers): Preserves the sign bit (the leftmost bit),
which is important for negative numbers.
- ENCRYPTION / DECRYPTION:
Program Automatically Handles the Bits:
• The C programming language automatically converts the characters into their
ASCII values, which are stored as binary in memory.
• The ^ (XOR) operator in C operates on these binary representations, doing
bitwise comparisons.
• You, as the programmer, don't need to manually handle the bits because the
program does that for you by converting the characters into their ASCII integer
values and then applying the XOR operation bitwise.
• When you apply the XOR (^) operation, it happens bit by bit.
For example, let's say you're using the key 0x41 (which is 'A' with ASCII 65 and
binary 01000001), and you're XORing it with another character 'B' (which has ASCII
66, and its binary is 01000010).
• Summary:
• The program automatically handles the conversion of characters to their ASCII
(integer) values.
• These ASCII values are represented in binary inside memory.
• The XOR operation (^) operates on the bits (binary digits) of those values.
• As a programmer, you only deal with the characters, but C takes care of converting
them to their underlying bit representation and performing the XOR on them.
•
•
•
• In ++i , first i is incremented and then printed.
• Whereas , if its i++ , first I will be printed and then incremented.
•
- DO WHILE LOOP :
•
•
•
• So i here is printed the number of times I wanted in this way
FOR LOOP:
•
•
• First i will be initialized . I = 0 is only done once. Then condition is checked , if its
correct , then block is executed . after the printf execution , i is incremented .
•
• We have to print ‘n’ natural numbers so condition will include n . so I <=n.
•
•
•
•
• For loop will continue until the i is non zero. It will stop at 1
• When there is a for loop and its starting from I = 0 to I < n , then for loop will continue
from 0 to n-1.
•
•
•
• Continue terminates or skip the [articular iteration . in this case , as soon as I becomes
5 , it goes to continue . continue says to skip the iteration and moves program to i++
which makes i = 6 , so now 6 will be printed and so on.
• If error is occurring , avoid initialising inside the for loop.
•
•
- PRACTISE SET:
So to correct this
- IN VS CODE , IF YOU HAVE TO CHANGE THE NAME OF ALL VARIABLES , RIGHT
CLICK ON IT AND CLICK ON CHANGE ALL OCCURANCES;
-
- CLICK ON FORMAT DOCUMENTS TO ENSURE ALL INDENTATIONS
FUNCTIONS:
•
• CONVERTING THE FOLLOWING CODE TO FUNCTIONS SYNTAX:
•
•
• It return int so we initialize it by int . also in function definition end , we write
return .
•
• Return is used because it helps to store the value in a variable later on .
• The value is meant to be stored in variable so that it can be used further in the
program processing.
• If I removed print statement from function definition . and then later in first part ,
do : int c = sum(a, b). due to this , value is stored in c and then when I write printf
below , the program will help us output the c
•
• AS long as we have our function prototype written . whether our function
definition Is written after main or before main , it doesn’t matter.
•
• Void is a function that returns nothing, means if I write int c = display() , program
wont return anything .
•
•
•
•
• DIFFERENCE BETWEEN ARGUMENT AND SUM:
•
• In C, when you pass variables to a function, they are passed by value. This
means that a copy of the variable is passed to the function, and any changes
made to this copy do not affect the original variable in the calling function.
•
• Pass by Value: In C, when you pass a variable to a function, the function gets
its copy. Any changes made to this copy within the function do not alter the
original variable in the calling function.
• Here , num was passed to the function , num original variable has 50 . so
when we call the function with num variable inside it , the function
changevalue is given or passed the copy of num variable * not the original
variable* . Therefore , any changes made to this copy within the function do
not alter the original variable in the calling function and the value of original
function which is 50 , remains same.
•
•
• In C , there is a library named (math.h) , which contains many things related to
maths.
- RECURSION:
•
• Factorial of 5 is factorial 4 * 5 .
• If we follow program without if condition , then when I go to find factorial of 0 ,it will go to
factorial(-1) * 0 . in the same way , it will go to negative infinity in that case . therefore , I
make the condition that whenever , the factorial is 1 or 0 , return 1 in the answer.
• Function always returns the value. I made the base case , so that the recursion program
ends at a particular instant.
- EXERCISE:
•
•
•
•
How the Code Works:
• Mod n ensures we access the original value of the element even if it has been modified.
• If arr[index] is greater than or equal to n, it means the element has been seen before,
and we print that it's a duplicate.
• If no duplicate is found by the end, the code prints "No duplicates found".
Summary of Steps:
• arr[0] = 2
• The value at arr[2] = 1 (not yet modified, so it's less than n).
• arr[1] = 3
• The value at arr[3] = 2 (not yet modified, so it's less than n).
• arr[2] = 6 (previously modified, but we use mod n to get the original value)
• The value at arr[1] = 3 (not yet modified, so it's less than n).
• arr[3] = 7 (previously modified, but we use mod n to get the original value)
• The value at arr[2] = 6 (greater than or equal to n, meaning we’ve seen this element
before).
• Action: Print that 2 occurs more than once.
• arr[4] = 3
• The value at arr[3] = 7 (greater than or equal to n, meaning we’ve seen this element
before).
he issue you are facing occurs because the input elements provided exceed the valid range that
the code expects (from 0 to n-1). In your case, the input values were 11, 22, 33, 44, which are
out of the expected range of 0 to 3.
The algorithm depends on the assumption that all elements in the array are within the range [0,
n-1] where n is the size of the array. When you provide numbers outside of this range, the logic
for marking elements and finding duplicates breaks, causing incorrect behavior, like reporting
that 3 is duplicated when it isn't.
- STRINGS:
•
•
• When we use double quotes for string , null character is automatically added.
• If we do <=3 , then we will also be able to see the null character
•
• If we just use %c in my printf statement , I can get the combined output as “abc”
•
• Therefore , to print the whole string , I have to run the for loop and check its parameters
and so on
• C says that you don’t need to do this hefty work of traversing to print the string.
• Just printf using %s .
•
•
• Here I make a string array of 4 elements ,which means that it can take 4 characters , but
note that string will only be of 3 characters bcs the 4th character would be of null
character.
•
• NOTE WE DIDN’T ADD & IN SCANF STATEMENT .
• & IS AN ADDRESS OPERATOR. BUT HERE THE ADDRESS IS IN ST NAME .
•
• SCANF HELPS TO TAKE INPUT OF NON MULTIPLE SPACED STRING AND STORES IT IN
ST. NOTE NO & IS NEEDED AS ST ITSLEF INDICATES THE ADDRESS SINCE ITS AN
ARRAY.
• IN THIS WAY , WE CAN TAKE INPUT OF A STRING USING %S FORMAT SPECIFIER AND
THEN PRINT IT.
•
• WE INPUT IT DIRECTLY
•
• AFTER CLICKING ENTER, IT GETS DISPLAYED.
•
• GET function can be used as replacement of scanf to take input of a string and store it in
array . the only difference is that , Scanf cannot take multi word string with spaces ,
while gets can take multi word string with spaces and store it in string array.
• Space String can be stored using get function.
•
• Put function can be used as a replacement of printf after get function, it helps to print
the string and put the cursor on next line for further possible works.
• Here , it will first input multi word spaced string array and then print using puts function .
The benefit of put function in place of printf is that it allows to place cursor on next line
for further processing.
• The above code when executed first asks us to input the string . just as we input the
string , it would automatically input hey on the next line.
•
• HOWEVER , ITS RECOMMENDED TO USE FGETS() FUNCTION INSTEAD OF GETS() AS
THERE IS POTENTIAL BUFFER OVERFLOW RISK AS GETS FUNCTION DOES NOT
PERFORM BOUND CHECKING ON THE SIZE OF INPUT BUFFER. IF THE INPUT
EXCEEDS THE SIZE OF THE BUFFER , IT LEADS TO A BUFFER OVERFLOW , WHICH
CAN CAUSE UNDEFINED BEHAVIOUR , CRASHES OR SECURITY VULNERABILITIES.
• FGETS ALLOWS THE PROGRAMMER TO SPECIFY THE MAXIMUM NUMBER OF
CHARACTERS TO READ , PREVENTING BUFFER OVERFLOW. fgets() also keeps the
newline character (\n) in the input unless it's removed manually.
- EXTRACTING CHARACTERS IN 1D ARRAY:
- SORTING THE 1D ARRAY:
- TRANPOSE 2D MATRIX:
To perform a transpose of a matrix, you simply swap elements across the main
diagonal. This means swapping mat[i][j] with mat[j][i] for all i < j. Here’s the code to
perform a transpose on a square matrix mat[N][N]
- RANDOM NUMBERS :
FGETS:
• fgets():
This is the function that reads a string from an input stream.
It takes three arguments: the string (or array) where the input will be stored, the
maximum number of characters to read, and the input stream (like stdin).
• str:
This is the array (or pointer) where the input string will be stored.
It must be large enough to hold the input plus the null terminator (\0).
• sizeof(str):
This specifies the maximum number of characters fgets() should read, including the
null terminator (\0).
sizeof(str) returns the size of the array str. In this case, the size of str is 20, so fgets() will
read a maximum of 19 characters and reserve 1 character for the null terminator.
If you hard-code the value instead of using sizeof(), like fgets(str, 20, stdin), it would also
work, but using sizeof() is safer in case the array size changes.
• stdin:
This specifies the input source.
stdin means standard input, which refers to the keyboard. This is where the user types
input.
You can also use fgets() to read from a file by replacing stdin with a file pointer, but for
keyboard input, we use stdin.
The newline character (\n) indicates that the user pressed Enter to finish the input. fgets()
includes it in the input string to faithfully represent what the user typed.
If you don’t want the newline to be part of the string (for example, when you're processing
the input later), you can remove it using this line:
We remove the newline character in the fgets() input because fgets() automatically reads
the newline character (\n) when the user presses the "Enter" key after entering a string.
• Normal Input:
o When you input a string and press "Enter", fgets() stores the characters in the
array, including the newline character at the end (if there is space left in the
array). For example:
•
•
#include <stdio.h>
int main() {
char str[20]; // Buffer to store the input, max 19 characters + 1 for null terminator
return 0;
Key Points:
• If the user inputs less than 19 characters, fgets() will include the newline (\n).
• If the user inputs 19 or more characters, fgets() will only read the first 19 characters
and automatically add a null terminator.
Q- If the user inputs less than 19 characters, fgets() will include the newline (\n). what is meant
by this help me understand with example . also help me understand what eah word in the fget
function is for. fgets(str, sizeof(str), stdin);
•
When you use scanf to read a number (e.g., 30), it reads the number but leaves the newline
character (\n, from pressing Enter) in the input buffer. This leftover newline can cause issues
when you use fgets immediately afterward.
o When you enter 30 and press Enter, scanf reads the 30 but leaves the newline
(\n) from pressing Enter in the input buffer.
o If you call fgets right after scanf without clearing the buffer, fgets will encounter
that leftover newline (\n) immediately.
o fgets will interpret the newline as the end of input, resulting in an empty string
(just the newline), which makes it look like the first line in your terminal is empty.
o This loop removes all characters in the buffer up to and including the newline.
So, when you call fgets next, it can read the actual input from the user without
any unexpected leftover newline.
- STANDARD LIBRARY FUNCTIONS
FOR STRINGS:
• Only calculates the size of string being seen , for eg if in char str[6] , we have hello , the
strlen(st) will only read hello and calculate its size , it wont consider null character , In
simple it would return length as n-1.
•
• Having strlen(st) in printf statement helps navigate printf statement to display size of
string in %d.
•
•
• If we want that s1 mai s2 jor jae so we use strcat(s1, s2).
•
• We include space in bahi after first quotation to get a space bcs str cat gives no space
by default.
•
• Output ^
•
• If it matches , 0 is returned
• If when comparing , the first character in first string appears first in word dictionary ,
then it will return negative value , and if the first character in second string appears first
, it willr return positive value/
•
• 1 in ascii values appear first in ASCII table so 1 is returned.
• Remember it by far joke is negative.
- EXERCISE:
Write a program to take string as an input from the user using %c and %s
confirm that the strings are equal
To declare a 2D array, you need to specify the number of rows and columns.
char names[5][20]; // 5 strings, each up to 19 characters long (+1 for the null terminator)
- 2D ARRAY QUESTIONS:
Q- LONGEST STRING
• The \" is used to print actual double quote characters in the output. Without
escaping, " would terminate the string, causing a syntax error.
• It allows you to format the output to include quotation marks around the string,
improving readability and clearly indicating which text is being referenced.
the frequency of characters used in their promotional slogans. They believe that analyzing
these
patterns can help them tailor their messaging to specific demographics and improve brand
recall.
You've been tasked with creating a C code function to analyze the character frequency in a
list of
slogans provided by the marketing team. This analysis will help identify the most common
letters
Input:
Expected Output:
● For "buy now": {'b': 1, 'u': 1, 'y': 1, ' ': 1, 'n': 1, 'o': 1, 'w': 1}
● For "save big": {'s': 1, 'a': 1, 'v': 1, 'e': 1, ' ': 1, 'b': 1, 'i': 1, 'g': 1}
● For "limited offer": {'l': 1, 'i': 1, 'm': 1, 't': 1, 'e': 2, 'd': 1, ' ': 1, 'o': 1, 'f': 1, 'r': 1}
•
• int char_count[256] = {0}; works because the array size is fixed (256), and C allows
compile-time initialization for arrays with known sizes.
• int char_count[num_slogans][256] = {0}; gives a warning because num_slogans is
not known at compile time, and C doesn't allow runtime-initialized arrays to be
initialized using the {0} syntax. You need to manually initialize arrays with sizes
determined at runtime.
• Better hard coat the values like :
• When scanf() and fgets is used in the code in such a way that you used scanf
before and is proceeding towards fgets , its better that you use getchar() to clear
the input buffer.
Question:
Requirements:
• The program should allow the user to input the number of strings and the maximum
length of each string.
• For each string, it should print the updated string (with duplicates removed) and also
count how many characters were removed from the original string.
You could use int to index the seen array, but it’s unnecessary and may lead to confusion.
Here's why:
• Array Indexing Range: The seen array only needs indices from 0 to 255 (for ASCII
characters). Using unsigned char makes the intention clear that you're working with
character values.
• Negative Values: If you were to use a signed char or int, you might inadvertently
index negative values, which could lead to undefined behavior or accessing out of
bounds in the array.
Summary
Using unsigned char ensures you are indexing the seen array correctly for all possible ASCII
characters, avoiding issues with negative indices.
In the function call, values is simply the array name, which is the same as the array
pointer. When you declare it as a parameter in a function signature, you can use either
values[] or values to represent the array.
Now, whatever A picks (1 to 4), B can always adjust his pick to make the remaining
count a multiple of 5.
Eventually, B will pick the last matchstick and win the game.
Now B has 10 matchsticks and can pick between 1 and 4 matchsticks, but whatever B
picks, A can respond in a way to leave a multiple of 5 again:
This strategy continues, and A can always leave B with a multiple of 5 after every
turn, ensuring that B eventually has to pick the last matchstick, allowing A to win.
Now B has 15 matchsticks, and A can continue forcing a multiple of 5 after each of
B’s turns.
Following this strategy, A can always respond in such a way that B faces a multiple of
5, eventually forcing B to pick the last matchstick, securing A’s win.
DECIMAL TO BINARY :
DECIMAL TO HEXADECIMAL:
o Adding '0' (the ASCII value of '0' is 48) to remainder converts it to the ASCII
character for that number:
o In ASCII, 'A' has the code 65. To get A when remainder is 10, we use remainder +
'A' - 10:
Examples
• If remainder = 4:
• If remainder = 13:
• Printing in reverse gives us FE, which is the hexadecimal equivalent of decimal 254.
• Since hexadecimal digits are stored from least significant to most significant in hex[], we
print them in reverse order to get the correct hexadecimal result.
The use of index - 1 in the loop is necessary because the index variable, after the loop that
stores the hexadecimal digits, points one position past the last valid entry in the hex array.
1. Conversion Loop: Suppose we’re converting the decimal number 254 to hexadecimal.
o First iteration:
▪ hex[0] = 'E'
▪ number = 254 / 16 = 15
▪ Increment index to 1
o Second iteration:
▪ hex[1] = 'F'
▪ Increment index to 2
o Since index is now 2, it points to one position after the last valid entry in hex[].
o To start from the last valid entry, we need to access hex[index - 1] (i.e., hex[1]),
which holds 'F'
The printf("\n"); is outside the for loop and is used to print a newline after the hexadecimal
number, making the output look cleaner. It ensures that the output cursor moves to the next
line after displaying the hexadecimal result, which is especially useful if there are more lines of
output following the hexadecimal number.
- HEXADECIMAL TO DECIMAL:
In hexadecimal:
Each hexadecimal digit's position represents a power of 16 (just as each digit in decimal
represents a power of 10):
• The next digit to the left represents 16116^1161 (the sixteens place),
• The next digit to the left represents 16216^2162 (the two hundred fifty-sixes place), and
so on.
Code Walkthrough
1. Initialize Variables:
o Multiply each value by base (current power of 16) and add it to decimal.
o If the character is not between 0-9 or A-F, the function prints an error message.
• Hexadecimal: 1A3
• Length: 3
Conversion Steps
o Update base = 16
2. Middle Character (A):
- HEXADECIMAL TO BINARY:
- BINARY TO DECIMAL:
Concept Recap
When searching for a string within a row, we need to make sure that there are enough columns
left in the row to fit the entire search string. If we start too close to the end of the row, we won’t
have enough space for the whole string, and we could end up reading outside the array’s
boundaries.
• j is the starting column position in the row from which we attempt to match the search
string.
The idea behind j <= COLS - strLen is to ensure that we only start searching in positions where
the entire search string can fit.
Step-by-Step Example
Let’s say:
• The search string we’re looking for is "CAT", so strLen = 3 (the string has 3 characters).
Row: AB C AT
Column:0 1 2 3 4
If we want to find "CAT" in this row, we need to look for it in 3 consecutive columns.
Breaking Down j <= COLS – strLen , this conditions define the boundaries for consecutive
searching . cols – strlen tells us that within bounds , if string length is 3 , then the only way
it can be consecutively searched within bounds is when we search from the starting
position of 0 , 1 and 2 . this condition specifies the starting position. Without it , who knows
we could be searching outside the bounds of array.
o COLS - strLen = 5 - 3 = 2
So, j <= 2 is the condition. This means we can only start searching from column indices 0, 1, or 2
(since j must be <= 2).
2. Why We Stop at j = 2:
If j were 3, we would need to check columns 3, 4, and 5 — but column 5 doesn’t exist (since the
last column index is 4), so we would be out of bounds.
Let's go through each possible starting position and see how the calculation prevents us from
going out of bounds.
1. If j = 0:
2. If j = 1:
3. If j = 2:
4. If j = 3 (out of bounds):
Thus, the condition j <= COLS - strLen ensures that we don’t start a search from a position
where the string would exceed the row length.
• If you start at position j and need to fit a string of length strLen, the last position you’ll
need to check is j + strLen - 1. -1 because array starts from 0.
• j+strLen−1<COLS
• j<COLS−strLen+1
This ensures that we only start searching from a position where there is enough room left in the
row to fit the search string.
POINTERS:
•
•
•
•
•
•
POINTER TO ARRAY:
•
•
• p is a pointer to an integer. When you set p = arr;, it points to the first element of
arr, i.e., &arr[0].
• When you increment p with p++, it moves to the next integer in memory, pointing
from &arr[0] to &arr[1].
• The pointer p increases by sizeof(int) bytes (typically 4 bytes on many systems)
because it’s pointing to individual integers.
• ptr is a pointer to an entire array of 5 integers (int[5]). When you set ptr = &arr;, it
points to the whole array arr.
• When you increment ptr with ptr++, it moves to the next array of 5 integers in
memory, not just the next integer.
• The pointer ptr increases by sizeof(int[5]) bytes (typically 20 bytes on many systems
if int is 4 bytes) because it’s pointing to a full array of 5 integers, not a single
integer.
Why Increment p and ptr?
The increments are performed here to demonstrate how the size of the data type that a
pointer points to affects its behavior during pointer arithmetic. This illustrates the
difference between:
•
•
• when i deference pointer to an array , it will return the address of first element , am
i right ? for eg if first element is 3 , it will only return its address . is this called base
address . does this base address in one way is the address of whole 5 element array
•
•
•
•
•
•
FUNCTION POINTERS:
•
•
•
•
- PASSING POINTERS:
If you passed a by value (without using a pointer), then the function would only receive a copy of
the variable, not the original variable itself. This means any changes made to a inside the
function would only affect the copy and not the original variable in main.
o Inside the function, you could modify a as much as you like, but it would not
affect x in main.
o When the function returns, x in main would still hold its original value.
POINTERS IS ALSO USED TO GIVE MULTIPLE RETURNS . NORMALLY IN C WE CAN GET ONE
RETURN VALUE BUT BY USING POINTERS , WE CAN RETURNMULTIPLE VALUES.
o In main, we declare sum and product as regular integer variables, not pointers:
int sum, product;
o These variables hold integer values (not addresses) that we want to store the
results in.
o This allows sumAndProduct to use pointers int *sum and int *product to directly
modify the values of sum and product in main.
3. Inside sumAndProduct Function:
o After sumAndProduct is called, the values of sum and product in main have
been updated to 9 and 20, respectively.
o sum and product in main now directly hold these computed values as regular
integers.
we passed address of max and min to the function because passing just max and min to the
function will just change the copy of max and min but not the original variable due to which
when we finally print max and min at the end , it would be same to the value , we initialized
The star max min in function parameter means that we take the address of max and min as
parameters.
Why a Pointer to a String (char *) is Used in the Search function while searching
strings in 2d array.
PATTERN PRINTING:
• With newline character , it is made like this
•
•
•
•
•
•
• Inner Loop: Iterates over each column of the current row, printing numbers from 1 to
rows - i + 1. This ensures that the number of numbers printed in each row decreases by
1.
• It’s a better practise to initialize row , even though you know the number of rows .its
handy in patterns.
•
•
• An = a +(n-1) * d ; where a is the first term ; n is the number of values you want in
sequence ; d is the difference between the values.
• SEE IF PATTERN IS THAT THE COLUMN NUMBER IN EACH ROW IS SAME AS ROW
NUMBER , THEN YOU SHOULD DO J=1; J<=N .
• Here the case was not like that whatever is the row number , there are same column in
that row , so I did manually .
• To produce a star mast , the formula to be used inside j for printing spaces is j<= rows – i
•
• After printing spaces . notice the space left corresponds to the row number . which
means we will use the typical logic of running a variable till i.
• But this time , we will use another variable called as k.
•
•
•
•
•
•
• If we wanted odd numbers then we would run as typical code but apply 2n-1 in
printf
•
• For this , recall typical star pattern code on far right . we have to do the same ,
just add spaces on left.
•
•
•
•
RECURSION:
•
• Whenever a function is called , its activation record would be maintained inside the
stack,
•
• As we know the execution starts from the main function , so an operating system first
calls the main function. So activation record of main(), would be first mantianed inside
the stack . first push comes down , stack is down to top.
• The activation record will consist of parameters , locals with the function , also it will
consist of return address to the caller.
• For the sake of simplicity , we are now only maintaining local variables in it.
•
• After this step , we see that we have a printf function , in which fun function is recalled ,
with n as its parameter.
• So who is the caller of this function , main function is a caller .n is 3 , which means we
are passing 3 to the function. Where is the definition of this function?
• The definition of this function is above.
• Therefore , we can say that from the main function , we are calling fun (3).
•
• With this passing , work begins in recursive function.
• AS the activation record also consist of parameters , so in this case n equals 3 will be
maintained inside the activation record of this function.
•
•
• Now inside the function , first condition is checked whether n ==1 or not.
•
• Fun is calling function again .
• Therefore , function will get replaced by 2.
•
• Now activation record of fun(2) will be maintained.
•
• So now , inside it , we write the paerameter as n = 2.
•
• After this , we call fun(1) function with n =1 parameter . n = 1 is == 1 . so now we return 1.
•
• Now , we unwind.
•
• Return means , that we are simply popping fun(1) activation record out of the stack.
•
•
• NOW , with backtracking / unwinding we get fun(2) function.
•
• This means you are returning back to the place where you left off . and following is the
place where you left fun(2).
•
• This is what I left of .
• So , now fun(1) will get replaced by value 1. 1 was returned by the function fun(1).
• So : 1+1 = 2;
• Therefore , now , we know fun(2) answer is 2.
• Now fun(2) , will be popped .
• Now , the stack goes to fun(3) . we redirect to the area where we left off.
•
• The value of fun(2) was 2 , so now fun(3) is 3.
• Now we pop fun(3).
• Now , value 3 will get returned to int main , but at which place , the place where I left off.
•
• I left at here.
• So now fun 3 wll get replaced by its value,
•
• Therefore , the output of this particular program is 3.
• Notice , that in end , we are returning 0 , so this means activation
record of int main will also be popped out.
• If we want to solve these questions in exam , we can use another
method.
• Here , we will directly go to int main function , and in printf function since our n
initialized as 3 , we will directly call fun(3) function . with calling of function , it will go to
its definition function . there , 3 is not equals to 1 , so it will not get evaluated.
• In else , it will be 1 + fun (n-1).
• In short it becomes 1 + fun(2). Before , evaluating the function , we need to find the value
of fun (2) , so function would be recalled , it goes into definition function . with this ,
fun(2) becomes .
• 1 + fun(1) . now fun(1) is recalled . the value of fun(1) is 1.
• So fun(2) = 1 + 1 = 2;
• Fun(3) = 1 + 2 = 3
•
’
• Write it like this
•
•
•
• ’
•
•
•
• Its answer is 15.
•
• BASIC STRUCUTRE OF ANY RECURSIVE PROGRAM
•
•
• IN order to write any recursive function , you need to first specify the recusive
procedure and then the base case.
•
•
• Lets suppose , we have to calculate factorial of 4 . now assume the simplest calculation
or factorial . think of a problem which is very easy to solve.
•
• Now , if you observe , we can replace 1 by fact(1) .
•
•
• Now here , we can see , we can write fact(3) as 3* fact(2) as fact(2) represents 2 * 1 .
•
• So , this is our recursive procedure.
•
• Base condition is the one which doesn’t require to call the same function again and it
helps in stopping the recursion .
• For eg , here fact(2) requires calling fact(1) so it cant be a base case.
• Fact(1) is simply 1 , so we can choose it as base case .
• We can also make fact(2) == 2 as base case.
• For the sake of simplicity , we will take 1 .
•
• EXECUTING THE FUNCTION.
•
•
TYPES OF RECURSION:
•
• A function is called direct recursive if it calls the same function again.
•
• Whatever programs we encountered previously were direct recursion programs.
•
• Here , you are recalling function fun() indirectly. We are first alling fun(2) and from fun(2)
we are calling fun().
•
• You will want your program to output as this
•
•
• We called odd function in int main bcs the first n number is 1 which is odd , so we first
call odd function.
• Once we call odd function , it first checks the condition of number being less than 10 . if
its less than 10 , then we print with 1 addition to odd number.
• In the end , we then increment n , to make it an even number and then subsequently call
even function , so that even function can handle the even number by substracting 1
from n and printing it.
• In the end ,then we increment n to make it an odd number and then call the odd
function.
•
• After processing , after the incrementation of n , even function is called , so activation
record is transferred to even function and activation record of evenf function will get
stored inside the stack.
•
•
• This process continues , when we encounter n = 11 , the condition fails so we encounter
return .
•
• Return means we are returning back to the position where we left off.
• As we return , the activation record of odd will be popped out of the stack.
• As the activation record of odd is popped out , we return back to even function which is
next In stack.
• In even function , we go back to the position where we left off.
• We left off the function at the point where its written odd().
• After the odd function , theres nothing , we encounter return statement again . this
means , you will return back to the position where you left off . this means you will get to
odd function . with this , even would be popped out
• Inside the odd function , we left at the point where its written even() . after even , there is
nothing , there is return . so when we encounter return we go back to the position in
even function where we left off . due to this switch to even function , odd function will be
popped off .
• This process will continue.
• Finally , when you encounter the main function . and you can see after this point of odd()
there is nothing written
• So int main function simply gets popped.
•
•
• you can clearly see that this is a recursive porogram. However , this is a tail recursive
program.
• A function is said to be tail recursive if the recursion call is the last thing done by the
function
• This is the last thing done by the function , because after this recursive call , you didn’t
find anything to evaluate. So this is a tail recursive function.
• The last line says : “there is no need to keep record of previous state”
• We can understand this with the simulation fo stack.
•
• As you can see , first int main function activation record is maintained , inside int main
fun (3) is called , so control transfers to fun(3) . the fun(3) activation record is mantianed
with its parameter as 3 . since the base case is not satisfied here , we then print 3 to the
screen.
• Lastly , return fun(n-1) is called . this means , we will simply call fun(2)
• As we know, now the control will transfer to fun(2)
• This continues . with fun(0) control , n is 0 , so it satsifies the base case , and hence the
backtracking starts.
•
• We encounter return , we get back to fun(1) get back to the position where we left off .
to the position of return fun(n-1) . 1- 1 is 0 . After this , there is nothing to evaluate .
• One property of stack , is that when we return back to the function , we are assumed to
do some evaluation . however , when we return back. But here , when we return back ,
there is nothing to be evaluated .
• That is why we say that there is no need to keep record of previous state.
• We generally maintain the result of previous state , because when we back track , there
is something to be evaluated.
• Since here , there is nothing to be evaluated .
• Hence , we can say that tail recursive function is not utilizing the properties of stack
properly.
• We simply return back to fun(2) and this continues .
• The output is 3 , 2 ,1 .
•
• With fun(0) , we will return back to fun(1) . this means activation record of fun(0) will get
poppedout.
• Now we are at fun(1) at the particular point where we left off . that point is: fun(n-1).
• after the recursive call , we need to evaluate printf , that’s why it’s a non tail function.
•
• We will get 1 as a first output.
• then after this activation record of fun(1) gets popped out.
• Now , we are In fun(2)
• 2 would be the output and then fun(2) gets popped out . 3 would be the next output .
with this fun(3) would be popped.
• After this control transfers to main function .
• After this function evaluation , we encounter return 0 , so int main gets popped.
•
• Why its a non tail function?
•
• Its non tail recursive , because fun (n over 2) returns something . the value returned by
function is getting added to 1.
• This means after returning back , we need to evaluate the addition . hence , it’s a non tail
recursive function.
•
• In this code , with fun(1) , we will simply return back , but with the value of 0 . so fun(1)
gets popped out.
• Now the control transfers to fun(2) at the particular point where we left off : fun(n over
2). As the value 0 is returned by fun(1) . therefore : 1 + fun(2 over 2) equals : 1 + fun(0) = 1
+ 0 = 1;
• Fun(2) gets retuned with the value of 1 . now the control transfers to fun(4) and we get
back to the point where we left off : fun(n / 2) . now fun(2) will get replaced by 1 . and 1 +
1=2;
• With this , the function fun(4) returns 2 and gets popped . the control now transfers to
fun(8) .
• The fun (8) gets back to the position where we left off and return with : 1+ fun(4) . fun(4)
is 2 . so the fun(8) returns 1+ 2 = 3;
• And now the fun(8) gets popped and control transfers to int main().
• In the main function , we left off at fun(8) , so now fun(8) will get replaced by 3 . and the
output will be 3.
PRACTISE QUESTIONS:
•
•
•
•
•
•
•
STATIC VARIABLES:
•
•
•
STRUCTURES:
• The structure in C is a user-defined data type that can be used to group items of
possibly different types into a single type. The struct keyword is used to define the
structure in the C programming language. The items in the structure are called
its member and they can be of any valid data type. Additionally, the values of a
structure are stored in contiguous memory locations.
•
•
•
•
• In structures , there are multiple attributes that are of different types. Arrays are also
used to store multiple attributes but of the same type.
•
•
•
• There will be no need to write struct syntax again if we declare varibale with declaration
of structure.
•
• Name will not be printed correctly.
•
• This gives error . the above pic is same as below pic . in above also , we declared ch in
struct syntax and then assigned a. name with name. this is bound to give error.
•
•
•
• In order to overcome this , either you have to store strings separately , or through a loop
, or through a strcpy function.
•
• This would perfectly work.
• This means that whenever we want to store the members of structure particularly of a
string ,we cannot store our name or any other string like this as it vgives error
•
•
• This is the correct way
•
• Nesting of structures.
• Struct pokeman picacho ; is an object and struct pokeman is class
•
•
• Here the error lies in struct emp e . basically , before even the struct employee is
created . I have nested another structure in it . first the structure should be made till };
and then we can do struct emp e
In order to store point decimal we use float datatype. What if I want to store decimal
numbers with my chosen name like realnumber y;
TYPEDEF:
•
• If we write typedef outside , then it would work for complete block of code , but If I write
it inside int main l, then it would only work for main.
•
•
• HOW ITS USED IN STRUCTURES.
•
• Initially , we have this
•
• Members can also be declared like this’
• Now with typedef , we can make declaration of variable shorter.
• In place of struct book , we can write something of our own choice.\
•
•
• This will give error
•
• Computer read it like we created one box for x pointer and one for y
•
• For now its an error
• SO WE CAN SOLVE THIS ISSUE USING TYPEDEF
•
ARRAY OF STRUCTURES:
• HERE , NOW IF I WANT TO CREATE 10 POKEMON MEMBERS , I HAVE TO WRITE IT
SEPERATELY , IT WOULD TAKE A LONG TIME . IN THIS CASE , ARRAY IN STRUCTURE
IS USED.
•
• Now this indicates that we can store the data of 10 pokemons
•
•
• NOW IN ORDER TO PRINT THE INFO OF ALL MEMBERS OF POKEMON.
• -
• NOW I ALSO WANT TO STORE THE NAME OF POKEMON . HOW WILL I INITIALIZE IT
WITH ARRAYS IN STRUCTURE METHOD?
•
Previously with scanf of name , it was giving error , either break it into first and last name or use
fgets
•
•
•
•
•
FEATURES OF STRUCTURE:
•
•
• DO WE NEED THIS MUCH LINE TO DO THIS?
COMPARING STRUCTURE:
•
•
• IF I WANT TO COMPARE THE COMPLETE STRUCTURE , DOING THIS GIVES ME THE
ERROR .
•
• YOU CAN COMPARE THE COMPLETE STRUCT SEPERATELY.
•
• WHENVER WE USE BOOL VARIABLE WE ADD #INCLUDE<STDBOOL.H>
•
•
NESTING OF STRUCTURES:
•
• one is normal pokemon and the other is legendary pokemon. Legendary pokemon
contains everything same as normal pokemon but it has ability also.
• So do we need to write complete attributes of it again?
• No , just write the thing which is extra . just write pokemon + any thing . this will
reperesent the complete pokemon structure ,
•
• NOW IF I WANT TO SET ALL THE THINGS OF LEGENDARY POKEMON , HOW WILL I DO
IT? When we had different members , we used mewto.hp . now how can I access when I
make the super class.
• FOR that , you will do | mewtwo.normal.attributes| . this will serve the purpose of
assigning.
•
• Now , continue writing remaining members.
• We can also do nesting within a nesting of structures .
•
•
•
•
•
• Last two are false.
• In first one . structure bolt is super class inside engine
•
•
• Here pokemon is our structure and I passed ‘p’ as an indication that any variabkle is
passed.
• However , you will think that with the passing of pikachu , my hp would be printed . but
no , there will be error.
•
• This error is because this isn’t our normal variable , this variable is made by me as user
defined datatype inside the main function , therefore due to this , baahir kai functions ko
iska access nahi hai .
• If I passed int float or any datatype , it could work but that’s not the case with structure.
• IN ORDER TO SOLVE THIS , WE DO GLOBAL DECLARATION.
•
• Now it will work.
• IT’S A BETTER PRACTISE TO DECLARE STRUCTURE OUTSIDE AS GLOBAL , SO THAT
EVERYHTING HAS ITS ACCESS.
• If I want to change the value of hp and attack through making a function like void
change(pokemon p) , will this change the value of hp and attack ?
•
• By passing to function and changing values , will this be possible?
• If the print value comes 60 , 50 and 100 , this means its pass by value , but if the value is
changed to 70 , 60 and 110 , this means , its pass by reference.
•
• Its clear meaning is that : when we tried to change the function , so the pokemon p
which is made by function call is a new pokemon which was the copy of our picachu , it
was not the original pickachu .
•
• Here , when we call change(pickachu) , so the p pokemon is made with 60 , 50 and 100
values , and so when we change values , values are changed in ‘p’ not in our intended
pokemon variable ‘pickacchu’ .
• THIS IS KNOWN AS PASS BY VALUE
• #STRUCTURES ARE PASSED BY VALUE
•
•
•
• Here we aren’t modifying anything , so when both structure copy is passed , they
are compared effectively.
•
STRUCTURE POINTERS:
•
•
• just as I did pokemon pickachu , a box was created for it .
• here we get the address of whole pickachu which was same as hp address.
•
•
• Just like array in which the first element address particularly known as base address
gets stored in x , here , also the address of hp ,as base address will get stored in x
• If we want the address of separate pickachu variables , then we do like this
•
• I want that through this x value , I store the value of age , weight and others
• This is useful when we have to do pass by reference and modify values in the structure.
•
• This wasn’t working
• Normally , if I wanted to change the value of any variable , I used to do like this
•
• Here q value will be changed to 7 , as we access q address through *p , and change
• If I wanted to store value in variable using pointers , It was done like this
•
• Here x value becomes 7
•
• Is this valid ? we wrote correct , it accessed address of pickachu and with .hp , it made
its value as 70
• Here you have to use bracket around x
•
• I can also modify the values of certain variable inside the function with this .
• Like , first I will do normally : pickachu.hp = 60 , and then later after ; pokemon* x =
&pickachu , by getting the address , I then modified value by : (*x).hp = 70 .
• So now my terminal will first show hp value as 60 and then 70
• This mechanism is also used in structure function to change values
•
• We passed by reference so the change was made in main..permenantly
•
• Using arrow is same thing.
• Previously , in pass by value , we were in function doing p.hp = 60; with pointers in place
of p , we write (*p).hp or p→hp.
•
•
• WITH THIS METHOD , YOU DON’T NEED TO DO STRCPY , IT WOULD BE MORE SIMPLER.
We cannot first initialize pickachu and tier using brackets form and then below it initialize hp
and attack , it will give error,
This will give error.
With function call , a box b would be made and in it its address would be present . so when we
do b→name , it means in b box , go that address , and in it , go to name and print
•
STRUCURES VS UNION:
• In structure , we can use all members , but in union we can only use one member at a
time.
We took movies pointer because when the movie will be added , it will be added to a particular
movie count , of movie structure . and since I want to take address as parameter , I took
temporary variable *movie as parameter. for eg : when I will call add movie function , it will be
addMovie(&movies[movieCount]). So in a nutshell , I need to give the address of that movie
count inside movie structure.. That’s why we used pointer.
Previously , when we needed to write the details of 100 movies ,we did after structure thingy.
But here , add movie function is there for it . so we initialized 100 movies array in int main . so
that It get used to add movie function . since we want to add the movie in structure and on top
of that on a particular movie count of structure , so we write add movie function like this:
addMovie(&movies[movieCount]);
FILE HANDLING:
•
•
•
•
• We will be using fgets or fputs
•
• By this , my first line is printed.
• By replacing if with while , my complete lines will be printed
•
• If I adjust the number of characters in size of area of fgets , I will get the string according
to it
•
• You must make sure that the array which holds your text from file has enough space to
store it so that correct processing can be done later
•
•
•
•
•
• Before reading a file , make sure its already created and have content in it.
•
• Fgets format now becomes , fgets(str,size,fileptr)
• WHAT IF I WANT TO CREATE A FILE . Although you can do it as we do in vs code , but
if we don’t want it , then we can also create a file through a code.
•
•
• Fputs format now becomes fputs(str,fileptr)
•
it’s a good practise to close the file when you open it for operations
•
• With fopen(“file.txt”,”w”) . if the file is not present , it would be created or if its
already there , then we would be able to write content in the file
•
•
QUESTIONS:
Here , we are reading a single line and storing in another file . first , we will declare file pointers
for both files as *inputfile and *outputfile. We also created one buffer array of 100 characters to
store the characters of one line . this is done , so that when we write it into output file , we can
use it in fputs(buffer, outputfile). Now first , we make validations to check whether the fie in
itself . it should not be null . after confirming this , then we make fgets with if because we want
to read one line . we do it like this if(fgets(buffer , sizeof(buffer),inputfile)!= NULL) , with this print
it into output file . do this using fputs . since you have read with one fgets statement , now store
it in output file by printing onto it . we do this by : fputs(buffer,outputfile) . in the end close the
files.
It is same as first , you will initialise the pointers of file of input and output by :
FILE *inputFile, *outputFile;
Then you create one buffer array . since here now we have to store *5 lines* , we will a 2d array.
char lines[5][100];
Then we open the input and output file and see if fopen returns null . this is verified in the way
that whatever is returned by fopen is stored in the pointer variable. So we check if pointer
variable is null , then we print error and return 1 to exit the program . we do this validation for
output files also.
Then now , since we have to read 5 lines , we could do this by while . but , it can also be done by
for loop running till the number of lines and then if condition with fgets with condition that if
input file is null , if fgets function return NULL , this means EOF is reached or there was error in
reading the file . , then we break for 2nd iteration which indicates 2nd line to continue ,
However , if its not null then we run one j loop which runs from 0 till i . this ensures that with
every successful input intobuffer array our whole output file gets updated in one go . with that j
loop , we use fputs.
FILING CRUD OPERATIONS:
• To insert a new record , we have to insert a record of one student , so make one object ,
not array of objects so that you can use it as temporary structure object to do the work.
• Next , to insert a record , you will open the file in append mode and then use scanf to
store a record in relevant structure area.
• In the end , to display the record added , use fprintf , it helps to input things in the file in
a formatted manner .
• Its syntax is that first you write file to indicated which file the data needs to be stored ,
then in between inverted commas write format specifiers . then , you will write structure
dot operators to indicate from where they have to pick the data .
• In the end , close the file..
WE CAN TAKE STUDENT STRUCTURE AS PARAMETER
• To display the record , you first declare file pointer , then make one member of the
structure to do your work on. We then open the file in read mode. We have to display the
records , so for that we use fscanf which can be used to read lines from the file
iteratively until it encounters EOF.
• So we write fscanf , the first parameter is file name which indicates that from where , we
need to take our data , then in inverted commas we write format spefcifiers , then give
them std.age std.name addresses to store their data on,
• We run fscanf in the while loop till it encounters EOF . After it reads each line , it prints
the record of one line through printf . printf is used because now we have to print data to
the console , not to the file;
• In last . we close our file.
Freopen in simple way closes the file which is previously opened in r+ mode , and then reopens
it in write mode . it tuncates all the content inside the file and then prepares the file for writing
all the updated records from the memory .
WE TAKE STUDENT ARRAY AND TARGET , ALSO WE CAN TAKE COUNT AS PARAMETERS
• First , we make a file pointer which would point to the base address of the file , then we
will make 100 members of structure student . In another way , there are 100 student
record . The 100 student records are already made in a file.
• Now we have to update the record , in order to update we need to first read all the
records inside our memory . by memory , we mean that they should be stored in our
structure array.
• For thagt , we will use fscanf which will read all the contents from the file until it reaches
EOF and subsequently store all the data in relevant structures array . we run this in a
while loop.
• Count is initialized as 0 , so that our read starts from 0 ad then increment with each read
.
• Found is also initialized as 0 ,as soon as target name is found , we equare found to 1 and
break.
• Inside the while loop , we run the count , so that we can successfully store our records
in structure by the way of count incrementation . Count incrementations later also
helps us in comparing the target name of the student .
• Once all the data is read from the memory . our work is done . we used to do this thing
with load members from file function
• Now , we ask to input the target name which needs to be updated. Then we run the for
loop till the count . and use strcmp to compare that name with the name of all the
student array.
• Once , its found , we then break from the loop and use freopen(filename , write mode ,
file pointer) .
• With freopen , student.txt is closed from the read mode and then all the contents of the
file is truncated .
• And the student.txt is opened in write mode , with this our file is ready to receive the
updated data.
• Below that ,we then use fprint to write formatted output to the file with the help of loop.
• PARAMETERS CAN BE STUDENT STRUCTURE AND COUNT.
•
• Initialize count , found as 0 . make an array of target to store our target name .
• First , you will read all the contents of the file into memory using fscanf and
simultaneously counting . with this , all contents of out file is stored into the respective
arrays of the structure , in one way , our data is loaded from the file into the array and
stored.
• With this , now comes the area of the target which needs to be deleted . once inputted .
RUN the for loop which runs till count . use strcmp with if condition which specifies to
return 0 if the student[i].name is equals to name of the target.
• Once found , keep found as 1 . in update records , we used to keep found as 1 after
detecting and making the user to write new updated record.
• Now with this , you have to run the j loop which starts with I and runs till count – 1 .
• This ensures that the deleted record is overwritten by the record which is written above
it .
• Once the for loop is down , decrement the count outside the loop and then break from
the I loop .
• In the end , if (found) . use freopen to open the file in write mode and delete all the
previous data and to keep the file ready for the updated record.
• Then run for loop from 0 till count and then use fprintf to write the formatted data back
to file
• In the end , close the file.
• When using freopen , you need to have a temporary array like 1d array to store the team
details .
•
• https://github.com/MujtabaChohan190/C-
Programs/blob/dbb7ed567f2b626ae6a0ee615e47b46f4da15adc/file_handling/Practice
/Team_mathes.c
•
•
• We made highestWinsTeam and other objects with structures . we initialized it to 0
•
ANOTHER QUES :
https://github.com/MujtabaChohan190/C-
Programs/blob/dbb7ed567f2b626ae6a0ee615e47b46f4da15adc/file_handling/Practice/Studen
t_file.c
ANOTHER QUES:
https://github.com/MujtabaChohan190/C-
Programs/blob/0e9980ba4aa91f20d7107ff88ebb4dc51db4c48a/file_handling/Practice/Player_
record.c
DYNAMIC MEMORY ALLOCATION:
• Dynamic memory allocation in C is a concept that allows you to allocate memory during
runtime rather than at compile time.
• This is essential when you don’t know the size of the data your program will process in
advance. It is particularly useful for handling data whose size may vary, such as user
input or data read from a file.
POINTERS RECAP:
•
•
•
•
•
•
•
•
•
C MALLOC():
• When you use malloc, the operating system allocates a block of memory of the
specified size.
• However, it does not clear or initialize this memory.
• The contents of this memory block are whatever random binary data was stored there
before it was assigned to your program.
1. Efficiency: Initializing memory (e.g., setting all bytes to zero) takes time. By not doing it,
malloc performs faster.
2. Flexibility: Some programs don’t need the memory to be initialized because they
immediately overwrite it with new data.
EXIT(0) EXPLANATION:
EXPLANATION
C CALLOC() :
•
•
•
• CALLOC ( N , ELEMENT SIZE) MAKES N BLOCKS OF ELEMENT SIZE , AND DYNAMICALLY
ALLOCATE IT TO PTR .
• CALLOC(5, SIZEOF(INT) ..MAKES 5 SEPARATE BLOCKS OF 4 BYTES AND ALLOCATE IT
TO PTR.
•
• WHEREAS . MALLOC(BYTE SIZE) / MALLOC ( 5 * SIZEOF(INT)) .. HERE ALLOCATES A
LARGE BLOCK OF 20 BYTES MEMORY BLOCK AND THIS BLOCK IS DYNAMICALLY
ALLOCATED TO PTR.
•
•
•
•
Free():
• When a program dynamically allocates memory using functions like malloc, calloc, or
realloc, the memory remains allocated to the program until it explicitly frees it using the
free function. If the program doesn't free this memory after it's no longer needed, it
causes a memory leak.
•
• The free function releases the memory previously allocated by malloc, calloc, or
realloc. Once freed, the memory becomes available for the system or the program to
reuse.
•
•
• Here, the allocated memory is lost after the program ends, and the operating system
must reclaim it. In long-running programs, this leads to problems.
•
• OS CLAIMS MEAN
•
•
• IN SHORT , IF YOU DON’T FREE THE MEMORY AFTER DYNAMICALLY ALLOCATING THE
MEMORY THEN SHORT LIVED PROGRAM AND LONG RUNNING PROGRM CAN HAVE
THEIR RESPECTIVE DAMAGE.
•
REALLOC():
•
•
•
•
•
•
•
•
•
DANGLING POINTERS:
•
•
•
• #include<stdlib.h> is required .
•
•
•
•
•
• When a pointer is not containing any memory address , then it’s a good practise to
initialize a pointer as null .
•
Next ,we input the values , output the values and in the end , we just free allocated memory
using the pointer that holds the starting address of the allocated memory block.
Each row column
First free the memory of each row column by traversing through each row as they indicate the
starting address of columns , then free each row by passing the first element\array which
corresponds to first row.
3D ARRAY:
3D ARRAY MEMORY ALLOCATION:
DMA AND POINTERS PRACTISE:
Q2-
• In matrix multiplication , we will have 2 matrix and one resultant matrix .
• First matrix will have rows and columns as user wants , the second matrix would
contain the rows equivalent to first matrix columns .
• The number of columns in the first matrix (mat1) must be equal to the number of
rows in the second matrix (mat2) for the multiplication to be valid.
• In matrix multiplication, if you have two matrices:
•
• The resultant matrix would contain the rows of first matrix as its rows and columns of
second matrix as its column.
•
• Multiplication of matrices is done in the way that each row elements multiply with each
column .
• For eg : first row 1 all elements would multiply with column 1 all elements . then , row 2
all elements would be multiplied with column 1 all element up and down ,
• Then , rows 1 mujltiply with column 2 and row and row 2 multiply with column 2.
•
•
•
•
•
•
Q3-
•
Q4-
Q-
https://github.com/MujtabaChohan190/C-
Programs/blob/d0dd3e4271ece2837871e314bdb0428442600c09/Dynamic%20Memory%20All
ocation/Square_matrix.c
0
Q- Question 2
https://github.com/MujtabaChohan190/C-
Programs/blob/5ed8c420adc7629c6688a8fb10048e9047cbf651/Dynamic%20Memory%20Allo
cation/Resizing_insertion.c
PROJECT NOTES:
•
•
•
•
•
•
•
•
•
•
•
• FSCANF READS DATA FROM THE FILE IN A LOOP UNTIL IT REACHES EOF.
•
•
•
•
•
•
•
•
• If you want to scanf string . its format is :
FPUTS VS FPRINTF:
‘
GETCHAR AND FGETS INPUT HANDLING:
Kionke getchar /n daal de tha hai doosre line pai to hum phir us line pai name likhte hai to jab
fgets read karta hai us line ko to wo pehle hi word pai /n dekhleta hai , fgets stops upon
encountering /n . therefore , name string would be empty.
Each element of members array is a structure having different member attributes.
DIFFERENCE BETWEEN PRINTF AND FPRINTF:
If in case , which is obviously not recommended to give the view of members in file , but even
then if we had to , then we could do like this
ASSIGNMENT QUERIES:
Date of joining[0] returns an integer , so we need to use & before &emp → dateofjoining[0] to
give scanf the address of where to store the first date.
In employee name , we didn’t need & because when we write emp→ employeename .
employeename is the array and when we write it , it automatically provides us the address of
the first element and hence the whole array , so no need of &.
MACRO FUNCTIONS: