COS201_2024-25
COS201_2024-25
1.4 Features of C
a) A knowledge of C will give you deep knowledge of what is going on beneath the surface of
higher- level languages like Java. The syntax of C pretty-well guarantees you will easily
understand other languages that came afterwards like C++, Java, Javascript, and C#.
b) A knowledge of C is now and has been for years a prerequisite for serious software
professionals and with the recent popularity and maturity of Open Systems this is even more
true.
c) C gives you access to the heart of the machine and all its resources at a fine-grained bit-
level.
d) C has been described as like “driving a Porsche with no brakes” - and because it is fast as
well this can be exhilarating. C is often the only option when speed and efficiency is crucial.
e) C has been called “dangerous” in that it allows low-level access to the machine but this
scariness is exactly what you need to understand as it gives you respect for the higher-level
languages you will use.
f) Many embedded miniaturised systems are all still written in C and the machine-to-machine
world of the invisible Internet for monitoring and process control often uses C.
g) C is more efficient than most programming languages.
h) The Linux kernel is scripted using C programming language.
i) When it comes to performance (speed of execution) nothing beats C.
j) C is the most widely-used portable language for low-level coding (compilers, and libraries,
and kernels).
1.5.1 Strengths
C’s strengths help explain why the language has become so popular:
i) Efficiency. Efficiency has been one of C’s advantages from the beginning. Because C
was intended for applications where assembly language had traditionally been used, it was
crucial that C programs could run quickly and in limited amounts of memory.
ii) Portability. Although program portability wasn’t a primary goal of C, it has turned out to
be one of the language’s strengths. When a program must run on computers ranging from
PCs to supercomputers, it is often written in C. One reason for the portability of C is that –
thanks to C’s early association with UNIX. Another is that C compilers are small and easily
written, which has helped make them widely available. Finally, C itself has features that
support portability (although there’s nothing to prevent programmers from writing non-
portable programs).
iii) Power. C’s large collection of data types and operators help make it a powerful
language. In C, it’s often possible to accomplish quite a bit with just a few lines of code.
iv) Flexibility. Although C was originally designed for systems programming, it has no
inherent restrictions that limit it to this area. C is now used for applications of all kinds, from
embedded systems to commercial data processing. Moreover, C imposes very few
restrictions on the use of its features; operations that would be illegal in other languages are
often permitted in C. For example, C allows a character to be added to an integer value (or,
for that matter, a floating-point number). This flexibility can make programming easier,
although it may allow some bugs to slip through.
v) Standard library. One of C’s great strngths is its standard library, which contains
hundreds of functions for input/output, string handling, storage allocations, and other useful
operations.
vi) Integration with UNIX. C is particularly powerful in combination with UNIX
(including the popular variant known as Linux). In fact, UNIX tools assume that the user
knows C.
1.5.2 Weaknesses
C’s weaknesses arise from the same source as many of its strengths: C’s closeness to the
machine. Here are a few of C’s most notorious problems:
i) C programs can be error-prone. C’s flexibility makes it an error-prone language.
Programming mistakes that would be caught in many other languages can’t be detected by a
C’s compiler. In this respect, C is a lot like assembly language, where most errors aren’t
detected until the program is run.
ii) C programs can be difficult to understand. Although C is a small language by most
measures, it has a number of features that aren’t found in all programming languages (and
that consequently are often misunderstood). These features can be combined in a great
variety of ways, many of which – although obvious to the original author of a program – can
be hard for others to understand. Another problem is the terse nature of C programs. C was
designed at a time when interactive communications with computers was tedious at best. As
a result, C was purposefully kept terse to minimize the time required to enter and edit
programs. C’s flexibility can also be a negative factor; programmers who are too clever for
their own good can make programs almost impossible to understand.
iii) C programs can be difficult to modify. Large programs written in C can be hard to
change if they haven’t been designed with maintenance in mind. Modern programming
languages usually provide features such as classes and packages that support the division of
a large program into more manageable pieces. C, unfortunately, lacks such features.
2.1 Introduction
Here, you are introduced to the C language so that you can understand what actually
programming in C is all about. What better way to gain an appreciation for this language
than by taking a look at an actual program written in C?
To begin with, let us consider an actual program written in C, which is a rather simple
example—a program that displays the phrase “Hello World!” in your window. The C program
below shows how to accomplish this task.
Program 2.1
#include <stdio.h>
int main()
{
/* my first program in C */
return 0;
}
In the C programming language, lowercase and uppercase letters are distinct. In addition, in
C, it does not matter where on the line you begin typing—you can begin typing your statement at
any position on the line. This fact can be used to your advantage in developing programs that are
easier to read. Tab characters are often used by programmers as a convenient way to indent lines.
Let us take a look at the various parts of the above program:
a) The first line of the program #include <stdio.h> is a preprocessor command which is
usually placed at the beginning of programs, tells a C compiler to include stdio.h
(standard input output header) file (which contains definition and declaration of system
defined function such as printf( ), scanf( ))before going to actual compilation. That is,
information about the standard input/output library will be included.
b) The next line int main() is the main function where the program execution begins and it is
encloses within the pair of curly braces. The abbreviation “int” implies that the main
function returns an integer. The main( ) function can be anywhere in the program but in
general practice it is placed in the first position.
c) The next line /*...*/ will be ignored by the compiler and it has been put to add additional
comments in the program. So such lines are called comments (details later) in the program.
d) The next line printf(...) is another function available in C which causes the message
"Hello, World!" to be displayed on your screen. The printf() function is defined in the
C Library - stdio.h include file. The last two characters in the string, namely the backslash
( \ ) and the letter n , are known collectively as the newline character. A newline character
tells the system to do precisely what its name implies — that is, go to a new line. Any
characters to be printed after the newline character then appear on the next line of the
display. In fact, the newline character is similar in concept to the carriage return key on a
typewriter.
All program statements in C must be terminated by a semicolon ( ; ).This is the reason for
the semicolon that appears immediately following the closing parenthesis of the printf call.
e) The next line return 0; terminates the main() function and return to the system a status value
of 0. You can use any integer here. Conventionally, zero is used to indicate that the program
completed successfully — that is, without running into any errors.
2.2 Compiler
Programs can be written in the C programming language. However, the CPU does not read C
directly. Instead, the C program that we create will be converted into binary (1's and 0's) by the
compiler. These 1's and 0's are typically referred to as machine language. The CPU will read the
instructions and information, represented in binary as machine language, and perform the
commands from the program.
The compiler is a program itself and is required in order to create the files needed to execute
programs written in C.
Take some time to explore Code::Blocks or whatever compiler you choose to install on your
computer. A robust IDE lets you perform these five steps easily, all from within the same
environment. You can compile your program, view any errors, fix the errors, run the program, and
look at the results, all from within the same screen and using a uniform set of menus.
2.7 Comments in C
Throughout a C program, you should add comments. Comments are messages scattered
throughout your programs that explain what’s going on. Comments are not C commands. C ignores
every comment in your program. Comments are for people, and the programming statements
residing outside the comments are for the computer. C programs can be cryptic, and comments
eliminate lots of confusion.
2.8 Whitespace
Whitespace is the collection of spaces and blank lines you find in many programs. In a way,
whitespace is more important than comments in making your programs readable. People need
whitespace when looking through a C program because those programs are more readable than
programs that run together too much.
3.1 Variables
The basic concept in a program is the concept of a variable. Today’s programming
languages allow you to concentrate more on solving the particular problem at hand than worrying
about specific machine codes or memory locations. They enable you to assign symbolic names,
known as variable names, for storing program computations and results. A variable name can be
chosen by you in a meaningful way to reflect the type of value that is to be stored in that variable.
The rules for forming variable names are quite simple:They must begin with a letter or
underscore ( _ ) and can be followed by any combination of letters (upper- or lower-case),
underscores, or the digits 0–9.The following is a list of valid variable names.
sum
pieceFlag
i
J5x7
Number_of_moves
_sysflag
On the other hand, the following variable names are not valid for the stated reasons:
sum$value $ is not a valid character.
piece flag Embedded spaces are not permitted.
3Spencer Variable names cannot start with a number.
int int is a reserved word.
It is important to note that there are certain words reserved for doing specific task, these
words are known as reserved word or keywords. These words are predefined and always written in
lower case or small letter. These keywords has special significance to the C compiler and cannot be
used as a variable name as it assigned with fixed meaning. Some examples are int, short,
signed,unsigned, default, volatile, float, long, double, break, continue,
typedef, static, do, for, union, return, while, do, extern, register, enum,
case, goto, struct, char, auto, const etc.
It should be noted that upper- and lowercase letters are distinct in C. Therefore, the variable
names sum , Sum , and SUM each refer to a different variable.
int sum;
sum = 50 + 25;
printf ("The sum of 50 and 25 is %i\n", sum);
return 0;
}
In Program 3.1, the first C program statement declares the variable sum to be of type integer.
C requires that all program variables be declared before they are used in a program. The declaration
of a variable specifies to the C compiler how a particular variable will be used by the program. This
information is needed by the compiler to generate the correct instructions to store and retrieve
values into and out of the variable. A variable declared as type int can only be used to hold integral
values; that is, values without decimal places.
The integer variable sum is used to store the result of the addition of the two integers 50 and
25. A blank line was intentionally left following the declaration of this variable to visually separate
the variable declarations of the routine from the program statements; this is strictly a matter of style.
Sometimes, the addition of a single blank line in a program can help to make the program more
readable.
The program statement
sum = 50 + 25;
reads as it would in most other programming languages:The number 50 is added (as indicated by
the plus sign) to the number 25 , and the result is stored (as indicated by the assignment operator,
the equal sign) in the variable sum.
The printf routine call in Program 3.1 now has two items or arguments enclosed within the
parentheses. These arguments are separated by a comma. The first argument to the printf routine
is always the character string to be displayed. However, along with the display of the character
string, you might also frequently want to have the value of certain program variables displayed. In
this case, you want to have the value of the variable sum displayed at the terminal after the
characters
“The sum of 50 and 25 is”
are displayed. The percent character inside the first argument is a special character recognised by
the printf function. The character that immediately follows the percent sign specifies what type of
value is to be displayed at that point. In the preceding program, the letter i is recognised by the
printf routine as signifying that an integer value is to be displayed.
Whenever the printf routine finds the %i characters inside a character string, it
automatically displays the value of the next argument to the printf routine. Because sum is the
next argument to printf, its value is automatically displayed after the characters “The sum of 50
and 25 is” are displayed.
#include <stdio.h>
int main (void)
{
int integerVar = 100;
float floatingVar = 331.79;
double doubleVar = 8.44e+11;
charcharVar = 'W';
_Bool boolVar = 0;
printf ("integerVar = %i\n", integerVar);
printf ("floatingVar = %f\n", floatingVar);
printf ("doubleVar = %e\n", doubleVar);
printf ("doubleVar = %g\n", doubleVar);
printf ("charVar = %c\n", charVar);
printf ("boolVar = %i\n", boolVar);
return 0;
}
integerVar = 100
floatingVar = 331.790009
doubleVar = 8.440000e+11
doubleVar = 8.44e+11
charVar = W
boolVar = 0;
Figure 3.1 Storing floating-point values often takes more memory than integers.
3.7 Working with Arithmetic Expressions
In C, just as in virtually all programming languages, the plus sign ( + ) is used to add two
values, the minus sign ( – ) is used to subtract two values, the asterisk ( * ) is used to multiply two
values, and the slash ( / ) is used to divide two values. These operators are known as binary
arithmetic operators because they operate on two values or terms.
Program 3.2 further illustrates the operations of subtraction, multiplication, and division.
4.1 Introduction
scanf and printf, which support formatted reading and writing, are two of the most
frequently used functions in C. As this laboratory section shows, both are powerful but tricky to use
proper
The values displayed can be constants, variables, or more complicated expressions. There’s
no limit on the number of values that can be printed by a single call of printf.
The format string may contain both characters and conversion specifications, which begin
with the % character. A conversion specification is a place holder representing a value to be filled in
during printing. The information that follows the % character specifies how the value is converted
from its internal form (binary) to printed form (characters) – that’s where the term “conversion
specification” comes from. For example, the conversion specification %d specifies that printf is to
convert an int value from binary to a string of decimal digits, while %f does the same for a float
value.
Ordinary characters in a format string are printed exactly as they appear in the string;
conversion specifications are placed by the values to be printed. Consider the following example:
int i, j;
float x, y;
i = 10;
j = 20;
x = 43.2892f;
y = 5527.0f;
printf (“i = %d, j = %d, x = %f, y = %f\n”, i, j, x, y);
This call of printf produces the following output:
i = 10, j = 20, x = 43.289200, y = 5527.000000
The ordinary characters in the format string are simply copied to the output line. The four
conversion specifications are replaced by the values of the variables i, j, x, and y, in that order.
alert (bell) \a
Backspace \b
New line \n
Horizontal tab \t
When they appear in printf format string, these escape sequences represent actions to
perform upon printing. Printing \a causes an audible beep on most machines. Printing \b moves the
cursor back one position. Printing \n advances the cursor to the beginning of the next line. Printing
\t moves the cursor to the next tab stop.
A string may contain any number of escape sequences. Consider the following example, in
which the format string contains six escape sequences:
Another common escape sequence is \”, which represents the ” character. Since the ”
character marks the beginning and end of a string, it can’t appear within a string without the use of
this escape sequence. Here’s an example:
printf(“\” Hello!\””);
int i, j;
float x, y;
scanf (“ %d %d %f %f”, &i, &j, &x, &y);
Note:
Forgetting to put the & symbol in front of a variable in a call of scanf will have
unpredictable – and possibly disastrous – results. A program crash is a common outcome. At the
very least, the value that is read from the input won’t be stored in the variable; instead, the variable
will retain its old value (which may be meaningless if the variable wasn’t given an initial value).
Omitting the & is an extremely common error – be careful!. Some compilers can spot this error and
produce a warning message such as “format arrangement is not a pointer” (The term pointer is
defined in Laboratory 7; the & symbol is used to create a pointer to a variable). If you get a
warning, check for a missing &.
4.5 Adding Fractions
To illustrate scanf’s ability to match patters, consider the problem of reading a fraction
entered by the user. Fractions are customarily written in the form numerator/denominator. Instead of
having the user enter the numerator and denominator a a fraction as separate integers, scanf makes
it possible to read the entire fraction. The following program, which adds two fractions, illustrates
this technique.
return 0;
}
Program output:
Enter first fraction: 5/6
Enter second fraction: ¾
The sum is 38/24
2. For each of the following pairs of scanf format strings, indicate whether or not the two
strings are equivalent. If they are not, show how they can be distinguished.
(a) “%d” versus “ %d”
(b) “%d-%d-%d” versus “%d -%d -%d”
(c) “%f” versus “%f ”
(d) “%f, %f” versus “%f, %f”
5.1 Introduction
A loop is simply a section of code that repeats a few times. You don’t want a loop to repeat
forever— that’s called an infinite loop. The loops you write (if you write them properly—and, of
course, you will) should come to a conclusion when they finish doing the job you set them up to do.
One of the fundamental properties of a computer is its ability to repetitively execute a set of
statements. These looping capabilities enable you to develop concise programs containing repetitive
processes that could otherwise require thousands or even millions of program statements to
perform. The C programming language contains three different program statements for program
looping. They are known as the for statement, the while statement, and the do statement. Each of
these statements are described in detail in this chapter.
The three expressions that are enclosed within the parentheses — init_expression,
loop_condition , and loop_expression — set up the environment for the program loop. The
program statement that immediately follows (which is, of course, terminated by a semicolon) can be
any valid C program statement and constitutes the body of the loop. This statement is executed as
many times as specified by the parameters set up in the for statement. The first component of the for
statement, labeled init_expression , is used to set the initial values before the loop begins. The
second component of the for statement the condition or conditions that are necessary for the loop to
continue. In other words, looping continues as long as this condition is satisfied.
Program 5.1 is a sample code to illustrate the usage of the for loop.
Program 5.1
/* Prints 1, 4, 7, 10, 13, 16 */
#include <stdio.h>
main()
{
for (int i = 1; i < 18; i += 3)
{
printf("%d ", i);
}
return 0;
}
Program 5.2
/* Program to calculate the sum of first 200 natural numbers
Introduction of the for statement
*/
#include <stdio.h>
int main (void)
{
int sum;
sum = 0;
for ( int counter = 1; counter <= 200; counter = counter + 1 )
sum = sum + counter;
printf ("The sum of first 200 natural numbers is %i\n", sum);
return 0;
}
Program 5.3 is an improvement on Program 5.2 whereby the result of each iteration is printed to
the screen
Program 5.3
/* Program to calculate the sum of first 200 natural numbers
Introduction of the for statement
*/
#include <stdio.h>
int main (void)
{
int sum;
sum = 0;
for ( int counter = 1; counter <= 200; counter = counter + 1 )
{ // added to print each iteration
sum = sum + counter;
printf ("The sum of first 200 natural numbers is %i\n", sum);
} // added to print each iteration
return 0;
}
i = 10;
for ( ; i > 0; --i )
printf (“T minus %d and counting \n”, i);
In this example, i has been initialized by a separate assignment, so we’ve omitted the first
expression in the for statement. (Notice that the semicolon between the first and second
expressions remains. The two semicolons must always be present, even when we’ve omitted some
of the expressions.)
If we omit the third expression if a for statement, the loop body is responsible for ensuring
that the value of the second expression eventually becomes false. Our for statement example could
be written like this:
return 0;
}
According to the output, the number 200 was typed in by the user. The program then proceeded to
calculate the sum of first 200 natural numbers and displayed the result of 20100 at the terminal. The
user could have instead typed in the number 10, or 30, if he desired to calculate those particular
sum of first natural numbers.
The first printf statement in Program 5.4 is used to prompt the user to type in a number. After
the message is printed, the scanf routine is called. The first argument to scanf is the format string
and is very similar to the format string used by printf. In this case, the format string doesn’t tell
the system what types of values are to be displayed but rather what types of values are to be read in
from the terminal. Like printf , the %i characters are used to specify an integer value.
The second argument to the scanf routine specifies where the value that is typed in by the user is
to be stored. The & character before the variable number is necessary in this case. Don’t worry about
its function here, though. Laboratory Seven, “Pointers,” discusses this character, which is actually
an operator, in great detail. & is called “Pointers” and it is necessary to place it in front of the
variable name in the scanf function call. If you forget, it causes unpredictable results and might
cause your program to terminate abnormally.
Sequel to the fore-going discussion, it can be seen that the scanf call from Program 4.4 specifies
that an integer value is to be read from the terminal and stored in the variable number.
After this number has been typed in (and the “Return” or “Enter” key on the keyboard pressed to
signal that typing of the number is completed), the program then proceeds to perform the
computation.
NOTE:
To display a double value, the format characters %f , %e , or %g characters used to display a
float value, can be used.
while ( expression )
program statement
The expression specified inside the parentheses is evaluated. If the result of the expression
evaluation is TRUE, the program statement that immediately follows is executed. After
execution of this statement (or statements if enclosed in braces), the expression is once again
evaluated. If the result of the evaluation is TRUE, the program statement is once again executed.
This process continues until the expression finally evaluates as FALSE, at which point the loop is
terminated. Execution of the program then continues with the statement that follows the program
statement.
As an example of its use, Program 5.5 sets up a while loop, which merely counts from 1 to 5.
It is worth noting in passing that Program 5.4 could have readily be accomplished using a for
statement. In fact, a for statement can always be translated into an equivalent while statement,
and vice versa. For example, the general for statement
init_expression;
while ( loop_condition )
{
program statement
loop_expression;
}
After you become familiar with the use of the while statement, you will gain a better feel as to
when it seems more logical to use a while statement and when to use a for statement.
i = 1;
while (i < = n) {
printf (“%10d%10d\n”, i, i * i);
i++;
}
return 0;
}
Note how the program displays numbers aligned numbers in neatly aligned colums. The trick is to
use a conversion specification like %10d instead of just %d, taking advantage of the fact that printf
right-justifies numbers when a field width is specified.
Clearly we’ll need a loop that uses scanf to read a number and then adds the number to a running
total.
Letting n represent the number just read and sum the total of all numbers previously read, we end
up with the following program:
Program 5.6 Summing a Series of Numbers
#include <stdio.h>
int main (void)
{
int n, sum =0;
return 0;
}
do
program statement
while ( loop_expression );
Execution of the do-while statement proceeds as follows: the program statement is executed
first. Next, the loop_expression inside the parentheses is evaluated. If the result of evaluating the
loop_expression is TRUE, the loop continues and the program statement is once again
executed. As long as evaluation of the loop_expression continues to be TRUE, the program
statement is repeatedly executed. When evaluation of the expression proves FALSE, the loop is
terminated, and the next statement in the program is executed in the normal sequential manner.
The do-while statement is simply a transposition of the while statement, with the looping
conditions placed at the end of the loop rather than at the beginning.
Note that, unlike the for and while loops, the do-while statement guarantees that the body of the
loop is executed at least once.
Our strategy will be to divide the user’s input by 10 repeatedly until it becomes 0; the number of
divisions performed is the number of digits. Clearly, we’ll need some kind of loop, since we don’t
know how many divisions it will take to reach 0. But should we use a while statement or do
statement? The do statement turns out to be more attractive, because every integer – even 0 – has at
least one digit. Here’s the program:
do {
n /= 10;
digits ++;
} while (n > 0);
return 0;
}
To see why the do statement is the right choice, let’s see what would happen if we were to replace
the do loop by a similar while loop:
while (n > 0)
{
n /= 10;
digits ++;
}
If n is 0 initially, this loop won’t execute at all, and the program would print
The number has 0 digit (s).
for ( ; ; ) {
printf (“Enter a number (enter 0 to stop): ”);
scanf (“%d”, &n);
if (n == 0)
break;
printf (“%d cubed is %d\n”, n, n * n);
The break statement transfers control out of the innermost enclosing while, do, for statement.
n = 0;
sum = 0;
while (n < 10)
{
scanf (“%d”, &i);
if (i ==0)
continue;
sum += i;
n++;
/* continue jumps to here */
A statement may have more than one label. The goto statement itself has the form
goto identifier ;
Executing the statement goto L; transfers control to the statement that follows the label L, which
must be in the same function as the goto statement itself.
If C didn’t have a break statement, here’s how we might use a goto statement to exit prematurely
from a loop:
done:
if (d < n)
printf (“%d is divisible by %d\n”, n, d);
else
printf (“%d is prime \n”, n);
5.7 Note:
A for loop offers more control than while and do-while. With a for loop, you can specify
exactly how many times you want to loop; with while loops, you must continue looping as long as
a condition is true.
6.1 Introduction
In Study Session 4, “Program Looping in C,” you learned that one of the fundamental properties of
a computer is its capability to repetitively execute a sequence of instructions. But another
fundamental property lies in its capability to make decisions. You saw how these decision-making
powers were used in the execution of the various looping statements to determine when to terminate
the program loop. Without such capabilities, you would never be able to “get out” of a program
loop and would end up executing the same sequence of statements over and over again,
theoretically forever (which is why such a program loop is called an infinite loop).
printf ("\n");
return 0;
}
After the number is typed in, the remainder after division by 2 is calculated. The first if
statement tests the value of this remainder to see if it is equal to zero. If it is, the message “The
number is even” is displayed.
The second if statement tests the remainder to see if it’s not equal to zero and, if that’s the case,
displays a message stating that the number is odd.
When writing programs, this “else” concept is so frequently required that almost all modern
programming languages provide a special construct to handle this situation. In C, this is known as
the if-else construct and the general format is as follows:
if
( expression )
program statement 1
else
program statement 2
The if-else is actually just an extension of the general format of the if statement. If the result of
the evaluation of expression is TRUE, program statement 1 , which immediately follows, is
executed; otherwise, program statement 2 is executed. In either case, either program statement 1 or
program statement 2 is executed, but not both.
You can incorporate the if-else statement into Program 6.2, replacing the two if statements with a
single if-else statement. The use of this new program construct actually helps to reduce the
program’s complexity and also improves its readability, as shown in Program 6.3.
Note:
Don’t confuse = = (equality) with = (assignment). The statement
if (i = = 0) …..
tests whether i is equal to 0. However, the statement
if (i = 0) …
assigns 0 to i, then tests whether the result in nonzero. In this case, the tests always fails.
Confusing = = with = is perhaps the most common C programming error, probably because =
means “is equal to” in mathematics (and in certain programming languages). Some compilers issues
a warning if they notice = where = = would normally appear.
6.4 Compound Relational Tests
The if statements discussed so far in this chapter is used to set up a simple relational tests between
two numbers. Sometimes, it becomes desirable, if not necessary, to set up more sophisticated tests.
The C language provides the mechanisms necessary to perform these types of compound
relational tests. A compound relational test is simply one or more simple relational tests joined by
either the logical AND or the logical OR operator. These operators are represented by the character
pairs && and || (two vertical bar characters), respectively. As an example, the C statement
Example:
a) (5==5) &&(3>6) //False
b) (5==5) || (3>6) //True
c) (8 = = 6*2) || (12 > 15) // False
d) !True //means False
e) !False //means True
f) !(5==5) //False
g) !(6<=4) //True
which effectively extends the if statement from a two-valued logic decision to a three-valued
logic decision. You can continue to add if statements to the else clauses, in the manner just shown,
to effectively extend the decision to an n-valued logic decision.
The preceding construct is so frequently used that it is generally referred to as an else if
construct and is usually formatted differently from that shown previously as
if ( expression 1 )
program statement 1
else if ( expression 2 )
program statement 2
else
program statement 3
This latter method of formatting improves the readability of the statement and makes it clearer
that a three-way decision is being made.
Pointer variables, often called pointers, let you do much more with C than you can with
programming languages that don’t support pointers. In fact, one of the most sophisticated features
of C programming is the pointer and provides the means for the true power of C.
Pointers operate based on the concept of indirection. A pointer provides an indirect means of
accessing the value of a particular data item.
Pointer variables hold addresses of other variables. That’s their primary purpose. Use the address-of
operator, &, to assign the address of one variable to a pointer. Until you assign an address of a
variable to a pointer, the pointer is uninitialized and you can’t use it for anything.
But enough talk—it’s time to see how pointers actually work. The following code defines an integer
variable named age and stores 19 in age. Then a pointer named variable pAge is defined and
initialized to point to age. The address-of operator reads just like it sounds. The second line that
follows tells C to put the address of age into pAge.
int age = 19; /* Stores a 19 in age */
int *pAge = &age; /* Links up the pointer to another variable */
You have no idea exactly what address C will store age at. However, whatever address C uses, pAge
will hold that address. When a pointer variable holds the address of another variable, it essentially
points to that variable. Assuming that age is stored at the address 18826 (only C knows exactly
where it is stored), Figure 7.1 pictures this concept.
Figure 7.1 The variable pAge points to age if pAge holds the address of age.
It should be noted that the asterisk, * dereferencing operator isn’t part of a pointer variable’s
name. It is simply used to tell C that the variable is a pointer, not a regular variable. The following
four statements do exactly the same thing as the previous two statements. Notice that you don’t use
* to store the address of a variable in a pointer variable unless you are also defining the pointer at
the same time.
int age; // Defines a regular integer
int * pAge; // Defines a pointer to an integer
age = 19; //Stores 19 in age
pAge = &age; // Links up the pointer to another variable, age
8.1 Introduction
This chapter teaches how C’s array and pointer variables share a lot of principles. As a matter of
fact, an array is a special kind of pointer. Because of their similarities, you can use pointer notation
to get to array values, and you can use array notation to get to pointed-at values.
8.2 An Array
An array is a series of elements of the same type placed in contiguous memory locations that can
be individually referenced by adding an index to a unique identifier. An array of characters is a
string. An array can also be described as a data structure used to group together data items of the
same type. That is, a collection of variables of the same type. Each element has a different index
number known as subscript.
The format for representing an array is:
type array_name [arraySize];
The items in an array are called elements.
As an example, the declaration
int values [10];
reserves enough space for an array called values that could hold up to 10 integer elements. You
can better conceptualize this reserved storage space by referring to Figure 8.1.
Program 8.1
//Program to stores five numbers and add them up
#include <stdio.h>
int main (void)
{
int array_values[5] = { 16, 1, 4, 9, 5 };
int sum=0;
for ( int i = 0; i < 5; ++i )
sum = sum + array_values[i];
printf ("Sum is %i\n", sum);
return 0;
}
Program 8.2 illustrates an array that stores five numbers, add them up and find the average.
Program 8.2
//Program to stores five numbers, add them up and find the average
#include <stdio.h>
int main (void)
{
int array_values[5] = { 16, 1, 4, 9, 5 };
int sum=0;
int avg=0;
for ( int i = 0; i < 5; ++i )
sum = sum + array_values[i];
avg = sum /5;
printf ("Sum = %i, Average = %i\n", sum, avg);
return 0;
}
num[2][1] =5;
9.1 Introduction
Function is an essential component of the C programming language. In fact, every C program has
a function therein, at least the main () funcion. The scanf () and printf () routines used so far
are also functions. Basically, program function provides the mechanism for producing programs that
are easy to write, read, understand, debug, modify, and maintain.
9.2 Functions
A function is a self contained block of codes or sub programs with a set of statements that
perform some specific task or coherent task when it is called. It can be described as hiring a person
to do some specific task like, every six months servicing a car and hand over to it.
By using functions, large and difficult program can be divided in to sub programs and solved.
When we want to perform some task repeatedly or some code is to be used more than once at
different place in the program, then function avoids this repetition or rewritten over and over.
Function declaration is also known as function prototype declaration. It inform the compiler
about three thing, those are name of the function, number and type of argument received by
the function and the type of value returned by the function.
While declaring the name of the argument is optional and the function prototype always
terminated by the semicolon.
If a function returns any value other than int, you should prototype that function. Actually,
you should prototype functions that return integers as well for clarity.
The word prototype means a model of something else. A prototype of a function is just a
model of the actual function.
The reason functions that return int values don’t need prototypes is that int is the default
prototyped return value unless you specify a different return value. Therefore, these two
prototypes both model the same function:
Syntax:-
return_type function(type 1 arg1, type2 arg2, type3 arg3) /*function header*/
{
Local variable declaration;
Statement 1;
Statement 2;
Return value;
}
The return_type denotes the type of the value that function will return and it is optional and if it
is omitted, it is assumed to be int by default. The body of the function is the compound statements
or block which consists of local variable declaration statement and optional return statement.
Note that the local variables declared inside a function is local to that function only. It can’t be
used anywhere in the program and its existence is only within this function. The arguments of the
function definition are known as formal arguments.
main()
{
function(arg1,arg2,arg3); /* calling function */
}
return expression;
This statement indicates that the function is to return the value of expression to the calling
routine. Parentheses are placed around expression by some programmers as a matter of
programming style, but their use is optional.
Example:
return a;
return a*b;
return (a*b+c);
An appropriate return statement is not enough. When the function declaration is made, you must
also declare the type of value the function returns. This declaration is placed immediately
before the function’s name.
Each of the previous examples discussed hitherto defined the function main to return an integer
value, which is why the keyword int is placed directly before the function name.
In a sense, the void data type is actually defining the absence of a data type. Therefore, a
function declared to be of type void has no value and cannot be used as if it does have a value in
an expression.
Programming is good.
Program 9.1 consists of two functions: printMessage and main. Program execution always
begins with main. Inside that function, the statement
printMessage ();
appears. This statement indicates that the function printMessage is to be executed. The open and
close parentheses are used to tell the compiler that printMessage is a function and that no
arguments or values are to be passed to this function (which is consistent with the way the function
is defined in the program). When a function call is executed, program execution is transferred
directly to the indicated function. Inside the printMessage function, the printf statement is
executed to display the message “Programming is good.” at the terminal. After the message has
been displayed, the printMessage routine is finished (as signaled by the closing brace) and the
program returns to the main routine, where program execution continues at the point where the
function call was executed. Note that it is acceptable to insert a return statement at the end of
printMessage like this:
return;
return 0;
}
return 0;
float answer;
return 0;
return firstSide;
else
return secondSide;
For your first program that illustrates a function that takes an array as an argument, you can write
a function minimum to find the minimum value in an array of 10 integers. This function, together
with a main routine to set up the initial values in the array, is shown in Program 9.5.
{
int scores[10], i, minScore;
return 0;
}
10.1 Introduction
The heap is the collection of unused memory in your computer. The memory left over—after
your program, your program’s variables, and your operating system’s workspace—comprises your
computer’s available heap space, as Figure 10.1 shows.
Many times you’ll want access to the heap, because your program will need more memory than
you initially defined in variables and arrays. The free heap memory is called free heap or
unallocated heap memory. The part of the heap in use by your program at any one time is called the
allocated heap. Your program might use varying amounts of heap space as the program executes.
You don’t assign variable names to heap memory. The only way to access data stored in heap
memory is through pointer variables. Aren’t you glad you learned about pointers already? Without
pointers, you couldn’t learn about the heap.
You must learn only two new functions to use the heap. The malloc() (for memory allocate)
function allocates heap memory, and the free() function deallocates heap memory. Note: be sure
to include the stdlib.h header file in all the programs you write that use malloc() and free().
Perhaps looking at an example of malloc() is the best place to start. Suppose you were writing a
temperature-averaging program for a local weather forecaster. The more temperature readings the
user enters, the more accurate the correct prediction will be. You decide that you will allocate 10
integers to hold the first 10 temperature readings. If the user wants to enter more, your program can
allocate another batch of 10, and so on.
You first need a pointer to the 10 heap values. The values are integers, so you need an integer
pointer. You need to define the integer pointer like this:
int * temps; /* Will point to the first heap value */
Here is how you can allocate 10 integers on the heap using malloc():
malloc(10 * sizeof(int))
This part of the statement told malloc() to allocate, or set aside, 10 contiguous integer locations
on the heap. In a way, the computer puts a fence around those 10 integer locations so that
subsequent malloc() calls do not intrude on this allocated memory. Now that you’ve mastered that
last half of the malloc() statement, there’s not much left to understand. The first part of malloc()
is fairly easy.
malloc() always performs the following two steps (assuming that enough heap memory exists to
satisfy your allocation request):
1. Allocates the number of bytes you request and makes sure no other program can overwrite
that memory until your program frees it
2. Assigns your pointer to the first allocated value
Figure 10.2 shows the result of the previous temperature malloc() function call. As you can see
from the figure, the heap of memory (shown here as just that, a heap) now contains a fenced-off
area of 10 integers, and the integer pointer variable named temps points to the first integer.
Subsequent malloc() function calls will go to other parts of the heap and will not tread on the
allocated 10 integers.
aVal = (int)salary;
The * inside a typecast means that the typecast is a pointer typecast. malloc() always returns a
character pointer. If you want to use malloc() to allocate integers, floating points, or any kind of
data other than char, you have to typecast the malloc() so that the pointer variable that receives
the allocation (such as temps) receives the correct pointer data type. temps is an integer pointer; you
should not assign temps to malloc()’s allocated memory unless you typecast malloc() into an
integer pointer.
Therefore, the left side of the previous malloc() simply tells malloc() that an integer pointer, not
the default character pointer, will point to the first of the allocated values.
Here comes the big question. What do you do with the 10 integers you just allocated? Treat them
like an array! You can store data by referring to temps[0], temps[1], and so on. Also
remember that each set of allocated memory will be contiguous, so the 10 integers will follow each
other just as if you allocated temps as a 10-integer array.
Programmers often use the not operator, !, instead of testing a value against 0, as done
here. Therefore, the previous if test would more likely be coded like this:
10.5 Illustration
Program 10.2 illustrates a heap that stores five numbers, add them up and find the average.
Program 10.2
/*Program to stores five numbers, add them up and find the average
using heap */
#include <stdio.h>
#include <stdlib.h>
if (!ptemps)
{
printf("Oops! Not Enough Memory! \n");
exit(1);
}
ptemps[0] = 197;
ptemps[1] = 100;
ptemps[2] = 350;
ptemps[3] = 153;
ptemps[4] = 453;
free(ptemps);
return 0;
}
11.1 Introduction
A structure is the collection of dissimilar data types or heterogeneous data types grouped together.
It means the data types may or may not be of same type.
The format for a Structure is as follows:
struct tagname
{
Data_type member_1;
Data_type member_2;
Data_type member_3;
. . . . . . . . . .
. . . . . . . . . .
Data_type member_n;
};
The date structure just defined contains three integer members called month, day, and year. The
definition of date in a sense defines a new type in the language in that variables can subsequently be
declared to be of type struct date, as in the declaration
struct date today;
You can also declare a variable purchaseDate to be of the same type by a separate declaration,
such as
struct date purchaseDate;
Or, you can simply include the two declarations on the same line, as in
struct date today, purchaseDate;
Unlike variables of type int, float, or char, a special syntax is needed when dealing with
structure variables. A member of a structure is accessed by specifying the variable name, followed
by a period, and then the member name. For example, to set the value of the day in the variable
today to 25, you write
today.day = 25;
#include <stdio.h>
return 0;
}
Program 11.1 Output
return 0;
The first statement inside main defines the structure called date to consist of three integer
members called month, day, and year. In the second statement, the variable today is declared to
be of type struct date. The first statement simply defines what a date structure looks like to the C
compiler and causes no storage to be reserved inside the computer. The second statement declares a
variable to be of type struct date and, therefore, does cause memory to be reserved for storing the
three integer values of the variable today. Be certain you understand the difference between
defining a structure and declaring variables of the particular structure type.
After today has been declared, the program then proceeds to assign values to each of the three
members of today, as depicted in Figure 11.1.
Figure 11.1. Assigning values to a structure variable.
After the assignments have been made, the values contained inside the structure are displayed by an
appropriate printf call. The remainder of today.year divided by 100 is calculated prior to being
passed to the printf function so that just 04 is displayed for the year. Recall that the format
characters %.2i are used to specify that two integer digits are to be displayed with zero fill. This
ensures that you get the proper display for the last two digits of the year.
Suppose you want to write a simple program that accepts today’s date as input and displays
tomorrow’s date to the user. Now, at first glance, this seems a perfectly simple task to perform. You
can ask the user to enter today’s date and then proceed to calculate tomorrow’s date by a series of
statements, such as
tomorrow.month = today.month;
tomorrow.day = today.day + 1;
tomorrow.year = today.year;
Of course, the preceding statements work just fine for the majority of dates, but the following two
cases are not properly handled:
One way to determine easily if today’s date falls at the end of a month is to set up an array of
integers that corresponds to the number of days in each month. A lookup inside the array for a
particular month then gives the number of days in that month. So the statement
int daysPerMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
defines an array called daysPerMonth containing 12 integer elements. For each month i, the value
contained in daysPerMonth[i - 1] corresponds to the number of days in that particular month.
Therefore, the number of days in April, which is the fourth month of the year, is given by
daysPerMonth[3], which is equal to 30. (You could define the array to contain 13 elements, with
daysPerMonth[i] corresponding to the number of days in month i. Access into the array could
then be made directly based on the month number, rather than on the month number minus 1.
If it is determined that today’s date falls at the end of the month, you can calculate
tomorrow’s date by simply adding 1 to the month number and setting the value of the day equal to
1.
To solve the second problem mentioned earlier, you must determine if today’s date is at the
end of a month and if the month is 12. If this is the case, then tomorrow’s day and month must be
set equal to 1 and the year appropriately incremented by 1.
Program 10.3 asks the user to enter today’s date, calculates tomorrow’s date, and displays
the results.
if ( today.day != daysPerMonth[today.month - 1] )
{
tomorrow.day = today.day + 1;
tomorrow.month = today.month;
tomorrow.year = today.year;
}
else if ( today.month == 12 )
{ // end of year
tomorrow.day = 1;
tomorrow.month = 1;
tomorrow.year = today.year + 1;
}
else { // end of month
tomorrow.day = 1;
tomorrow.month = today.month + 1;
tomorrow.year = today.year;
}
return 0;
}
/* Program to generate the previous date given a date, assumes date given as dd mm yyyy
separated by space and performs error checking of the current date entered. */
#include <stdio.h>
#include <conio.h>
int main ()
{
/* Date Entry */
if (validDate) {
if (day == 1) {
if (month == 1) {
year --;
day = 31;
month =12;
}
else if (month == 3)
int rval = 0;
if (year %4 == 0)
{
rval =1;
if ((year % 100) == 0 && (year % 400) != 0)
{
rval = 0;
}
}
if (rval == 1)
{
day = 29;
month --;
}
else
{
day = 28;
month --;
}
}
else if (month ==2 || month == 4 || month == 6 || month == 9 || month == 11)
{
day = 31;
month --;
}
else
{
day = 30;
month --;
}
}
else
{
day --;
}
getche ();
return 1;
12.1 Introduction
This laboratory session introduces you to a data type that has not yet been described: the
enumerated data type.
defines a data type primaryColor. Variables declared to be of this data type can be assigned the
values red, yellow, and blue inside the program, and no other values. That’s the theory anyway!
An attempt to assign another value to such a variable causes some compilers to issue an error
message. Other compilers simply don’t check.
To declare a variable to be of type enum primaryColor, you again use the keyword enum,
followed by the enumerated type name, followed by the variable list. So the statement
defines the two variables myColor and gregsColor to be of type primaryColor. The only
permissible values that can be assigned to these variables are the names red, yellow, and blue. So
statements such as
myColor = red;
and
if ( gregsColor == yellow )
…
are valid. As another example of an enumerated data type definition, the following defines the type
enum month, with permissible values that can be assigned to a variable of this type being the
months of the year:
enum month { january, february, march, april, may, june, july, august,
september, october, november, december };
The C compiler actually treats enumeration identifiers as integer constants. Beginning with the first
name in the list, the compiler assigns sequential integer values to these names, starting with 0. If
your program contains these two lines:
the value 1 is assigned to thisMonth (and not the name february) because it is the second
identifier listed inside the enumeration list.
If you want to have a specific integer value associated with an enumeration identifier, the
integer can be assigned to the identifier when the data type is defined. Enumeration identifiers that
subsequently appear in the list are assigned sequential integer values beginning with the specified
integer value plus 1. For example, in the definition
an enumerated data type direction is defined with the values up, down, left, and right. The compiler
assigns the value 0 to up because it appears first in the list; 1 to down because it appears next; 10 to
left because it is explicitly assigned this value; and 11 to right because it appears immediately after
left in the list.
12.3 Illustration
Program 12.1 shows a simple program using enumerated data types. The enumerated data type
month sets january to 1 so that the month numbers 1 through 12 correspond to the enumeration
values january, february, and so on. The program reads a month number and then enters a
switch statement to see which month was entered. Recall that enumeration values are treated as
integer constants by the compiler, so they’re valid case values. The variable days is assigned the
number of days in the specified month, and its value is displayed after the switch is exited. A special
test is included to see if the month is February.
switch (aMonth ) {
case january:
case march:
case may:
case july:
case august:
case october:
case december:
days = 31;
break;
case april:
case june:
case september:
case november:
days = 30;
break;
case february:
days = 28;
break;
default:
printf (“bad month number\n”);
days = 0;
break;
}
if ( days != 0 )
printf (“Number of days is %i\n”, days);
if ( amonth == february )
printf (“...or 29 if it’s a leap year\n”);
return 0;
}