Professional Documents
Culture Documents
Programming Lab Manual
Programming Lab Manual
Programming Fundamentals
CSC-103
Lab Manual
Name
Registration Number
Class
Instructor’s Name
Introduction
This Lab Manual is for CSC-103 Programming Fundamentals course. The labs
constitute 25 % of the total marks for this course.
During the labs students will work individually. You are required to complete the
‘Pre-Lab’ section of the lab before coming to the lab. You will be graded for this
and the ‘In-Lab’ tasks during the in-lab viva. You will complete the ‘Post-Lab’
section of each lab before coming to the next week’s lab.
You are not allowed to wander in the lab or consult other groups when performing
experiments. Similarly the lab reports must contain original efforts. CUI has a
zero tolerance anti-plagiarism policy.
Apart from these weekly labs you will complete three mini projects. One mini
project will count towards theory assignments. The other two mini-projects will
count towards your Lab Terminal score. The grading policy is already discussed in
the Course Description File.
Acknowledgement
The labs for CSC-103 Programming Fundamentals were designed by Dr. Omar
Ahmad. The manuals were prepared by Mr. Dilshad Sabir. The first version was
completed in Session Spring 2019. Typesetting and formatting of this version was
supervised by Dr. Omar Ahmad.
History of Revision
Version
and Date Team Comments
of Issue
Safety Precautions
• Be calm and relaxed, while working in lab.
• When working with voltages over 40 V or current over 10 A , there must be at least two
• Be sure about the locations of fire extinguishers and first aid kit.
• No loose wires or metals pieces should be lying on the table or neat the circuit.
• Avoid using long wires, that may get in your way while making adjustments or
changing leads.
• Be aware of bracelets, rings, and metal watch bands (if you are wearing any of them).
• When working with energize circuit use only one hand while keeping rest of your body
o Disconnect the power source from the circuit breaker and pull out the plug using
insulated material.
Table of Contents
Introduction .................................................................................................................................. 2
Acknowledgement ........................................................................................................................ 3
History of Revision ...................................................................................................................... 3
Safety Precautions ........................................................................................................................ 4
Lab # 01 Introduction to Development Tools, Basics of C Programming and Debugging ......... 8
Objectives ................................................................................................................................. 8
Pre Lab ..................................................................................................................................... 8
In-Lab ..................................................................................................................................... 16
Post Lab Task: ........................................................................................................................ 19
Critical Analysis / Conclusion ............................................................................................... 20
Lab # 02 Basic Steps for Algorithm Development and Piece-Wise Functions using if/else
Statement .................................................................................................................................... 21
Objectives: .............................................................................................................................. 21
Pre-Lab Reading 1: The 4-Step Process of Algorithm Development .................................... 21
Pre-Lab Reading 2: Using if – else Constructs in C Programs .............................................. 27
In Lab Tasks: .......................................................................................................................... 28
Post Lab Task: ........................................................................................................................ 29
Critical Analysis / Conclusion ............................................................................................... 30
Lab # 03 Using Loops to Print Number Sequences and Patterns............................................... 31
Objectives: .............................................................................................................................. 31
Pre-Lab Reading: Loops in C Language: ............................................................................... 31
In Lab: .................................................................................................................................... 34
Critical Analysis / Conclusion ............................................................................................... 35
Lab # 04 Working with State Machines and Different Data Types ........................................... 36
Objectives: .............................................................................................................................. 36
Pre-Lab Reading 1: State Machine Based Program Design ................................................... 36
Pre-Lab Reading 2: Data Types in C Language ..................................................................... 37
In Lab: .................................................................................................................................... 40
Post Lab Task: ........................................................................................................................ 41
Critical Analysis / Conclusion ............................................................................................... 42
Lab # 05 Working with Custom Functions in C ........................................................................ 43
Objectives: .............................................................................................................................. 43
Pre Lab Reading: Functions in C ........................................................................................... 43
In-Lab Task 1: ........................................................................................................................ 45
In-Lab Task 2: ........................................................................................................................ 46
Post Lab Task: ........................................................................................................................ 46
Critical Analysis / Conclusion ............................................................................................... 47
Lab 06 Functions, scope of variables and argument passing ..................................................... 48
Objectives: .............................................................................................................................. 48
Pre-Lab Reading 1: Scope of Variables. ................................................................................ 48
In-Lab Task 01: ...................................................................................................................... 51
In-Lab Task 02: ...................................................................................................................... 51
Post Lab Task: ........................................................................................................................ 52
Critical Analysis / Conclusion ............................................................................................... 53
Lab # 07 The Compilation Process ............................................................................................ 54
Objectives: .............................................................................................................................. 54
Pre-Lab Reading 1: GNU C Compiler (GCC) Compilation Process ..................................... 54
Pre-Lab Reading 2: Splitting Your Code in Multiple Files ................................................... 57
In-Lab Task 1: ........................................................................................................................ 60
In-Lab Task-2: ........................................................................................................................ 60
Post-Lab Task:........................................................................................................................ 60
Critical Analysis / Conclusion ............................................................................................... 61
Lab # 08 Functions and Pointers in C ........................................................................................ 62
Objectives: .............................................................................................................................. 62
Pre-Lab Reading 1: Addresses of variables and Pointers in C ............................................... 62
Pre-Lab Reading 2: Returning multiple values from a function ............................................ 64
In-Lab Task 1: ........................................................................................................................ 65
In-Lab Task 2: Color Space Conversion ................................................................................ 65
Post Lab Task: Recursion ....................................................................................................... 66
Critical Analysis / Conclusion ............................................................................................... 67
Lab # 09 Working with Arrays and Pointers.............................................................................. 68
Objectives: .............................................................................................................................. 68
Reading Task 1: Working with Arrays .................................................................................. 68
Objectives
• Learn to use IDE such as Code Blocks for compiling and debugging computer programs
written in C language.
Softwares Used
Pre Lab
Get the Code Block IDE and MinGW C Compiler setup files from the lab and install them on
your computer.
3. Press Next
4. Select option C
6. Press Finish
7. Project is created, double click on Sources and click on main file, now you can modify
C code as per your notion.
2. To add a breakpoint, right click on line and click on Add breakpoint. It is the point from
where complier will execute program line by line.
6. Click on play option it will show yellow triangle, now program is appeared to start
8. By clicking on next line in debugger menu output appears line by line. One can easily
detect the error.
In-Lab
In-Lab Task 1: Fix syntax errors in given C program.
Make a new C project (console application) using CodeBlocks and type the following code in
the main.c file. Build the code, fix the indicated errors, and run it.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int N = 0; // Take a number N.
printf("Enter a number for which you want to find the factorial: \n");
Scanf("%d", &N); // Get input from the user
printf("\nYou entered: %d\n\n", n); // Display what the user entered.
Code Listing 1
{ 𝑛 𝑖𝑠 𝑎𝑛 𝑖𝑛𝑡𝑒𝑔𝑒𝑟
Fill the table using the above equation for values of n from -20 to 20. You will be using this
table to compare the output of the program in the next task and fixing some logical errors.
n f[n] n f[n]
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int range_min = -20;
int range_max = 20;
int n;
int output;
}
printf("\n\n");
return 0;
}
Code Listing 2
−𝑛 − 4, 𝑛<3
𝑛2 − 7, 3 ≤ 𝑛 ≤ 10
120
𝑓[𝑛] = + 𝑛, 𝑛 > 10
𝑛
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn to develop algorithms for different computational problems
• Learn basic input-out in C using printf() and scanf() functions
• Learn basics of conditional execution using if/else statements
Required Tools:
Software Tools:
• Code Blocks IDE or similar.
The first step in trying to design an algorithm is to work at least one instance of the problem—
picking specific values for each parameter—yourself (by hand). Often this step will involve
drawing a diagram of the problem at hand, in order to work it precisely. The more precisely
you can perform this problem (including the more precisely you can draw a diagram of the
situation if applicable), the easier the remainder of our steps will be. A good example of the
sort of picture you might draw would be the diagrams drawn in many science classes
(especially physics classes). The figure shows multiple copies of the box for this step layered
one on top of the other, as you may need to perform this step multiple times to generalize the
algorithm properly.
is prime," is not of much use—you just used a fact you know and did not actually work out the
problem. For a problem such as this one, which has a "yes or no" answer, we probably want to
work at least one example that comes up with a "yes" answer, and one that comes up with a
"no" answer.
Another example would be if we wanted to write a program to compute x raised to the y power.
To do Step 1, we would pick particular values for x and y, and work them by hand. We might
try x = 3 and y = 4, getting an answer of 3^4 = 81.
If you get stuck at this step, it typically means one of two things. The first case is that the
problem is ill-specified—it is not clear what you are supposed to do. In such a situation, you
must resolve how the problem should be solved before proceeding. In the case of a classroom
setting, this resolution may require asking your professor or TA for more details. In an
industrial setting, asking your technical lead or customer may be required. If you are solving a
problem of your own creation, you may need to think harder about what the right answers
should be and refine your definition of the problem.
The second case where Step 1 is difficult is when you lack domain knowledge—the knowledge
of the particular field or discipline the problem deals with. In our primality example, if you did
not remember the definition of a prime number, that would be an example of lacking domain
knowledge—the problem domain is mathematics, and you are lacking in math knowledge. No
amount of programming expertise nor effort ("working harder") will overcome this lack of
domain knowledge. Instead, you must consult a source of domain expertise—a math textbook,
website, or expert. Once you have the correct domain knowledge, you can proceed with
solving your instance of the problem. Note that domain knowledge may come from domains
other than math. It can come from any field, as programming is useful for processing any sort
of information.
Sometimes, domain knowledge may come from particular fields of computer science or
engineering. For example, if you intend to write a program that determines the meaning of
English text, the relevant domain field is actually a sub-field of computer science, called
Natural Language Processing. Here the domain knowledge would be the specific techniques
developed to write programs that deal with natural language. A source of domain knowledge
on English (an English professor or textbook) is unlikely to contain such information.
For this step, you must think about what you did to solve the problem, and write down the
steps to solve that particular instance. Another way to think about this step, is to write down a
clear set of instructions that anyone else could follow to reproduce your answer for the
particular problem instance that you just solved. If you do multiple instances in Step 1, you
will repeat Step 2 multiple times as well, once for each instance you did in Step 1. If an
instruction is somewhat complex, that is all right, as long as the instruction has a clear
meaning—later, we will turn these complex steps into their own programming problems,
which will get solved separately.
The difficult part of Step 2 is thinking about exactly what you did to accomplish the problem.
The difficulty here is that it is very easy to mentally gloss over small details, "easy" steps, or
things that you do implicitly. This difficulty is best illustrated by the peanut butter and jelly
exercise we mentioned earlier. Implicit assumptions about what to do, or relying on common
sense lead to imprecise or omitted steps. The computer will not fill in any steps you omit, thus
you must be careful to think through all the details.
Returning to our example of computing x to the y, we might write down the following steps for
x = 3 and y = 4:
The steps are very precise—and leave nothing to guess work. Anyone who can perform basic
arithmetic can follow these steps to get the right answer. Computers are very good at
arithmetic, so none of these steps is even complex enough to require splitting into a sub-
problem.
Having solved one or more problems from the class we are interested in and written down the
particular steps we executed to solve them, we are ready to try to generalize those steps into an
algorithm. In our Step 2 steps, we solve particular instances, but now we need to find the
pattern that allows us to solve the whole class. This generalization typically requires two
activities. First, we must take particular values that we used and replace them with
mathematical expressions of the parameters. Looking at our Step 2 steps for computing 3^4,
we would see that we are always multiplying 3 by something in each step. In the more general
case, we will not always use 3—we are using 3 specifically because it is the value that we
picked for x. We can generalize this slightly by replacing this occurrence of 3 with x:
The second common way to generalize steps is to find repetition—the same step repeated over
and over. Often the number of times that the pattern repeats will depend on the parameters. We
must generalize how many times to do the steps, as well as what the steps are. Sometimes, we
may find steps which are almost repetitive, in which case we may need to adjust our steps to
make them exactly repetitive. In our 3^4 example, our multiplication steps are almost
repetitive—both multiply x by "something," but that "something" changes (3 then 9 then 27).
Examining the steps in more detail, we will see that the "something" we multiply is the answer
from the previous step. We can then give it a name (and an initial value) to make all of these
steps the same:
Now, we have the same exact step repeated three times. We can now contemplate how many
times this step repeats as a function of x and/or y. We must be careful not to jump to the
conclusion that it repeats x times because x = 3—that is just a coincidence in this case. In this
case, it repeats y - 1 times. The reason for this is that we need to multiply 4*3s together, and we
already have one in n at the start, so we need y - 1 more. This would lead to the following
generalized steps:
We need to make one more generalization of a specific value to a function of the parameters.
We start with n = 3; however, we would not always want to start with 3. In the general case, we
would want to start with n = x:
Sometimes you may find it difficult to see the pattern, making it hard to generalize the steps.
When this happens, returning to Steps 1 and 2 may help. Doing more instances of the problem
will provide more information for you to consider, possibly giving you insight into the patterns
of your algorithm.
After Step 3, we have an algorithm that we think is right. However, it is entirely possible that
we have messed up along the way. The primary purpose of Step 4 is to ensure our steps are
actually right before we proceed. To accomplish this, we test our algorithm with different
values of the parameters than the ones we used to design our algorithm. We execute our
algorithm by hand and compare the answer it obtains to the right answer. If they differ, then we
know our algorithm is wrong. The more test cases (values of parameters) we use, the more
confident we can become that our algorithm is correct. Unfortunately, it is impossible to ensure
that our algorithm is correct by testing. The only way to be completely sure that your algorithm
is correct is to formally prove its correctness (using a mathematical proof), which is beyond the
scope of this specialization.
One common type of mistake is misgeneralizing in Step 3. As we just discussed, one might
think that the steps repeated x times because x = 3 and the steps repeated 3 times. If we had
written that down in Step 3, our algorithm would only work when x = y – 1; otherwise we
would count the wrong number of times and get the wrong answer. If that were the case, we
would hopefullydetect the problem by testing our algorithm by hand in Step 4. When we detect
such a problem, we must go back and re-examine the generalizations we made in Step 3. Often,
this is best accomplished by returning to Steps 1 and 2 for whatever test case exposed the
problem. Redoing Steps 1 and 2 will give you a concrete set of steps to generalize differently.
You can then find where the generalization you came up with before is wrong, and revise it
accordingly.
Another common type of mistake is that there are cases we did not consider in designing our
algorithm. In fact, in our x^y example, we did not consider what happens when y = 0, and our
algorithm handles this case incorrectly. If you execute the algorithm by hand with x = 2, y = 0,
you should get 2^0=1; however, you will get an answer of 2. Specifically, you will start with n
= x = 2. We would then try to count up from 1 to 0 – 1 = –1, of which there are no numbers, so
we would be done counting right away. We would then give back n (which is 2) as our answer.
To fix our algorithm, we would go back and revisit Steps 1 and 2 for the case that failed (x = 2,
y = 0). This case is a bit tricky since we just know that the answer is 1 without doing any work
(x^0=1 for any x). The fact that the answer requires no work makes Step 2 a little different—
we just give an answer of 1. While this simplicity may seem nice, it actually makes it a little
more difficult to incorporate it into our generalized steps. We might be tempted to write
generalized steps like these:
These steps check explicitly for the case that gave us a problem (y = 0), give the right answer
for that case, then perform the more general algorithm. For some problems, there may be
corner cases which require this sort of special attention. However, for this problem, we can do
better. Note that if you were unable to see the better solution and were to take the above
approach, it is not wrong per se, but it is not the best solution.
Instead, a better approach would be to realize that if we count no times, we need an answer of
1, so we should start n at 1 instead of at x. In doing so, we need to count 1 more time (to y
instead of to y– 1)—to multiply by x one more time:
Whenever we detect problems with our algorithm in Step 4, we typically want to return to
Steps 1 and 2 to get more information to generalize from. Sometimes, we may see the problem
right away (e.g., if we made a trivial arithmetic mistake, or if executing the problematic test
case by hand gives us insight into the correct generalization). If we see how to fix the problem,
it is fine to fix it right away without redoing Steps 1 and 2, but if you are stuck, you should
redo those steps until you find a solution. Whatever approach you take to fixing your
algorithm, you should re-test it with all the test cases you have already used, as well as some
new ones.
Determining good test cases is an important skill that improves with practice. For testing in
Step 4, you will want to test with cases which at least produce a few different answers (e.g., if
your algorithm has a "yes" or "no" answer, you should test with parameters which produce
both "yes" and "no"). You should also test any corner cases—cases where the behavior may be
different from the more general cases. Whenever you have conditional decisions (including
limits on where to count), you should test potential corner cases right around the boundaries of
these conditions. For example, if your algorithm makes a decision based on whether or not x <
3 , you might want to test with x = 2, x = 3, and x = 4. You can limit your "pencil and paper"
testing somewhat, since you will do more testing on the actual code once you have written it.
When your execution arrow reaches an if statement, evaluate the conditional expression.
Evaluating this expression proceeds just like evaluating any other expression. If the result is
true, move the execution arrow immediately inside the “then” block and continue executing
statements as usual. When your execution reaches the close curly brace that ends the “then”
block, skip over the else block, placing your execution arrow immediately after the close curly
brace of the “else” block, and continue executing statements from there.
If the result of the conditional expression is false, you should instead skip the “then” block and
execute the “else” block. Move your execution arrow into the start of the “else” block, and
continue executing statements from there. When your execution arrow reaches the close curly
brace that ends the “else” block, simply move it past that curly brace (which has no effect—it
just denotes the end of the block) and continue executing statements normally.
C permits if with no else, which is equivalent to an empty “else” block (as if the programmer
had written else {}). If you execute an if with no else, then simply imagine the empty “else”
block. If the conditional expression evaluates to true, you should execute the “then” block as
previously described, however, there is no “else” block to skip. Instead, continue executing
statements immediately after the end of the “then” block (skipping over the nonexistent “else”
block). If the conditional expression evaluates to false, then skip the “then” block, and execute
whatever statements follow it (doing nothing for the “else” block).
if/else statements may be nested—one (or more) may occur in the “then” or “else” block of
another if/else statement. When you encounter nested statements, the same rules apply. The
inner statement is just one of the (possibly) many statements in the block, and is executed
according to its rules—the condition is evaluated, whichever of the “then” or “else” blocks is
appropriate is executed, and then execution continues after the end of the “else” block. When
the execution arrow reaches the end of the outer “then” or “else” block, it behaves no
differently than if there were no inner if statement. The next video demonstrates the execution
of some if/else statements.
In Lab Tasks:
Following figure shows a pattern of squares generated for different input values of N (for N=0
to N=5). Develop a general algorithm to fill in the grid for any input N. Use the 4 step process
that was discussed in the class (and is given below for reference)
Write a C program for following piecewise function. Program must take input from user and
calculate and print the function result on screen.
−𝑛 − 4, 𝑛<3
𝑛2 − 7, 3 ≤ 𝑛 ≤ 10
120
𝑓[𝑛] = + 𝑛, 𝑛 > 10
𝑛
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn to use loops for repetitive tasks.
• Practice conditional execution in loops to generate patterns of asterisks.
Required Tools:
Software Tools:
• CodeBlocks IDE or similar
While loops
There are three kinds of loops in C. The first of these is the while loop. The syntax for a while
loop is shown in Figure 2.9. The keyword while is followed by an expression in parenthesis.
Much like an if statement, this expression is evaluated to determine whether or not to enter the
block of code immediately following it, which is known as the body of the loop. If the
conditional expression evaluates to true, the execution arrow moves inside the body of the loop
and its statements are executed normally. The while loop differs from the if statement in what
happens when the execution arrow reaches the closing curly brace. In the case of a while loop,
it jumps up to the top of the loop, immediately before the while keyword. The conditional
expression is then re-evaluated, and if it is still true, execution re-enters the loop body. If the
conditional expression evaluates to false, then the execution arrow skips to immediately after
the closing curly brace of the loop body, and proceeds from there.
Another type of loop in C is the do-while loop. Unlike a while loop, which checks its
conditional expression at the top of the loop, the do-while loop checks its conditional
expression at the bottom of the loop—after it has executed the body. While this distinction may
seem contrived— either way the condition is checked between iterations—it is important at the
start of the loop. A while loop may execute its body zero times, skipping the entire loop, if the
condition is false initially. By contrast, a do-while loop is guaranteed to execute its body at
least once because it executes the loop body before ever checking the condition. Figure 2.10
shows the syntax of a do-while loop. The keyword do is followed by the loop body. After the
loop body, the keyword while is followed by the conditional expression and a semicolon.
Execution of a do-while loop proceeds by first entering the loop body and executing all of the
statements contained in it. When the execution arrow reaches the while at the end of the loop
body, its conditional expression is evaluated. If the expression evaluates to true, then the
execution arrow jumps back to the start of the loop body. If the expression evaluates to false,
then it moves past the end of the loop and execution continues with the next statement after the
loop.
For Loops
The third type of loop in C is a for loop. The for loop is syntactic sugar—it does not introduce
any new behavior, but instead provides a more convenient syntax for a common programming
idiom. In the case of for loops, the common idiom is counting from one number to another.
Figure 2.11 shows the syntax of a for loop, and how it is de-sugared into a while loop—that is,
how we could write the for loop in terms of the already familiar while loop. Knowing how the
for loop de-sugars to a while loop tells us how to execute it. We can imagine the equivalent
while loop, and follow the execution rules we have already learned for it. The for keyword is
followed by three pieces, separated by semicolons, inside of parenthesis. The first of these is
the “initialization statement”. It happens once before the first time the loop’s condition is
checked. In the de-sugaring, this statement appears right before the while loop. The second
piece is not a statement (even though it is followed by a semicolon), but rather the conditional
expression for the loop. In the de-sugaring, this expression is the conditional expression of the
while loop. The third statement is the “increment statement”. In the de-sugaring, it appears
immediately before the close curly brace of the loop body. After all of these is the loop body,
which (except for the addition of the “increment statement” at the end) is the loop body of the
while loop in the de-sugared version. If you examine Figure 2.11 carefully, you will notice that
there is a set of curly braces around the entire piece of while-based code. These curly braces
are there for a subtle, but important reason. The scope of any variables declared in the
“initialization statement” of the for loop have a scope which is limited to the for loop. Recall
that a variable typically has a scope which is limited to the curly braces which enclose its
declaration. For a variable declared in the start of the for loop, the scope appears to be an
exception to this rule, however, it is not if we think of it in terms of the de-sugaring shown
above with the curly braces surrounding the declaration.
Just as if/else statements may be nested, loops may also be nested. Similarly, loops follow
exactly the same rules no matter how they are nested. In fact, if/else statements and loops may
be nested within each other in any combinations. The rules are always the same regardless of
any combinations or depths of nesting.
Sometimes a programmer wants to leave the loop body early, rather than finishing all of the
statements in side of it. There are two possible behaviors that a programmer might want when
leaving the loop body early. One behavior would be to exit the loop completely, making the
execution arrow jump to immediately after the close curly brace which ends the loop (the same
place that it goes when the loop’s condition evaluates to false). This behavior is obtained by
using the break; statement—which we have already seen in the context of switch/case.
Whenever the execution arrow encounters a break statement, it executes the statement by
jumping out of the innermost enclosing loop (whether it is a while, do-while, or for loop), or
switch statement. If the break statement is inside multiple of these which are nested together
(e.g. a loop inside a case of a switch statement), then it exits only the most immediately
enclosing one. If a break statement occurs and is not inside one of these loops or a switch
statement, it is an error in the program. The other possible behavior that the programmer might
want to have is for the execution arrow to jump back to the top of the loop. This behavior is
accomplished with the continue; statement. Executing the continue statement jumps to the top
of the innermost enclosing loop (if it is not in a loop, it is an error). In the case of a for loop,
the “increment statement” in the for loop is executed immediately before the jump. This fact
complicates the de-sugaring of a for loop into a while loop slightly relative to the explanation
given above. If the for loop contains any continue statements, then the “increment statement” is
written not only before the close curly brace of the loop, but also before any continue
statements.
In Lab:
Task 1:
Write a program that prints all even numbers from N to M, where N and M are user input
integers.
Task 2:
Write C programs that output the following patterns exactly. Use loops to implement the
repetitive part of the code. No functions or arrays are allowed.
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn to use state machine as a program design tool
• Practice the conditional execution of code combined with loops by implementing state
machines.
• Learn about different data types.
Software Tools:
• CodeBlocks IDE or similar.
FSM-based programming is generally the same, but, formally speaking, doesn't cover all
possible variants, as FSM stands for finite state machine, and automata-based programming
doesn't necessarily employ FSMs in the strict sense.
If you look at the first line of code in Figure 3.5, you can see the char c declared and initialized
to the value 'A'. Notice that we wrote A in single quotation marks—these indicate a character
literal . In the same way that we could write down a string literal in Section 2.3.2, we can also
write down a character literal: the specific constant character value we want to use. Writing
We have said that an int is a 32-bit value interpreted as an integer directly from its binary
representation. As it turns out, this is only half of the story—the positive half of the story. If we
dedicate all 32 bits to expressing positive numbers, we can express 232 values, from 0 up to
The final two basic data types in C allow the programmer to express real numbers. Since there
are an infinite number of real numbers, the computer cannot express them all (that would
require an infinite number of bits!). Instead, for values that cannot be represented exactly, an
approximation of the value is stored. If you think about the fact that that computers can only
store values as 0s and 1s, you may wonder how it is possible to store a real number, which has
a fractional part. In much the same way that decimal representations of a number can have a
fractional portion with places to the right of a decimal point (the tenth’s, hundredth’s,
Figure 4: Floating Point Representation. A float has 32 bits and a double has 64 bits to express
notation, number 403 can be expressed as 4.03 × 102. Computers use floating point notation,
the same notation but implicitly in base 2: m × 2e. m is called the mantissa (though you may
also hear it referred to as the significand). e is the exponent. A float has 32 bits used to
represent a floating point number. These 32 bits are divided into three fields. The lowest 23
bits encode the mantissa; the next 8 bits encode the exponent. The most significant bit is the
sign bit, s, which augments our formula as follows: (−1)s × m × 2e. (When s = 1, the number is
negative. When s = 0, the number is positive.) A double has 64 bits and uses them by
extending the mantissa to 52 bits and the exponent to 11 bits. Examples of both a float and a
double are shown in Figure 3.6.
Task 1:
Write a C program that solves a simple user-entered mathematical expression. It should take
input from the user (two floating type values and operations like *, /, + and -), calculate the
result and show it on screen. e.g. if the user inputs “5 + 6” the program should add numbers 5
and 6 and print the answer 11 on to the console.
Task 2:
Following program prints a menu. It then takes input from user and displays the entered choice.
Type-in the C program given below into a new project, compile and run to see how it works.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int choice=0;
while(choice!=4)
{
printf("\n\tMENU DEMONSTRATION");
printf("\n\t------------------------------");
printf("\n\n\t 1. OPTION 1");
printf("\n\t 2. OPTION 2");
printf("\n\t 3. OPTION 3");
printf("\n\t 4. EXIT");
printf("\n\n Enter Your Choice: ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("\nYOU SELECTED OPTION %d",choice);
break;
case 2:
printf("\nYOU SELECTED OPTION %d",choice);
break;
case 3:
printf("\nYOU SELECTED OPTION %d",choice);
break;
case 4:
printf("\nYOU SELECTED OPTION %d",choice);
exit(0);
default:
printf("\nINVALID SELECTION...Please try again");
}
getchar();
}
}
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn to use custom functions in C
• Learn to implement mathematical functions in programs using C functions.
• Learn to use math.h library
Tools:
Software Tools:
• CodeBlocksIDE or similar.
Figure 2 shows a function declaration. The function’s name may be any valid identifier, just
like a variable’s name. In this particular example, the function’s name is myFunction.
Immediately before the function’s name is its return type—the type of value that this function
will compute. As mentioned earlier, we will learn more about types later. For now, we will just
work with ints, which are numbers. The fact that this function returns an int means that its
“answer” is an int. After the function’s name comes a set of parenthesis, with the parameter list
The body of the function then comes between a set of curly braces, and is comprised of zero or
more statements. The body of this function has two statements. The first statement in this
function’s body is the now familiar declaration and initialization of a variable: z is declared as
a variable of type int, and initialized to the value of the expression x - 2 * y.
The second statement within the body of this function is a new type of statement which we
have not seen before: a return statement. A return statement starts with the keyword return,
which is then followed by an expression. The effect of this statement is to say what the
“answer” is for the current function, leaving its computation and returning to the code which
called it.
To understand this last concept completely, we must first see the other aspect of using a
function—calling the function. A function is another kind of expression, whose value is
whatever “answer” the called function comes up with when it is executed with the specified
arguments— values of its parameters. This “answer” is more formally called the function’s
return value.
Evaluating a function call is more complex than evaluating the other kinds of expressions that
we have seen so far—it may take many steps of executing the code in the function to determine
its answer. In fact, code may call one function, which itself may call other functions before
finally coming up with an answer. While this may seem daunting, we can do it properly by
following a few rules for executing function calls by hand.
As a first step towards reading code with function calls, we must first group together the
variables belonging to one particular function into a larger box, labeled with the function’s
Notice that in the example of Figure 1, one of the functions is named main. The function
named main is special—execution of a program starts at the start of main. We start by drawing
an empty frame for main, and putting the execution arrow right before the first line of code in
main. We then execute statements of the code until main returns, which ends the program.
Calls to functions may appear in expressions, in which case we must evaluate the function to
determine its return result. To do this evaluation, we take the following steps:
1. Draw a frame for the function being called. Place a box in that frame for each
parameter that this function takes.
2. Initialize the parameters by evaluating the corresponding expressions in the function
call, and copying the resulting values into the parameter’s box in the called function’s
frame.
3. Mark the location of the function call, and note that location in the corner of the
function’s frame.
4. Move the execution arrow immediately before the first line of code in the called
function.
5. Evaluate the lines of code inside the called function.
6. When you reach a return statement, evaluate its argument to a value. Note down this
return value.
7. Return the execution arrow back to where the function was called—you know this
location because you noted it in the corner of the frame. You will return the arrow to
the middle of the line of code (rather than the typical “between them”) because that line
of code is part-way done.
8. Erase the frame for the called function.
9. Use the return value of the function as the value of the function call in the expression in
which it appears.
In-Lab Task 1:
Write a C function 'int test_prime(int);' that takes in a positive number as input and returns true
(1) if the input number is prime or false (0) if the input is not prime. Then using this function,
write a C program that takes a number (N) as input from the user and prints out the first N
prime numbers.
Hint: include the ‘math.h’ library and use the following functions. Remember that these
functions expect inputs to be in Radians.
𝜃 2
𝑓1 (𝜃) = (cos )
2
1 + cos 2𝜃
𝑓2 (𝜃) = 0.5√
2
1
𝑓3 (𝜃) =
2
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Understand the scope of variables when working with custom functions
• Provide more practice for custom functions
Local Variables:
Variables that are declared inside a function or a block are called local variables and are said to
have local scope. These local variables can only be used within the function or block in which
these are declared. We can use (or access) a local variable only in the block or function in which
it is declared. It is invalid outside it.
Local variables are created when the control reaches the block or function containing the local
variables and then they get destroyed after that. Consider the following code:
#include <stdio.h>
void fun1()
{
/*local variable of function fun1*/
int x = 4;
printf("%d\n",x);
}
int main()
{
/*local variable of function main*/
int x = 10;
{
/*local variable of this block*/
int x = 5;
printf("%d\n",x);
}
printf("%d\n",x);
fun1();
}
10
The value of the variable ‘x’ is 5 in the block of code ({ }) defined inside the function ‘main’ and
the value of this variable ‘x’ in the ‘main’ function outside this block of code ({ }) is 10. The
value of this variable ‘x’ is 4 in the function ‘fun1’.
Global Variables:
Variables that are defined outside of all the functions and are accessible throughout the program
are global variables and are said to have global scope. Once declared, these can be accessed and
modified by any function in the program. We can have the same name for a local and a global
variable but the local variable gets priority inside a function. Consider the following code:
#include <stdio.h>
/*Global variable*/
int x = 10;
void fun1()
{
/*local variable of same name*/
int x = 5;
printf("%d\n",x);
}
int main()
{
printf("%d\n",x);
fun1();
}
You can see that the value of the local variable ‘x’ was given priority inside the function ‘fun1’
over the global variable have the same name ‘x’.
Formal Parameters:
Formal Parameters are the parameters which are used inside the body of a function. Formal
parameters are treated as local variables in that function and get a priority over the global
variables. Consider the following code:
#include <stdio.h>
/*Global variable*/
int x = 10;
void fun1(int x)
{
/*x is a formal parameter*/
printf("%d\n",x);
}
int main()
{
fun1(5);
}
#include <stdio.h>
int main(void)
{
printf("Enter four numbers separated by commas: ");
scanf("%d,%d,%d,%d", &n1, &n2, &n3, &n4);
return(0);
}
y = f1[n] + f2[n]
where
5
𝑓1 (𝑛) = ∑26
𝑛=1 (𝑛+5)+3
The program should print the value of y on the console screen as well. Write separate functions
to compute f1[n] and f2[n]
(−1)𝑛
𝑓1 (𝑛) =
(𝑛 + 1)!
4
𝑓2 (𝑛) = ∑ 2𝑛
𝑛=0
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Understand the C compilation process.
• Learn to use Command Line Interface (CLI) of GNU C Compiler (GCC).
• Learn to compile single code files using GCC, CLI
• Learn to compile multiple code files using GCC, CLI
1. Preprocessing
2. Compilation
3. Assembly
4. Linking
We will be using the following piece of code to illustrate this process. Save this code in a file
(using any text editor) and name it “test1.c”
#include<stdio.h>
int main(void)
{
int x = 0; // A variable to hold some data
int y = 5; // and another variable
return(0);
}
Pre-processing:
This is the first phase through which source code is passed. This phase includes:
• Removal of Comments
• Expansion of Macros
In this stage, lines starting with a ‘#’ character are interpreted by the preprocessor as
preprocessor commands. These commands form a simple macro language with its own syntax
and semantics. This language is used to reduce repetition in source code by providing
functionality to inline files, define macros, and to conditionally omit code.
Before interpreting commands, the preprocessor does some initial processing. This includes
joining continued lines (lines ending with a \) and stripping comments.
To print the result of the preprocessing stage, pass the -E option to gcc:
gcc -E “Path\test1.c” -o “Path\test1.i”
or call the sub-process cpp as follows
cpp “Path\test1.c” -o “Path\test1.i”
Given the “test1.c” example above, the preprocessor will produce the contents of the stdio.h
header file joined with the contents of the test1.c file, stripped free from its leading comments.
[lines omitted for brevity]
return(0);
}
Compilation:
The second stage of compilation is confusingly enough called compilation. In this stage, the
preprocessed code is translated to assembly instructions specific to the target processor
architecture. These form an intermediate human readable language.
The existence of this step allows for C code to contain inline assembly instructions and for
different assemblers to be used.
Some compilers also support the use of an integrated assembler, in which the compilation stage
generates machine code directly, avoiding the overhead of generating the intermediate assembly
instructions and invoking the assembler.
To save the result of the compilation stage, pass the -S option to gcc:
gcc -S “Path\test1.i” -o “Path\test1.s”
This will create a file named ‘test1.s’, containing the generated assembly instructions. On
Windows 7 the following output is generated:
.file "test1.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "The sum of x and y is: %d\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
call ___main
movl $0, 28(%esp)
movl $5, 24(%esp)
movl 28(%esp), %edx
movl 24(%esp), %eax
addl %edx, %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
.ident "GCC: (tdm-1) 5.1.0"
.def _printf; .scl 2; .type 32; .endef
Assembly:
During this stage, an assembler is used to translate the assembly instructions to object code. The
output consists of actual instructions to be run by the target processor.
To save the result of the assembly stage, pass the -c option to gcc:
gcc -c “Path\test1.c” -o “Path\test1.o”
or invoke the Assembler as follows:
as “Path\test1.s” -o “Path\test1.o”
Running the above command will create a file named ‘test1.o’, containing the object code of the
program. The contents of this file are in a binary format and can be inspected using Notepad++:
Linking:
The object code generated in the assembly stage is composed of machine instructions that the
processor understands but some pieces of the program are out of order or missing. To produce an
executable program, the existing pieces have to be rearranged and the missing ones filled in. This
process is called linking.
The linker will arrange the pieces of object code so that functions in some pieces can
successfully call functions in other ones. It will also add pieces containing the instructions for
library functions used by the program. In the case of the “test1.c” program, the linker will add
the object code for the printf function.
The result of this stage is the final executable program. When run without options, gcc will name
this file test1.exe (on a Windows machine). To name the file something else, pass the -o option
to gcc:
gcc “Path\test1.c” -o “Path\test1.exe”
Or invoke the linker directly passing the Object file as input:
ld “Path\test1.o” -o “Path\test1.exe ...libraries...” (This will only work if the correct path
to libraries is provided. Out of scope for this lab.)
This process can be summarized by the following figure:
We saw when discussing functions, that one way of including custom-written functions in your
C code, is to simply place them in your main source file, above the declaration of the main()
function. A better way to re-use functions that you commonly incorporate into your C programs
is to place them in their own file, and to include a statement above main() to include that file.
When compiled, it's just like copying and pasting the code above main(), but for the purpose of
editing and writing your code, this allows you to keep things in separate files. It also means that
if you ever decide to change one of those re-usable functions (for example if you find and fix an
error) that you only have to change it in one place, and you don't have to go searching through all
of your programs and change each one.
Header files
A common convention in C programs is to write a header file (with .h suffix) for each source file
(.c suffix) that you link to your main source code. The logic is that the .c source file contains all
of the code and the header file contains the function prototypes, that is, just a declaration of
which functions can be found in the source file.
This is done for libraries that are provided by others, sometimes only as compiled binary "blobs"
(i.e. you can't look at the source code). Pairing them with plain-text header files allows you see
what functions are defined, and what arguments they take (and return).
Example:
Let's say you want to write a program that takes one integer input from the user, and determines
whether that integer is a prime number or not. Now let's say that you don't want to write your
own code for determining primality, so you ask your friend, who you know has written such a
function already. He sends you a pair of files (primes.h and primes.c). His header file (primes.h)
looks like this:
So we know a couple of things from this header file. It declares a function prototype for
isPrime(). We can see this function takes a single integer as an input argument, and returns an
integer value: 1 if the input value is a prime number, and 0 if it is not. Now we know all we need
to know in order to use this function (without even looking at the function's source code, which
resides in primes.c).
Here is what the primes.c file look like:
int isPrime(int n)
{
int i;
for (i=3; i*i < n; i++) { // test divisibility up to sqrt(n)
if ((n % i) == 0) {
return 0;
}
}
return 1;
}
#include <stdio.h>
#include <stdlib.h>
#include "primes.h"
int main(void)
{
int N;
int prime;
while(1)
{
printf("Enter a number");
scanf("%d", &N);
if(isPrime(N) != 0)
printf("The number %d is prime ",N);
else
{
printf("The number %d is not prime ",N);
break;
}
}
return 0;
Search path
The compiler will look in several places for header files that you include with the #include
directive, depending on how you use it. If you use include with the angled brackets (e.g. #include
<stdio.h>) then the compiler will look in a series of "default" system-wide locations (see Search
Path for details). If you use double-quotes (e.g. #include "neuron.h") then the compiler will look
in the directory containing the current file. It's possible to add other directories to the search path
by using the -Idir compiler option, where dir is the other directory. You might have to do this if
you link your code to an external C library that is not part of the standard C library, and does not
reside in the usual "system" default locations.
In-Lab Task 1:
Using the Notepad (the Windows text editor), save the program given in Code Listing 1 as a C
file (test1.c). Then use the GNU CLI to compile the program and generate the intermediate files
like, test1.i, test1.s, test1.o and finally test1.exe.
Hint: You will have to provide the complete path to source and destination files in double quotes
(e.g. “Path\test1.c”).
In-Lab Task-2:
Using the Notepad (the Windows text editor), save the programs given in Code Listing 2, 3 and 4
as c/h files (primes.h, primes.c, and go.c). Then use the GNU CLI to compile the program and
generate the intermediate files like, go.i, go.s, go.o and finally go.exe.
Post-Lab Task:
Submit a hand written report on what difficulties you faced in the lab, what sources of
information did you refer to to solve your problems, and what were the solutions you
implemented.
Reference Links:
1. https://www.gribblelab.org/CBootCamp/12_Compiling_linking_Makefile_header_files.html
2. https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
3. https://www.classes.cs.uchicago.edu/archive/2017/winter/51081-1/LabFAQ/lab2/compile.html#compilation_steps
4. https://www.gribblelab.org/CBootCamp/
5. https://www.geeksforgeeks.org/compiling-a-c-program-behind-the-scenes/
6. https://www.youtube.com/watch?v=VDslRumKvRA
7. https://www.youtube.com/watch?v=N2y6csonII4
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn the basics of Pointers in C language
• Learn argument passing by reference to C functions
• Learn to return multiple outputs from functions using pointers
We see that the computer has selected memory location 65524 as the place to store the value 3.
The location number 65524 is not a number to be relied upon, because some other time the
computer may choose a different location for storing the value 3. The important point is, i’s
address in memory is a number. We can print this address number through the following
program:
main( )
{
int i = 3 ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nValue of i = %d", i ) ;
}
The output of the above program would be: Address of i = 65524 Value of i = 3 look at the first
printf( ) statement carefully. ‘&’ used in this statement is C’s ‘address of’ operator. The
expression &i returns the address of the variable i, which in this case happens to be 65524. Since
65524 represents an address, there is no question of a sign being associated with it. Hence it is
printed out using %u, which is a format specifier for printing an unsigned integer.
We have been using the ‘&’ operator all the time in the scanf( ) statement. The other pointer
operator available in C is ‘*’, called ‘value at address’ operator. It gives the value stored at a
particular address. The ‘value at address’ operator is also called ‘indirection’ operator.
Observe carefully the output of the following program:
main( )
{
int i = 3 ;
printf ( "\nAddress of i = %u", &i ) ;
printf ( "\nValue of i = %d", i ) ;
printf ( "\nValue of i = %d", *( &i ) ) ;
}
We can return more than one values from a function by using the method called “call by
address”, or “call by reference”. In the invoker function, we will use two variables to store the
results, and the function will take pointer type data. So we have to pass the address of the data.
In this example, we will see how to define a function that can return quotient and remainder after
dividing two numbers from one single function.
#include<stdio.h>
In-Lab Task 1:
For the given program find (and print) the addresses assigned to all the variables against their
names.
#include<stdio.h>
void test(void);
int main()
{
int x, y=5, z = 5;
test();
}
void test()
{
char ch1 = ‘F’, ch2 = 69, ch3 = 100;
int x = 5, y = 55, z = 8;
}
Y′CbCr color spaces are defined by a mathematical coordinate transformation from an associated
RGB color space. If the underlying RGB color space is absolute, the Y′CbCr color space is an
absolute color space as well; conversely, if the RGB space is ill-defined, so is Y′CbCr.
Write a C function which takes three integer inputs, corresponding to RGB components of a
colored pixel, and coverts them to the YUV color space. The function should have the following
prototype.
Example:
1. main.c
2. my_lib.h
3. my_lib.o
Complete the function rgb2ycbcr() , compile the project using command line and run the code.
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn the basic operations on arrays (e.g. traversal, value swapping, retrieving indices
etc)
• Accessing array elements via pointers.
• Practice array operations by implementing simple sorting algorithms.
The algorithm divides the input list into two parts: the sublist of items already sorted, which is
built up from left to right at the front (left) of the list, and the sublist of items remaining to be
sorted that occupy the rest of the list. Initially, the sorted sublist is empty and the unsorted sublist
is the entire input list. The algorithm proceeds by finding the smallest (or largest, depending on
sorting order) element in the unsorted sublist, exchanging (swapping) it with the leftmost
unsorted element (putting it in sorted order), and moving the sublist boundaries one element to
the right.
Example:
Selection sort can also be used on list structures that make add and remove efficient, such as a
linked list. In this case it is more common to remove the minimum element from the remainder
of the list, and then insert it at the end of the values sorted so far. For example:
arr[] = 64 25 12 22 11
// Find the minimum element in arr[0...4]
// and place it at beginning
11 25 12 22 64
// Find the minimum element in arr[1...4]
// and place it at beginning of arr[1...4]
11 12 25 22 64
// Find the minimum element in arr[2...4]
// and place it at beginning of arr[2...4]
11 12 22 25 64
// Find the minimum element in arr[3...4]
// and place it
#include <stdio.h>
#include <stdlib.h>
#define ASCENDING 0
#define DESCENDING 1
#define ARRAY_SIZE 50
int main(void)
{
int num_array[ARRAY_SIZE]; /// Declare an integer array
int * ptr_ar = &num_array[0]; /// A pointer to the start of the array
int mx_idx = find_max(ptr_ar, ARRAY_SIZE); /// Print the maximum value and its index
printf("\nThe maximum number is %d at index %d \n", num_array[mx_idx], mx_idx);
int mn_idx = find_min(ptr_ar, ARRAY_SIZE); /// Print the minimum value and its index
printf("\nThe minimum number is %d at index %d \n", num_array[mn_idx], mn_idx);
return 0;
}
int find_max(int * ptr_array, int size)
{
int max_val = 0;
int max_idx = 0;
}
int find_min(int * ptr_array, int size)
{
return 0;
}
void selection_sort(int * ptr_array, int size, int order)
{
Write a similar function ‘int find_min(int * ptr_array, int size)’ and print the value and index of
the smallest number in the array as well.
Your second task is to implement the Selection Sort algorithm by making a function with the
following prototype;
This function takes as input a pointer to the start of the array, and the array size and sorts it in-
place. The last input to the function is the sorting order (0 for ascending and 1 for descending).
You should call the functions (find_max(), find_min()) developed in lab-task 1 to implement
Selection Sort algorithm.
This function takes as input a pointer to the start of the array, and the array size and sorts it in-
place. The last input to the function is the sorting order (0 for ascending and 1 for descending).
References:
1. https://www.toptal.com/developers/sorting-algorithms
2. https://en.wikipedia.org/wiki/Selection_sort
3. https://en.wikipedia.org/wiki/Insertion_sort
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn the basic operations on 2D arrays.
• Printing 2D array contents to console screen.
• Accessing 2D array elements via pointers.
• Practicing 2D array operations by implementing a Magic Square algorithm.
A method for constructing magic squares of odd order was published by the French diplomat de
la Loubère in his book, “A new historical relation of the kingdom of Siam” (Du Royaume de
Siam, 1693), in the chapter entitled The problem of the magical square according to the Indians.
The method operates as follows:
1. The method prescribes starting in the central column of the first row with the number 1.
2. After that, the fundamental movement for filling the squares is diagonally up and right,
one step at a time.
3. If a filled square is encountered, one moves vertically down one square instead, then
continues as before.
4. When an "up and to the right" move would leave the matrix, it is wrapped around to the
last row or first column, respectively.
• Then you should initialize the array with ones (using nested loops).
• Next you have to write a function array_multiply() which takes in the array or its
pointer as argument and multiplies all its entries with a user input number. (Hint: you
will also need to pass in the dimensions of the matrix to this function).
• Similarly write a function array_add() that adds a constant number to all the entries in a
2D array.
• Asks the user to enter the order ‘n’ of the magic square (odd numbers only).
1. https://en.wikipedia.org/wiki/Magic_square#A_method_for_constructing_a_magic_
square_of_odd_order
You can fill in the following 5 x 5 grid to see if you have grasped the working of the algorithm.
You can test your work by checking the sum of rows, columns and the main diagonal. They
should all be the same.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("Enter the order of Magic Square (positive Odd Nums only): \n");
scanf("%d", &n);
printf("\n\n");
if(magic_square(n) != 0)
printf("\nPlease enter correct value for n!!");
return 0;
}
void magic_square(int n)
{
/// to rule out zero, negative and even inputs
if((n<1) || (n%2 == 0))
return(-1);
/// Declare an n x n array using C VLAs (Variable Length Arrays)
int mSquare[n][n];
/// Initialize the matrix with zeros
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
mSquare[i][j] = 0;
}
}
int count = 1; /// The first entry in the Magic Square
///start from middle col in the first row.
int col = (n-1)/2;
int row = 0;
/// Step1: Fill 1 in the middle column first row
mSquare[row][col] = count;
int row_t; /// for temporary storage
int col_t;
/************ INSERT YOUR CODE HERE ********/
/// Print the Magic Square
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
printf("%d\t", mSquare[i][j]);
}
printf("\n");
}
return(0);
}
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Objectives:
• Learn the basic operations with Strings.
• Differentiate between C Strings and 2D arrays.
• Using built-in C functions for string manipulation.
• Develop custom functions for C String manipulation.
The following declaration and initialization create a string consisting of the word "Hello". To
hold the null character at the end of the array, the size of the character array containing the string
is one more than the number of characters in the word "Hello."
If you follow the rule of array initialization then you can write the above statement as follows:
Actually, you do not place the null character at the end of a string constant. The C compiler
automatically places the '\0' at the end of the string when it initializes the array. Let us try to print
the above-mentioned string:
#include <stdio.h>
int main ()
{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
printf("Greeting message: %s\n", greeting );
return 0;
}
When the above code is compiled and executed, it produces the following result:
1
strcpy(s1, s2);
Copies string s2 into string s1.
2
strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
3
strlen(s1);
Returns the length of string s1.
4
strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
5
strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
6
strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.
#include <stdio.h>
#include <string.h>
int main () {
return 0;
}
When the above code is compiled and executed, it produces the following result:
strlen(str1) : 10
In-Lab Task 1:
Write a C Program that does the following:
1. Declares a C-String called ‘m1’ and initializes it with text “Programming is great fun!”.
2. Uses C-function puts() to print this string.
3. Asks the user to enter a String named ‘m2’ (Hint: Use gets() function for this.)
4. Concatenates the two strings and stores the result in ‘m3’.
For example if the user enters m2 as “Not Really!”, m3 should be “Programming is great
fun! Not really!”
5. Inserts the user entered array (m2) into m1 after “Programming is ...”
For the above example, the resultant String would become “Programming is Not really!
great fun!”
In-Lab Task 2 a:
Write a program that converts a string like "124" to an integer 124.
In-Lab Task 2 b:
Write a program that replaces two or more consecutive blanks in a string by a single blank. For
example, if the input is
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4
Lab # 12 Structures in C
Objectives:
• Learn the basics of C Structures.
• Learn to declare structures.
• Accessing elements of a structure.
• Develop programs for using C Structures
In-Lab Task 1:
Write a C Program that does the following:
In-Lab Task 2 a:
Write a C program that declares an array of structures of type ‘car’ from previous example, and
asks the user to fill in the elements. Once all the structures have been initialized, the program
should present a menu to the user so that he can print a certain structure, or modify its elements.
In-Lab Task 2 b:
There is a structure called employee that holds information like employee code, name, date of
joining. Write a program to create an array of the structure and enter some data into it. Then ask
the user to enter current date. Display the names of those employees whose tenure is 3 or more
than 3 years according to the given current date.
Lab Assessment
Pre Lab /1
In Lab /5
Data
Post Lab /4 /4
Presentation
Writing Style /4