BASIC COMPUTER PROGRAMMING
BASIC COMPUTER PROGRAMMING
FACULTY OF EDUCATION
JANUARY, 2023
COURSE DESCRIPTION
The focus of the course is on problem analysis and the development of algorithms and computer programs
in a modern high-level language. Prerequisites: There are no formal prerequisites, but some familiarity with
computers in general is assumed of all students.
Learning Outcomes:
Upon successful completion of the course, students should be able to:
1. Develop their logical abilities.
2. Describe concepts of computer programming language.
3. Develop the algorithms for solving Engineering problems.
4. Develop skills to write, compile and debug programs with C compiler.
5. Describe constants, variables and data types
Syllabus Topic Content Hour Weeks
s
1. Number Introduction and type of Number system, 3 1
System Conversion between number system,
Arithmetic operations on number system,
Signed and unsigned number system
Software, Computer Languages and
Computer Program.
2. Introduction Features of C language, structure of C 3 2
to ‘C’ Program, Flow Charts and Algorithms
Programming Types of errors, debugging,
tracing/stepwise execution of program,
watching variables values in memory.
Study
Materials
Textbooks, magazines, and journal publications
PowerPoint presentations
Online resources
INTRODUCTION
BASIC is a family of general-purpose, high-level programming languages designed for ease of use. The
original version was created by John G. Kemeny and Thomas E. Kurtz at Dartmouth College in 1963. They
wanted to enable students in non-scientific fields to use computers.
Computer Programming is a step by step process of designing and developing various sets of computer
programs to accomplish a specific computing outcome. The process comprises several tasks like analysis,
coding, algorithm generation, checking accuracy and resource consumption of algorithms, etc.
The purpose of computer programming is to find a sequence of instructions that solve a specific problem on
a computer.
Computer Programming is very easy if it is appropriately managed. There are many computer
programming languages available so finalizing the right programming language is not an easy task.
Basic of programming
English is the most popular and well-known Human Language. The English language has its own set of
grammar rules, which has to be followed to write in the English language correctly.
Likewise, any other Human Languages (German, Spanish, Russian, etc.) are made of several elements like
nouns, adjective, adverbs, propositions, and conjunctions, etc. So, just like English, Spanish or other human
languages, programming languages are also made of different elements.
Just like human languages, programming languages also follow grammar called syntax. There are certain
basic program code elements which are common for all the programming languages.
Programming Environment
1. Data Types
2. Variables
3. Keywords
4. Logical and Arithmetical Operators
5. If else conditions
6. Loops
7. Numbers, Characters and Arrays
8. Functions
9. Input and Output Operations
Computer programming is a set of written instructions that the computer follows. These instructions can be
written in various languages. Each programming languages have their unique ways of organizing the
commands which are called syntax.
Multiple programming languages can help you solve the same programming problem. However, you need
to select a language that you feel is relevant to perform your task. If you decide that a language does not
suit your business requirement, you can always move on to a new language. Your skill in the chosen
language will also be a deciding factor. Expected software system response time, a number of simultaneous
users, security, maintains, compatibility with web, mobile, devices are few other factors to consider while
choosing a language
Take marketing, for instance: you can use data skills you have learnt from coding to understand
performance data or customer trends and use this to inform your marketing strategy.
Coding can also open up many opportunities for you in more creative fields, such as graphic design, web or
app development. Alternatively, coding can be beneficial for non-tech roles if you are a writer and you
NUMBER SYSTEM
The Number System includes any of the numerous sets of symbols and the rules for using them to denote
numbers, which are used to state how many objects are there in a given set. Thus, the idea of “oneness” can
be denoted by the Roman numeral I, by the Greek letter alpha α which was the first letter used as a
numeral, by the Hebrew letter aleph which is the first letter used as a numeral, or by the modern number 1,
which is nothing but Hindu-Arabic in origin.
Most likely, the beginning system of the inscribed symbol in ancient Mesopotamia was a system of
symbols for numbers. The present number systems are place-value systems. That is, the value of these
numbers depends upon the position or place of the numbers in the representation; for example, the 3 in 30
and 300 represents 3 ten’s and 3 hundred, respectively. In the ancient systems, such as the Egyptian
civilization, Roman, Hebrew, and Greek Number systems, did not have a positional characteristic, and it
was a very complicated arithmetical calculation. Other systems though, including the Babylonian, one
version each of the Chinese and Indian, as well as the Mayan system, did use the principle of place value.
Type of Number system, Conversion between number system, Arithmetic operations on number system,
Signed and unsigned number system Software, Computer Languages and Computer Program.
Team University Lecture Material - Introduction to Basic Computer Programming Page 9
Type of Number system
When we type any letter or word, the computer translates them into numbers since computers can
understand only numbers. A computer can understand only a few symbols called digits and these symbols
describe different values depending on the position they hold in the number. In general, the binary number
system is used in computers. However, the octal, decimal and hexadecimal systems are also used
sometimes.
The number system helps to represent numbers in a small symbol set. Computers, in general, use binary
numbers 0 and 1 to keep the calculations simple and to keep the amount of necessary circuitry less, which
results in the least amount of space, energy consumption and cost.
The base 1 number system is called the unary numeral system and is the simplest numeral system to
represent natural numbers.
For example, if / stands for one, * for ten and - for 100, then the number 304 can be compactly represented
as --- //// and the number 123 as - ** /// without any need for zero and this is called sign-value notation.
In computers, the main system of numbers is based on the positional system in base 2 which is a binary
numeral system, with two digits of binary, 0's and 1's. Positional systems received by grouping binary
digits by three, which is the octal numeral system or four which is the hexadecimal numeral system, are
commonly used. For very large numbers, bases 232 or 264, you can group the binary digits by 32 or 64,
which is the portion of the machine word.
Number system represents a valuable set of numbers that consists of natural numbers, integers, real
numbers, irrational numbers, rational numbers and so on.
Natural Numbers
The natural (or counting) numbers are from 1, 2, 3, 4, 5, 6, 7, 8, 9, etc. Natural numbers are infinite
numbers. The set of natural numbers, {1, 2, 3, 4, 5, 6, 7, 8...}, is denoted by N in short form.
The addition of any 2 natural numbers is also a natural number (for instance, 4 + 5000 = 5004), and the
product of any two natural numbers is also a natural number (4 × 3500 = 14000). The subtraction and
division of any two or more natural numbers is not equal to natural numbers, though.
Integers
Integers are natural numbers consisting of the set of real numbers, their additive inverses and zero.
{..., -9, -8, -7, -6, −5, −4, −3, −2, −1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...}
The set of integers is denoted by J or Z in short form. These integer values can be represented on the
number line. These numbers can be a whole number or decimal numbers. You can represent -6.5 on a
number, 6 on a number line.
The addition, product, and difference between any two integers is also an integer. But this is not true for
division.
Rational Numbers
Rational numbers are figures which can be formulated as a ratio between two integers. For instance, the
fractions 13 and −11118 are both rational numbers. Rational numbers include all the integers since any
integer is denoted by z.
Irrational Numbers
An irrational number is a number that cannot be written as a proportion (or fraction). The irrational number
does not end or repeats in a decimal form. The ancient Greek mathematician discovered that not all integers
are rational numbers; there are equations that cannot be solved using ratios of integers.
The square root of 2 is about 1.414, because 1.4142=1.999396, which is almost equal to 2. You will never
get the exact number by squaring the fraction (or terminating decimal numbers). The square root of 2 is an
irrational number, meaning its decimal equivalent goes on forever, with no repetitive pattern
The golden ratio is another famous irrational number, a number which has great importance in biology:
1 + 5√2 = 1.61803398874989…
π = 3.14159265358979…
e = 2.71828182845904…
Real Numbers
Real numbers are the set of numbers containing all the irrational numbers and all the rational numbers.
They consist of “all the numbers” on the number scale. Real numbers are infinite numbers just as there are
infinitely many numbers in each of the other sets of numbers. But, the infinity of the real numbers is a
bigger infinity.
Complex Numbers
Complex numbers are the set {a+bi | real numbers are a and b}, where the imaginary unit is i, -1
Complex numbers include the set of real numbers, which includes the set of both rational and irrational
numbers. The real numbers, in the complex system, are denoted in the form a + 0i = a. a real number.
This set is always denoted by C in the short form. The set of complex numbers is significant because for
any polynomial p(x) with real number coefficients, all the solutions of p(x) = 0 will be in C.
Binary to Octal
Example: 1100011
Octal means 8
Starting from the least significant bit, we will make a group of three bits First pair = 011
Second group = 100
Third group = 001
Now, we know that 011 = 3, 100 = 4, and 001 = 1, so the equivalent octal number system will be (143)8.
Binary to Decimal
Example: 1101001
Starting from the least significant bit from 20, then 21, till the nth most significant bit, i.e., 2ⁿ.
1 = 2⁰ = 1
1 = 2³.1 = 8
0 = 2⁴ .0= 0
1 = 2⁵ = 32
1 = 2⁶ = 64
= 1 + 0 + 0 + 8 + 0 + 32 + 64 = (105)10
Binary to Hexadecimal
Example: 101010001
We know that hexadecimal means 16, so we will start from the least significant bit and make groups of 4
bits:
First pair = 0001 = 1
Second pair = 0101 = 5
Third pair = 0001 = 1
(10000011)2
Decimal to Hexadecimal
Example: (650)10
1. Divide 650 by 16, we get the quotient as 40 and the remainder as 10 or A
2. Divide 40 by 16, we get the quotient as 2 and the remainder as 8
3. Divide 2 by taking the quotient as 0, we get the remainder as 2
= 7 Χ 8¹ + 9 Χ 8⁰= 56 + 9 = 65
First 20 Binary number system conversions to Decimal, Octal, and Hexadecimal systems:
00000 0 000 00
00010 2 002 02
00011 3 003 03
00100 4 004 04
00101 5 005 05
00110 6 006 06
00111 7 007 07
01000 8 008 08
01001 9 009 09
01010 10 010 0A
1011 11 011 0B
01100 12 012 0C
01101 13 013 0D
01110 14 014 0E
01111 15 015 0F
10000 16 016 10
10001 17 017 11
10010 18 018 12
10011 19 019 13
10100 20 020 14
Conclusion
The most commonly used Number system is the decimal positional number system, the decimal referring to
the use of 10 numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 to construct all the required numbers. This discovery was
made by the Indians. There are other two common number systems which are used in computers and
computing science. They are the binary system, and these are denoted by 0's and 1's, and the hexadecimal
system, which has 16 symbols (We can understand by the term Hex which is 16) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
A, B, C, D, E, F.
3. The main system of numerals is based on ____________________in base 2 with two digits of binary, 0
and 1. (Ans: the positional system)
2. The complex numbers include the set of real numbers, that is, which includes the set of both rational and
irrational numbers. () (Ans: true )
3. The real numbers are the set of numbers containing all of the irrational numbers ( ) (Ans: false)
4. The integers are the natural numbers consisting of the set of real numbers, their additive inverses and
zero. ( ) (Ans: true)
(Ans: d. /)
Arithmetic is an elementary part of mathematics that consists of the study of the properties of the traditional
operations on numbers addition, subtraction, multiplication, division, exponentiation, and extraction of
roots
Arithmetic operations is a branch of mathematics, that involves the study of numbers, operation of numbers
that are useful in all the other branches of mathematics. It basically comprises operations such as Addition,
Subtraction, Multiplication and Division.
Arithmetic operations like addition, subtraction, multiplication and division are performed in various radix
bases. These arithmetic operations may also use r's complement and (r-1)'s complement representation
A number system is a set of symbols used to represent values derived from a common base or radix. In a
number, the value of each digit can be determined using digit, position of the digit in the number, and the
base of the number system. The base is defined as the total number of digits are available in the number
system. This is known as positional number system.
Binary 2 0, 1
Octal 8 0, 1, 2, 3, 4, 5, 6, 7
Decimal 10 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
Hexadecimal 16 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F
Arithmetic operations like addition, subtraction, multiplication and division are performed in various radix
bases. These arithmetic operations may also use r’s complement and (r-1)’s complement representation.
These representation techniques hold basic laws for various arithmetic operations:
(i) Unique Existence Law: The sum and product of any two numbers exist uniquely. Where 0 is the
identity element for additions and 1 is the identity element for multiplication.
(iv) Distributive Law:Multiplication of binary numbers is distributive over two or more terms in addition.
Now, arithmetic operations for various number systems are explained as following below.
The arithmetic operators perform addition, subtraction, multiplication, division, exponentiation, and modulus
operations.
Addition + Adds one operand to the other
Subtraction - Subtracts the second operand from the first
Modulo % Divides the first INTEGER operand by the second, and returns the
remainder
Exponentiation ** Lets you refer to a number in terms of a base value and an exponent
Operand Type
Operands for the arithmetic operators can be integers or real numbers.
SuperSet contains all members of both subsets with no duplicates. If either of the subsets is a single
member, then the plus operator is the equivalent of the SetAddMember function.
SubSet is the set containing all members of SuperSetA that are not also contained in SuperSetB.
Note: The exclusion of set B from set A is equivalent to: SetIntersection (A, SetComplement (B)).
The following examples should make the behavior of set exclusion operations more clear:
Operation Resulting set
Red - [COLORS]{Green, Blue} Red
In the third example above, the specification of a single member as the right operand works like
the SetRemove function to remove that member from the left operand set.
Binary arithmetic is essential part of various digital systems. You can add, subtract, multiply, and divide
binary numbers using various methods. These operations are much easier than decimal number arithmetic
operations because binary system has only two digits: 0 and 1.
Binary additions and subtractions are performed as same in decimal additions and subtractions. When we perform
binary additions, there will have two outputs: Sum (S) and Carry (C) . There are four rules for binary addition. These
are given as following below,
Input A Input B Sum (S)A+B Carry (C)
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1
There are four rules for binary subtraction. These are given as following below,
Input A Input B Subtract (S)A-B Borrow (B)
0 0 0 0
1 0 1 0
1 1 0 0
Borrow 1 is required from next higher order bit to subtract 1 from 0. So, result became 0.
There are four rules for binary multiplication. These are given as following below,
Input A Input B Multiply (M)AxB
0 0 0
0 1 0
1 0 0
1 1 1
Whenever at least one input is 0, then multiplication is always 0.
There are four part in any division: Dividend, Divisor, quotient, and remainder. These are given as following rules for
binary division,
Input A Input B Divide (D)A/B
0 0 Not defined
0 1 0
1 0 Not defined
1 1 1
Whenever divisor is 0, then result is always not defined.
0 0 1 2 3 4 5 6 7
1 1 2 3 4 5 6 7 10
2 2 3 4 5 6 7 10 11
3 3 4 5 6 7 10 11 12
5 5 6 7 10 11 12 13 14
6 6 7 10 11 12 13 14 15
7 7 10 11 12 13 14 15 16
With the help of above table, we can perform additions of octal numbers.
Similarly, we can perform subtraction of octal numbers same as decimal number sutractions. But you can
only take borrow of a number 7, which is maximum digit allowed in octal number systems.
In the multiplication of octal numbers, if the product is less than radix of octal (i.e, 8), then we take it as
the result, else divide it by radix of octal (i.e., 8) and take the remainder as the LSB (least significant bit).
The quotient is taken as carry in the next significant digit.
Similarly, division of octal numbers can be performed by following the rules of division of decimal
numbers but maximum allowed digit will be 7.
Arithmetic operations of hexadecimal numbers can be performed using addition table for hexadecimal numbers
which is given as below:
+ 0 1 2 3 4 5 6 7 8 9 A B C D E F
0 0 1 2 3 4 5 6 7 8 9 A B C D E F
1 1 2 3 4 5 6 7 8 9 A B C D E F 10
2 2 3 4 5 6 7 8 9 A B C D E F 10 11
3 3 4 5 6 7 8 9 A B C D E F 10 11 12
4 4 5 6 7 8 9 A B C D E F 10 11 12 13
5 5 7 7 8 9 A B C D E F 10 11 12 13 14
6 6 7 8 9 A B C D E F 10 11 12 13 14 15
7 7 8 9 A B C D E F 10 11 12 13 14 15 16
8 8 9 A B C D E F 10 11 12 13 14 15 16 17
9 9 A B C D E F 10 11 12 13 14 15 16 17 18
B B C D E F 10 11 12 13 14 15 16 17 18 19 1A
C C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B
D D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C
E E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D
F F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E
With the help of above table, we can perform additions of hexadecimal numbers.
Subtraction of hexadecimal numbers can be performed by using complement methods or simple as decimal
sutractions. The rule of simple hexadecimal subtraction is the digit borrowed from the immediate higher
place is counted as 16.
In the multiplication of hexadecimal numbers, if the product is less than radix of hexadecimal (i.e, 16), then
we take it as the result, else divide it by radix of hexadecimal (i.e., 16) and take the remainder as the LSB
(least significant bit). The quotient is taken as carry in the next significant digit. Using these rules, you can
make a table for hexadecimal multiplications.
Similarly, division of hexadecimal numbers can be performed by following the rules of division of decimal
numbers but maximum allowed digit will be F(=15 in decimal).
Arithmetic operations of decimal numbers are very popular and much easier. These operations are also
performed as same in other number systems.
These basic mathematical operations (+, -, ×, and ÷) we use in our everyday life. Whether we need to
calculate the annual budget or distribute something equally to a number of people, for every such aspect of
our life, we use arithmetic operations.
Let us understand each of the basic arithmetic operations in detail.
Addition Definition
The addition is a mathematical process of adding things together. The addition process is denoted
by ‘+’ sign. It involves combining two or more numbers into a single term. In addition process, the order
does not matter. It means that the addition process is commutative. It can involve any type of number
whether it be a real or complex number, fraction, or decimals.
Addition Rules
The following are the addition rules for integers:
Addition of two positive integers is a positive integer
Addition of two negative integers is a negative integer
While adding positive and negative integers, subtract the integers and use the sign of the largest integer
number
Subtraction Definition
The subtraction operation gives the difference between two numbers. Subtraction is denoted by ‘-‘ sign. It
is almost similar to addition but is the conjugate of the second term. It is the inverse process of addition.
The addition of the term with the negative term is known as subtraction. This process is mostly used to find
how many are left when some things are taken away.
Example: 15 – 7
The term can also be re-written as 15 + (-7)
Adding terms we have, 8.
Subtraction Rules
The following are the subtraction rules for integers:
I. If both the signs of the integers are positive, the answer will be the positive integer
II. If both the signs of the integers are negative, the answer will be the negative integer
III. If the signs of the integers are different, subtract the values, and take the sign from the largest
integer value.
Example: 2 × 3 = 6
Here, “2” is the multiplier, “3” is the multiplicand, and the result “6” is called the product.
The product of two numbers says ‘a’ and ‘b’ results in a single value term ‘ab,‘ where a and b are the
factors of the final value obtained.
Multiplication Rules
The following are the multiplication rules for the integers.
The product of two positive integers is a positive integer
The product of two negative integers is a positive integer
The product of positive and negative integer is a negative integer
Division Definition
The division is usually denoted by ‘÷‘ and is the inverse of multiplication. It constitutes two terms dividend
and divisor, where the dividend is divided by the divisor to give a single term value. When the dividend is
greater than the divisor, the result obtained is greater than 1, or else it would be less than 1.
Example: 4 ÷ 2 = 2
Here, “4” is the dividend, “2” is the divisor, and the result “2” is called the quotient.
Read: Multiplication and Division of Integers
Division Rules
The following are the division rules for integers:
The division of two positive integers is a positive integer
The division of two negative numbers is a positive integer
The division of integers with different signs results in the negative integer.
Mathematical Operations
The basic mathematical operations are the four arithmetic operations that we have already learned in the
above sections.
Addition and subtraction are inverse operations of each other. It means if the addition of two numbers gives
the third number, then subtraction of an added number from the third number will result in the original
number.
Example:
4 + 7 = 11
Now, if we subtract 7 from 11, we get;
Commutative Property
This property is applicable only for two arithmetic operations, i.e., addition and multiplication.
Suppose A and B are two numbers, then, according to commutative property;
A+B = B+A Example: 1 + 2 = 2 + 1
AxB=BxA Example: 1 x 2 = 2 x 1
Thus, the order of numbers in addition and multiplication does not change the result.
Associative Property
Like commutative property, the associative property is also applicable to addition and multiplication.
A+(B+C) = (A+B)+C Example: 1 + (2+3) = (1+2)+3
Distributive Property
According to the distributive property, if A, B and C are any three real numbers, then,
A x (B + C) = A x B + A x C
Example: 2 x (3 + 4) = (2 x 3) + (2 x 4)
2x7=6+8
14 = 14
Hence, proved.
Solved Examples
Q.1: Add 23 and 40 and then subtract 20 from the sum.
⇒2+9–9
⇒ 11 – 9
⇒2
To learn more about numbers and different Maths-related concepts, visit BYJU’S- The Learning App.
Broadly, there are eight types of operators in C and C++. They are:
1) Increment and decrement operators.
2) Bitwise operators.
3) Assignment operators.
4) Logical operators.
5) Relational operators.
6) Special operators.
7) Conditional operators.
8) Arithmetic Operators.
Our number system ranges from minus infinity to plus infinity, with zero in the middle. However,
programming has two types of numbers: signed and unsigned. The potential to employ negative numbers is
the primary difference between a signed and an unsigned number.
Unsigned numbers can only have values that are equal to or greater than zero. On the other hand, signed
numbers have a more natural range that covers negative and positive numbers.
Variables such as integers can be represent in two ways, i.e., signed and unsigned. Signed numbers use sign
flag or can be distinguish between negative values and positive values. Whereas unsigned numbers stored
only positive numbers but not negative numbers.
Number representation techniques like: Binary, Octal, Decimal and Hexadecimal number representation
techniques can represent numbers in both signed and unsigned ways. Binary Number System is one the
type of Number Representation techniques. It is most popular and used in digital systems.
In the Binary System, there are only two symbols or possible digit values, i.e., 0 and 1. Represented by any
device that only 2 operating states or possible conditions. Binary numbers are indicated by the addition of
either an 0b prefix or an 2 suffix.
The requirement to express numeric values with limited resources drove the creation of signed vs. unsigned
numbers. When utilizing 8 bits, there are only 256 possible combinations. Any value between 0 and 255 is
considered an unsigned number.
On the other hand, having a signed number means you've already lost a bit for representing the sign. With 7
bits, you can only have 128 permutations. Hence an 8-bit signed number's range is -128 to 127. Using
unsigned numbers was the way to go if you had limited resources, which was the case in the early days of
computers.
Unsigned integers range from 0 to 4,294,967,295 or around 4 billion in 32-bit integers. The signed version
ranges from –2,147,483,648 to 2,147,483,647, or around -2 billion to +2 billion. The range is the same,
but the values are shifted on the number line.
Unsigned value - Variables with unsigned numerals can store only 0 and positive numbers.
Table of the Range of Values Each Integer Type Can Store Refer
Min
Storage
Type Min signed value Max signed value unsigned Max unsigned value
(Bytes)
value
Tinyint 1 -128 127 0 255
Smallint 2 -32768 32767 0 65535
Mediumint 3 -8388608 8388607 0 16777215
Int 4 -2147483648 2147483647 0 4924967295
BIGINT 8 -9,223,372,036,854,775,808 9,223,372,036,854,775,807 0 18,446,744,073,709,551,615
Example
Simply convert it into Binary number, it contains only magnitude of the given number.= (92) 10
= (1x26+0x25+1x24+1x23+1x22+0x21+0x20)10
= (1011100)2
It’s 7 bit binary magnitude of the decimal number 92.
Example-2: Find range of 5 bit unsigned binary numbers. Also, find minimum and maximum value in this
range.
Since, range of unsigned binary number is from 0 to (2n-1). Therefore, range of 5 bit unsigned binary
number is from 0 to (25-1) which is equal from minimum value 0 (i.e., 00000) to maximum value 31 (i.e.,
11111).
Since magnitude of number zero (0) is always 0, so there can be two representation of number zero (0),
positive (+0) and negative (-0), which depends on value of sign bit. Hence these representations are
ambiguous generally because of two representation of number zero (0). Generally sign bit is a most
significant bit (MSB) of representation. The range of Sign-Magnitude form is from (2(n-1)-1) to (2(n-1)-1).
For example, range of 6 bit Sign-Magnitude form binary number is from (25-1) to (25-1) which is equal
from minimum value -31 (i.e., 1 11111) to maximum value +31 (i.e., 0 11111). And zero (0) has two
representation, -0 (i.e., 1 00000) and +0 (i.e., 0 00000).
You can get negative number by 1’s complement of a positive number and positive number by using 1’s
complement of a negative number. Therefore, in this representation, zero (0) can have two representation,
that’s why 1’s complement form is also ambiguous form. The range of 1’s complement form is from (2(n-1)-
1) to (2(n-1)-1) .
For example, range of 6 bit 1’s complement form binary number is from (25-1) to (25-1) which is equal
from minimum value -31 (i.e., 1 00000) to maximum value +31 (i.e., 0 11111). And zero (0) has two
representation, -0 (i.e., 1 11111) and +0 (i.e., 0 00000).
You can get negative number by 2’s complement of a positive number and positive number by directly
using simple binary representation. If value of most significant bit (MSB) is 1, then take 2’s complement
from, else not.
Therefore, in this representation, zero (0) has only one (unique) representation which is always positive.
The range of 2’s complement form is from (2(n-1)) to (2(n-1)-1).
For example, range of 6 bit 2’s complement form binary number is from (25) to (25-1) which is equal from
minimum value -32 (i.e., 1 00000) to maximum value +31 (i.e., 0 11111). And zero (0) has two
representation, -0 (i.e., 1 11111) and +0 (i.e., 0 00000).
C and C++
Both languages are widely used in computer science and programming. C and C++ developers can make
use of compilers for a wide variety of platforms, making applications developed in these languages largely
transportable. Both C and C++ are considered high-performance languages.
But what language should you learn? You'll find a seemingly infinite number of programming languages that
are free to learn and develop projects with online. With the field of technology growing exponentially each
year, the internet is a great place to start when trying to explore the latest developments or discover a new
skill.
In this article, we'll explore some of the most common types of programming languages and give you some
resources you can use to start learning.
4. Scripting languages
Programmers use scripting languages to automate repetitive tasks, manage dynamic web content, or support
processes in larger applications. Some common scripting languages include:
i. PHP
ii. Ruby
iii. Python
iv. bash
v. Perl
vi. Node.js
Front-end languages are primarily concerned with the ‘user’ aspect of the software. The front end deals with
all of the text, colors, buttons, images, and navigation that the user will face when navigating your website or
application. Anyone with a background in graphic design or art may be more inspired to begin learning one of
the front-end languages.
Back-end languages deal with storage and manipulation of the server side of software. This is the part of the
software that the user does not directly come into contact with but supports their experience behind the
scenes. This includes data architecture, scripting, and communication between applications and underlying
databases.
Anyone with experience in mathematics or engineering may find more interest in back-end development.
The biggest factor that differentiates high- and low-level programming languages is whether the language is
meant to be easily understood by a human programmer or a computer. Low-level languages are machine-
friendly, which makes them highly efficient in terms of memory usage but difficult to understand without the
help of an assembler. Since they're not very people-friendly, they're also not widely used anymore. Examples
include machine code and assembly languages.
High-level languages, on the other hand, are less memory efficient but much more human friendly. This
makes them easier to write, understand, maintain, and debug. Most popular programming languages in use
today are considered high-level languages.
Compiled languages go through a build step where the entire program is converted into machine code. This
makes it faster to execute, but it also means that you have to compile or "build" the program again anytime
you need to make a change.
C is a general-purpose programming language that is extremely popular, simple, and flexible to use. It is a
structured programming language that is machine-independent and extensively used to write various
applications, Operating Systems like Windows, and many other complex programs like Oracle database,
Git, Python interpreter, and more.
It is said that ‘C’ is a god’s programming language. One can say, C is a base for the programming. If you
know ‘C,’ you can easily grasp the knowledge of the other programming languages that uses the concept of
‘C’
It is essential to have a background in computer memory mechanisms because it is an important aspect
when dealing with the C programming language.
The core features of a programming language describe its ability and uniqueness and how beneficial it can
be in developing a website or software. Listed below are some of the significant features of C language:
2 ) Fast
It is a well-known fact that statically typed programming languages are faster than dynamic ones. C is a
statically typed programming language, which gives it an edge over other dynamic languages. Also,
unlike Java and Python, which are interpreter-based, C is a compiler-based program. This makes the
compilation and execution of codes faster.
Another factor that makes C fast is the availability of only the essential and required features. Newer
programming languages come with numerous features, which increase functionality but reduce efficiency
and speed. Since C offers limited but essential features, the headache of processing these features reduces,
resulting in increased speed.
3) Portability
Another feature of the C language is portability. To put it simply, C programs are machine-independent
which means that you can run the fraction of a code created in C on various machines with none or some
machine-specific changes. Hence, it provides the functionality of using a single code on multiple systems
depending on the requirement.
4)Extensibility
You can easily (and quickly) extend a C program. This means that if a code is already written, you can add
new features to it with a few alterations. Basically, it allows adding new features, functionalities, and
operations to an existing C program.
5)Function-Rich Libraries
C comes with an extensive set of libraries with several built-in functions that make the life of a programmer
easy. Even a beginner can easily code using these built-in functions. You can also create your user-
9)Pointers
With the use of pointers in C, you can directly interact with memory. As the name suggests, pointers point
to a specific location in the memory and interact directly with it. Using the C pointers, you can operate with
memory, arrays, functions, and structures.
10)Recursion
C language provides the feature of recursion. Recursion means that you can create a function that can call
itself multiple times until a given condition is true, just like the loops. Recursion in C programming
provides the functionality of code reusability and backtracking.
If you want to learn more about the C language and other such programming languages, you can sign up on
Simplilearn’s SkillUp platform. The platform provides several free courses to help you excel in the
development field.
HISTORY OF C LANGUAGE
The base or father of programming languages is ‘ALGOL.’ It was first introduced in 1960. ‘ALGOL’ was
used on a large basis in European countries. ‘ALGOL’ introduced the concept of structured programming
to the developer community. In 1967, a new computer programming language was announced called as
‘BCPL’ which stands for Basic Combined Programming Language.
BCPL was designed and developed by Martin Richards, especially for writing system software. This was
the era of programming languages. Just after three years, in 1970 a new programming language called ‘B’
was introduced by Ken Thompson that contained multiple features of ‘BCPL.’ This programming language
was created using UNIX operating system at AT&T and Bell Laboratories. Both the ‘BCPL’ and ‘B’ were
system programming languages.
In 1972, a great computer scientist Dennis Ritchie created a new programming language called ‘C’ at the
Bell Laboratories. It was created from ‘ALGOL’, ‘BCPL’ and ‘B’ programming languages. ‘C’
programming language contains all the features of these languages and many more additional concepts that
make it unique from other languages.
‘C’ is a powerful programming language which is strongly associated with the UNIX operating system.
Even most of the UNIX operating system is coded in ‘C’. Initially ‘C’ programming was limited to the
UNIX operating system, but as it started spreading around the world, it became commercial, and many
compilers were released for cross-platform systems.
Today ‘C’ runs under a variety of operating systems and hardware platforms. As it started evolving many
different versions of the language were released. At times it became difficult for the developers to keep up
with the latest version as the systems were running under the older versions.
To assure that ‘C’ language will remain standard, American National Standards Institute (ANSI) defined a
commercial standard for ‘C’ language in 1989. Later, it was approved by the International Standards
Organization (ISO) in 1990. ‘C’ programming language is also called as ‘ANSI C’.
C Basic Commands
Following are the basic commands in C programming language:
C Basic commands Explanation
This command includes standard input output header file(stdio.h) from the C library
#include <stdio.h>
before compiling a C program
int main() It is the main function from where C program execution begins.
{ Indicates the beginning of the main function.
Whatever written inside this command “/* */” inside a C program, it will not be
/*_some_comments_*/
considered for compilation and execution.
printf(“Hello_World!
This command prints the output on the screen.
“);
getch(); This command is used for any character input from keyboard.
return 0; This command is used to terminate a C program (main function) and it returns 0.
} It is used to indicate the end of the main function.
It shares the same concepts such as data types, operators, control statements and many more. ‘C’ can be
used widely in various applications. It is a simple language and provides faster execution. There are many
jobs available for a ‘C’ developer in the current market.
‘C’ is a structured programming language in which program is divided into various modules. Each module
can be written separately and together it forms a single ‘C’ program. This structure makes it easy for
testing, maintaining and debugging processes.
‘C’ contains 32 keywords, various data types and a set of powerful built-in functions that make
programming very efficient.
Another feature of ‘C’ programming is that it can extend itself. A ‘C’ program contains various functions
which are part of a library. We can add our features and functions to the library. We can access and use
these functions anytime we want in our program. This feature makes it simple while working with complex
programming.
Various compilers are available in the market that can be used for executing programs written in this
language.
It is a highly portable language which means programs written in ‘C’ language can run on other machines.
This feature is essential if we wish to use or execute the code on another computer.
Nowadays, various compilers are available online, and you can use any of those compilers. The
functionality will never differ and most of the compilers will provide the features required to execute both
‘C’ and ‘C++’ programs.
Summary
‘C’ was developed by Dennis Ritchie in 1972.
It is a robust language.
It is a low programming level language close to machine language
It is widely used in the software development field.
It is a procedure and structure oriented language.
It has the full support of various operating systems and hardware platforms.
Many compilers are available for executing programs written in ‘C’.
A compiler compiles the source file and generates an object file.
A linker links all the object files together and creates one executable file.
It is highly portable.
STRUCTURE OF C PROGRAM
All human beings have a definite structure, i.e., head, neck, and four limbs connected to a torso. Almost
everything has a definite structure. Likewise, in the case of programming languages, all of them have a
definite structure. These structures have to be followed while writing the code.
The structure of a C program can be mainly divided into six parts, each having its purpose. It makes the
program easy to read, easy to modify, easy to document, and makes it consistent in format.
Algorithm
You've to subtract the current year from your birth year and get your age.
Let's implement this and check:
Code:
/** //Documentation
* file: age.c
* author: you
Definition
A preprocessor directive in C is any statement that begins with the "#" symbol. The #define is a
preprocessor compiler directive used to create constants. In simple terms, #define basically allows the
macro definition, which allows the use of constants in our code.
#define is typically used to make a source program easy to modify and compile in different execution
environments.
Global Declaration
This section includes all global variables, function declarations, and static variables. The variables declared
in this section can be used anywhere in the program. They're accessible to all the functions of the program.
Hence, they are called global variables.
Main() Function
In the structure of a C program, this section contains the main function of the code. The compiler starts
execution from the main() function. It can use global variables, static variables, inbuilt functions, and user-
defined functions. The return type of the main() function can be void and also not necessarily int.
int main(void)
{
int current = 2021;
printf("Age: %d", age(current));
return 0;
}
Here, we've declared a variable named current and assigned the value as 2021. Then we've called
the printf() function, with calls the age() function, which takes only one parameter.
Subprograms
This includes the user-defined functions called in the main() function. User-defined functions are generally
written after the main() function irrespective of their order.
When the user-defined function is called from the main() function, the control of the program shifts to the
called function, and when it encounters a return statement, it returns to the main() function. In this case,
we've defined the age() function, which takes one parameter, i.e., the current year.
int age(int current) {
return current - BORN;
}
This function is called in the main function. It returns an integer to the main function.
The term ‘machine learning’ is often, incorrectly, interchanged with Artificial Intelligence[JB1] , but
machine learning is actually a sub
field/type of AI. Machine learning is also often referred to as predictive analytics, or predictive modelling.
Coined by American computer scientist Arthur Samuel in 1959, the term ‘machine learning’ is defined as a
“computer’s ability to learn without being explicitly programmed”.
At its most basic, machine learning uses programmed algorithms that receive and analyse input data to
predict output values within an acceptable range. As new data is fed to these algorithms, they learn and
optimise their operations to improve performance, developing ‘intelligence’ over time.
There are four types of machine learning algorithms: supervised, semi-supervised, unsupervised and
reinforcement.
Supervised learning
In supervised learning, the machine is taught by example. The operator provides the machine learning
algorithm with a known dataset that includes desired inputs and outputs, and the algorithm must find a
method to determine how to arrive at those inputs and outputs. While the operator knows the correct
answers to the problem, the algorithm identifies patterns in data, learns from observations and makes
predictions. The algorithm makes predictions and is corrected by the operator – and this process
continues until the algorithm achieves a high level of accuracy/performance.
Classification: In classification tasks, the machine learning program must draw a conclusion from
observed values and determine to
what category new observations belong. For example, when filtering emails as ‘spam’ or ‘not spam’, the
program must look at existing observational data and filter the emails accordingly.
Regression: In regression tasks, the machine learning program must estimate – and understand – the
relationships among variables. Regression analysis focuses on one dependent variable and a series of other
changing variables – making it particularly useful for prediction and forecasting.
Forecasting: Forecasting is the process of making predictions about the future based on the past and
present data, and is commonly used to analyse trends.
Semi-supervised learning
Semi-supervised learning is similar to supervised learning, but instead uses both labelled and unlabelled
data. Labelled data is essentially information that has meaningful tags so that the algorithm can understand
the data, whilst unlabelled data lacks that information. By using this
combination, machine learning algorithms can learn to label unlabelled data.
Unsupervised learning
Here, the machine learning algorithm studies data to identify patterns. There is no answer key or human
operator to provide instruction. Instead, the machine determines the correlations and relationships by
analysing available data. In an unsupervised learning process, the machine learning algorithm is left to
interpret large data sets and address that data accordingly. The algorithm tries to organise that data in some
way to describe its structure. This might mean grouping the data into clusters or arranging it in a way that
looks more organised.
As it assesses more data, its ability to make decisions on that data gradually improves and becomes more
refined.
Dimension reduction: Dimension reduction reduces the number of variables being considered to find the
exact information required.
Reinforcement learning
Reinforcement learning focuses on regimented learning processes, where a machine learning algorithm is
provided with a set of actions, parameters and end values. By defining the rules, the machine learning
What are the most common and popular machine learning algorithms?
Despite its simplicity, the classifier does surprisingly well and is often used due to the fact it outperforms
more sophisticated classification methods.
ANNs are inspired by biological systems, such as the brain, and how they process information. ANNs are
essentially a large number of interconnected processing elements, working in unison to solve specific
problems.
ANNs also learn by example and through experience, and they are extremely useful for modelling non-
linear relationships in high-dimensional data or where the relationship amongst the input variables is
difficult to understand.
Clearly, there are a lot of things to consider when it comes to choosing the right machine learning
algorithms for your business’ analytics. However, you don’t need to be a data scientist or expert statistician
to use these models for your business. At SAS, our products and solutions utilise a comprehensive selection
of machine learning algorithms, helping you to develop a process that can continuously deliver value from
your data.
In curriculum, it can be helpful for teachers to use examples of algorithms in everyday life to make the
concept more approachable.
Many everyday algorithms are surprisingly complex but they also come naturally to us. For instance,
deciding what to wear in the morning is (for some of us) a complex algorithm of identifying what’s clean
and available, which options are suitable for the weather, which articles of clothing match (each other or
our style and what we’re comfortable wearing that day, etc.). Some are surprisingly simple, such as the
process of pouring a glass of water.
Below, we offer 7 unique examples that students can relate to that illustrate algorithms in everyday life:
2. Following a Recipe
Recipes are a great example of an algorithm in everyday life. They illustrate a replicable set of steps to
accomplish a specific goal (such as baking blueberry muffins or cooking spaghetti sauce from scratch).
Recipes are designed to create a duplicatable outcome, or to help individuals regardless of background be
able to create a specific food by following a set of detailed instructions—just as an algorithm in computer
science details steps to create replicable outcomes.
3. Classifying Objects
A process for classifying objects is another great example of algorithms in everyday life. Whether
classifying foods into different food groups, sorting household items by function, or organizing blocks from
smallest to largest, students can often complete these algorithms relatively simply. Asking students to
define the process they use to classify the objects (a flowchart of qualities they look for in each specific
food to determine its food group or how they compare one block to its surrounding blocks) is an example of
algorithmic thinking, or the process of developing an algorithm that can be used to replicate a process.
Final Thoughts
Understanding algorithms is the first step for students mastering algorithmic thinking. To learn more about
how Learning.com can help support this learning process in your classroom or district curriculum, sample
EasyTech today.
TYPES OF ERRORS
There are 5 types of error in C:
Syntax Errors.
Runtime Errors.
Logical Errors.
Linked Errors.
Semantic Errors.
Here we will see different types of errors using a C program. In any programming language errors are
common. If we miss any syntax like parenthesis or semicolon then we get syntax errors. Apart from this
we also get run time errors during the execution of code.
1. Syntax Errors
These are also referred to as compile-time errors. These errors have occurred when the rule of C writing
techniques or syntaxes has been broken. These types of errors are typically flagged by the compiler prior
to compilation.
Example 1: In the below program we are getting an error because of a missing semicolon at the end of
the output statement (printf()) called syntax error.
// C program to demonstrate
// a syntax error due to
// missing semi colon
#include <stdio.h>
// Driver code
int main()
{
// missing semicolon
printf("Geeks for geeks!")
return 0;
}
Output:
Example 2: In this case, we are getting errors because of missing parenthesis before the output
statement and below the main(). This type of error is also called syntax error.
C
// C program to demonstrate
// a syntax error due to
// missing parenthesis
#include <stdio.h>
Output:
2. Runtime Errors
This type of error occurs while the program is running. Because this is not a compilation error, the
compilation will be completed successfully. These errors occur due to segmentation fault when a number
is divided by division operator or modulo division operator.
Example: Let us consider an array of length 5 i.e. array[5], but during runtime, if we try to access 10
elements i.e array[10] then we get segmentation fault errors called runtime errors. Giving only an array
length of 5
C
// C program to demonstrate
// a runtime error
#include <stdio.h>
// Driver code
int main()
{
int array[5];
printf("%d", array[10]);
return 0;
}
Output
-621007737
But in output trying to access more than 5 i.e if we try to access array[10] during runtime then the
program will throw an error or will show an abnormal behavior and print any garbage value.
3. Logical Errors
Even if the syntax and other factors are correct, we may not get the desired results due to logical issues.
These are referred to as logical errors. We sometimes put a semicolon after a loop, which is syntactically
correct but results in one blank loop. In that case, it will display the desired output.
// C program to demonstrate
// a logical error
#include <stdio.h>
// Driver code
int main()
{
int i;
for(i = 0; i <= 5; i++);
{
printf("Geeks for Geeks");
}
return 0;
}
Output
Geeks for Geeks
4. Linker Errors
When the program is successfully compiled and attempting to link the different object files with the main
object file, errors will occur. When this error occurs, the executable is not generated. This could be due to
incorrect function prototyping, an incorrect header file, or other factors. If main() is written as Main(), a
linked error will be generated.
// C program to demonstrate
// a linker error
#include <stdio.h>
// Driver code
int Main()
{
printf("Geeks for Geeks");
return 0;
}
Output:
// C program to demonstrate
// a semantic error
#include <stdio.h>
// Driver code
int main()
{
int x = 10;
b = 20, c;
x + y = c;
printf("%d", c);
return 0;
}
Output:
DEBUGGING
Debugging is the art of diagnosing errors in programs and determining how to correct them. "Bugs" come
in a variety of forms, including: coding errors, design errors, complex interactions, poor user interface
designs, and system failures. Learning how to debug a program effectively, then, requires that you learn
how to identify which sort of problem you're looking at, and apply the appropriate techniques to eliminate
the problem.
Bugs are found throughout the software life cycle. The programmer may find an issue, a software tester
might identify a problem, or an end user might report an unexpected result. Part of debugging effectively
involves using the appropriate techniques to get necessary information from the different sources of
problem reports.
Application development in C remains strong despite the advent of other languages such as Java and
Python, predominantly due to its performance, flexibility, and its use for memory management.
This example uses CentOS 7, gcc 4.8, and TotalView 2020.2 You can use any supported Linux version and
compiler.
Bugs in Detail
What are these different kinds of bugs, then?
With coding errors, the source of the problem lies with programmer induced erroneous or improper code.
Software users readily see some design errors, while in other cases design flaws make a program more
difficult to improve or fix, and those flaws are not obvious to a user. Obvious design flaws are often
demonstrated by programs that run up against the limits of a computer, such as available memory, available
disk space, available processor speed, and overwhelming input/output devices.
Complex interactivity bugs arise in scenarios where multiple parts of a single program, multiple programs,
or multiple computers interact.
Poor user interface designs often lead users to use the program in ways that accomplish something other
than what they intend. For example, a "search" page for a web site might have an option for "case-
insensitive" searching. When the option is hard for the user to find or see, that user might report a bug that
some of their data is "lost", simply because it is not found by the case sensitive search.
Sometimes, computer hardware simply fails, and it usually does so in wildly unexpected ways.
Determining that the problem lies not with the software itself, but with the computer(s) on which it is
usually complicated by the fact that the person debugging the software may not have access to the hardware
that shows the problem
Preventing Bugs
No discussion of debugging software would be complete without a discussion of how to prevent bugs in the
first place. No matter how well you write code, if you write the wrong code, it won't help anyone. If you
Although it is outside the scope of this discussion to describe the myriad techniques for avoiding bugs,
many of the techniques here are equally useful after the fact, when you have a bug and need to uncover it
and fix it. Thus, a brief discussion follows.
Users frequently want more than software can actually deliver, or have contradictory aims, such as software
that does more, but doesn't require that they learn anything new. In short, ask the users what their goals are.
Absent those goals, users will keep reporting bugs that do not add up to a coherent whole.
int main()
{
int i;
int numTerms = 10;
int t1 = 0, t2 = 1;
int nextTerm;
return 0;
}
2. Compile the fib.c file using the gcc compiler and the -g flag to enable debug symbols.
6. Use the Next button to step through the loop and watch the values of the variables in the Local
Variables window change as you do so.
7. A unique feature TotalView provides is the ability to record the execution of your program so you can
step back through the execution history.
Try turning on reverse debugging through the Replay Engine toolbar by pressing the Red Record button
and then stepping backward as well as forwards through the code.
Watch this video tutorial on Reverse Debugging.
8. Run the program to completion either by disabling the breakpoint and pressing GO or by
pressing Next multiple times until the for loop completes and observe the output in the Input / Output
window.
If the Input/Output View is not open, select it from the Window > Views > Input/Output menu item.
Data obtained from transmissions should be checked to make sure the entire message (data) was received.
Complex data that must be parsed and/or processed may contain unexpected combinations of values that
were not anticipated, and not handled correctly. By inserting checks for likely error symptoms, the program
can detect when data has been corrupted or not handled correctly.
If an error is severe enough to cause the program to terminate abnormally, the existence of a bug becomes
obvious. If the program detects a less serious problem, the bug can be recognized, provided error and/or log
messages are monitored. However, if the error is minor and only causes the wrong results, it becomes much
more difficult to detect that a bug exists; this is especially true if it is difficult or impossible to verify the
results of the program.
This step often involves iterative testing. The programmer might first verify that the input is correct, next if
it was read correctly, processed correctly, etc. For modular systems, this step can be a little easier by
checking the validity of data passed across interfaces between different modules. If the input was correct,
but the output was not, then the source of the error is within the module. By iteratively testing inputs and
outputs, the debugger can identify within a few lines of code where the error is occurring.
Skilled debuggers are often able to hypothesize where the problem might be (based on analogies to
previous similar situations), and test the inputs and outputs of the suspected areas of the program. This form
of debugging is an instance of the scientific method. Less skilled debuggers often step sequentially through
the program, looking for a place where the behavior of the program is different from that expected.
Note that this is still a form of scientific method as the programmer must decide what variables to examine
when looking for unusual behavior. Another approach is to use a "binary search" type of isolation process.
By testing sections near the middle of the data / processing flow, the programmer can determine if the error
happens during earlier or later sections of the program. If no data problems are detected, then the error is
probably later in the process.
A good understanding of the system is vital to successfully identifying the source of the bug. A trained
debugger can isolate where a problem originates, but only someone familiar with the system can accurately
identify the actual cause behind the error. In some cases it might be external to the system: the input data
was incorrect. In other cases it might be due to a logic error, where correct data was handled incorrectly.
Other possibilities include unexpected values, where the initial assumptions were that a given field can
have only "n" values, when in fact, it can have more, as well as unexpected combinations of values in
different fields (field x was only supposed to have that value when field y was something different).
Another possibility is incorrect reference data, such as a lookup table containing incorrect values relative to
the record that was corrupted.
In some cases, a fix is simple and obvious. This is especially true for logic errors where the original design
was implemented incorrectly. On the other hand, if the problem uncovers a major design flaw that
permeates a large portion of the system, then the fix might range from difficult to impossible, requiring
a total rewrite of the application.
In some cases, it might be desirable to implement a "quick fix", followed by a more permanent fix. This
decision is often made by considering the severity, visibility, frequency, and side effects of the problem, as
well as the nature of the fix, and product schedules (e.g., are there more pressing problems?).
For large systems, it is a good idea to have regression tests, a series of test runs that exercise the system.
After significant changes and/or bug fixes, these tests can be repeated at any time to verify that the system
still executes as expected. As new features are added, additional tests can be included in the test suite.
Even when the program appears to work, if you examine it with the thought that there is at least one bug
remaining and you are going to find it, then you are more likely to find something wrong with the program.
In addition to detecting problems, considerations should be given as to how best to handle each error.
Options include:
i. Report error, set invalid fields to a default value, and continue
ii. Report error, discard the record associated with the invalid value, and continue
iii. Report error, transfer invalid record into separate file/table so the user can examine and possibly
correct the problem
iv. Report error and terminate the program
v. Treat user input with suspicion
Any data that originated from users (including external systems) should be treated with suspicion. Carefully
validate all such input data, performing syntactical and semantical integrity checks. Such invalid data are a
common source of programming errors. Think not just of data entered in error, but malicious data as well,
as in buffer overflow exploits.
If data are entered interactively by users, you can provide appropriate error messages and allow the user to
correct the invalid field(s). If data are not from an interactive source, then the erroneous records should be
handled as described above.
Each entry should be date/time stamped so that entries from different logs can be correlated.
Test suites
A standard set of tests that can be run to perform tests can assist in finding errors before they make it into
production. These test cases should be automated as much as possible to reduce the amount of effort
required to perform these tests. As new features are added to the system, additional tests should be created
to exercise those features.
The fact that your changes didn't do anything indicates one of several things:
Programs, that are available under different Architectures (e.g. Operation Systems like MS Windows,
MacOSX, Linux or Processors like Intel Pentium, PowerPC or DEC Alpha) sometimes react differently on
other Systems (especially for subsequent errors). Sometimes it is far more easy to find the error on a
different architecture.
When a bug has been found, think of other places where the same mistake might have been made. Check
those places and see if the same problem exists there as well.
Another method of debugging is the log-file. Outputting the contents of certain variables can provide
valuable information on how your program performs. Outputting a string containing the name of the
function when the function is called can be useful in locating when an error is introduced. For finding
where a program crashes it's more practical to use the debugger.
Large programs are hard to debug, small programs are (relatively) easy to debug. So the key is to turn a
large program into a lot of small programs for debugging. This is called "Unit testing" and involves
compiling a part of your program (a routine, a collection of related routines, a module or even a complete
subsystem) with extra code to allow it to run without the rest of the code in place.
Full screen application (especially games) can be hard to debug as you won't be able to see the debuggers
output. A solution lays in using a null-modem cable, a second computer and a terminal program (e.g.
Hyper-terminal). Pipe the output of the debugger through the null modem cable to the second computer.
e.g.
The static variables are stored in the data segment of the memory. The data segment is a part of the
virtual address space of a program.
All the static variables that do not have an explicit initialization or are initialized to zero are stored in the
uninitialized data segment( also known as the BSS segment).
Here we will see how to print the memory representation of C variables. Here we will show integers, floats,
and pointers.
To solve this problem, we have to follow these steps −
i. Get the address and the size of the variable
ii. Typecast the address to the character pointer to get byte address
iii. Now loop for the size of the variable and print the value of typecasted pointer.
Example
#include <stdio.h>
typedef unsigned char *byte_pointer; //create byte pointer using char*
void disp_bytes(byte_pointer ptr, int len) {
//this will take byte pointer, and print memory content
int i;
for (i = 0; i < len; i++)
printf(" %.2x", ptr[i]);
printf("
");
}
void disp_int(int x) {
disp_bytes((byte_pointer) &x, sizeof(int));
}
void disp_float(float x) {
disp_bytes((byte_pointer) &x, sizeof(float));
}
void disp_pointer(void *x) {
disp_bytes((byte_pointer) &x, sizeof(void *));
}
main() {
int i = 5;
float f = 2.0;
int *p = &i;
disp_int(i);
disp_float(f);
disp_pointer(p);
disp_int(i);
}
Output
05 00 00 00
Team University Lecture Material - Introduction to Basic Computer Programming Page 62
00 00 00 40
3c fe 22 00 00 00 00 00
05 00 00 00
A constant is a value that doesn't change throughout the execution of a program. A variable is an identifier
which is used to store a value. There are four commonly used data types such as int, float, char and a void.
Each data type differs in size and range from one another.
Character Set, C tokens, Keywords and Identifiers, Constants, Variables, Data types, Declaration of
Variables, Assigning values to variables, typedef, and Defining symbolic constants.
A variable is an identifier which is used to store some value. Constants can never change at the time of
execution. Variables can change during the execution of a program and update the value stored inside it.
A single variable can be used at multiple locations in a program. A variable name must be meaningful. It
should represent the purpose of the variable.
Example: Height, age, are the meaningful variables that represent the purpose it is being used for. Height
variable can be used to store a height value. Age variable can be used to store the age of a person
A variable must be declared first before it is used somewhere inside the program. A variable name is
formed using characters, digits and an underscore.
Following are the rules that must be followed while creating a variable:
1. A variable name should consist of only characters, digits and an underscore.
2. A variable name should not begin with a number.
3. A variable name should not consist of whitespace.
4. A variable name should not consist of a keyword.
5. ‘C’ is a case sensitive language that means a variable named ‘age’ and ‘AGE’ are different.
For example, we declare an integer variable my_variable and assign it the value 48:
int my_variable;
my_variable = 48;
By the way, we can both declare and initialize (assign an initial value) a variable in a single statement:
int my_variable = 48;
Data types
‘C’ provides various data types to make it easy for a programmer to select a suitable data type as per the
requirements of an application. Following are the three data types:
1. Primitive data types
2. Derived data types
3. User-defined data types
Array, functions, pointers, structures are derived data types. ‘C’ language provides more extended versions
of the above mentioned primary data types.
Each data type differs from one another in size and range. Following table displays the size and range of
each data type.
An integer typically is of 2 bytes which means it consumes a total of 16 bits in memory. A single integer
value takes 2 bytes of memory. An integer data type is further divided into other data types such as short
int, int, and long int.
Each data type differs in range even though it belongs to the integer data type family. The size may not
change for each data type of integer family.
The short int is mostly used for storing small numbers, int is used for storing averagely sized integer values,
and long int is used for storing large integer values.
Whenever we want to use an integer data type, we have place int before the identifier such as,
int age;
Here, age is a variable of an integer data type which can be used to store integer values.
A floating point value is a real number that contains a decimal point. Integer data type doesn’t store the
decimal part hence we can use floats to store decimal part of a value.
Generally, a float can hold up to 6 precision values. If the float is not sufficient, then we can make use of
other data types that can hold large floating point values. The data type double and long double are used to
store real numbers with precision up to 14 and 80 bits respectively.
While using a floating point number a keyword float/double/long double must be placed before an
identifier. The valid examples are,
float division;
double BankBalance;
Integer constants
An integer constant is nothing but a value consisting of digits or numbers. These values never change
during the execution of a program. Integer constants can be octal, decimal and hexadecimal.
Decimal constant contains digits from 0-9 such as,
Character constants
A character constant contains only a single character enclosed within a single quote (”). We can also
represent character constant by providing ASCII value of it.
Example, 'A', '9'
Above are the examples of valid character constants.
String constants
A string constant contains a sequence of characters enclosed within double quotes (“”).
Example, "Hello", "Programming"
These are the examples of valid string constants.
Real Constants
Like integer constants that always contains an integer value. ‘C’ also provides real constants that contain a
decimal point or a fraction value. The real constants are also called as floating point constants. The real
constant contains a decimal point and a fractional value.
By using the #define pre-processor directive which doesn’t use memory for storage and without putting a
semicolon character at the end of that statement
#include <stdio.h>
7 Data Types: A Better Way to Think about Data Types for Machine Learning
With 7 Data Types to reference we should all be able to more quickly evaluate and discuss the encoding
options and imputation strategies available.
TL;DR;
Think and talk about each of your features as one of the following seven data types to save time and transfer
knowledge:
Useless
Nominal
Binary
Ordinal
Count
Time
Interval
UPDATE
Read all the way through to see the additional 4 data types for machine learning.
Data generally needs to be put into numeric form for machine learning algorithms to use the data to make
predictions. In machine learning guides categorical string data is usually one-hot-encoded (aka dummy
encoded). Dan Becker refers to it as “The Standard Approach for Categorical Data” in Kaggle’s Machine
Learning tutorial series.
Oftentimes in tutorials it is assumed that all data that arrived in numeric form is ready to be used as is and
that all string data needs one-hot-encoded. While many tutorials do dig a bit deeper into the types of data
Coming to machine learning after having been trained in social science methods and statistics in graduate
school, I found it surprising that there wasn’t much talk about ordinal data. For example, I kept finding
myself trying to figure out the best way to encode and impute ordinal scale data in string form and nominal
(truly categorical) data in numeric form. Without clear and consistent categories for types of data, this took
more time than necessary.
The 7 Data Types was inspired by Steven’s typology of measurement scales and my own observations about
the types of data that need special consideration for machine learning models. Let’s first look at the
measurement scales in use and where they came from before introducing the 7 Data Types.
Ratio (equal spaces between values and a meaningful zero value — mean makes sense)
Interval (equal spaces between values, but no meaningful zero value — mean makes sense)
Ordinal (first, second, third values, but not equal space between first and second and second and third —
median makes sense)
Nominal (no numerical relationship between the different categories — mean and median are meaningless)
Steven’s typology became extremely popular, especially in the social sciences. Since then, other researchers
have further expanded the number of scales (Mosteller & Tukey) including as many as ten categories
(Chrisman). Nonetheless, Steven’s typology has reigned in the social sciences and is occasionally referenced
in data science, despite not providing clear guidance in many cases.
Other machine learning and data science practitioners have adopted parts of Steven’s typology in various
ways, leading to a variety of nomenclatures. For example, Hastie, Tibshirani, and Friedman in The Elements
of Statistical Learning 2nd Ed. combine ratio and interval into quantitative and break
out ordinal and categorical in one example (p. 504). Elsewhere Hastie et. al. refer to ordinal as ordered
categorical variables and categorical variables as qualitative, discrete, or factors (p. 10). Statistics for
Dummies breaks the types of data into numerical, ordinal, and categorical —
lumping ratio with interval under numerical. DataCamp refers to continuous, ordinal, and nominal data
types in this tutorial.
A classification that occasionally comes up in statistics is between discrete and continuous variables.
Discrete data has distinct values while continuous data has an infinite number of potential values in a range.
But generally in machine learning numerical and categorical is the divide that you’ll see (e.g. here). The
popular Pandas library’s lumps together ordinal and nominal data in it’s optional Category dtype. Overall,
By providing clear categories, I hope to help my colleagues, especially newcomers, more quickly build
models and discover new options for improving model performance.
I propose the following taxonomy of 7 Data Types most useful for machine learning practitioners:
i. Useless
ii. Nominal
iii. Binary
iv. Ordinal
v. Count
vi. Time
vii. Interval
1. Useless
Useless data is unique, discrete data with no potential relationship with the outcome variable. A useless
feature might have high cardinality. An example would be bank account numbers that were generated
randomly.
If a feature consists of unique values with no order and no meaning, that feature is useless and need not be
included when fitting a model.
Same goes for a feature with no variance. If everyone in your dataset is an adult, a column full of 1s to
represent that information isn’t helpful to your model.
2. Nominal
Nominal data is made of discrete values with no numerical relationship between the different categories
mean and median are meaningless. Animal species is one example. For example, pig is not higher than bird
and lower than fish.
Nationality is another example of nominal data. There is group membership with no numeric order being
French, Mexican, or Japanese does not in itself imply an ordered relationship.
You can one-hot-encode or hash nominal features. Do not ordinal encode them because the relationship
between the groups cannot be reduced to a monotonic function. The assigning of values would be random.
3. Ordinal
For example, the distance between first and second may not be the same as the distance between second and
third. Think of a 10k race. The winner might have run 30:00 minutes, second place might have run 30:01
minutes and third place might have run 400:00 minutes. Without the time data, we don’t know the relative
distance between the ranks.
Broadly speaking, ordinal data can be encoded one of three ways. It can be assumed to be close enough to
interval data, with relatively equal magnitudes between the values, to treat it as such. Social scientists make
this assumption all the time with Likert scales. For instance, on a scale from 1 to 7, 1 being extremely
unlikely, 4 being neither likely nor unlikely and 7 being extremely likely, how likely are you to recommend
this movie to a friend? Here the difference between 3 and 4 and the difference between 6 and 7 can be
reasonably assumed to be similar.
A second option is to treat ordinal data as nominal data, where each category has no relationship to any
other. One-hot encoding it or a similar scheme can be used in that case.
A third option that will be explored in more detail in a future article is something like reverse Helmert
coding, which can be used to encode various potential magnitudes between the values.
There’s merit in categorizing ordinal data as it’s own type of data.
4. Binary
Binary data is discrete data that can be in only one of two categories either yes or no, 1 or 0, off or on, etc.
Binary can be thought of as a special case of ordinal, nominal, count, or interval data.
Binary data is a very common outcome variable in machine learning classification problems. For example,
we may want to create a supervised learning model to predict whether a tumor is malignant or benign.
Binary data is common and merits its own category when thinking about your data.
5. Count
Count data is discrete whole number data no negative numbers here. Count data often has many small
values, such as zero and one.
Count data is usually treated similarly to interval data, but it is unique enough and widespread enough to
merit its own category.
6. Time
Time data is a cyclical, repeating continuous form of data. The relevant time features can be any period—
daily, weekly, monthly, annual, etc.
The Pandas python library was designed with time series data in mind. Financial and marketing data often
have a time series component that is important to capture.
Time series data often take some wrangling and manipulation to create features with the periods that might
be meaningful for your model.
Missing time series data is often filled using unique methods appropriate to seasonal or daily data.
Time series data has some of its own models and is definitely worth thinking about in a separate mental
bucket.
7. Interval
Interval data has equal spaces between the numbers and does not represent a temporal pattern. Examples
include percentages, temperatures, and income.
Interval data is the most precise measurement scale data and very common. Although each value is a
discrete number, e.g. 3.1 miles, it doesn’t generally matter for machine learning purposes whether it is a
continuous scale (e.g. infinitely smaller measurement sizes are possible) nor does it matter whether there is
an absolute zero.
Interval data is generally easy to work with but you may want to create bins to cut down on the number of
ranges.
Although many experienced machine learning practitioners certainly do think of some of the types of data
described with these labels differently in practice, a clear taxonomy for the field is lacking. I posit that using
the taxonomy above will help folks more quickly evaluate options for encoding, imputing, and analyzing
their data.
Note that most of these seven categories could show up in your raw data in most any form. We aren’t talking
about float64 vs bool: the Python type or (Numpy or Pandas dtype) is not the same as the type of data
discussed here.
Introduction to Operators and its types, Evaluation of expressions, Precedence of arithmetic operators,
Type conversions in expressions, Operator precedence and associatively
Expressions perform specific actions, based on an operator, with one or two operands. An operand can be a
constant, a variable or a function result. Operators are arithmetic, logical, and relational.
As with C, some operators vary in functionality according to the data type of the operands specified in the
expression.
Operator precedence
Expressions are normally evaluated left to right. Complex expressions are evaluated one at a time. The
order in which the expressions are evaluated is determined by the precedence of the operators used. The
standard C ordering is followed.
1. negation (-) unary
2. power
3. multiplication, division and modulo
4. addition and subtraction
If an expression contains two or more operators with the same precedence, the operator to the left is
evaluated first. For example, 10 / 2 * 5 will be evaluated as (10 / 2) and the result multiplied by 5.
When a lower precedence operation should be processed first, it should be enclosed within parentheses. For
example, 30 / 2 + 8. This is normally evaluated as 30 divided by 2 then 8 added to the result. If you want to
divide by 2 + 8, it should be written as 30 / (2 + 8).
Parentheses can be nested within expressions. Innermost parenthetical expressions are evaluated first.
Assignment Operator (= )
Use the assignment operator (=) to copy a constant, literal, variable expression result, or function result
to a variable. The script language does not support multiple assignments in a single statement (such as
a=b=c=0). String lengths are defined based on the size of the string assigned to the variable and can
change dynamically at runtime.
If the end of one string is encountered before the end of the corresponding string, the strings are considered
to be of unequal length and result in an unequal condition.
If any character in a string does not match the corresponding character in the other string, the comparison
stops and the strings are considered not equal. Strings are case-sensitive.
Examples:
Str1 = "abcdefg";
Str2 = "abcdefg";
Str3 = "abcdef";
Str4 = "ABCDEFG";
If (str1 == str2)... results in an equal/true conditions
If (str1 == str3).... Results in a not equal condition
because str3 is shorter than str1
The Plus(+) operator, when applied to strings, results in the concatenation of the two strings.
Example:
Str1 = "abc";
Str2 = "def";
Str3 = str1 + str2; results in "abcdef"
Programs use data, known as ‘values’. Variables hold values. Each variable in a program must have a data
type. Sometimes a programmer needs to store a lot of related data. To do this they use structures such as
arrays.
Operators
In computer science, an operator is a character or characters that determine the action that is to be
performed or considered.
Arithmetic operators
Computers are designed to carry out calculations. Arithmetic operators allow arithmetic to be performed on values.
Arithmetic operation Operator Example
Addition + x=x+5
Subtraction - x=x-5
Multiplication * x=x*5
Division / x=x/5
Integer division DIV x = x DIV 5
Remainder MOD x = x MOD 5
Relational operators
Relational operators allow for assignment and enable comparisons to be made. They are used in condition
testing.
Input/output (I/O) management involves controlling the flow of data into and out of a data processing
complex. In an automated environment, you might want to change your approach to I/O activities that
previously required manual intervention, such as tape and printer management.
Reading, processing, and writing of data are the three essential functional functions of a computer program
input and output operations.
Most programs take some data as input and display the processed data, often known as information or
results, on a suitable medium. So far we have seen two methods of providing data to the program variables.
One method is to assign values to variables through the assignment statements such as x=5; a=0; and so on.
Another method is to use the input and out function scanf which can read data from a keyboard. We have
used both the methods in most of our earlier example programs.
For outputting results we have used extensively the fuction printf which sends results out to a terminal.
Unlike other high-level languages, C does not have any built-in input/output statements as part of its
syntax. All input/output operations are carried out through function calls such as printf and scanf.
There exist several functions that have more or less become standard for input and output operations in C.
These functions are collectively known as the standard input and output library.
However, one should consult the system reference manual for exact details of these functions and also to
see what other functions are available.
#include <math.h>
Where a math library function cos(x) has been used. This is to instruction the compiler to fetch the function
cos(x) from the math library, and that it is not a part of C language.
Similarly, each program that uses a standard input/output function must contain the statement
#include <stdio.h>
at the beginning. However there might be exceptions. For example, this is not necessary for the
functions printf and scanf which have been defined as a part of the C language.
Reading a Character
The simplest of all managing input and output operations in c is reading a character from the ‘standard
input’ unit (usually the keyboard) and writing it to the ‘standard output’ unit (usually the screen).
variable_name=grtchar();
variable_name is a valid C name that has been declared as char type. When this statement is encountered,
the computer waits until a key is pressed and then assigns this character as a value to getchar function.
Since getchar is used on the right hand side of an assignment statement, the character value of fetchar is in
turn assigned to the variable name on the letf.
char name;
name = getchar();
Will assign the character ‘H’ to the variable name when we press the key H on the keyboard. Since getchar
is a function, it requires a set of parentheses as shown.
The program displays a question of YES/NO type to the user and reads the user’s response in a single
character (Y or N). If the response is Y or Y, it outputs the message My name is BUSY BEE
Program
#include <stdio.h>
main()
{
char answer;
printf("Would you like to know my name?\n");
printf("Type Y for YES and N for NO: ");
answer = getchar(); /* .... Reading a character...*/
if(answer == 'Y' || answer == 'y')
printf("\n\nMy name is BUSY BEE\N");
else
printf("\n\nYou are good for nothing\n");
}
Output
Would you like to know my name?
Type Y for YES and N for NO: Y
Would you like to know my name?
Type Y for YES and N for NO: n
You are good for nothing
The getchar function may be called successively to read the characters contained in a line of text. For
example, the following program segment reads characters from keyboard one after another untile the
‘Return’ key is pressed.
The getchar() function accepts any character keyed in. This includes RETURN and TAB . This means
when we enter single character input, the newline character is waiting in the input queue
after getchar() returns.
Note : We shall be using decision statements like if, if…else and while extensively in this chapter. They are
discussed in detail next chapter.
where variable_name is a type char variable containing a character. This statement display the character
contained in the variable_name at the terminal.
answer = 'Y' ;
putchar (answer);
will display the character Y on the screen. The statement putchar (‘\n’); would cause the cursor on the
screen to move to the beginning of the next line.
The function toupper converts the lowercase argument into an uppercase alphabet while the function
tolower does the reverse.
Formatted Input
Formatted input to an input data that has been arranged in a particular format. For example, consider the
following data: 15.75 123 John
This line contains three pieces of data, arranged in a particular form. Such data has to be read conforming
to the format of its appearance.
For example, the first part of the data should be read into a variable float, the second into int, and the third
part into char. This is possible in C using the scanf function. (scanf means scan formatted)
The control string specifies the field format in which the data is to be entered and the argument arg1, arg2,
… argn specify the address of locations where the data is stored, Control string and arguments are separted
by commas.
Field (or format) specifications, consisting of the conversion character % a data type character (or type
specifier), and an optional number, specifying the field width.
This kind of error may be eliminated if we use the field specifications without the without the field width
specifications. That is the statement scanf(“%d %d”, &num1, &num2);
Input data items must be separated by spaces, tabs or newlines, punctuation marks do not count as
separators.
When the scanf function searches the input data line for a value to be read, it will always bypass any white
space characters.
The data type character d may be preceded by ‘I’ (letter ell) to read long integers and h to read short
integers.
Note : we have provided white space between the field specifications. These spaces are not necessary with
the numeric input, but it is a good practice to include the.
The first scanf requests input data for three integer value a,b and c, and accordingly three values 1,2 and 3
are keyed in. Because of the specification %*d the value 2 has been skipped and 3 is assigned to the
variable b.
The second scanf specifies the format %2d and %4d for the variables x and y respectively. Whenever we
specify field width for reading integer numbers, the input numbers sholud not contain more digits that the
specifid size.
Otherwise, the extra digits on the right hand side will be truncated and assigned to the next variable in the
list.
Note : It is legal to use a non whitespace character between field specification. However, the scanf expects
a matching character in the given location.
will assign the value 475.89 to x, 4.321 to y, and 678.0 to z. The input field specifications may be separated
by any arbitrary blank spaces.
If the number to be read is of double type, the specification should be %if instead of simple %f. A number
may be skipped using %*f specification.
We have already seen how a single character can be read from the terminal using the getchar function. The
same can be achieved using the scanf function also.
In addition, a scanf function can input strings containg more than one character. Following are the
specifications for reading character strings: %ws or %wc
The corresponding argument should be a pointer to a character array. However, %c may be used to read a
single character when the argument is a pointer to a char variable.
when we use %wc for reading a string, the system will wait until the w character is keyed in.
When a scanf function completes reading its, it returns the value of number of items that are successfully
read. This value can be used to test whether any errors occurred in reading the input.
The function scanf is expected to read three items of data and therefore, when the values for all the three
variables are read correctly, the program prints out their values.
During the third run, the second item does not match with the type of variable and therefore the reading is
terminated and the error message is printed. Same is the case with the fourth run.
In the last run, although data items do not match the variables, no error message has been printed when we
attempt to read a real number for an int variable, the integer part is assigned to variable and the truncated
decimal part is assigned to the next variable.
New feature are added to these routines from time to time as never versions of systems are released. We
should consult the system referance manual before using these routines.
All function arguments, except the control string must be pointers to variables.
The reading will be terminated, when scanf encounters a ‘mismatch’ of data or a character that is not valid
for value being read.
When searching for a value, scanf ignores line boundaries and simply looks for the next appropriate
character.
Any under data items in a line be considered as part of the data input to the next scanf call.
When the field width specifier w is used, it should be large enough to contain the input data size.
Rules for scanf
Each variable to be read must have a filed have a specification.
For each field specification, there must be a variable address of proper type.
Any non-whitespace character used in the formated string must have a matching character in the user input.
Never end the format string with whitespace. It is a fatal error!
An array is a fundamental data structure built into C. A thorough understanding of arrays and their use is
necessary to develop effective applications. Misunderstandings of array and pointer usage can result in
hard-to-find errors and less than optimal performance in applications. Array and pointer notations are
closely related to each other and can frequently be used interchangeably in the right context.
A common misconception is that an array and a pointer are completely interchangeable. An array name is
not a pointer. Although an array name can be treated as a pointer at times, and array notation can be used
with pointers, they are distinct and cannot always be used in place of each other. Understanding this
difference will help you avoid incorrect use of these notations. For example, although the name of an array
used by itself will return the array’s address, we cannot use the name by itself as the target of an
assignment.
Arrays support many parts of an application and can be single or multidimensional. In this chapter, we will
address the fundamental aspects of arrays as they relate to pointers to provide you with a deep
understanding of arrays and the various ways they can be manipulated with pointers. You will see their use
in more advanced contexts throughout the book.
We start with a quick review of arrays and then examine the similarities and differences between array and
pointer notation. Arrays can be created using malloc type functions. These functions provide more
flexibility than that afforded by traditional array declarations. We will see how the realloc function can be
used to change the amount of memory allocated for an array.
Dynamically allocating memory for an array can present challenges, especially when we are dealing with
arrays with two or more dimensions, as we have to ensure that the array is allocated in contiguous memory.
There is nothing inherent in an array’s internal representation that determines its length. If we do not pass
the length, the function has no standard means of knowing where the array ends. We will also examine how
to create jagged arrays in C, although they are infrequently used. A jagged array is a two-dimensional array
where each row may have a different number of columns.
To demonstrate these concepts, we will use a vector for single-dimensional arrays and a matrix for two-
dimensional arrays. Vectors and matrices have found extensive use in many areas, including analyzing
electromagnetic fields, weather prediction, and in mathematics.
Two-dimensional arrays are common, and we typically use the terms rows and columns to describe the
position of an array’s element. Arrays with three or more dimensions are not as common but can be quite
useful in some applications. A two-dimensional array is not to be confused with an array of pointers. They
are similar but behave slightly differently, as will be shown in the sectionUsing a One-Dimensional Array
of Pointers.
Variable length arrays were introduced in C99 version of C. Previously, techniques using
the realloc function were used to support arrays whose sizes change. We illustrate the realloc function in
the section Using the realloc Function to Resize an Array.
NOTE
Arrays have a fixed size. When we declare an array, we need to decide how big it should be. If we specify
too many elements, we waste space. If we specify too few elements, we limit how many elements we can
process. The realloc function and variable length arrays provide techniques for dealing with arrays whose
size needs to change. With a little work, we can resize an array and use just the right amount of memory.
One-Dimensional Arrays
A one-dimensional array is a linear structure. It uses a single index to access its members. The following is
a declaration of a five-element array of integers:
int vector[5];
Array indexes start with 0 and end at one less than their declared size. Valid indexes for the
array vector start at 0 and end at 4. However, C does not enforce these bounds. Using an invalid index for
an array can result in unpredictable behavior.
Figure 4-1 illustrates how the array is allocated in memory. Each element is four bytes in length and is
uninitialized. Depending on the memory model used, as explained in Memory Models, the size may be
different.
printf("%d\n", sizeof(vector)/sizeof(int));
One-dimensional arrays can be readily initialized using a block type statement. In the following sequence,
each element is initialized to an integer starting at one:
Two-Dimensional Arrays
Two-dimensional arrays use rows and columns to identify array elements. This type of array needs to be
mapped to the one-dimension address space of main memory. In C this is achieved by using a row-column
ordering sequence. The array’s first row is placed in memory followed by the second row, then the third
row, and this ordering continues until the last row is placed in memory.
The following declares a two-dimensional array with two rows and three columns. The array is initialized
using a block statement. Figure 4-2 illustrates how memory is allocated for this array. The diagram on the
left shows how memory is mapped. The diagram on the right shows how it can be viewed conceptually:
int matrix[2][3] = {{1,2,3},{4,5,6}};
Multidimensional Arrays
Multidimensional arrays have two or more dimensions. As with two-dimensional arrays, multiple sets of
brackets define the array’s type and size. In the following example, we define a three-dimensional array
consisting of three rows, two columns, and a rank of four. The term rank is often used to denote the
elements of the third dimension:
int arr3d[3][2][4] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
The elements are allocated contiguously in row-column-rank order as illustrated in Figure 4-3.
When an array name is used by itself, the array’s address is returned. We can assign this address to a
pointer as illustrated below:
int vector[5] = {1, 2, 3, 4, 5};
The variable pv is a pointer to the first element of the array and not the array itself. When we first assigned
a value to pv, we assigned the address of the array’s first element.
We can use either the array name by itself or use the address-of operator with the array’s first element as
illustrated below. These are equivalent and will return the address of vector. Using the address-of operator
is more verbose but also more explicit:
printf("%p\n",vector);
printf("%p\n",&vector[0]);
The expression &vector is sometimes used to obtain the address of an array. It differs from the other
notations in that it returns a pointer to the entire array. The other two approaches yield a pointer to an
integer. Instead of returning a pointer to an integer, it returns a pointer to an array of integers. The use of
this type will be illustrated in the section Passing a Multidimensional Array.
We can also use array subscripts with pointers. Effectively, the notation pv[i] is evaluated as:
*(pv + i)
The pointer pv contains the address of a block of memory. The bracket notation will take the address
contained in pv and adds the value contained in the index i using pointer arithmetic. This new address is
then dereferenced to return its contents.
As we discussed in the section Pointer Arithmetic, adding an integer to a pointer will increment the address it
holds by the product of the integer and the data type’s size. The same is true if we add an integer to the
name of an array. The following two statements are equivalent:
*(pv + i)
*(vector + i)
Assume the vector is located at address 100 and pv is located at address 96. Table 4-1 and Figure 4-4 illustrate
the use of array subscripts and pointer arithmetic with both the array name and the pointer for various
values.
When we add 1 to the array address we effectively add 4, the size of an integer, to the address since this is
an array of integers. With the first and last operations, we addressed locations outside the array’s bounds.
While this is not a good practice, it does emphasize the need to be careful when using indexes or pointers to
access elements of an array.
Array notation can be thought of as a “shift and dereference” operation. The expression vector means start
with vector, which is a pointer to the beginning of the array, shift two positions to the right, and then
dereference that location to fetch its value. Using the address-of operator in conjunction with array
notation, as in &vector, essentially cancels out the dereferencing. It can be interpreted as go left two
positions and then return that address.
The following demonstrates the use of pointers in the implementation of the scalar addition operation. This
operation takes a value and multiplies it against each element of the vector:
pv = vector;
int value = 3;
for(int i=0; i<5; i++) {
*pv++ *= value;
}
Differences Between Arrays and Pointers
There are several differences between the use of arrays and the use of pointers to arrays. In this section, we
will use the vector array and pv pointer as defined below:
int vector[5] = {1, 2, 3, 4, 5};
int *pv = vector;
The code generated by vector[i] is different from the code generated by vector+i. The
notation vector[i] generates machine code that starts at location vector, moves i positions from this location,
There is a difference when the sizeof operator is applied to an array and to a pointer to the same array.
Applying the sizeof operator to vector will return 20, the number of bytes allocated to the array. Applying
the sizeof operator against pv will return 4, the pointer’s size.
The pointer pv is an lvalue. An lvalue denotes the term used on the lefthand side of an assignment operator.
An lvalue must be capable of being modified. An array name such as vector is not an lvalue and cannot be
modified. The address assigned to an array cannot be changed . A pointer can be assigned a new value and
reference a different section of memory.
WARNING
In the previous example we used *(pv+i) instead of *pv+1. Since the dereference operator has higher
precedence than the plus operator, the second expression’s pointer is dereferenced, giving us the value
referenced by the pointer.
We then add i to this integer value. This was not what was intended. In addition, when we use this
expression as an lvalue, the compiler will complain. Thus, we need to force the addition to be performed
first, followed by the dereference operation, in order for it to work correctly.
To illustrate the realloc function, we will implement a function to read in characters from standard input
and assign them to a buffer. The buffer will contain all of the characters read in except for a terminating
return character. Since we do not know how many characters the user will input, we do not know how long
the buffer should be.
We will use the realloc function to allocate additional space by a fixed increment amount. The code to
implement this function is shown below:
char* getLine(void) {
const size_t sizeIncrement = 10;
Team University Lecture Material - Introduction to Basic Computer Programming Page 90
char* buffer = malloc(sizeIncrement);
char* currentPosition = buffer;
size_t maximumLength = sizeIncrement;
size_t length = 0;
int character;
while(1) {
character = fgetc(stdin);
if(character == '\N') { break; }
if(newBuffer == NULL) {
free(buffer);
return NULL;
}
maximumLength The maximum number of characters that can be safely stored in the buffer
If we have exceeded the buffer’s size, the realloc function creates a new block of memory. This block
is sizeIncrement bytes larger than the old one. If it is unable to allocate memory, we free up the existing
allocated memory and force the function to return NULL. Otherwise, currentPosition is adjusted to point to
the right position within the new buffer and we assign the variable buffer to point to the newly allocated
buffer. The realloc function will not necessarily keep your existing memory in place, so you have to use the
pointer it returns to figure out where your new, resized memory block is.
The variable newBuffer holds the allocated memory’s address. We needed a separate variable, not buffer,
in case the realloc was unable to allocate memory. This allows us to detect and handle the condition.
We did not free buffer if realloc was successful because realloc will copy the original buffer to the new
buffer and free up the old buffer. If we had tried to free buffer, then it would normally result in the
program’s termination because we tried to free the same block of memory twice.
Figure 4-6 illustrates memory being allocated for the getLine function with an input string of “Once upon a
time there was a giant pumpkin.” The program stack has been simplified to ignore the local variables
except for buffer and currentPosition. The buffer has been extended four times, as indicated by the
rectangle containing the input string.
while(*old) {
*(new++) = *(old++);
}
*new = 0;
return (char*) realloc(phrase,strlen(phrase)+1);
}
int main() {
char* buffer = (char*)malloc(strlen(" cat")+1);
strcpy(buffer," cat");
printf("%s\n",trim(buffer));
}
The first while loop uses the tmp variable to skip over any leading blanks. The second while loop copies
the remaining characters in the string to the beginning of the string. It will evaluate to true until NUL is
reached, which will evaluate to false.
A zero is then added to terminate the string. The realloc function is then used to reallocate the memory
based on the string’s new length.
Figure 4-7 illustrates the function’s use with an original string of “cat.” The state of string before and after
the trim function executes is shown. The memory in red is the old memory and should not be accessed.
When a one-dimensional array is passed to a function, the array’s address is passed by value. This makes
the transfer of information more efficient since we are not passing the entire array and having to allocate
memory in the stack for it. Normally, this means the array’s size must be passed. If we don’t, from the
function’s perspective all we have is the address of an array with no indication of its size.
Unless there is something integral to the array to tell us its bounds, we need to pass the size information
when we pass the array. In the case of a string stored in an array, we can rely on the NUL termination
character to tell us when we can stop processing the array. We will examine this in Chapter 5.
Generally, if we do not know the array’s size, we are unable to process its elements and can wind up
working with too few elements or treating memory outside of the array as if it were part of the array. This
will frequently result in abnormal program termination.
We can declare the array in the function declaration using one of two notations: array notation or pointer
notation.
The sequence’s output will be the numbers 1 through 5.We passed the number 5 to the function that
indicates its size. We could have passed any positive number and the function would attempt to display the
corresponding number of elements, regardless of whether the size was correct.
The program may terminate if we attempt to address memory outside of the array’s bounds. The memory
allocation for this example is shown in Figure 4-8.
WARNING
A common mistake is to use the sizeof operator with the array in order to determine its number of elements,
as shown below. However, as explained in the section
One-Dimensional Arrays, this is not the correct way of determining its size. In this case, we would be
passing the value of 20 to the array.
displayArray(arr, sizeof(arr));
It is a common practice to pass a size smaller than the actual number of elements in an array. This is done
to process only part of an array. For example, assume we read in a series of ages into an array but did not
fill up the array. If we called a sort function to sort it, we would only want to sort the valid ages, not every
array element.
We could have used the following equivalent pointer notation for the loop’s body:
*(arr+i) = (int*)malloc(sizeof(int));
**(arr+i) = i;
This notation is harder to follow, but understanding it will further your C expertise. We are using two levels
of indirection in the second statement. Mastery of this type of notation will separate you from the less
experienced C programmers.
The subexpression (arr+i) represents the address of the array’s i th element. We need to modify the content
of this address so we use the subexpression *(arr+i). The allocated memory is assigned to this location in
the first statement. Dereferencing this subexpression a second time, as we do in the second statement,
returns the allocated memory’s location. We then assign the variable i to it. Figure 4-9 illustrates how
memory is allocated.
*arr[0] 0
**arr 0
**(arr+1) 1
arr[0][0] 0
arr[3][0] 3
The first three expressions are similar to those in the previous explanation. The last two are different. The
use of a pointer to a pointer notation suggests we are dealing with an array of pointers. In effect, this is
what we are doing. If we reexamine Figure 4-9 and pretend each element of arr points to an array of size
one, then the last two expressions make sense. What we have is a five-element array of pointers to a series
of one-element arrays.
The expression arr[3][0] refers to the fourth element of arr and then the first element of the array it points
to. The expression arr[3][1] does not work because the array the fourth element is pointing to does not have
two elements.
This suggests the ability to create jagged arrays. This is indeed possible and is the subject of
the sectionJagged Arrays and Pointers.
If we had left the parentheses off, we would have declared a five-element array of pointers to integers. The
size of the first dimension is 2 since we know the dimensions of the matrix. If a different size is used to
access the array, then the results are unpredictable.
Its size is 20. We can verify this with the following statement, which will display 20:
printf("%d\n",sizeof(matrix[0])); // Displays 20
To access the array’s second element, we need to add 1 to the first row of the array as follows: *(matrix[0]
+ 1). The expression, matrix[0], returns the address of the first element of the first row of the array. This
address is the address of an array of integers. Thus, when we add one to it, the size of a single integer is
added to it, giving us the second element. The output will be 104 and 2.
printf("%p %d\n", matrix[0] + 1, *(matrix[0] + 1));
We can graphically depict the array as illustrated in Figure 4-11.
If we want to use array notation within the function, it is imperative to specify the array’s shape. Otherwise,
the compiler is unable to use subscripts.
In the first version, the expression arr[] is an implicit declaration of a pointer to an array. In the second
version, the expression (*arr) is an explicit declaration of the pointer.
WARNING
The following declaration will not work correctly:
void display2DArray(int *arr[5], int rows) {
While it will not generate a syntax error, the array passed is assumed to be a five-element array of pointers
to integers.
void main() {
int matrix[2][5] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10}
};
display2DArray(matrix, 2);
}
The function does not allocate memory for the array. Only the address is passed. The program stack’s state
for this call is shown in Figure 4-13.
Team University Lecture Material - Introduction to Basic Computer Programming Page 101
Figure 4-13. Passing multidimensional array
You may encounter a function declared as follows. It is passed a single pointer and the number of rows and
columns:
void display2DArrayUnknownSize(int *arr, int rows, int cols) {
for(int i=0; i<rows; i++) {
for(int j=0; j<cols; j++) {
printf("%d ", *(arr + (i*cols) + j));
}
printf("\n");
}
}
The printf statement calculates the address of each element by adding to arr the number of elements in the
previous row(s), (i*cols), and then adding j to specify the column. To invoke the function, we can use the
following:
display2DArrayUnknownSize(&matrix[0][0], 2, 5);
Within the function, we cannot use array subscripts as shown below:
printf("%d ", arr[i][j]);
This is not possible because the pointer is not declared as a two-dimensional array. However, it is possible
to use array notation as shown below. We can use a single subscript since it will be interpreted simply as an
offset within the array, whereas two subscripts cannot be used because the compiler doesn’t know the size
of the dimensions:
printf("%d ", (arr+i)[j]);
The first element’s address is passed using &matrix[0][0] instead of matrix. While using matrix will
execute correctly, a warning will be generated, indicating incompatible pointer types. The
expression &matrix[0][0] is a pointer to an integer, whereas matrix is a pointer to an array of integers.
Team University Lecture Material - Introduction to Basic Computer Programming Page 102
When passing an array with more than two dimensions, all but the size of the first dimension need to be
specified. The following demonstrates a function written to display a three-dimensional array. The last two
dimensions are specified in the declaration:
void display3DArray(int (*arr)[2][4], int rows) {
for(int i=0; i<rows; i++) {
for(int j=0; j<2; j++) {
printf("{");
for(int k=0; k<4; k++) {
printf("%d ", arr[i][j][k]);
}
printf("}");
}
printf("\n");
}
}
The following code shows the function’s invocation:
int arr3d[3][2][4] = {
{{1, 2, 3, 4}, {5, 6, 7, 8}},
{{9, 10, 11, 12}, {13, 14, 15, 16}},
{{17, 18, 19, 20}, {21, 22, 23, 24}}
};
display3DArray(arr3d,3);
The output follows:
{1 2 3 4 }{5 6 7 8 }
{9 10 11 12 }{13 14 15 16 }
{17 18 19 20 }{21 22 23 24 }
Allocation of the array’s memory is depicted in Figure 4-14.
Team University Lecture Material - Introduction to Basic Computer Programming Page 103
Figure 4-14. Three-dimensional array
The expression arr3d[1] refers to the array’s second row and is a pointer to a two-dimensional array with
two rows and four columns. The expression arr3d[1][0] refers to the second row, first column of the array
and is a pointer to a one-dimensional array of size 5.
However, when we use a function such as malloc to create a two-dimensional array, there are variations in
how memory can be allocated. Since a two-dimensional array can be treated as an array of arrays, there is
no reason the “inner” arrays need to be contiguous. When array subscripts are used with such an array, the
array’s noncontiguous nature is handled transparently.
NOTE
Whether or not it is contiguous can affect other operations, such as copying a block of memory. Multiple
copies may be required if the memory is not contiguous.
Team University Lecture Material - Introduction to Basic Computer Programming Page 104
Figure 4-15. Noncontiguous allocation
The actual allocation depends on the heap manager and the heap’s state. It may well be contiguous.
We will present two approaches for allocating contiguous memory for a two-dimensional array. The first
technique allocates the “outer” array first and then all of the memory for the rows. The second technique
allocates all of the memory at once.
The first technique is illustrated in the following sequence. The first malloc allocates an array of pointers to
integers. Each element will be used to hold a pointer to a row. This is the block allocated at address 500
in Figure 4-16.
The second malloc allocates memory for all of the elements of the array at location 600. In the for loop,
each element of the first array is assigned a portion of the memory allocated by the second malloc:
int rows = 2;
int columns = 5;
int **matrix = (int **) malloc(rows * sizeof(int *));
matrix[0] = (int *) malloc(rows * columns * sizeof(int));
for (int i = 1; i < rows; i++)
Team University Lecture Material - Introduction to Basic Computer Programming Page 105
matrix[i] = matrix[0] + i * columns;
Technically, the memory for the first array may be separated from the memory for the array’s “body.”
However, a contiguous region of memory is allocated for the body.
In the second technique shown below, all of the memory for the array is allocated at one time:
int *matrix = (int *)malloc(rows * columns * sizeof(int));
Team University Lecture Material - Introduction to Basic Computer Programming Page 106
Figure 4-17. Contiguous allocation with a single malloc call
When the array is referenced later in code, array subscripts cannot be used. Instead, indexes into the array
need to be calculated manually, as illustrated in the following code sequence.
This approach has limited use in the real world, but it does illustrate the relationship between the concept of
a two-dimensional array and the one-dimensional nature of main memory. The more convenient two-
dimensional array notation makes this mapping transparent and easier to use.
We have demonstrated two general approaches for allocating contiguous memory for a two-dimensional
array. The approach to use depends on the needs of the application. However, the last approach generates a
single block of memory for the “entire” array.
Team University Lecture Material - Introduction to Basic Computer Programming Page 107
Figure 4-18. Jagged array
Before we learn how to create such an array, let’s examine a two-dimensional array created
using compound literals. A compound literal is a C construct that consists of what appears to be a cast
operator followed by an initializer list enclosed in braces.
An example of a compound literal follows for both a constant integer and an array of integers. These would
be used as part of a declaration:
(const int) {100}
(int[3]) {10, 20, 30}
In the following declaration, we create the array arr1 by declaring it as an array of pointers to an integer and
using a block statement of compound literals to initialize it:
int (*(arr1[])) = {
(int[]) {0, 1, 2},
(int[]) {3, 4, 5},
(int[]) {6, 7, 8}};
This array has three rows and three columns. The array’s elements are initialized with the value 0 through 8
in row column order. Figure 4-19 depicts how memory is laid out for this array.
Team University Lecture Material - Introduction to Basic Computer Programming Page 108
Figure 4-19. Two-dimensional array
The following sequence displays the addresses and values of each array element:
for(int j=0; j<3; j++) {
for(int i=0; i<3; i++) {
printf("arr1[%d][%d] Address: %p Value: %d\n",
j, i, &arr1[j][i], arr1[j][i]);
}
printf("\n");
}
When executed, we will get the following output:
arr1[0][0] Address: 0x100 Value: 0
arr1[0][1] Address: 0x104 Value: 1
arr1[0][2] Address: 0x108 Value: 2
Team University Lecture Material - Introduction to Basic Computer Programming Page 109
arr1[1][0] Address: 0x112 Value: 3
arr1[1][1] Address: 0x116 Value: 4
arr1[1][2] Address: 0x120 Value: 5
This declaration can be modified slightly to create a jagged array as depicted in Figure 4-18. The array
declaration follows:
int (*(arr2[])) = {
(int[]) {0, 1, 2, 3},
(int[]) {4, 5},
(int[]) {6, 7, 8}};
We used three compound literals to declare the jagged array. The array’s elements are initialized in row-
column order starting with a value of zero. The next sequence will display the array to verify its creation.
The sequence required three for loops because each row had a different number of columns:
int row = 0;
for(int i=0; i<4; i++) {
printf("layer1[%d][%d] Address: %p Value: %d\n",
row, i, &arr2[row][i], arr2[row][i]);
}
printf("\n");
row = 1;
for(int i=0; i<2; i++) {
printf("layer1[%d][%d] Address: %p Value: %d\n",
row, i, &arr2[row][i], arr2[row][i]);
}
printf("\n");
row = 2;
for(int i=0; i<3; i++) {
printf("layer1[%d][%d] Address: %p Value: %d\n",
row, i, &arr2[row][i], arr2[row][i]);
}
printf("\n");
The output of this sequence follows:
arr2[0][0] Address: 0x000100 Value: 0
arr2[0][1] Address: 0x000104 Value: 1
arr2[0][2] Address: 0x000108 Value: 2
arr2[0][3] Address: 0x000112 Value: 3
Team University Lecture Material - Introduction to Basic Computer Programming Page 110
arr2[2][0] Address: 0x000124 Value: 6
arr2[2][1] Address: 0x000128 Value: 7
arr2[2][2] Address: 0x000132 Value: 8
Figure 4-20 depicts how memory is laid out for this array.
In these examples, we used array notation as opposed to pointer notation when accessing the array’s
contents. This made it somewhat easier to see and understand. However, pointer notation would have
worked as well.
Compound literals are useful in creating jagged arrays. However, accessing elements of a jagged array can
be awkward, as demonstrated with the previous three for loops. This example can be simplified if a
separate array is used to maintain the size of each column. While you can create jagged arrays in C, it may
not be worth the effort.
Summary
We started with a quick review of arrays and then examined the similarities and differences between array
and pointer notation. Arrays can be created using malloc type functions. These type of functions provide
more flexibility than afforded by traditional array declaration. We saw how we can use the realloc function
to change the amount of memory allocated for an array.
Dynamically allocating memory for an array can present challenges. In the case with two or more
dimensional arrays, we have to be careful to make sure the array is allocated in contiguous memory.
Team University Lecture Material - Introduction to Basic Computer Programming Page 111
We also explored the problems that can occur when passing and returning arrays. Passing the array’s size to
a function is normally required so the function can properly handle the array. We also examined how to
create jagged arrays in C.
Dynamic memory allocation is when an executing program requests that the operating system give it a
block of main memory. The program then uses this memory for some purpose. Usually the purpose is to
add a node to a data structure.
In object oriented languages, dynamic memory allocation is used to get the memory for a new object.
The memory comes from above the static part of the data segment. Programs may request memory and may
also return previously dynamically allocated memory. Memory may be returned whenever it is no longer
needed. Memory can be returned in any order without any relation to the order in which it was allocated.
The heap may develop "holes" where previously allocated memory has been returned between blocks of
memory still in use.
A new dynamic request for memory might return a range of addresses out of one of the holes. But it might
not use up all the hole, so further dynamic requests might be satisfied out of the original hole.
If too many small holes develop, memory is wasted because the total memory used by the holes may be
large, but the holes cannot be used to satisfy dynamic requests. This situation is called memory
fragmentation. Keeping track of allocated and deallocated memory is complicated. A modern operating
system does all this.
The concept of dynamic memory allocation in c language enables the C programmer to allocate memory
at runtime. Dynamic memory allocation in c language is possible by 4 functions of stdlib.h header file.
malloc()
calloc()
realloc()
free()
Before learning above functions, let's understand the difference between static memory allocation and dynamic
memory allocation.
memory can't be increased while executing memory can be increased while executing
program. program.
Team University Lecture Material - Introduction to Basic Computer Programming Page 112
calloc() allocates multiple block of requested memory.
Team University Lecture Material - Introduction to Basic Computer Programming Page 113
The syntax of calloc() function is given below:
ptr=(cast-type*)calloc(number, byte-size)
Let's see the example of calloc() function.
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
realloc() function in C
If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by realloc() function. In
short, it changes the memory size.
Let's see the syntax of realloc() function.
free() function in C
The memory occupied by malloc() or calloc() functions must be released by calling free() function.
Otherwise, it will consume memory until program exit.
Let's see the syntax of free() function.
The string can be defined as the one-dimensional array of characters terminated by a null ('\0'). The
character array or the string is used to manipulate text such as word or sentences. Each character in the
array occupies one byte of memory, and the last character must always be 0.
The termination character ('\0') is important in a string since it is the only way to identify where the string
ends. When we define a string as char s[10], the character s[10] is implicitly initialized with the null in the
memory.
Team University Lecture Material - Introduction to Basic Computer Programming Page 114
There are two ways to declare a string in c language.
By char array
By string literal
Let's see the example of declaring string by char array in C language.
char ch[10]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
As we know, array index starts from 0, so it will be represented as in the figure given below.
Play Video
While declaring string, size is not mandatory. So we can write the above code as given below:
char ch[]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
We can also define the string by the string literal in C language. For example:
char ch[]="javatpoint";
In such case, '\0' will be appended at the end of the string by the compiler.
The string literal cannot be reassigned to another set of characters whereas, we can reassign the characters
of the array.
String Example in C
Let's see a simple example where a string is declared and being printed. The '%s' is used as a format
specifier for the string in c language.
#include<stdio.h>
#include <string.h>
int main(){
char ch[11]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
char ch2[11]="javatpoint";
Team University Lecture Material - Introduction to Basic Computer Programming Page 115
printf("Char Array Value is: %s\n", ch);
printf("String Literal Value is: %s\n", ch2);
return 0;
}
Output
Char Array Value is: javatpoint
String Literal Value is: javatpoint
Traversing String
Traversing the string is one of the most important aspects in any of the programming languages. We may
need to manipulate a very large text which can be done by traversing the text. Traversing string is
somewhat different from the traversing an integer array. We need to know the length of the array to
traverse an integer array, whereas we may use the null character in the case of string to identify the end the
string and terminate the loop.
Team University Lecture Material - Introduction to Basic Computer Programming Page 116
int count = 0;
while(s[i] != NULL)
{
if(s[i]=='a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u' || s[i] == 'o')
{
count ++;
}
i++;
}
printf("The number of vowels %d",count);
}
Output
The number of vowels 4
It is clear from the output that, the above code will not work for space separated strings. To make this code
working for the space separated strings, the minor changed required in the scanf function, i.e., instead of
writing scanf("%s",s), we must write: scanf("%[^\n]s",s) which instructs the compiler to store the string s
while the new line (\n) is encountered. Let's consider the following example to store the space-separated
strings.
#include<stdio.h>
void main ()
{
char s[20];
printf("Enter the string?");
scanf("%[^\n]s",s);
printf("You entered %s",s);
}
Output
Enter the string?javatpoint is the best
You entered javatpoint is the best
Team University Lecture Material - Introduction to Basic Computer Programming Page 117
Here we must also notice that we do not need to use address of (&) operator in scanf to store a string since
string s is an array of characters and the name of the array, i.e., s indicates the base address of the string
(character array) therefore we need not use & with it.
Instead of using scanf, we may use gets() which is an inbuilt function defined in a header file string.h. The
gets() is capable of receiving only one string at a time.
As we know that string is an array of characters, the pointers can be used in the same way they were used
with arrays. In the above example, p is declared as a pointer to the array of characters s. P affects similar to
s since s is the base address of the string and treated as a pointer internally. However, we can not change
Team University Lecture Material - Introduction to Basic Computer Programming Page 118
the content of s or copy the content of s into another string directly. For this purpose, we need to use the
pointers to store the strings. In the following example, we have shown the use of pointers to copy the
content of a string into another.
#include<stdio.h>
void main ()
{
char *p = "hello javatpoint";
printf("String p: %s\n",p);
char *q;
printf("copying the content of p into q...\n");
q = p;
printf("String q: %s\n",q);
}
Output
String p: hello javatpoint
copying the content of p into q...
String q: hello javatpoint
Once a string is defined, it cannot be reassigned to another set of characters. However, using pointers, we
can assign the set of characters to the string. Consider the following example.
#include<stdio.h>
void main ()
{
char *p = "hello javatpoint";
printf("Before assigning: %s\n",p);
p = "hello";
printf("After assigning: %s\n",p);
}
Output
Before assigning: hello javatpoint
After assigning: hello
File Handling is the storing of data in a file using a program. In C programming language, the programs
store results, and other data of the program to a file using file handling in C. Also, we can extract/fetch data
from a file to work with it in the program.
File handling refers to the method of storing data in the C program in the form of an output or input that
might have been generated while running a C program in a data file, i.e., a binary file or a text file for
future analysis and reference in that very program.
Team University Lecture Material - Introduction to Basic Computer Programming Page 119
In programming, we may require some specific input data to be generated several numbers of times.
Sometimes, it is not enough to only display the data on the console. The data to be displayed may be very
large, and only a limited amount of data can be displayed on the console, and since the memory is volatile,
it is impossible to recover the programmatically generated data again and again.
However, if we need to do so, we may store it onto the local file system which is volatile and can be
accessed every time. Here, comes the need of file handling in C.
File handling in C enables us to create, update, read, and delete the files stored on the local file system
through our C program. The following operations can be performed on a file.
i. Creation of the new file
ii. Opening an existing file
iii. Reading from the file
iv. Writing to the file
v. Deleting the file
Team University Lecture Material - Introduction to Basic Computer Programming Page 120
Opening File: fopen()
We must open a file before it can be read, write, or update. The fopen() function is used to open a file. The
syntax of the fopen() is given below
Mode Description
Team University Lecture Material - Introduction to Basic Computer Programming Page 121
It sets up a character pointer which points to the first character of the file.
Consider the following example which opens a file in write mode.
#include<stdio.h>
void main( )
{
FILE *fp ;
char ch ;
fp = fopen("file_handle.c","r") ;
while ( 1 )
{
ch = fgetc ( fp ) ;
if ( ch == EOF )
break ;
printf("%c",ch) ;
}
fclose (fp ) ;
}
Output
The content of the file will be printed.
#include;
void main( )
{
FILE *fp; // file pointer
char ch;
fp = fopen("file_handle.c","r");
while ( 1 )
{
ch = fgetc ( fp ); //Each character of the file is read and stored in the character file.
if ( ch == EOF )
break;
printf("%c",ch);
}
fclose (fp );
}
Closing File: fclose()
The fclose() function is used to close a file. The file must be closed after performing all the operations on it.
The syntax of fclose() function is given below:
int fclose( FILE *fp );
File Handling is the storing of data in a file using a program. In C programming language, the programs
store results, and other data of the program to a file using file handling in C. Also, we can extract/fetch
data from a file to work with it in the program.
Team University Lecture Material - Introduction to Basic Computer Programming Page 122
The operations that you can perform on a File in C are −
Creating a new file
Opening an existing file
Reading data from an existing file
Writing data to a file
Moving data to a specific location on the file
Closing the file
Creating or opening file using fopen()
The fopen() function is used to create a new file or open an existing file in C. The fopen function is defined
in the stdio.h header file.
Now, lets see the syntax for creation of a new file or opening a file
file = fopen(“file_name”, “mode”)
Let’s see can example which will make the concept clear, Suppose we are opening a file named hello.txt
using the fopen function. The following will be the statement,
Team University Lecture Material - Introduction to Basic Computer Programming Page 123
}
Output
File opened successfully in read mode
We have created a file named hello.txt in our current directory but if we try to access other file then we
will get “The file is not present! cannot create a new file using r mode” as output.
Mode = “rb” − open for reading in binary mode, this mode will open the file for reading in binary mode
only, i.e. the contents can only be viewed and nothing else like edits can be done to it.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using this
mode.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb mode");
fclose(file);
return 0;
}
Output
The file is not present! cannot create a new file using rb mode
Mode = “w” − open for writing only, this mode will open the file if present in the current directory for
writing only i.e. reading operation cannot be performed. If the file is not present in the current directory,
the program will create a new file and open it for writing.
If we open a file that contains some text in it, the contents will be overwritten.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w")){
printf("File opened successfully in write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in write mode or a new file is created
You can see here, we have tried to open file “helo.txt” which is not present in the directory, still the
function returned the success message because it has create a file named “helo.txt”.
Team University Lecture Material - Introduction to Basic Computer Programming Page 124
Mode = “wb” − open for writing in binary mode, this mode will open the file if present in the current
directory for writing in binary mode i.e. reading operation cannot be performed. If the file is not present in
the current directory, the program will create a new file and open it for writing in binary mode.
If we open a file that contains some text in it, the contents will be overwritten.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb")){
printf("File opened successfully in write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in write in binary mode or a new file is created
Mode = “a” − open for append only, this mode will open the file if present in the current directory for
writing only i.e. reading operation cannot be performed. If the file is not present in the current directory,
the program will create a new file and open it for writing. If we open a file that contains some text in it, the
contents will not be overwritten; instead the new text will be added after the existing text in the file.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a")){
printf("File opened successfully in append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in append mode or a new file is created
Mode = “ab” − open for append in binary, this mode will open the file if present in the current directory
for writing in binary only i.e. reading operation cannot be performed. If the file is not present in the current
directory, the program will create a new file and open it for writing in binary.
If we open a file that contains some text in it, the contents will not be overwritten; instead the new text will
be added after the existing text in the file.
Example
Live Demo
Team University Lecture Material - Introduction to Basic Computer Programming Page 125
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab")){
printf("File opened successfully in append in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in append in binary mode or a new file is created
Mode = “r+” − open for reading and writing both, this mode will open the file for both reading and
writing purposes i.e. both read and write operations can be performed to the file.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using this
mode.
If we open a file that contains some text in it and write something, the contents will be overwritten.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "r+")){
printf("File opened successfully in read and write both");
}
else
printf("The file is not present! cannot create a new file using r+ mode");
fclose(file);
return 0;
}
Output
File opened successfully in read and write both
We have created a file named hello.txt in our current directory but if we try to access another file then we
will get “The file is not present! cannot create a new file using r+ mode” as output.
Mode = “rb+” − open for reading in binary mode, this mode will open the file for reading in binary mode
only, i.e. the contents can only be viewed and nothing else like edits can be done to it.
This mode cannot create a new file and open() returns NULL, if we try to create a new file using this
mode.
If we open a file that contains some text in it and write something, the contents will be overwritten.
Example
Team University Lecture Material - Introduction to Basic Computer Programming Page 126
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("program.txt", "rb+")){
printf("File opened successfully in read mode");
}
else
printf("The file is not present! cannot create a new file using rb+ mode");
fclose(file);
return 0;
}
Output
The file is not present! cannot create a new file using rb+ mode
Mode = “w” − open for writing and reading, this mode will open the file if present in the current directory
for writing and reading operation both. If the file is not present in the current directory, the program will
create a new file and open it for reading and writing.
If we open a file that contains some text in it, the contents will be overwritten.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("helo.txt", "w+")){
printf("File opened successfully in read-write mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-write mode or a new file is created
You can see here, we have tried to open file “helo.txt” which is not present in the directory, still the
function returned the success message because it has create a file named “helo.txt”.
Mode = “wb+” : open for writing and reading in binary mode, this mode will open the file if present in the
current directory for writing and reading in
binary mode. If the file is not present in the current directory, the program will create a new file and open
it for reading and writing in binary mode. If we open a file that contains some text in it, the contents will
be overwritten.
Example
Team University Lecture Material - Introduction to Basic Computer Programming Page 127
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "wb+")){
printf("File opened successfully in read-write in binary mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-write in binary mode or a new file is created
Mode = “a+” − open for read and append, this mode will open the file if present in the current directory
for both reading and writing. If the file is not present in the current directory, the program will create a new
file and open it for reading and writing.
If we open a file that contains some text in it, the contents will not be overwritten; instead the new text will
be added after the existing text in the file.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "a+")){
printf("File opened successfully in read-append mode or a new file is created");
}
else
printf("Error!");
fclose(file);
return 0;
}
Output
File opened successfully in read-append mode or a new file is created
Mode = “ab+” − open for read and append in binary, this mode will open the file if present in the current
directory for both reading and writing in binary. If the file is not present in the current directory, the
program will create a new file and open it for reading and writing in binary. If we open a file that contains
some text in it, the contents will not be overwritten; instead the new text will be added after the existing
text in the file.
Example
Team University Lecture Material - Introduction to Basic Computer Programming Page 128
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "ab+")){
printf("File opened successfully in read-append in binary mode or a new file is created");
}
else
printf("Error!”);
fclose(file);
return 0;
}
Output
File opened successfully in read-append mode or a new file is created
Reading Data for from an existing file
We can read content of a file in c using the fscanf() and fgets() and fgetc() functions. All are used to read
contents of a file. Let’s see the working of each of the function −
fscanf()
The fscanf() function is used to read character set i.e strings from the file. It returns the EOF, when all the
content of the file are read by it.
Syntax
int fscanf(FILE *stream, const char *charPointer[])
Parameters
FILE *stream: the pointer to the opened file.
const char *charPointer[]: string of character.
Example
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
while(fscanf(file,"%s", str)!=EOF){
printf("%s", str);
}
}
else
printf("Error!”);
fclose(file);
return 0;
}
Output
LearnprogrammingattutorialsPoint
fgets()
The fget() function in C is used to read string from the stream.
Team University Lecture Material - Introduction to Basic Computer Programming Page 129
Syntax
char* fgets(char *string, int length, FILE *stream)
Parameter
char *string: It is a string which will store the data from the string.
int length: It is an int which gives the length of string to be considered.
FILE *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
char str[500];
if (file = fopen("hello.txt", "r")){
printf("%s", fgets(str, 50, file));
}
fclose(file);
return 0;
}
Output
Learn programming at tutorials Point
fgetc()
The fgetc() function in C is used to return a single character from the file. It gets a character from the file
and returns EOF at the end of file.
Syntax
char* fgetc(FILE *stream)
Parameter
FILE *stream: It is the pointer to the opened file.
Example
#include <stdio.h>
int main(){
FILE * file;
char str;
if (file = fopen("hello.txt", "r")){
while((str=fgetc(file))!=EOF)
printf("%c",str);
}
fclose(file);
return 0;
}
Output
Learn programming at tutorials Point
Writing Data to a file in C
We can write data to a file in C using the fprintf(), fputs(), fputc() functions. All are used to write contents
to a file.
Let’s see the working of each of the function −
fprintf()
The fprintf() function is used to write data to a file. It writes a set of characters in a file.
Syntax
Team University Lecture Material - Introduction to Basic Computer Programming Page 130
int fprintf(FILE *stream, char *string[])
Parameters
FILE for *stream: It is the pointer to the opened file.
char *string[]: It is the character array that we want to write in the file.
Example
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fprintf(file, "tutorials Point”) >= 0)
printf("Write operation successful");
}
fclose(file);
return 0;
}
Output
Write operation successful
fputf()
The fputf() function in C can be used to write to a file. It is used to write a line (character line) to the file.
Syntax
int fputs(const char *string, FILE *stream)
Parameters
Constant char *string[]: It is the character array that we want to write in the file.
FILE for *stream: It is the pointer to the opened file.
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
if(fputs("tutorials Point", file) >= 0)
printf("String written to the file successfully...");
}
fclose(file);
return 0;
}
Output
String written to the file successfully…
fputc()
The fputc() function is used to write a single character to the file.
Syntax
int fputc(char character , FILE *stream)
Parameters
char character : It is the character that we want to write in the file.
FILE for *stream: It is the pointer to the opened file.
Team University Lecture Material - Introduction to Basic Computer Programming Page 131
Example
Live Demo
#include <stdio.h>
int main(){
FILE * file;
if (file = fopen("hello.txt", "w")){
fputc('T', file);
}
fclose(file);
return 0;
}
Output
‘T’ is written to the file.
fclose()
The fclose() function is used to close the open file. We should close the file after performing operations on
it to save the operations that we have applied to it.
Syntax
fclose(FILE *stream)
Parameters
Team University Lecture Material - Introduction to Basic Computer Programming Page 132
Types of Files
When dealing with files, there are two types of files you should know about:
Text files
Binary files
1. Text files
Text files are the normal .txt files. You can easily create text files using any simple text editors such as
Notepad.
When you open those files, you'll see all the contents within the file as plain text. You can easily edit or
delete the contents.
They take minimum effort to maintain, are easily readable, and provide the least security and takes bigger
storage space.
2. Binary files
Binary files are mostly the .bin files in your computer.
Instead of storing data in plain text, they store it in the binary form (0's and 1's).
They can hold a higher amount of data, are not readable easily, and provides better security than text files.
File Operations
In C, you can perform four major operations on files, either text or binary:
Creating a new file
Opening an existing file
Closing a file
Reading from and writing information to a file
fopen("E:\\cprogram\\oldprogram.bin","rb");
Let's suppose the file newprogram.txt doesn't exist in the location E:\cprogram. The first function creates a
new file named newprogram.txt and opens it for writing as per the mode 'w'.
The writing mode allows you to create and edit (overwrite) the contents of the file.
Team University Lecture Material - Introduction to Basic Computer Programming Page 133
Now let's suppose the second binary file oldprogram.bin exists in the location E:\cprogram. The second
function opens the existing file for reading in binary mode 'rb'.
The reading mode only allows you to read the file, you cannot write into the file.
Open for append in binary mode. If the file does not exist, it will be
ab
Data is added to the end of the file. created.
Open for both reading and writing in If the file does not exist, fopen() returns
rb+
binary mode. NULL.
wb+ Open for both reading and writing in If the file exists, its contents are
binary mode. overwritten.
Team University Lecture Material - Introduction to Basic Computer Programming Page 134
Opening Modes in Standard I/O
Open for both reading and appending If the file does not exist, it will be
ab+
in binary mode. created.
Closing a File
The file (both text and binary) should be closed after reading/writing.
Closing a file is performed using the fclose() function.
Team University Lecture Material - Introduction to Basic Computer Programming Page 135
III. Notes
IV. Status
V. Assigning documents for processing in a queue.
VI. Add or edit metadata of files.
VII. Create, modify, delete, or manage other file operations.
VIII. Simple interact to access and manage files.
IX. Managing different types of files with extensions .xls, .pdf, .doc etc
Team University Lecture Material - Introduction to Basic Computer Programming Page 136
Keeping computerized data organized is critical for any business. Businesses often have many documents
organized into folders by customer, date or other criteria so they can be found quickly. A file
management program is a tool for organizing files into folders on your computer, as well as locating,
moving, opening and copying existing files.
Windows Explorer is an example of this type of utility, and there are equivalent programs for Apple
macOS, various distributions of Linux, and the smartphone operating systems iOS and Android.
Nowadays, you may also use a cloud-based file management tool to organize and store your personal or
business data remotely.
Often, you'll want to browse through your hard drive or external storage such as USB memory sticks for
particular files. You may also want to reorganize your files into new hierarchies of folders so that you
can easily find them. For example, if you run a small business, you might organize files initially by client
and then create a second layer of folders organizing them by year or month when the folders start to be
crowded with files.
Open the Explorer tool by clicking the Start Menu and browsing for it by name or by clicking the folder
icon on the Windows task bar.
On a Mac computer, use Mac's built-in Finder tool. Click the Finder icon on the system dock and
navigate through the files and folders on your Mac.
If you're running Ubuntu Linux, the default file manager is called Nautilus. On an Android phone, there's
usually a file manager installed when you purchase the phone, and you can install additional file
managers through the Google Play store. Apple iPhones ship with a file manager called Files, and you
can install additional managers through the App Store.
Team University Lecture Material - Introduction to Basic Computer Programming Page 137
When you install a third-party file manager on your computer or phone, make sure it's from a source you
trust, since it will have permissions to read, write and reorganize your files.
Some of the popular tools in this category include Dropbox, Google Drive, Microsoft
OneDrive and Apple iCloud. Many cloud services provide you a limited amount of free storage, and you
can pay for additional storage space as needed. Some systems for advanced users allow you to store data
using other cloud systems, like Amazon's Simple Storage Service. Shop around for a service that meets
your needs at a good price.
You can usually either manipulate files and folders directly through the cloud system's web or
smartphone app interface or allow it to sync file and folder structures that already exist on your devices.
Many cloud providers also provide business accounts that can be useful for allowing multiple employees
or people in an organization to share files and set up the right security permissions
Team University Lecture Material - Introduction to Basic Computer Programming Page 138