PC Exam
PC Exam
PC Exam
Fundamentals
a. Properties and definitions
An algorithm is a strictly defined finite sequence of well-defined statements that
provides the solution to a problem or to a specific class of problems for any acceptable
set of input values. In other words, an algorithm is a step-by-step procedure to solve a
given problem. An algorithm must satisfy the following properties:
- Input: The algorithm must have input valuesform a specified set.
- Output: The algorithm must produce the output valuesform a specified
set of input values. The output values are the solution to a problem.
- Finitness: For any input, the algorithm must terminate after a finite
number of steps.
- Definiteness: All steps of the algorithm must be precisely defined.
- Effectiveness: It must be possible to perform each step of the algorithm
correctly and in a finite amount of time. That is, its steps must be basic
enough so that, for example, someone using a pencil and a paper could
carry them out exactly, and in a finite amount of time. It is enough that
each step is definite, but it must also be feasible.
b. Methods of description
The main parts of an algorithm description are
Pictures are often the clearest way to explain data structures, particularly when pointers
are required. Whenever a picture is used, it should be a numbered, captioned figure. Figures
should be (nearly) comprehensible without the accompanying text. Make sure the caption
explains what the figure means. Something like ``Figure 3. Step 2 of the algorithm.'' is nearly
useless. A better caption might be ``Figure 3. Swapping out-of-order data elements pointed to
by i and j.''
Instead of flowcharts, most algorithms are now described using pseudo-code. The
pseudo-code syntax can be based on any structured language (Algol, Pascal, C, Ada, ...), but
should be readable by someone familiar only with a different language. Tests and statements
are not written in full detail, instead the intent of the statement or test is given. For example,
pseudo-code for finding the minimum of an array might look like:
Pseudo-code should be properly indented and either displayed like the example above,
or put into a figure with a figure number and caption.
c. Example: logic diagram of the Euclid algorithm for CMMDC of two numbers
b. Main function ()
Every C-programs needs to have the main function. Each main function contains 2 parts.
A declaration part and an Execution part. The declaration part is the part where all the variables
are declared. The execution part begins with the curly brackets and ends with the curly close
bracket. Both the declaration and execution part are inside the curly braces.
int main(void)
{
int a=10;
printf(" %d", a);
return 0;
}
c. User functions
A function is a block of code that performs a specific task. C allows us to define functions
according to a specific need. These functions are known as user-defined. For example:
printf(…) is a function.
d. Execution stages
The C program follows many steps in execution. To understand the flow of C program
well, let us see a simple program first.
#include <stdio.h>
int main(){
printf("Hello C Language");
return 0;
}
1) C program (source code) is sent to the preprocessor first. The preprocessor is
responsible to convert preprocessor directives into their respective values. The
preprocessor generates an expanded source code.
2) Expanded source code is sent to the compiler which compiles the code and
converts it into assembly code.
3) The assembly code is sent to the assembler which assembles the code and
converts it into object code. Now a simple.obj file is generated.
4) The object code is sent to linker which links it to the library such as header files.
Then it is converted into executable code. A simple.exe file is generated.
5) The executable code is sent to the loader which loads it into memory and then
it is executed. After execution, output is sent to the console.
3. Data input in C
a. Scanf () function
In C programming, scanf() is one of the commonly used function to take input from the
user. The scanf() function reads formatted input from the standard input such as keyboards.
#include <stdio.h>
int main()
{
int testInteger;
printf("Enter an integer: ");
scanf("%d", &testInteger);
printf("Number = %d",testInteger);
return 0; }
b. Format specifiers
The format specifier is used during input and output. It is a way to tell the compiler what
type of data is in a variable during taking input using scanf() or printing using printf().
Some examples are %c, %d, %f, etc.
printf():
decimal integer : %d
Integer may be octal or in hexadecimal : %i
Double floating-point number : %lf
String input : %s
Character input : %c
An unsigned integer: %u
Long long int: %lld
Octal integer without leading zero: %o
Hexadecimal integer without 0x before the number: %x
c. Alternative functions
To convert the input, there are a variety of functions that you can use:
● strtoll, to convert a string into an integer
● strtof/d/ld, to convert a string into a floating-point number
● sscanf, which is not as bad as simply using scanf, although it does
have most of the downfalls mentioned below.
● There are no good ways to parse a delimiter-separated input in plain
ANSI C. Either use strtok_r from POSIX or strtok, which is not
thread-safe. You could also roll your own thread-safe variant using
strcspn and strspn, as strtok_r doesn't involve any special OS support.
● It may be overkill, but you can use lexers and parsers (flex and bison
being the most common examples).
d. standard input / output buffer memory control
Temporary storage area is called a buffer.
All standard input output devices are containing input output buffers.
In implementation when we are passing more than the required number of values as an
input then the rest of all values will automatically hold in the standard input buffer, this
buffer data will automatically pass to next input functionality if it exists.
flushall()
it is a predefined function which is declared in stdio.h. by using flushall we can remove
the data from standard input output buffer.
fflush()
it is a predefined function in "stdio.h" header file used to flush or clear either input or
output buffer memory.
fflush(stdin)
it is used to clear the input buffer memory. It is recommended to use before writing
scanf statement.
fflush(stdout)
it is used to clear the output buffer memory. It is recommended to use before printf
statement.
4. Display of data in C
a. The printf () function
In C programming, printf() is one of the main output functions. The function sends
formatted output to the screen. For example,
#include <stdio.h>
int main()
{
// Displays the string inside quotations
printf("C Programming");
return 0;
}
Output: C Programming
I) All valid C programs must contain the main() function. The code
execution begins from the start of the main() function.
II) The printf() is a library function to send formatted output to the
screen. The function prints the string inside quotations.
III) To use printf() in our program, we need to include stdio.h header
file using the #include <stdio.h> statement.
IV) The return 0; statement inside the main() function is the "Exit
status" of the program. It's optional.
b. Format specifiers
printf():
Step 1 - Include all the header files which are used in the program. And declare all the user
defined functions.
Step 2 - Define a 'Node' structure with two members data and next.
Step 3 - Define two Node pointers 'front' and 'rear' and set both to NULL.
Step 4 - Implement the main method by displaying Menu of list of operations and make suitable
function calls in the main method to perform user selected operation.
o Step 3 − If the stack is not empty, accesses the data element at which
top is pointing.
o Step 4 – Point a variable I to the node and actualize the Top to point
to the previous node.
o Step 5 – Point the *next pointer of node I to null and delete node I
from the memory.
*…*
*…*
Theory:
a. Numeric types
Numerical integer types: They can store a whole number value, such as 7 or 1024. They exist in a variety of sizes, and
can either be signed or unsigned, depending on whether they support negative values or not.
Floating-point types: They can represent real values, such as 3.14 or 0.01, with different levels of precision,
depending on which of the three floating-point types is used.
c. Variables
Variables are memory locations of predefined sizes that can store data of a certain type and are identified by name. The variable
name is an identifier (word) consisting of one or more letters and numbers, the first symbol being a letter. The variable name can
also contain the underscore symbol.
d. Variables initialization
When the variables are declared, they have an undetermined value until they are assigned a value for the first time. But it is
possible for a variable to have a specific value from the moment it is declared. This is called the initialization of the variable.
In C++, there are three ways to initialize variables. They are all equivalent and are reminiscent of the evolution of the language
over the years:
1. The first one, known as c-like initialization (because it is inherited from the C language), consists of appending an equal sign
followed by the value to which the variable is initialized:
type identifier = initial_value;
For example, to declare a variable of type int called x and initialize it to a value of zero from the same moment it is declared, we
can write:
int x = 0;
2. A second method, known as constructor initialization (introduced by the C++ language), encloses the initial value between
parentheses (()):
type identifier (initial_value);
For example:
int x (0);
3. Finally, a third method, known as uniform initialization, similar to the above, but using curly braces ({}) instead of parentheses
(this was introduced by the revision of the C++ standard, in 2011):
type identifier {initial_value};
For example:
int x {0};
6. Selection statements
a. The if statement
The if keyword is used to execute a statement or block, if, and only if, a condition is fulfilled. Its syntax is:
if (condition) statement
Here, condition is the expression that is being evaluated. If this condition is true, statement is executed. If it is false, statement is
not executed (it is simply ignored), and the program continues right after the entire selection statement.
b. The operation?
The conditional operator evaluates an expression, returning one value if that expression evaluates to true, and a different one if
the expression evaluates as false. Its syntax is:
condition ? result1 : result2
If condition is true, the entire expression evaluates to result1, and otherwise to result2.
c. Switch () statement
Its purpose is to check for a value among a number of possible constant expressions. It is something similar to concatenating if-
else statements, but limited to constant expressions. Its most typical syntax is:
switch (expression)
{
case constant1:
group-of-statements-1;
break;
case constant2:
group-of-statements-2;
break;
.
default:
default-group-of-statements
}
If expression was not equal to constant1, it is then checked against constant2. If it is equal to this, it executes group-of-
statements-2 until a break is found, when it jumps to the end of the switch.
Finally, if the value of expression did not match any of the previously specified constants (there may be any number of these), the
program executes the statements included after the default: label, if it exists (since it is optional).
Break statements are needed after each group of statements for a particular label. If break is not included, all statements following
the case (including those under any other labels) are also executed, until the end of the switch block or a jump statement (such
as break) is reached.
7. Loops
A common type of program loop is one that is controlled by an integer that counts up from a initial value to an upper limit. Such
a loop is called a counting loop. The integer is called a loop control variable. Loops are implemented with the conditional branch,
jump, and conditional set instructions.
For
1. initialization is executed. Generally, this declares a counter variable, and sets it to some initial value. This is executed a
single time, at the beginning of the loop.
2. condition is checked. If it is true, the loop continues; otherwise, the loop ends, and statement is skipped, going directly
to step 5.
3. statement is executed. As usual, it can be either a single statement or a block enclosed in curly braces { }.
4. increase is executed, and the loop gets back to step 2.
5. the loop ends: execution continues by the next statement after it.
The three fields in a for-loop are optional. They can be left empty, but in all cases the semicolon signs between them are required.
For example, for (;n<10;) is a loop without initialization or increase (equivalent to a while-loop); and for (;n<10;++n) is a loop
with increase, but no initialization (maybe because the variable was already initialized before the loop). A loop with
no condition is equivalent to a loop with true as condition (i.e., an infinite loop)
Condition-controlled loop - the loop that repeats the execution of a sequence of instructions as long as a condition remains true.
The condition is described by a Boolean or arithmetic test expression.
1. While
A thing to consider with while-loops is that the loop should end at some point, and thus the statement shall alter values checked
in the condition in some way, so as to force it to become false at some point. Otherwise, the loop will continue looping forever.
Note that the complexity of this loop is trivial for a computer, and so the whole countdown is performed instantly, without any
practical delay between elements of the count
2. Do… While
The do-while loop is usually preferred over a while-loop when the statement needs to be executed at least once, such as when the
condition that is checked to end of the loop is determined within the loop statement itself.
c. Nested loops
C programming allows to use one loop inside another loop.
while(condition) {
while(condition) {
statement(s);
}
statement(s); // you can put more statements.
}
do {
statement(s); // you can put more statements.
do {
statement(s);
} while( condition );
} while( condition );
1. Break
When the break statement is encountered inside a loop, the loop is immediately terminated and program control
resumes at the next statement following the loop.
2.Continue
The continue instruction causes the program to skip the rest of the loop in the present iteration as if the end of the statement block
would have been reached, causing it to jump to the following iteration.
8. User functions in C
a. Description / declaration
A function declaration tells the compiler about a function's name, return type, and parameters. A function definition provides
the actual body of the function.
Defining a Function
The general form of a C++ function definition is as follows −
Return Type − A function may return a value. The return_type is the data type of the value the function returns.
Some functions perform the desired operations without returning a value. In this case, the return_type is the
keyword void.
Function Name − This is the actual name of the function. The function name and the parameter list together constitute
the function signature.
Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This
value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the
parameters of a function. Parameters are optional; that is, a function may contain no parameters.
Function Body − The function body contains a collection of statements that define what the function does.
Function Declarations
A function declaration tells the compiler about a function name and how to call the function. The actual body of the function
can be defined separately.
b. Function parameters
Parameters − A parameter is like a placeholder. When a function is invoked, you pass a value to the parameter. This
value is referred to as actual parameter or argument. The parameter list refers to the type, order, and number of the
parameters of a function. Parameters are optional; that is, a function may contain no parameters.
c. Local variables
A variable defined inside a function (defined inside function body between braces) is called a local variable or automatic
variable.
Its scope is only limited to the function where it is defined. In simple terms, local variable exists and can be accessed only inside
a function.
The life of a local variable ends (It is destroyed) when the function exits.
d. Returning results
When you write a user-defined function, you get to determine whether your function will return a value back to the caller or not.
To return a value back to the caller, two things are needed.
First, your function has to indicate what type of value will be returned. This is done by setting the function’s return type, which
is the type that is defined before the function’s name. In the example above, function getValueFromUser has a return type
of void, and function main has a return type of int. Note that this doesn’t determine what specific value is returned -- only the
type of the value.
Second, inside the function that will return a value, we use a return statement to indicate the specific value being returned to the
caller. The specific value returned from a function is called the return value. When the return statement is executed, the return
value is copied from the function back to the caller. This process is called return by value.
Practice:
With +operator
#include <bits/stdc++.h>
int main()
{
string s1,s2; //two string
cin>>s1>>s2;
cout<<result;
return 0;
Without +operator:
START
End Loop
STOP
#include <iostream>
int main()
int i, j;
str1[i] = str2[j];
str1[i] = '\0';
cout<<str1;
return 0;
The idea is to run a loop from start to end and for every index in the given string check whether the sub-string can be formed
from that index. This can be done by running a nested loop traversing the given string and in that loop run another loop checking
for sub-string from every index.
For example, consider there to be a string of length N and a substring of length M. Then run a nested loop, where the outer loop
runs from 0 to (N-M) and the inner loop from 0 to M. For very index check if the sub-string traversed by the inner loop is the
given sub-string or not.
#include <bits/stdc++.h>
using namespace std;
int M = s1.length();
int N = s2.length();
int j;
pattern match */
if (s2[i + j] != s1[j])
break;
if (j == M)
return i;
return -1;
/* Driver code */
int main()
string s1 = "for";
string s2 = "geeksforgeeks";
if (res == -1)
else
return 0;
}
10. Describe the operation of two strings comparing.
11. Describe the operation of copying a part of the string S into string Q (given length, and
start position).
12. Describe the operation of removing a part of the string (given length, and start position)
13. Describe the operation of insertion of the string S into string Q (in a given position)
Theory:
9. Structures in C
struct Point
int x, y;
Or
struct Point
int x, y;
};
int main()
Structure members cannot be initialized with declaration. For example the following C
program fails in compilation.
struct Point
};
b. Arrays of structures
struct Point
{
int x, y;
};
int main()
{
// Create an array of structures
struct Point arr[10];
}
struct Point
{
int x, y;
};
int main()
{
struct Point P1;
A linked list is an ordered collection of nodes, each of which contains some data,
connected using pointers. Each node is actually a struct variable, which contains an ID,
the additional data of the object and a pointer variable that points to the next node. For
example, the next structure is defined for a list of cars in a car lot.
struct carType
{
int vehicleID;
char make[20];
char model[20];
int year;
int mileage;
double cost;
Car *next; // ptr to next car in list
};
See more on point 12.
Queue is a FIFO (First-In, First-Out) list, a list-like structure that provides restricted
access to its elements: elements may only be inserted at the back and removed from the
front. Similarly to stacks, queues are less flexible than lists.
c. operations on queue
Last (new)
First
element
element
1. Allocate a new node and hold the pointer to it in a variable. Return from the insert
function now signaling an error if the new node cannot be allocated.
1. Allocate a new node and hold the pointer to it in a variable. Return from the insert
function now signaling an error if the new node cannot be allocated.
2. Store the information in the newly created node.
3. Make the newly created node point to null.
4. Make the old rear node point the newly created node.
5. Make rear point to the newly created node.
Checking for an empty queue checks to see if either the front or the rear points to null.
Checking for a full queue should always return false.
Delete an element:
1. If the queue is empty, return a flag indicating that removal could not be performed.
The Lee algorithm is one possible solution for maze routing problems. It always gives an
optimal solution, if one exists, but is slow and requires large memory for dense layout.
3. Remove the position you are on from the queue and continue to the next element.
Using the example of a maze solving algorithm, a depth-first approach will try every
possible path one by one until it either reaches a dead end or the finish and returns the
result. However, the path it returns might not be the most efficient, but simply the first
complete path to the finish that the algorithm was able to find.
A breadth-first search will instead go out to each open space adjacent to the starting
point, then look for other possible open spaces. It will keep doing this, going out layer by
layer and trying each possible path in tandem, until it finds the finish point. Since you're
trying each path at the same time, you can be sure that the first complete path from
start to finish is also the shortest.
C++ has the queue already implemented in the <queue> library, but if you are using
something else you are welcome to implement your own version of queue.
C++ code:
int dl[] = {-1, 0, 1, 0}; // these arrays will help you travel in the 4 directions more easily
int dc[] = {0, 1, 0, -1};
void lee()
{
int x, y, xx, yy;
while(!X.empty()) // while there are still positions in the queue
{
x = X.front(); // set the current position
y = Y.front();
for(int i = 0; i < 4; i++)
{
xx = x + dl[i]; // travel in an adiacent cell from the current position
yy = y + dc[i];
if('position is valid') //here you should insert whatever conditions should apply for
your position (xx, yy)
{
X.push(xx); // add the position to the queue
Y.push(yy);
mat[xx][yy] = -1; // you usually mark that you have been to this position in the
matrix
}
X.pop(); // eliminate the first position, as you have no more use for it
Y.pop();
}
}
Stack is a LIFO (Last-In, First-Out) list, a list-like structure in which elements may be
inserted or removed from only one end (last-in, first-out). Stacks are less flexible than
lists, but are easier to implement, and more efficient (for those operations they can do).
Given a stack, the accessible element of the stack is called the top element.
Elements are not said to be inserted; they are pushed onto the stack.
When an element (the last one) is removed, an element is said to be popped from the
stack.
b. Stack structure
c. Stack operations
Given two numbers N1 and N2 represented by two stacks, such that their most
significant digits are present at the bottom of the stack, the task is to calculate and
return the sum of the two numbers in the form of a stack.
2. Initialize variables rem and sum to store the carry generated and the sum of top
elements respectively.
3. Keep popping the top elements of both the stacks and push the sum % 10 to res and
update rem as sum/10.
4. Repeat the above step until the stacks are empty. If rem is greater than 0,
insert rem into the stack.
5. Reverse the res stack so that the most significant digit present at the bottom of
the res stack.
Example:
A linked list is an ordered collection of nodes, each of which contains some data,
connected using pointers.
A linked list can only be accessed sequentially. To find the 5th element, for instance, you
must start from the head and follow the links through four other nodes.
Every node has an ID. When adding a new node in the list, we need to find firstly the
idea of the next node from the one we want to add and do the operation. This way
the list remains ordered.
When deleting the node, you search it by it’s ID and then extract it from the least,
before destroying it, otherwise you may lose half of the list.
Unordered List:
Doesn’t differ any much from what a queue or a stack is. The nodes are added either
to the front or to the back of the list.
When deleted, you can either erase the first node, the last one or find the one with
the information you want to delete from the list, extract it and erase it from the
memory.
Properties:
Each element in the list points to the next element. That’s how they hold together.
Imagine a bunch of children, which have names and are holding with the left hand the
right shoulder of the next child. The information are their names, the pointer to the next
child are their left hand. If you break one of the connections, you lose al the nodes (kids)
after the broken connection. For example, if you have the list “ABCDEFG” and you break
the connection between “C” and “D”, you lose the sublist “DEFG”.
c. List operations
Step 1: Create the new node, pointing to null, and insert the information in it.
Step 2: Find in the list the node A before which you want to add the new node, and
the node B, which is after A. Generate an error if you don’t find the points.
Step 3: Point the *next pointer of your new node to B.
Step 4: Point the *next pointer of A to your new node.
Step 1: Create the new node, pointing to null, and insert the information in it.
Step 2: Point the *next pointer of your new node to the top node.
Step 3: Actualize the top node, which is your new variable.
Adding a node at the bottom of the list:
Step 1: Create the new node, pointing to null, and insert the information in it.
Step 2: Find the bottom node, knowing that it’s pointer *next points to null.
Step 3: Point the *next pointer of the bottom node to your new node.
Erasing a node between 2 nodes:
Step 1: Find in the list the node before the one with the information you want to
erase. If you can’t find it, generate an error message.
Step 2: Point the *next pointer of the node to the *next pointer of the next node of
the one you want to delete.
Step 3: Point the *next pointer of the node you want to delete to null.
Step 4: Erase the node from the memory.
Couldn’t find anything on the internet. But, the operation is simple. Read the elements
of the string, transform them to nodes and add to the list in ordered form (only if the
order of the character in the string does not actually matter, otherwise, just add the
nodes to the top), search through the list by ID and that’s all.
Practice:
{
int temp = 0;
for (int i = 0; i < str.length(); i++) {
// Since ASCII value of character from '0'
// to '9' are contiguous. So if we subtract
// '0' from ASCII value of a digit, we get
// the integer value of the digit.
temp = temp * 10 + (str[i] - '0');
// ASCII of number x – ASCII of 0 = number x
}
return temp;
}
Step 2: a mod b = R
Step 5: GCD = b
Step 6: Finish
function gcd(a, b) {
var R;
while ((a % b) > 0) {
R = a % b;
a = b;
b = R;
}
return b;
}
17. Algorithm for checking whether a number is prime or composite
if (n == 0 || n == 1 || n == 2) {
isPrime = false;
}
else {
for (i = 2; i <= n / 2; ++i) {
if (n % i == 0) {
isPrime = false;
break;
}
}
}
if (isPrime)
cout << n << " is a prime number";
else
cout << n << " is not a prime number";
float sqRoot(float N) {
x = (x + y)/2;
y = N/x;
}
return x;
Let d be the digit and N the number. d = N mod 10. N = N div 10. Write d, repeat until N=0.
while (number > 0)
{
int digit = number % 10;
number /= 10;
//print digit
}
1. X is the number in base 10, b is the new base, i=0 and S is an empty string. While x>0
repeat steps 2 and 3;
2. R is the reminder of X/b. Add to S the (R+’0’).
3. Increase i by one, divide X by b.
4. Result is 0. Iterative, form the last element of S down to the first one, multiply the result
to 10 and add the number from string to it. That’s the answer.
int From10toB (int number, int b)
String S;
while (x>0) {
rem=x % b;
S[i]=rem + ’0’;
i++;
x \= b;
};
int result=0;
return result;
Theory
13. Dynamic memory allocation in C. Functions for dynamic memory allocation:
a. calloc ()
b. malloc ()
c. realloc ()
d. free ()
Dynamic Memory Allocation is manual allocation and freeing of memory
according to your programming needs. Dynamic memory is managed and served with
pointers that point to the newly allocated memory space in an area which we call the
heap.
a) C malloc()
The name malloc stands for "memory allocation". It is a function which is used to
allocate a block of memory dynamically. It reserves memory space of specified size and
returns the null pointer pointing to the memory location. The pointer returned is usually
of type void. It means that we can assign C malloc() function to any pointer
Syntax of malloc()
ptr = (cast-type*) malloc(byte-size).
Here, ptr is pointer of cast-type.
The malloc() function returns a pointer to an area of memory with size of byte size. If
the space is insufficient, allocation fails and returns NULL pointer.
b) C Calloc()
The C calloc() function stands for contiguous allocation. This function is used to allocate
multiple blocks of memory. It is a dynamic memory allocation function which is used to
allocate the memory to complex data structures such as arrays and structures.
Malloc() function is used to allocate a single block of memory space while the calloc() in C
is used to allocate multiple blocks of memory space. Each block allocated by the calloc()
function is of the same size and also calloc() sets all bytes to zero.
Syntax of calloc()
ptr = (cast-type*) calloc (n, element-size);
d) C free()
Dynamically allocated memory created with either calloc() or malloc() doesn't get freed
on its own. We must explicitly use free() to release the space.
Syntax of free()
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.
c) C realloc()
Using the C realloc() function, we can add more memory size to already allocated
memory. It expands the current block while leaving the original content as it is. Realloc() in
C stands for reallocation of memory.
Realloc() can also be used to reduce the size of the previously allocated memory.
Syntax of realloc()
ptr = realloc(ptr, newsize);
Here, ptr is reallocated with size of newsize.
14. Recursion in C:
a. The notion of recursive approach
b. The structure of the recursive function
d. Example. Recursive fibonacci numbers calculation / analysis
a) The process in which a function calls itself directly or indirectly is called recursion
and the corresponding function is called a recursive function. Using recursive
algorithm, certain problems can be solved quite easily. Recursion cannot be applied to
all the problems, but it is more useful for the tasks that can be defined in terms of
similar subtasks. For example, recursion may be applied to sorting, searching, and
traversal problems.
b) The recursive functions should be used very carefully because, when a function
called by itself it enters into the infinite loop. And when a function enters into the
infinite loop, the function execution never gets completed. We should define the
condition to exit from the function call so that the recursive function gets terminated.
When a function is called by itself, the first call remains under execution till the last call
gets invoked. Every time when a function call is invoked, the function returns the
execution control to the previous function call.
Example: Sum of Natural Numbers Using Recursion
#include <stdio.h>
int sum(int n);
int main() {
int number, result;
result = sum(number);
int sum(int n) {
if (n != 0)
// sum() function calls itself
return n + sum(n-1);
else
return n;
}
Output
Initially, the sum() is called from the main() function with number passed as an argument.
Suppose, the value of n inside sum() is 3 initially. During the next function call, 2 is passed
to the sum() function. This process continues until n is equal to 0.
When n is equal to 0, the if condition fails and the else part is executed returning the sum
of integers ultimately to the main() function.
c) Fibonacci series is a series of numbers formed by the addition of the preceding two
numbers in the series. The first two terms are zero and one respectively. The terms after
this are generated by simply adding the previous two terms.
The base case for finding factorial
fibonacci(0) = 0
fibonacci(1) = 1
General case for finding factorial
fibonacci(n) = fibonacci(n-1) + fibonacci(n-2)
Algorithm:- fibonacci(n)
if (n<=1)
then return n
else
return fibonacci(n-1) + fibonacci(n-2)
a) A pointer is a variable that stores the address of another variable. Unlike other
variables that hold values of a certain type, pointer holds the address of a variable. For
example, an integer variable holds (or you can say stores) an integer value, however an
integer pointer holds the address of an integer variable.
The general form of a pointer variable declaration is:
type *var-name;
Here, type is the pointer's base type; it must be a valid C data type and var-name is the
name of the pointer variable. When asterisk (*) is used in this manner in a definition, it
indicates that the variable being defined is a pointer. The asterisk notation used to
declare pointer variables does not distribute to all variable names in a declaration. Each
pointer must be declared with the * prefixed to the name.
Pointers should be initialized when they’re defined, or they can be assigned a value. A
pointer may be initialized to NULL, 0 or an address. A pointer with the value NULL
points to nothing. NULL is a symbolic constant defined in the <stdio.h>.
Initializing a pointer to 0 is equivalent to initializing a pointer to NULL, but NULL is
preferred. When 0 is assigned, it’s first converted to a pointer of the appropriate type.
The value 0 is the only integer value that can be assigned directly to a pointer variable.
b) The &, or address operator, is a unary operator that returns the address of its operand.
After declaration of a pointer variable, we need to initialize the pointer with the valid
memory address; to get the memory address of a variable Address Of" (&) Operator is
used.
c) The interaction of pointers and arrays can be confusing but here are two fundamental
statements about it:
1) A variable declared as an array of some type acts as a pointer to that type. When used
by itself, it points to the first element of the array.
2) A pointer can be indexed like an array name.
The first case often is seen to occur when an array is passed as an argument to a
function. The function declares the parameter as a pointer, but the actual argument may
be the name of an array.
The second case often occurs when accessing dynamically allocated memory.
Pointers and array names can pretty much be used interchangeably; however, there are
exceptions. You cannot assign a new pointer value to an array name. The array name
will always point to the first element of the array.
It is also valid for a function to return a pointer to one of the array elements from an
array passed as an argument to a function. A function should never return a pointer to a
local variable, even though the compiler will probably not complain. When declaring
parameters to functions, declaring an array variable without a size is equivalent to
declaring a pointer. Often this is done to emphasize the fact that the pointer variable will
be used in a manner equivalent to an array.
A void pointer is a pointer that has no associated data type with it. A void pointer can hold address
of any type and can be typcasted to any type.
int a = 10;
char b = 'x';
void *p = &a; // void pointer holds address of int 'a'
p = &b; // void pointer holds address of char 'b'
A void pointer does not have any data type associated with it.It can store address of any type of
variable.
If any pointer is pointing to the memory address of any variable but after some time that variable
has deleted from the memory location while pointer is still pointing such memory location then such
pointer is called as Dangling pointer.
In case, if you don’t have address to be assigned to pointer then you can simply use
NULL.
Pointer which is initialized with NULL value is considered as NULL pointer.
(4) Near pointer :
A pointer variable which can handle only one segment of 1MB data. It is called near
pointer
Near pointer will handles only 1 segment i.e data segment only
(5) Far pointer :
Which pointer variable can handle any segment of 1MB data, it is called far pointer.
Unintialized pointer variable or which pointer not initialized with any variable
address. It is called wild pointer
Wild pointer is also called Bad pointer, because without assigning any variable
address , it points to the memory location.
struct name {
member1;
member2;
.
.
};
int main()
{
struct name *ptr, Harry;
}
struct my_structure {
char name[20];
int number;
int rank;
};
int main()
ptr = &variable;
return 0;
c) int arr[3][4] = {
{11,22,33,44},
{55,66,77,88},
{11,66,77,44}
};
The above 2-D array can be visualized as following:
The following figure shows how a 2-D array is stored in the memory:
A 2-D array is actually a 1-D array in which each element is itself a 1-D array. So arr is an
array of 3 elements where each element is a 1-D array of 4 integers.
In the above example, the type or base type of arr is a pointer to an array of 4 integers.
Since pointer arithmetic is performed relative to the base size of the pointer. In the case
of arr, if arr points to address 2000 then arr + 1 points to address 2016 (i.e 2000 + 4*4).
We know that the name of the array is a constant pointer that points to the 0th element of
the array. In the case of a 2-D array, 0th element is a 1-D array. So the name of the array in
case of a 2-D array represents a pointer to the 0th 1-D array. Therefore in this case arr is a
pointer to an array of 4 elements. If the address of the 0th 1-D is 2000, then according to
pointer arithmetic (arr + 1) will represent the address 2016, similarly (arr + 2) will
represent the address 2032.
From the above discussion, we can conclude that:
arr points to 0th 1-D array.
(arr + 1) points to 1st 1-D array.
(arr + 2) points to 2nd 1-D array.
Here is an example :
int (*sum)(); //legal declaration of pointer to function
A function pointer can point to a specific function when it is assigned the name of that
function:
int sum(int, int);
s = sum;
return x+y;
int main( )
return 0;}
17. Operations in C.
a. Arithmetic operations
b. Relational operations
c. Logical operations
d. Priority of operations
a) Basic arithmetic operations include addition, subtraction, multiplication and
subtraction. They are performed on numerical data types like int, float and double.
Operator Description
+ Adds two operands.
== Equal to.
The precedence of <, <=, > and >= operators are same and they associate from left to
right. However, the precedence of == and != is lower than other relational operators and
they associate from left to right. The precedence of relational operators is lower than the
arithmetic operators.
c) Logical operators are used to evaluate two or more conditions. In General, Logical
operators are used to combine relational expressions, but they are not limited to just
relational expression you can use any kind of expression even constants. If the result of
the logical operator is true then 1 is returned otherwise 0 is returned.
Operator Description
&& Called Logical AND operator. If both the operands are non-zero,
then the condition becomes true.
|| Called Logical OR Operator. If any of the two operands is
non-zero, then the condition becomes true.
! Called Logical NOT Operator. It is used to reverse the logical
state of its operand. If a condition is true, then Logical NOT
operator will make it false.
d)
Precedenc Operator Description Associativity
e
1 ++ -- Suffix/postfix increment and decrement
() Function call
[] Array subscripting
. Structure and union member access Left-to-right
-> Structure and union member access through
pointer
(type) {list} Compound literal
2 ++ -- Suffix/postfix increment and decrement
+- Unary plus and minus
! ~ Logical NOT and bitwise NOT
(type) Cast
* Indirection (dereference) Right-to-left
& Address-of
sizeof Size-of
_Alignof Alignment requirement
Practice
22. Conversion of integer numbers in base b to base 10
Input number is given as string and output is an integer.
23. Determining the element of maximal value (of minimal value) in the array
1) Let maxE and minE be the variable to store the minimum and maximum element of
the array.
2) Initialise minE as INT_MAX and maxE as INT_MIN.
3) Traverse the given array arr[].
4) If the current element is smaller than minE, then update the minE as current element.
5) If the current element is greater than maxE, then update the maxE as current element.
6) Repeat the above two steps for the element in the array.
To find the maximum value, you initialize a placeholder called max with the value of the
first element in the array. Then you go through the array element by element. If any
element is greater than max you replace max with that element. Here is the pseudocode:
SET Max to array[0]
FOR i = 1 to array length - 1
IF array[i] > Max THEN
SET Max to array[i]
ENDIF
ENDFOR
PRINT Max
Bit operations in C
b. | or
If a=0 , b=0 , a|b=0 because above are false
If a=1 , b=0 , a|b=1 because a is true
If a=0 , b=1 , a|b=1 because b is true
If a=1 , b=1 , a|b=1 because above are true
c. ^ exclusive or , it means just 1 should be true
If a=0 , b=0 , a^b=0 because above are false
If a=1 , b=0 , a|b=1 because just one is true
If a=0 , b=1 , a|b=1 because just one is true
If a=1 , b=1 , a|b=0 because above are true
d. ~ complement, all 0 becomes 1 and 1 becomes 0
A=00111001
~A=11000110
Take a=10 , 10/2=5 r=0
5/2=2 r=1
2/2=1 r=0
1/2=0 r=1
A=01010
~A=10101
~a=-11
2) Bit movement operations
<< , >> shift operators , it moves all bits to the left or right and in empty cells put 0
A=60
a=00111100
a>>2 = 00001111=15
a<<2 = 11110000=240
3) Setting the value of bit k , it set the bit with number k to be equal with 1.
Lets take a=56
a=111000
if a has 6 bit => 0<=k<6
because we start to count with 0 from the right and k should be smaller then number of bits
let set the 2-nd bit 2 1 0
111000
if k=2 a=111100
if k=4 a=111000 because 4th bit has already set
4) Fast calculation 2k
The most efficient is the example with bit transformation
For example :
A124
124 -> (01111100)2
Now we take 2position of bit if this bit is equal with 1 and sum them .
(01111100)2 ->26+25+24+23+22
A124=A2^6 * A2^5 *A2^4 *A2^3 *A2^2
TEXT FILES
getc , fprintf and fscanf works similarly like scanf and printf but with files
3) Riding data from a text file
fscanf(….
4) Writing data in a text file
fprintf(….
3) Multidimensional arrays
Arrays can be unidimensional bidimensional and so on till k dimensional
a[ ]
a[ ] [ ]
…
4) Memory allocation models for arrays
For each element of array is allocated standard memory for its data type
For example
Integer 4 bite
Char 1 bite
Double 8 bite
1) Information is organized or classified data, which has some meaningful values for the receiver.
Information is the processed data on which decisions and actions are based
2) Digitalization of information
Digitization is the process of converting information into a digital. The result is the
representation of an object, image, sound, documents or signal by generating a series of
numbers that describe a discrete set of points or samples. The result is called digitalization of
information or, more specifically, a digital image , for the object, and digital form, for the signal.
In modern practice, the digitized data is in the form of binary numbers (binary code , 0 and 1
sequences ), which facilitate processing by digital computers and other operations, but, strictly
speaking, digitizing simply means the conversion of analog source material into a numerical
format; the decimal or any other number system that can be used instead.
3) Data is bit sequences that was or need to be processed by computer .
4) Binary codes A binary code represents text, computer processor instructions, or any other data
using a two-symbol system. The two-symbol system used is often "0" and "1" from
the binary number system. The binary code assigns a pattern of binary digits, also known as bits,
to each character, instruction, etc.
Practice:
Problem 29
for(int i=0;i<k;i++)
for(int j=0;j<n;j++) if (j==0){ m=a[j] ; a[j]=a[j+1];} else if (j==n-1) a[j]=m; else a[j]=a[j+1];
problem 30
bubble sort
int m;
for(int i=0;i<n-1;i++)
problem 31
selection sort
int m , n, k , z;
m=0;
z=a[n+1];
a[n+1]=a[m];
a[m]=z;
m=0;
n--;
Problem 32
Insertion sort
Int m;
m=a[i];
a[j]=m;
break ; }
problem 33
Determining the longest sequence of numbers equal to each other from an array
int m=0, k =0, j=0;
else
{ j=a[i];
If (m<k)m=k;
K=0;
Problem 34
else
{ j=a[i];
If (m<k)m=k;
K=0;
Problem 35
The number of “hills” from an array (The element A[i] is called “hill” if it’s bigger than
Int m=0;