C Programming Language Quickstart Guide - Simplified Guide For Beginners - PDF Room
C Programming Language Quickstart Guide - Simplified Guide For Beginners - PDF Room
Language
By:
R.J. KHAN
Introduction
Are you looking for a simple, complete and quick reference for programming in
C? If yes, you’ll find this book more useful than any other book out there. The
book presents the general-purpose language, step by step. The book is written
following a programmer’s approach and is therefore ideal for using as a quick
guide and reference.
We study in detail about the Functions in C. The book discusses the built in
functions as well as describes the rules and basics of writing your own functions.
The chapter also includes programming examples.
Arrays, pointers and Strings are strong points of C language and hence are
discussed separately in one chapter. The topics are closely related, hence
comparisons and contrasts are worth the discussion.
R.J. Khan
The trademarks that are used are without any consent, and the publication of the
trademark is without permission or backing by the trademark owner. All
trademarks and brands within this book are for clarifying purposes only and are
the owned by the owners themselves, not affiliated with this document.
TABLE OF CONTENTS
Chapter 1
Let’s C………………………………………………………………6
1. Background……………………………………………………………….6
2. ANSI C……………………………………………………………………...7
3. Strengths of C……………………………………………………………8
4. Programming in C……………………………………………………..9
5. Nothing is Perfect……………………………………………………..10
Chapter 2
Tokens and Syntax…………………………………………..11
1. Preprocessors…………………………………………………………….11
2. Variables……………………………………………………………………14
3. Constants…………………………………………………………………..16
4. Keywords…………………………………………………………………..17
5. Character Constants……………………………………………………18
2. Floating point……………………………………………………………38
4. Storage classes…………………………………………………………..39
5. Default Initializers…………………………………………………….43
Chapter 4
Loops and Decisions………………………………………..44
1. If else……………………………………………………………44
2. Switch case…………………………………………………….46
3. For loop………………………………………………………….48
4. While loop………………………………………………………50
5. Do while loop…………………………………………………….51
6. Nested Loops…………………………………………………….52
Chapter 5
Functions……………………………………….……………….54
1. Function Definition……………………………………………54
3. Alternative Declarations……………………………………..58
4. Function Invocation……………………………………………59
5. Environment……………………………………………………..60
6. Recursion………………………………………………………….61
7. Examples…………………………………………………………..62
Chapter 6
Arrays, Strings and Pointers………………………………66
1. 1-D Arrays…………………………………………………………66
2. Pointers…………………………………………………………...68
3. Strings……………………………………………………………...72
4. 2D-Arrays…………………………………………………………75
5. 3D-Arrays…………………………………………………………76
Chapter 7
Structures ……………………………………………………….77
1. Declaration……………………………………………………..77
2. Memory Allocation………………………………………….78
4. Definition……………………………………………………….80
1. Composition…………………………………………………… 90
2. Insert Function………………………………………………..91
3. Search Function……………………………………………….92
Conclusion
Chapter 1: Let’s C
By the early 1980s, the language has transformed itself into what it looks like
today, commonly known as the traditional C. ANSI standard C was introduced
in the later part of the same decade. The committee added the void, function
prototypes, a new function definition syntax, and more functionality for the
preprocessor, and in general made the language definition more precise.
ANSI C maintained its standard in an amazing way that it is still used in many
programs as a system language. It is one of the most commonly used
programming languages of the world, and it is found in colleges and universities
for learning purposes. It is mostly the first programming course offered to any IT
students. C++ is an extension of ANSI standard C which incorporates the object
oriented programming paradigm, which kind of revolutionized the programming
world. This book describes the ANSI version of the C
are important in a sense that everyone can have his own perspective. For
example, while travelling in a train, what seems to be stationary for you, might
example, while travelling in a train, what seems to be stationary for you, might
be moving for someone outside the train. ANSI Committee X3Jl1 is responsible
for setting the standard for the programming language C. In the late 1980s, the
committee created draft standards for what is known as ANSI C or standard C.
In 1990, the International Organization for Standardization (ISO) approved the
standard for ANSI C as well.
and defines the standards for how these programs are to be interpreted. The
standardization results in better portability, reliability, maintainability, and
efficient execution of C language programs on different machines. All the
compilers follow this standard and hence there is uniformity in interpretation of
code.
1.3 Strengths of C:
The programming languages that are being used today are so powerful that
nothing remains impossible. But this power depends directly on how vast a
language is, which is determined by number of reserved keywords. C has fewer
keywords than Pascal, but it is more powerful than it. The power of C lies in the
unrestricted structure of programming in it. Although, C has its limitations like
any other language but it comes as the best in its capacity. Because C is a small
language, hence it is ideal to start your programming career from it. It is easy to
master when compared with other languages. Once you have mastered C, you
can then easily move on to the more powerful and vast languages.
We will now briefly discuss the strong characteristics of C, which will motivate
the readers to program in C.
• C is small but has a very powerful set of operators. Some of these operators
allow the programmer to access the machine at the bit level. For example, a
powerful increment operator “++” can manipulate the machine in the same way
as machine code does. This results in higher efficiency as other languages
require multiple statements to complete the equivalent task.
• C is modular. C uses the external functions, for which arguments are passed
using call-by-value technique. Pointers are used for passing arguments using
call-by-reference technique. The nesting of functions is not allowed. Using the
storage class static within files provides a limited form of privacy. These
features, along with tools provided by the operating system, readily support user-
defined libraries of functions and modular programming.
• C laid the basis for C++ and Java. This can be clearly seen by analyzing the
common attributes and functionalities of these languages. C++ and Java support
the basic structure of functions, methods or routines in C++ or Java. The
primitive data types are retained as well. Thus, learning C prior to learning C++
Assembly language has short labels for certain commands to do certain tasks, for
example ADD, MOV etc. High Level languages are the easiest way for a
programmer to communicate with a machine.
The source code for C is written in some text editor and compiler. Common
examples of such editors are Turbo C++, Borland C++ etc. We will be using
Visual Studio 2012 for coding throughout in this book.
First of all, you need to set up your IDE (Integrated Development Environment).
We recommend Borland C++. Visual Studio is for pros but is not a good choice
for students because of its helpful nature. From here onwards, we assume that
you have an IDE installed on your computer system and can compile a source
code in C.
You need to create a new file with .c or .cpp extension. This file will have your
source code, which will be compiled using your respective compiler. Let’s name
our file as “myFirstProgram.c”.
In “myFirstProgram.c”:
#include <iostream>
void main(void)
Before going any further, let’s just try to compile and execute this code. On
doing so, you’ll realize that a black screen appears for a millisecond and then
disappears.
What actually happens is, that the computer runs the program and exits when the
source code ends. So it exits before us seeing any of the output. To stop our
program from doing it, we need to add an extra line at the end of our code.
#include <iostream>
void main(void)
system("pause");
If
no
errors
are
made,
the
output
will
be
like
this:
The first line of our program includes a library in our program. This library has
the functions like printf, system and similarly others which we can use in our
program.
The next line declares our main method. The main method in any program is the
entry point for our logic. Programs start from executing this function. The word
“void” is used to indicate that the parameter under consideration is null and void.
The first void represents that the main function returns nothing. The next void
inside parenthesis indicates that the main function is passed nothing at the start.
We’ll see how these two void types can be replaced by other data types as
demanded by our program logic.
It is important to note that braces are used to represent blocks in our code. For
now, you need to know that the body of our main function lies within braces.
Anything outside these braces is not executed when main function is executed.
Inside our main function, we have two statements; printf and system. Printf takes
a String, a stream of characters as input and displays it on the screen. The ‘\n’ at
the end of our line in printf statement indicates the start of new line. The next
line uses the system to pause the program, so that we can see the output as
explained earlier.
So, we stop here for now. Coding or programming isn’t a difficult thing at all.
So, we stop here for now. Coding or programming isn’t a difficult thing at all.
All it demands is a little practice. We strongly believe you will be an efficient
coder in C
1.5 Nothing is perfect: Like every other language, C has its shortcomings. It has
a complicated syntax. For example, a common programming error is to use
different operator instead of the operator ==. Nevertheless, C is still a decent
language. It doesn’t restrict the programmer to access the machine. Some can
consider the lifting of restrictions as an imperfection, but I personally think it has
more pros than cons. C attracts programmers because of these “imperfections”.
Modularity in the source code is often considered critical. In C, it is actually
dependent on programmers, which always prefer that there is minimal
dependency between functions. A C programmer welcomes experimentation and
interaction as well, depending upon certain situations.
Chapter 2:Tokens and Syntax
In this chapter, we explain the syntax and lexical elements of the C programming
language. C is a high level programming language. Like other high level
languages, it has rules and principles for putting together different components
to create legal and working programs. These rules and principles define the
syntax of the language.
The program that checks on the legality of C code is called the compiler. The
compiler translates each line of code into machine language to see if there are
any errors. If there is an error, the compiler will print an error message and stop.
If the compiler finds no errors, then the source code is correct, and the code is
translated into object code. The object code is used by loader to create an
executable file.
2.1 Preprocessors C compiler has a preprocessor built into it. Lines that begin
with a # are called preprocessors. We have so far used #define and #include. The
compiler processes these preprocessors before actually compiling a code. For
example, when we defined a constant using #define in section 2.2, the compiler
replaced all the instances of PI with the value specified at the start before
compiling the code. Such constants are usually known as Symbolic constants.
We write all the #define statements at the top of our file. It is a convention to
write all the letters of a constant in capital. Following this convention enables
programmers to easily identify Symbolic constants or any other constants as
well. It is important to note that though, the preprocessor never changes the
contents of quoted strings. For example, in the following statement, only second
PI will be replaced by the value defined by preprocessor PI.
#define C 299792.458
The C system provides a number of standard header files. Some examples are
stdio.h, string.h, and math.h. These files contain the declarations of functions in
the standard library, macros, structure templates, and other programming
elements that are commonly used. Common examples of such header files are
conio.h, stdio.h, stdfx.h, math.h and others. These files contain certain system
functions such as stdio provides the coder with functions as printf and scanf. We
must include this header file before we can use these functions in our program.
We, so far have used iostream, which is short form of input/output stream
included using the #include directive.
Let us just see an example demonstrating how using a header file works.
Following is code written in a header file named as “myFirstHeaderFile.h”
#include "iostream"
#define PI 3.14159265359
#define PI 3.14159265359
The following is the code to be written in a .cpp file which includes our header
file in it.
If you are using Visual Studio, simply add the header file in the same project as
the .c or .cpp) file is in.
#include "myFirstHeaderFile.h"
void main(void)
float Area=PI*LENGTH*HEIGHT*HEIGHT*WIDTH;
printf("Length: %d\n", LENGTH);
system("pause");
As you can see, the program works just as the code in the header file was written
in our c file. This is just a simple example to demonstrate the use of header files.
We actually use header files because programs become too complex and it’s
better to handle them in smaller files with lesser complexity. We divide the
functionality into different categories and write code and functions for each
category in a separate file. In this way, it becomes easier to digest each smaller
chunk of a code.
In ANSI C, there are six kinds of tokens: keywords, identifiers, constants, string
constants, operators and punctuators. We will discuss each of these tokens in this
constants, operators and punctuators. We will discuss each of these tokens in this
chapter. The role of a compiler is to check if all the tokens can be translated into
proper understandable strings according to the compiler requirements. Most
compilers are very precise in their requirements.
Computers are dumb. We, the humans have the capability to understand a line
more efficiently if an extra punctuation mark is used in a sentence but computers
on the other hand will not be able to understand a sentence if it has an extra
punctuation mark called token, it is not familiar with. Hence, the programmer
must be familiar with which tokens can be used and which cannot be.
In the remaining part of this chapter, we will be covering the basic structure
elements of any C program. Every large thing in the universe comprises of
smaller components.
The scenario mentioned above is true for the language C as well. C consists of
individual components called Functions. Functions are considered as basic
structural element in C
2.2 Variables
There is a code for everything we do in life. Similarly, we have rules for writing
variable name in C. Variable name can be composed of uppercase and/or
variable name in C. Variable name can be composed of uppercase and/or
lowercase letters, digits and only one special character that is ‘_’. The first letter
of a variable must be either a letter or an underscore. But, it is discouraged to
start variable name with an underscore though it is legal because, variable name
that starts with underscore can conflict with system names and compiler may
complain. The length of a variable name has no restrictions. However, the first
31 characters of a variable are discriminated by the compiler. So, the first 31
letters of two variables in a program should be different by at least one character.
Let us get to know the use of variables by quoting some practical applications.
Here is a program to calculate sum of two numbers: #include <iostream>
void main(void)
int firstNumber=10;
int secondNumber=5;
int sum=firstNumber+secondNumber;
system("pause");
Some of you might be wondering why use the variables here instead of just
using the numbers. That would be easy but it will have limited use as well as a
bad programming approach. Let us add a few more lines to the above code to
prove these two points: #include <iostream>
void main(void)
int firstNumber=10;
int secondNumber=5;
int sum=firstNumber+secondNumber;
firstNumber=3;
firstNumber=3;
secondNumber=4;
sum=firstNumber+secondNumber;
system("pause");
As you can see that the print statements are duplicated in the second code, but
the values are changed by just changing the variables. So, we can use same code
to get different output by just changing variables. This gives us a huge
advantage. For example, consider a scenario that you have a list of 300 students
with their obtained marks in a uniform C programming test. What would be the
best way to represent total marks for this list? Would you recommend writing
total marks with each entry? Absolutely not but just consider for a second that
you do that and then you find out that total marks are 50
instead of hundred. You are bound to make a change i each entry. To avoid all
this, you could just assign a value to a variable and use that variable in each
entry. This is what variables are actually used for. Variables are a critical
component of any program.
2.3 Constants
A constant is something whose value does not change throughout the program
execution. These are fixed for a purpose though. For example, using standard
values for certain entities, for having not to type a long digit or value like
3.141517... or making the program easy to follow by mentioning all the constant
values in one place.
#include <iostream>
#define PI 3.14159265359
void main(void)
int radius=10;
float Area=PI*radius*radius;
system("pause");
void main(void)
int radius=10;
float Area=PI*radius*radius;
system("pause");
}
2.4 Keywords
Keywords are reserved words in any language. These words are already reserved
for a particular functionality so programmers cannot use them. These keywords
represent primitive data types, pre-built functions and other programming
components.
Functionality
auto
break
case
char
const
continue
default
This keyword along with ‘while’ is used for a special kind of loop.
double
else
Used along with ‘if’ for defining an alternate for a certain condition.
enum
extern
float
for
goto
if
int
long
Defines a long type variable of required type, e.g. int.
register
signed
sizeof
static
struct
switch
typedef
union
unsigned
volatile
while
2.5 Character Constants This section addresses the character constants which
have a certain meaning in certain situations. Character literals are enclosed in
single quotes, e.g., 'a' and can be stored in a simple variable of char type.
consists of two characters actually. First one is ‘a’ and the next one is ‘0/’. The
second one represents NULL.
Escape
sequence
Meaning
\\
\ character
\'
' character
\"
" character
\?
? character
\a
Alert or bell
\b
Backspace
\f
Form feed
\n
Newline
\r
Carriage return
\t
Horizontal tab
\v
Vertical tab
\ooo
\xhh . .
Hexadecimal number of one or more digits Then we have ASCII characters, that
are listed below: Char Dec Action
NUL
Null character
SOH
End of text
EOT
4
End of transmission, not the same as ETB
ENQ
BEL
BS
10
Line Feed
VT
11
Vertical tab
FF
12
Form Feed, page eject
CR
13
Carriage Return
SO
14
SI
15
16
DC1
17
DC2
18
19
20
Device control 4
NAK
21
Negative acknowledge
SYN
22
Synchronous idle
ETB
23
CAN
24
EM
25
SUB
26
Substitute
ESC
27
Escape, next character is not echoed FS
28
File separator
GS
29
Group separator
RS
30
31
Unit separator
The above is list of all the control ASCII characters. Following is the list of
printable ASCII characters in ASCII.
32 Space
33 Exclamation mark
"
34 Quotation mark
#
36 Dollar sign
37 Percent sign
&
38 Ampersand
40 Opening parentheses
41 Closing parentheses
43 Plus
44 Comma
46 Period
48 Zero
49 One
50 Two
51
Three
52 Four
53 Five
54 Six
55 Seven
55 Seven
56 Eight
57 Nine
58 Colon
59 Semicolon
<
61 Equals sign
>
63 Question mark
64 At-sign
65 Uppercase A
B
B
66 Uppercase B
67 Uppercase C
68 Uppercase D
69 Uppercase E
70 Uppercase F
71
Uppercase G
72 Uppercase H
73 Uppercase I
74 Uppercase J
75 Uppercase K
76 Uppercase L
77 Uppercase M
78 Uppercase N
79 Uppercase O
80 Uppercase P
81 Uppercase Q
82 Uppercase R
83 Uppercase S
84 Uppercase T
85 Uppercase U
V
86 Uppercase V
87 Uppercase W
88 Uppercase X
89 Uppercase Y
90 Uppercase Z
94 Caret (Circumflex)
95 Underscorè
97 Lowercase a
98 Lowercase b
99 Lowercase c
100 Lowercase d
101 Lowercase e
102 Lowercase f
103 Lowercase g
104 Lowercase h
105 Lowercase i
106 Lowercase j
k
107 Lowercase k
108 Lowercase l
109 Lowercase m
110 Lowercase n
111 Lowercase o
112 Lowercase p
113 Lowercase q
114 Lowercase r
115 Lowercase s
116 Lowercase t
117 Lowercase u
v
118 Lowercase v
119 Lowercase w
120 Lowercase x
121 Lowercase y
122 Lowercase z
2.6 Operators and Punctuators Like every other programming language, C has
many characters with certain meanings.
Examples include the Arithmetic operators which stand for the usual arithmetic
operations of addition, subtraction, multiplication, division, and modulus,
respectively.
X = A + B ;
int x = 15 % 4 ;
void main(void)
void main(void)
int a, b = 2, c = 3;
a = (b * (b + c));
The parenthesis used right after main are used as an operator. By rules, they are
used to indicate that main is a function. After the parenthesis, the symbols “{” ,
“,”, “,”, “;”, “(”, “(”, “)”, “)” and “;” are all punctuators. Both operators and
punctuators are collected by the compiler as tokens (characters), and along with
white space, they serve to separate language elements like identifiers, constants,
functions, keywords, operators and others.
Tokens depend on their context a lot. For example, as explained in the previous
paragraph, the parentheses are sometimes used to indicate a function name while
they can be used as punctuators as well. Another example is given by the
expressions C= a + b ;
++ a ;
a + = b ;
They all use + as a character, but ++ and += are increment and assignment
operators respectively while the first one is a simple arithmetic operator. This
dependency of symbols meaning on context leads to the short but more effective
programming language C.
The operator “(” has the highest parenthesis in this expression so we dissect it
before anything else. Then we have three operators inside parenthesis.
Multiplication and division have equal precedence so we perform whatever
comes first in the expression. In this case, we perform 4 * 10 and have a result of
40. We divide 40 by 5 and result is 8.
We subtract 20 from 8 and the result is -12. Now that parenthesis are closed, we
compute the operations outside it. We add -12 to 30 and the result is 18.
Humans with good mathematics will always find the answer to be 18. But guys,
who are not familiar with DMAS rule will have different answers. We want our
computer to be good with mathematics, so we have made it familiar with the
precedence of operators in the standard way so it always leads to one correct
answer.
Operator Name
Operations
Add
Subtract
Multiply
Multiply
Divide
Modulus
Negation
Bitwise OR
Power
<<
Left Shift
>>
Right Shift
void main(void)
system("pause");
The first four operators are pretty common and straightforward so we’ll not
discuss them here. Modulus returns us the remainder after dividing one number
by the other. A % B returns the remainder after dividing A by B. For instance,
the example in our code divides 50 by 17, 2 is quotient while 16 is the
remainder. The remainder is returned and printed. Remember, we can always
assign this value by using assignment operators.
Negation operator is used to invert a binary number using 2’s complement form.
If the input is boolean, as is in our program, the result is inverted.
00010001
00010000
00110010
00010001
00110001
Similarly, Bitwise XOR operation performs XOR on every bit of the numbers
provided.
In XOR, the result is high bit only if there are odd number of high bits in the
operation.
00110010
00010001
00100011
Shift operators are used to shift binary digits to the left or right. By using left
shift operators, the left operands value is moved left by the number of bits
specified by the right operand. For example, in our program we used A<<2. It
means that bits in A must be shifted to left by two digits:
means that bits in A must be shifted to left by two digits:
00110010
00110010<<2
11001000
Left Shift operator shifts bits to the left and add 2 zeros to the right and hence
the value is changed to 200 as clear from above explanation.
By using right shift operators, the left operands value is moved right by the
number of bits specified by the right operand. For example, in our program we
used A>>2. It means that bits in A must be shifted to right by two digits:
00110010
00110010>>2
00001100
Right Shift operator shifts bits to the right and add 2 zeros to the left and hence
the value is changed to 12 as clear from above explanation.
Equal to
a += b
a = a + b
a = a - b
a = a * b
a /= b
a = a / b
a = a % b
a = a & b
a = a | b
a = a ^ b
Performs bitwise XOR on a and b, stores in a Here’s a program to show the use
of these assignment operators with output: #include "iostream"
void main(void)
simpleAssignment = A + B;
A = 10, B = 3;
A -= B;
A = 10, B = 3;
A *= B;
A = 10, B = 3;
A /= B;
A = 10, B = 3;
A %= B;
A = 10, B = 3;
A &= B;
A = 10, B = 3;
A |= B;
system("pause");
Operations
++a
Prefix increment
Prefix decrement
The increment operator ++ and the decrement operator -- are unary operators. ++
and -
#include "iostream"
void main(void)
int A = 10;
system("pause");
So, the initial value of A is 10. Prefix increment increments the value to 11
So, the initial value of A is 10. Prefix increment increments the value to 11
before assignments and thus prints 11 in 3rd line of output. Fourth line just prints
and shows that A has been assigned the value 11. Sixth line of output has a
postfix increment which means A will be incremented after any assignments in
the expression. Thus, the same value, 11 is printed and then A is incremented to
12 which can be seen in the next line.
Prefix decrement decrements the value to 11 before assignments and thus prints
11 in 9th line of output. Next line just prints and shows that A has been assigned
the value 11.
12th line of output has a postfix decrement which means A will be decremented
after any assignments in the expression. Thus, the same value, 11 is printed and
then A is decremented to 10 which can be seen in the next line.
2.6.4 Logical Operators Logical operators are used to get a binary output
depending upon certain operations between one or more operands. They are
handy when developing decision statements.
Operator Name
Operations
!a
Negative
a && b
Logical OR
Returns true if a or b or both are true Following is an example illustrating the use
of these logical operators: #include "iostream"
void main(void)
system("pause");
Operator Name
Operations
a == b
Equals
a < b
Not equal to
a <= b
Less than
a >= b
Greater than
Returns true if a is less than or equal to b Greater than or equal to Returns true if
a is greater than or equal to b
#include "iostream"
void main(void)
int a = 10, b = 5;
system("pause");
The ternary operator, the one we have consistently used in previous examples is
quite useful. Its syntax is as follows:
So, ternary operator checks a certain condition and depending upon the boolean
output, selects one of the alternative cases.
C provides the unary operator sizeof to find the number of bytes needed to store
an object. It has the same precedence and associativity as all the other unary
operators. The syntax of expression is as follows:
sizeof(object)
2.7 Precedence and Associativity As we discussed earlier as well, we have
rules of precedence and associativity that are used to determine how certain
expressions are evaluated. Let us briefly discuss how precedence rules are used
by a C compiler to compute the unique and correct answer of an expression.
Category
Operator
Associativity
Postfix
() [] -> . ++ - -
Left to right
Unary
Right to left
Multiplicative * / %
Left to right
Additive
+ -
Left to right
Shift
<< >>
Left to right
Relational
Left to right
Equality
== !=
Left to right
Bitwise AND
&
Left to right
Bitwise XOR
Left to right
Bitwise OR
Left to right
Logical AND
&&
Left to right
Logical OR
Logical OR
||
Left to right
Conditional
?:
Right to left
Assignment
Right to left
Comma
Left to right
Consider the following code and try to compute the results. We will discuss the
output but it is better if you try it yourself before matching our results.
#include "iostream"
void main(void)
a = b = c += 2;
printf("a= %d\n",a);
printf("b= %d\n",b);
printf("c= %d\n",c);
a = 20, b = 10, c = 5;
a = ++b -= c = 2;
printf("a= %d\n",a);
printf("b= %d\n",b);
printf("b= %d\n",c);
system("pause");
The initial values of a, b and c are 20, 10 and 5 respectively. The equivalent
expression for the first expression can be: (a = (b = ( c = c + 2 ))); The inner
most parentheses assigns the value 5 to c. The other two parenthesis simply
assign c to b and b to a. So, all the variables contain 7 after the execution of first
assign c to b and b to a. So, all the variables contain 7 after the execution of first
assignment.
(a=((b=b+1)=b-(c=2)));
The inner most parenthesis stores 2 in variable c. The next parenthesis then
compute b-c, equivalent to 10-2, and results 8 which is stored in b. Then b is
incremented by 1
All the operators on a given line, such as * / % have equal precedence with
respect to each other, but have higher precedence than all the operators that
occur on the lines below them. We have associativity for all the operators in the
rightmost column. For every operator, we will declare its precedence and
associativity so that there is a standard to compute a mathematical expression.
These rules are to be remembered by every C programmer for efficient
programming.
Chapter 3:Data Types
Data types refer to various categories of data that is to be manipulated. C
provides several default data types. We need to discuss limitations on what can
be stored in each type.
The keywords signed char, unsigned char, char, signed long int, signed short int,
signed int, unsigned int, unsigned short int, unsigned long int, float, double, and
long double are the default data types but for programmers’ ease, it is allowed to
use the short forms.
The next paragraph has those legal shortened forms of data types in C.
Fundamental data types include long, short, signed char, unsigned char, char, int,
float, double, long double, unsigned, unsigned short and unsigned long.
These are all keywords which means that they cannot be used as names of
variables.
Usually, the keyword signed is not used. The reason is that the signed int is
equivalent of int, and because shorter names are easier to type, int is used on
most of the occasions.
The type char, however, is special in this regard as we’ll see in the later parts of
this
chapter
Let us assume that the category type is defined to be anyone of the types given in
the preceding paragraph. Using this category, we can provide the syntax of
declaring a variable of any type:
type identifier;
For example, this can represent int x or double a or char alphabet etc.
It is always easy to understand things when they are grouped (except cats). The
default data types can also be grouped according to their functionality. The
integral types can be used to hold integer values; the floating and double types
are those that be used to hold real values in them. These both categories, when
combined form Arithmetic data types.
float
signed char
double
unsigned char
long double
short
int
long
unsigned short
unsigned
unsigned long
3.1 Integral Data Types The data type int, the short for integer is the most used
integral data type in C. This type, along the other integral types such as char,
short, and long, is designed for working the integer values that are representable
on a machine. Mathematics define integers as positive and negative whole
numbers such as -11, 13, 66 etc.
Since machines are designed within bounds, we can have integers up to a certain
limit.
To calculate the range we use the power rule. On a 16 bit system, we can have
2^16 =
65536 distinct values, half of which would be negative if we are dealing with
signed numbers. Similarly on a 32 bit system, we can have 2^32 = 4294967296
distinct values, half of which are negative if we are dealing with signed numbers.
In C, the data type integer is considered the "natural" or "usual" type for working
with integer. There are other integral types such as char, short, and long. The
data type short, for example, can be used in situations where we need to use less
number of bytes to store our integer, although it is not required to do so in
today’s advanced world as we do not have any storage issues nowadays. In a
similar fashion, the type long might be in situations where large integer values
are needed. The compiler may provide storage greater than it is required for a
natural integer. Typically, short is stored in 2 bytes and along is stored in 4
bytes. Machines with 4 byte systems have equal sized short and long data types.
3.2 Floating Point Data Types C provides the three floating types: float,
double, and long double. Floating point variables are used to store real values
like 3.14, 1.33334 etc. A suffix can be added to a floating constant to specify its
type. Any floating constant without suffix is of type double. The working
floating type for C is double rather than float.
Integers can be used as floating constants, but they must be written with a
decimal point. For example, the constants 1. 0 and 2.0 are both of type double,
whereas as integers, their value will be 1 and 2 respectively.
A floating type number consists of four parts: an integer part, a decimal point, a
fractional part, and an exponential part (if any). A floating type number must
contain either a decimal point or an exponential part or both. If a decimal point is
present, either an integer part or fractional part or both must be present. If no
decimal point is present, then there must be an integer part along with an
exponential part to indicate the possible position of decimal point.
The C language provides the programmer to define a data type using existing
data types but with his own customized names. This is achieved through typedef
mechanism, which allows the programmer to use an identifier of his choice to
represent certain data types. Some examples are
In each of these type definitions, the named identifiers can be used later to
declare variables or functions in the same way ordinary types can be used.
numberOfStudents Strength;
The advantage of using typedef for customized data types is in abbreviating long
declarations. Another advantage is having names that reflect the intended use
like numberOfStudents.
3.4 Storage Classes Variables and functions in C have two attributes: type and
storage class. You must have gathered around the first attribute so far. Let us
now discuss the storage class attribute.
The storage classes are used for certain utilities of variables and functions. The
most common storage class is auto. There are three other storage classes defined
by these keywords:
auto
extern
register
static
3.4.1 The Storage Class auto By default, C variables declared within function
definitions are automatic. Thus, automatic is the most used of the four storage
classes. If a compound statement starts with able declarations, then these
variables can be acted on within the scope of the
When the program control exits a block, the system releases the memory that
was set aside for the automatic variables. As soon as the blocks are gone, gone
are the variables.
3.4.2 Storage Class extern The communication between blocks is critical. One
way of transmitting information across your scope is using methods to pass
parameters to another scope. But, this method is not applicable in certain
situations. The storage class extern provides us with another mechanism for
communication between different environments or scopes.
void printMe()
void main(void)
globalVariable+=10;
printMe();
}
Note that we could have written the following statement as traditional C did not
allow it but modern ANSI compilers do not complain about this format and also
consider a variable outside any scope of extern class even if extern keyword is
not used: extern int globalVariable = 10;
Such variables cannot be of automatic or register class but they can be static if
required as explained in storage class static section. The keyword extern is used
to make compiler look for this variable anywhere in this file or in any other file
for definition and use.
Another important point to remember is that external variables are not de-
allocated entirely through the program but the may be hidden if a similar
identifier is redefined inside a scope. If this happens, the local variable is
accessed, not the global variable in that scope.
extern double sum(double a, double b); 3.4.3 Storage Class register The
register storage class makes variables to work as high speed register. Obviously,
it might have hardware based restrictions since there are a limited number of
registers in physical space. Because of physical restrictions, variables of this
class are automatically converted to auto type whenever compiler finds it
impossible to use the variable as a memory register.
Register class is used when fast execution is critical. When speed is a concern,
the programmer may choose a few variables that are frequently accessed and
declare them to be of storage class register. Registers take lesser number of clock
cycles when they are accessed for use or modification than normal memory
cycles when they are accessed for use or modification than normal memory
location. Since registers store integer values, hence extern variables are integer
by default as well. Therefore following two declarations are equivalent: extern
int variable;
extern variable;
3.4.4 Storage Class static Static means something which keeps its state
constant. Static class have two basic uses.
The primary use is similar to what the word static means: for declaring variables
which retain their state when blocks are entered and exited frequently.
Remember, normal variables are de-allocated as soon as the block is closed. The
second use is its use with external class declarations.
Here is an example:
void demo()
int normalVariable = 5;
normalVariable += 10;
staticVariable += 10;
staticVariable += 10;
void main(void)
demo();
demo();
demo();
system("pause");
As you can see in the output of above program, static variable retains its
previous value for second and third function call as well. The static declaration
of variable is executed only the first time function is called. After that, the
compiler ignores it. The next time, static variable has value 15 and 10 is added in
to it and 25 is printed. The third function call uses the retained value 25 for static
variable and adds 10 to it. On the other hand, normal variable is initialized again
and again to 5 and 10 is added. Each of the three function calls creates a normal
variable of its own while static variable is only generated the first time and then
retained for future references.
Let us now discuss the static external variables. Extern and static together
provide better privacy options to the programmer. As you know that global or
external variables are accessible only to the functions defined after their
declaration. The static variables on
declaration. The static variables on
the other hand are dependent on their blocks that can be molded for use by
programmers.
Let us use this facility to provide a variable that is global to a family of functions
but, at the same time, is private to the file.
This use causes the scope of the function to be restricted. Static functions are
visible only within the file in which they are defined. Unlike ordinary functions,
which can be accessed from other files, a static function is available throughout
its own file, but no other.
3.5 Default Initializations In C, both external variables and static variables that
are not assigned any values at the time of declaration are automatically
initialized with 0. This default initialization is applicable on arrays, strings,
pointers, structures and union.
C supports all the basic loops provided by other high level languages. These
include for loop, while loop and do while loop. We will discuss each of these
loops with example in this chapter.
4.1 If else statement The most basic and most commonly used decision
statement in any programming language is if else statement. This statement can
be used for multiple scenarios. It can be used for one or any number of
scenarios. Here’s a program only with one if statement:
void main(void)
printf("Program starts\n");
int x=0;
scanf("%d", &x);
if(x==0)
printf("If executes\n");
printf("If executes\n");
printf("Program ends\n");
system("pause");
This program takes an integral input from user using scanf function. If the user
enters 0, then the logical operation in if statement holds true and therefore the
body of if statement is executed. If any other number is entered, the body of if
statement is not executed.
Let us now see another example which involves if else statement: void
main(void)
printf("Program starts\n");
int x=0;
scanf("%d", &x);
if(x==0)
printf("If executes\n");
}
}
else
printf("Else executes\n");
printf("Program ends\n");
system("pause");
This program has an alternate condition in the block covered by else statement.
Else statement is always used with if statement. In the case, when if statement
holds true, the compiler just ignores the else statement. Otherwise, when if
statement is false, the body of else block is executed.
printf("Program starts\n");
int x=0;
scanf("%d", &x);
if(x==0)
if(x==0)
printf("1st If executes\n");
else if(x<10)
printf("2nd If executes\n");
else if(x<20)
printf("3rd If executes\n");
else
printf("Else executes\n");
printf("Program ends\n");
system("pause");
4.2 Switch Case statement Switch case is another popular decision making
statement in C programming language.
The use is very similar to if else statements but instead of conditions which
result in Boolean values, this decision making statement has certain cases for
different values.
void main(void)
printf("Program starts\n");
char x;
x=getchar();
switch(x)
printf("Program ends\n");
system("pause");
An important thing to note is the break statement at the end of each case. Break
statement is used to leave the current block in any situation. For example, if you
are in for loop, you will ignore the code inside for loop after the break statement.
Here, break statement is necessary if we do not want multiple cases to be
associated with one input.
printf("Program starts\n");
char x;
x=getchar();
switch(x)
printf("Program ends\n");
system("pause");
In the above program, if user enters character b as input, two cases are executed.
Starting from case ‘b’, compiler executes every line of code unless it reaches a
break statement or end of switch case block.
4.3 For Loop As we described earlier, loops are used for repetitive execution of
statements. When we know the number of iterations, for loop is the ideal loop to
use in a program.
printf("Program starts\n");
char x;
x=getchar();
switch(x)
printf("Program ends\n");
system("pause");
The above program executes the statements within for loop five times. When
compiler reaches for loop, it first of all initializes the variable involved. After
that, condition is checked. If condition is true, keep going else stop. So, in the
first execution cycle, I is initialized to 0 and condition is true as 0 is less than 5.
After first execution cycle, increment or decrement statement at the end of for
loop is executed and condition is checked. Now, increment operator gives I the
value of 1, which is again less than 5 so loop keeps going. Similarly, loop goes
on for three more cycles. After a total of five cycles, value of I will be 5. For 6th
possible cycle, value of I is compared with 5 and the answer will be false as 5 is
not less than 5. Hence, 6th cycle won’t be executed and loop is terminated.
4.4 While Loop This loop uses only a condition to determine how many
iterations are to be computed.
{
{
printf("Program starts\n");
char x='a';
x=getchar();
while(x!='e')
switch(x)
printf("Enter e to exit. Else, enter another small alphabet and press enter: ");
x=getchar ();
system ("pause");
This program keeps repeating until user enters ‘e’. Thus, user is given the
control of how many iterations are made by using while loop. This can be done
with for loop too, but while is designed for this particular purpose. While loop is
highly recommended if the number of iterations required are unknown.
4.5 Do While Loop Do while loop is almost similar to while loop except that do
while always execute its first cycle without testing any condition. On the other
hand, while loop always checks that the condition given is true, even for the first
execution cycle.
Consider following example and compare it with the while loop example: void
main(void)
char x='a';
do
x=getchar();
switch(x)
} while(x!='e');
system ("pause");
4.6 Nested Loops Nested loops refer to loops within loops. They are usually
useful when dealing with 2-D
arrays. Here is an example in which a 2-D array is initialized using a nested for
loop: void main (void)
int Two_D[10][10];
Two_D[i][j] = i+j;
system ("pause");
Similarly, we can use nested loops for a while and do while. You can nest
different loops together as well.
Chapter 5: Functions
A function, also known as a method or routine, is simply the programming unit
which performs an operation on possible inputs and returns (if required) the
outputs.
The concept of functions come from the need to divide large and complex tasks
into smaller and simpler problems. It is always easy to manage smaller tasks.
Functions are entirely up-to the will of programmer, but it is recommended that
each function has a specific and unique tasks. Assembly of every individual
function solves the basic problem. For example, in a Calculator application,
there should be a function for every operation so that coding and debugging is
easy.
5.1 Function Definition The function definition is the actual code which is
executed whenever that particular function is executed.
{body}
The first line represents the header of a function. Second line here represents the
body of a function enclosed in braces by convention. The parameter list refers to
a possible multiple inputs. functionName is the name of function while type
represents the output of the function.
sum = a + b;
return sum;
In the program above, there are two integer inputs whose sum is returned as an
output.
The first int represents the return type. Then “sum” is the name of function. A
list of parameters passed or inputs (both integer type) is enclosed inside
parenthesis. Then, the body is enclosed within braces. The last statement has the
keyword “return”, which is used for returning an output in specified format and
along with that, program control also returns to the point from where sum(a, b)
are called.
The following are two ways to calculate sum of two numbers. One involves use
The following are two ways to calculate sum of two numbers. One involves use
of function and the other does not. Please see the differences to understand the
utility of functions:
1. Without Function:
a = b = c += 2;
a = 20, b = 10, c = 5;
a = ++b -= c = 2;
printf("b= %d\n",b);
printf("b= %d\n",c);
a = 20, b = 10, c = 5;
printf("%d",(a=((b=b+1)=b-(c=2))));
a = 20, b = 10, c = 5;
printf("%d",((b=b+1)=b-(c=2)));
system("pause");
2. With Function:
int answer = a + b;
printf("Answer = %d\n",answer);
return answer;
void main(void)
system("pause");
The order in the declaration of parameters does not matter. Since ANSI standard
allows most of the features provided by traditional C, hence C compiler
nowadays accept both formats for definition of functions.
5.1.1 The return statement When a return statement is executed, the current
program finishes its execution and returns to the environment from which it was
called. If the return statement is followed by an expression such as ++b; or a;
then a value is returned to the calling environment which can be stored and used
for further processing. Moreover, this value will be converted, if necessary, to
the type of the function as specified in the function definition.
A function can have zero or more return statements. If there are no return
statements in a function, it completes its execution at the end of braces and then
return to previous environment. An illustration is followed for better
understanding: void sumAndPrint(int a, int b)
int answer = a + b;
printf("Answer = %d\n",answer);
return;
Now, the above function prints the sum only once and returns to previous
environment without executing the last statement. If there were no return
statement in the code, the answer would have been printed twice. Of course, this
example was just to illustrate the use of return statement, but you often come
across situations in practical problems that you don’t need to fully execute a
function.
If someone understands the prototypes, he can use the function in his program.
For example, the above function prototype tells us that we need to input two
numbers and (most probably) their sum will be returned. Hence, I can write the
following statement even though I have not written the sum function myself:
Answer = sum ( a, b);
Function prototypes allow the compiler to check the code in more detail by
specifying all the functions that are used in your program. As we mentioned
earlier, the type of parameters may need conversion. Function prototypes make it
easier for the compiler to implement these conversions. For example, if we call
our sum function like this: Answer = sum (2.5, 4.3);
If we have used prototypes, compiler knows that sum function needs two
integers rather than double and therefore either converts the input parameters
into integers or generates an error of input type mismatch.
In C++ function prototypes, the use of void in the parameter type list in both
function prototypes and function definitions is optional. This is different from
traditional C. For example:
In C++, both of these prototypes represent same thing: there are no input
parameters but in traditional C, the first prototype is illegal and second function
prototype refers that there can be any number of parameters for this function.
Void is not a keyword in traditional C and hence cannot be used in function
declaration and definition.
5.3 Alternative Style for Declarations Some of you may have noticed that we
have not used function prototypes in the program of section 4.1. Instead, we
defined the functions above the main function. This is an alternative for
prototypes, acceptable by ANSI C compilers. We write the preprocessors,
followed by all the function definitions and then finally our main program. This
is recommended, if you have only one file to work with. For example, please
refer to the examples in section 4.1.
5.4 Function Invocation This section is intended to make you familiar with how
a function call works. Every C
a = a + 10;
void main(void)
int a = 10;
changeValue(a);
system ("pause");
So, as you can see, the changeValue function adds 10 to the value of passed
parameter but the change is not visible to the variable “a” in main program. The
change is made
5.5 Environment
What is an ideal way to work in a group? The ideal way to work in a group is to
play an assigned ole within certain limits and boundaries. Everyone has his
privileges and certain limitations. If everyone pokes into each other’s work
without necessity, it will lead the group to a disaster. The C structure follows
these basic principles for the success of every program. As we discussed earlier,
C provides locality of variables in functions. At the same time, C gives the
programmer to choose the scope of a variable by himself. If a programmer wants
something to be shared by multiple functions, C
The basic rule of scoping is that variables are accessible only within the block of
their declaration. They are unknown outside the boundaries of that block unless
specified otherwise using special techniques. This is an easy rule to be followed
but programmers seem to use same identifiers in different environments. For
example, see the second example in Examples section at the end of this chapter.
The programmer used the identifier ‘a’ to represent multiple variables in
different scope. If there were no rules for Scoping, the compiler could not have
differentiated between these identifiers. Let us see another example:
a = a + 10;
int localVariable=20;
changeValue(localVariable);
printf("\n");
system ("pause");
The above program uses four scopes. The first one is global which means it can
be accessed anywhere and changes made to it in one place are visible to
everyone else. All the others are local scopes which mean they are visible only
to their scope. The identifiers “local Variable”, “a” and “x” are all variables
defined in local scope. The first two variables follow the general rules of scope
but x violates it. This program fails to compile because variable x, declared in
the “for” loop is accessed outside its scope. The compiler is unable to identify x
the “for” loop is accessed outside its scope. The compiler is unable to identify x
as an identifier outside for loop. To make this program work, just delete the
second last statement in main program.
5.6 Recursion
Recursion is a very important as it provides a way for more efficient and concise
code for difficult program.
system ("pause");
if (n <= 1)
return 1;
else
return (n * factorial(n - 1));
void main(void)
int f=factorial(5);
system("pause");
5.7 Examples
5.7.1 Equalizers
void printHeading();
void main(void)
printHeading();
int x = 1;
for(x=1;x<=10;x++)
{
printTable(x);
system("pause");
void printTable(int a)
printf("%d\t",x*a);
printf("\n");
void printHeading()
printf("-----------------------------Table of Tables-----------------------------\n\n"); }
In a file Implementation1.c:
void func(int a)
In a file Implementation2.c
void funcSquare(int a)
void func(int a)
In a file main.c
#include "header.h"
void main(void)
func(5);
funcSquare(5);
funcCube(5);
funcCube(5);
system("pause");
int normalVariable = 5;
normalVariable += 10;
staticVariable += 10;
void main(void){
demo();
demo();
demo();
system("pause");
5.7.4 Pointers
int tmp;
tmp = *p;
*q = tmp ;
void main(void){
swap(&a, &b);
system("pause");
int i, j;
swap(&a[j-1], &a[jJ);
C provides a data structure that can store multiple values of same type in it by
associating each value to a subscript. It is extremely useful in common
programming.
An array is a random access data structure, where each element can be accessed
directly and in constant time. A typical illustration of random access is a book -
each page of the book can be open independently of others.
Arrays in C consist of contiguous memory locations which means that they are
placed in memory together. The lowest member of array has the lowest address
and last member of array has the highest memory address assigned to it.
1-D arrays refer to one dimensional arrays. Such arrays can be considered as a
single row or column containing a fixed number of elements. They have only
one index. An array is just like a normal variable except for index. Index always
start from 0 and end at (arraySize-1).
Arrays may be of storage class automatic, static or extern but not register. ANSI
C
supports the initialization of all three types of arrays using an initializer but
traditional C
int table[10] = { 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 };
printf("5 x %d = %d\n",i+1,table[i]);
system("pause");
Here is an illustration of using a 1-D array, using a loop for initialization rather
than common initializer:
void main(void)
int table[10];
//initialization of array
table[i-1] = i * 5;
printf("5 x %d = %d\n",i+1,table[i]);
printf("5 x %d = %d\n",i+1,table[i]);
system("pause");
6.2 Pointers
Pointer variables can be declared in programs and then used to take addresses for
initialization. The declaration is as follows: int *p;
int x = 5;
p = &x;
The above lines declare a pointer variable p of integer type which stores address
of a memory location specified by another integer variable x. Following is a
program which uses pointers to access other variables: void main(void)
program which uses pointers to access other variables: void main(void)
int *p;
int x = 5;
p = &x;
system("pause");
Normal variable has two numbers associated with it: an address of variable, a
Normal variable has two numbers associated with it: an address of variable, a
value stored on this address. The variable name accesses the value while
ampersand with variable name accesses the address. A pointer variable has three
numbers associated with it: an address of pointer variable itself, a value stored in
it after initialization, a value pointed by value stored in the pointer variable. The
first two are accessed using variable name and ampersand variable name, just
like normal variables. The third value associated with pointers is accessed using
* sign with identifier.
int arr[10];
arr[i-1] = *(p+i-1);
printf("5 x %d = %d\n",i+1,arr[i]);
void main(void)
void main(void)
int table[10];
//initialization of array
table[i-1] = i * 5;
printMe(table);
system("pause");
So, we passed just the starting address of an array as a pointer to another method
and we were able to access the array defined in another function. Note that the
identifier representing an array, if written without an index is equivalent to the
starting address of array (&identifier[0]). *(p+i) is used for indexing. If value of
I is 1, and integer is of 4
I is 1, and integer is of 4
bytes, the program accesses the next integer rather than just next byte.
p[i]=10;
void main(void)
int table[10];
int table[10];
//initialization of array
table[i-1] = i * 5;
printf("5 x %d = %d\n",i+1,table[i]);
changeMe(table);
printf("5 x %d = %d\n",i+1,table[i]);
system("pause");
}
}
So, we accessed an array defined in our main function inside another function
and changed all of its values to 10. The change was visible in our main program.
This is what “call by reference” mechanism is used for. The mechanism is
clearly possible, only due to pointers.
Although pointers and arrays are almost synonymous in terms of how they are
used to access memory, as is clear from above example as well, there are
differences, and these differences are subtle and important. A pointer variable
can take different addresses as values which means they can be redefined at any
point of time. This is not the case with arrays. An array name is an address, or
pointer, that is fixed.
6.3 Strings
As strings can have a variable length, we have a mechanism to identify the end
of a string. Every string, by default ends in the null character \0. The size of a
string must include the storage needed for the end-of-string character as well. It
is programmer’s job to never access a character from a string that over runs the
size of string.
In contrast to char arrays which are represented in single quotes, strings are
initialized with double quotes. For example, "abc" is a string of size 4, with the
last element being the null character \0.
Although, char constants and strings seem closely related but they are not same.
For example, "a" and 'a' are not the same. “a” has two characters one of which is
‘a’ and the other one is \0.
A string is considered by the compiler as a pointer. Its value is the base address
of the string. Consider the following code: char
*pointer
=
=
"abc";
printf(“%s %s\n”, pointer, pointer + 1); The pointer variable is assigned the
starting value of string. The first string is printed starting from ‘a’. The second
string moves its address by one unit (char is of 1 byte, usually) and hence starts
from ‘b’. So, the output for above lines of code will be: abc bc
Let us now see an example which uses a char array as well as a string. You can
see the convenience in using strings:
void main(void)
char *s = "aString";
char characters[10] = { 'c', 'h', 'a', 'r', 'a', 'c', 't', 'e', 'r', 's'};
for(int i=0;i<10;i++)
printf("%c", characters[i]);
printf("\n%s\n", s);
system("pause");
}
For technical reasons, it is better not to print null characters. Strings do not print
null character unless we use pointer to access the last character of the string.
int count = 0;
while (isspace(*str))
++str;
if(*str != '\0')
count++;
}
}
return ++count;
Function Name
Description
char strcat(char s1, canst char *s2); Concatenates second string to the end of
first string and returns it.
int strcmp(const char s1, const char s2); Compares two strings. It returns a value
less than 0 if first string is less than second, a value greater than 0 if first string is
greater than second and returns 0 if both are equal.
char *strcpy(char s1, const char s2); String s1 is overwritten by String s2 and s1
is returned.
int Two_D[5][4];
Nested loops are usually used for dealing with 2-Dimensional arrays.
Two_D[0][2]
Two_D[0][3]
Two_D[1][0]
Two_D[1][1]
Two_D[1][2]
Two_D[1][3]
Two_D[2][0]
Two_D[2][1]
Two_D[2][2]
Two_D[2][3]
Two_D[3][0]
Two_D[3][1]
Two_D[3][2]
Two_D[3][3]
Two_D[3][3]
Two_D[4][0]
Two_D[4][1]
Two_D[4][2]
Two_D[4][3]
Arrays of dimension higher than two work in a similar fashion. Let us describe
how three-dimensional arrays work. If we declare Int Three_D[5][3][2];
The compiler allocates 5*3*2 memory address for integer type. The base address
is Three_D[0][0][0].
Here is a function that adds the elements of a three dimensional array and returns
the total.
int i, j, k, sum = 0;
sum += Three_D[i][j][k];
sum += Three_D[i][j][k];
return sum;
}
Chapter 7: Structures
C is an easily extensible language. It can be extended using header files and
standard libraries to use certain functions and macros. It can also be extended by
defining data types that are constructed from the fundamental types such as an
array which is a group of default data type variables.
Arrays are used for storing variables of same type. As a simple example, let us
define a structure that describes a student. A student has various attributes of
different types such as Name, Course, Section, CGPA and ID. A student can be
defined as a structure in C. We can declare the structure type for student using
the keyword struct as follows: struct Student
char *Name;
char Section;
double CGPA:
} ;
This declaration creates the derived data type struct student. It is a user defined
data type. The structures one defined can be used to define identifiers of this
user-defined type. The tag name or identifier along with keyword struct is used
to declare variables of type student:
to declare variables of type student:
The above declarations for struct variables allocates storage for the identifiers,
which now represent a Student. An alternative way to declare these identifiers is
as follows:
struct Student
char *Name;
char Section;
double CGPA:
char *Name;
char Section;
double CGPA:
} Student;
s1.Name = “R Khan”
s1.Course = 18;
s1.ID = 786;
s1.Section = ‘A’;
s1.CGPA = 3.74;
typedef struct
char *Name;
char Section;
double CGPA;
}Student;
void printUsingPointer(Student *s) {
printf("%s %d %d %c %f\n", s -> Name, s -> ID, s -> Course, s -> Section, s ->
CGPA); }
void main(void)
Student s1,s2;
s1.Course = 18;
s1.ID = 786;
s1.Section = 'A';
s1.CGPA = 3.74;
s2.Course = 18;
s2.ID = 890;
s2.Section = 'A';
s2.CGPA = 3.14;
printUsingPointer(&s2);
system("pause");
Following are a few statements and equivalent access methods are listed as well:
struct student s, *p = &s; s.Section == 'A'; s.Name= "Khan"; s.student_id =
786;
p -> grade
‘A’
s.Name
p -> Name
“Khan”
(*p).ID
p -> ID
786
*p -> Name + 1
(p -> Name)[2]
7.4 Definition All external and static variables, including struct variables, are
initialized by the programmer are automatically initialized by the system to zero,
unless specified otherwise. In traditional C, only external and static variables can
be initialized. ANSI C
Student s1 = {“Mashal”, 18, 123, ‘A’, 3.79}; Pair a[3][3] = { {{1.0, -10}, {20.0,
0.2}, {3.5, 0.3}}, {{4.7, -0.4}, {2.0, 0.5}, {6.0, 1.6}} }; 7.5 Abstract Data
Types The term abstract data type (ADT) refers to a data structure together with
its operations, without specifying an implementation. Suppose we wanted a new
integer type, one that could hold arbitrarily larger values than the default value.
The new integer type together with its arithmetic operations will be an ADT. The
idea of ADT comes from variety of requirements that keeps growing with
innovative applications. Native types such as char, int, and double are already
implemented by the C compiler and cannot be altered.
So, we need a mechanism to define our own Data types with certain operations.
7.5.1 Stacks An ADT stack is a container of objects that follows the last-in first-
out (LIFO) principle.
It means that you can access only the latest element you have entered. A stack is
a limited access data structure - elements can be added and removed from the
stack only at the top. For accessing other elements, you need to remove the
objects on top of them.
Only two primary operations are necessary for stack implementation: push and
pop.
Push refers to adding an element to the top of stack while pop removes the item
at the top of the stack. A helpful analogy is to think of a stack of dumbbells on a
steel rod; you can remove only the top dumbbell, also you can add a new
dumbbell on the top.
Now we develop and implement the ADT stack, one of the most useful standard
data structures. The typical operations that can be implemented for a stack are
push, pop, top, empty, full, and reset. The push and pop operations are discussed
earlier. The empty operator tests if the stack is empty or not and results in a
Boolean value. The full operator tests if the stack is full, which also returns a
Boolean value. The reset operator removes all the elements of stack and
initializes it.
We will use a fixed-length char array to store the contents of the stack. The top
of the stack will be an integer-valued member named top. The various stack
operations discussed in the previous paragraph will be implemented as functions,
each of whose parameter lists includes a parameter of type pointer to stack.
Using a pointer results in better efficiency by avoiding to copy large stack
values.
values.
int stack[MAX_SIZE];
void push();
int pop();
int is_empty();
int peek();
int main()
while(1)
switch (choice)
{
{
case 1:
if (TOP == MAX_SIZE - 1)
push(element);
break;
case 2:
if (TOP == -1)
element = pop();
break;
case 3:
if (!is_empty()) {
element = peek();
else
if (is_empty())
case 5:
exit(0);
TOP++;
stack[TOP] = value;
int pop()
int element;
if (TOP == -1)
return TOP;
element = stack[TOP];
TOP--;
return element;
int is_empty()
if (TOP == - 1)
return 1;
else
return 0;
int peek()
return stack[TOP];
int queue_array[MAX_SIZE];
int rear = - 1;
int front = - 1;
void main(void)
int choice;
while (1)
switch (choice)
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
display();
display();
break;
case 4:
exit(1);
default:
void insert()
int add_item;
if (rear == MAX - 1)
else
if (front == - 1)
front = 0;
rear = rear + 1;
queue_array[rear] = add_item; }
void delete()
else
void display()
int i;
if (front == - 1)
else
{
printf("Queue is : \n");
7.5.3 Linked Lists A linked list is a sequential access data structure, where each
element can be accessed only in particular order. A typical illustration of
sequential access finding a particular file from an unorganized pile of files. It is
like a clothes line on which the data structures hang sequentially. A head pointer
addresses the first element of the list, and each element points at a successor
element, with the last element having a NULL value.
Here’s a code that implements a linked list. Linked list consists of adjacent
nodes with each having the address of next node. Starting from head, we can
traverse through the whole list by using the pointer next in each node. We can
take another pointer in node which can hold address for previous node as well.
struct Node
int val;
};
void main()
int i;
head = NULL;
for(i=1;i<=10;i++)
curr->next = head;
head = curr;
curr = head;
while(curr) {
}
Chapter 8: Binary Trees
A tree is a finite set of elements, often known as nodes. Every tree has a unique
starting node, called the root node, whereas the remaining nodes are a disjoint
collection of subtrees of this root node. Each node keeps track of its parents
or/and children so that traversal can be made possible. A node with no children
is called a leaf node or a terminal node.
A binary tree is a tree whose nodes can have a maximum of two children. A
binary tree is a data structure which comprises of two possible sub-elements of
every node, called left child and right child. If a node does not have a left or
right child, they are assigned NULL values. Each link must point at a new object
not pointed at or be NULL.
Char value;
};
The binary tree is a useful data structure for rapidly storing sorted data and
rapidly retrieving stored data. This results in an immense increase in efficiency
of searching and sorting.
Generally, the left node has a lesser value than parent while right child has a
greater key value than its parents. Due to these two simple rules, the efficiency
of trees is enormous.
As a result, the leaves on the farthest left of the tree have the lowest values and
we already know that so if we want to get the lowest value, we only need to
traverse to the lowermost leaf node to the left instead of going through every
element of the tree.
Similarly, the leaves on the right of the tree have the greatest values and
therefore if we need to find the highest number, we just need to traverse to one
side of the tree and we
can reach the destination much quicker than a program which used sorting and
searching algorithms to accomplish this task.
More importantly, as each leaf connects to two other leaves, it is the beginning
of a new, smaller, binary tree. Due to this reason, it is possible to easily access
and insert any type data in a binary tree at any point of time, using search and
insert functions recursively called on successive leaves and maintaining the
order of tree as well. The newly inserted node always goes to the right place.
8.2 Insert Function The following insert function inserts elements in a tree. If
tree is not created, the element creates it as well. It uses pointers to pointers in
order to handle the case of a tree that might not exist. By taking a pointer to a
pointer, it is possible to allocate memory if the root pointer is NULL.
if( *terminal == 0 )
(*terminal)->right = 0;
The insert function follows the two basic rules of a binary tree. For any current
node, move left if you have a lower value to enter and move right for a greater
value, until it reaches a NULL node, which it allocates memory for and
initializes with the new key value. The pointers to the second last node are
updated and pointers for newly initialized node are set to NULL. Once, the
element has been added, the insert function will stop calling itself and return
program control to normal environment for execution.
8.3 Search Function Here is a search function for a binary tree. It takes a key
value and a starting node and searches the key value in the tree recursively. If
leaf node is found, it is returned elsewise 0 is returned.
if( terminal != 0 )
if(key==terminal->key_value) {
return terminal;
else if(key<terminal->key_value) {
else
}
}
else return 0;
The search function shown above recursively moves down the tree until it either
reaches a node with a key value equal to the value for which the function is
searching. The value being searched for may not be stored in the binary tree and
hence we and hence we maintain a condition when search reaches a node with
NULL value, it is concluded that the key value leaf is not there in the binary tree.
It returns a pointer to the node to the previous instance of the function which
called it.
Conclusion
The book is a simple, complete and quick reference for programming in C. The
book presents the general purpose language, step by step. It is written following
a programmer’s approach and is therefore ideal for using as a quick guide and
reference for people who aim to code in C.
The book covers all the basic concepts of programming in detail like Operators,
Functions, Pointers, Arrays, Strings, and decision making statements. The book
has the flexibility to help the readers if they are interested in selective study. The
chapters are written with minimum possible inter-dependency.
At the end of the book, the reader must be an efficient programmer in C and will
be familiar with following concepts of C: • An overview of the language
be familiar with following concepts of C: • An overview of the language
• Lexical elements of C
• Loops
• Arrays ()
• Strings
• Pointers
• Functions
• Stacks
• Queues
• Linked lists
• Binary Tree
If you’ve found the book helpful, please leave a review for it now. Also check
out my other books on Kindle.
R.J. Khan
Check Out My Other Books: