C Programming Language
C Programming Language
An array is a collective name given to a group of similar quantities. These similar quantities
could be percentage marks of 100 students, number of chairs in home, or salaries of 300
employees or ages of 25 students. Thus an array is a collection of similar elements. These
similar elements could be all integers or all floats or all characters etc. Usually, the array of
characters is called a “string”, where as an array of integers or floats is called simply an
array. All elements of any given array must be of the same type i.e we can’t have an array
of 10 numbers, of which 5 are int and 5 are float.
Arrays and pointers have a special relationship as arrays use pointers to reference memory
locations.
Declaration of an Array
Arrays must be declared before they can be used in the program. Standard array declaration
is as
type variable_name[lengthofarray];
Here type specifies the variable type of the element which is going to be stored in the array.
In C programming language we can declare the array of any basic standard type which C
language supports. For example
double height[10];
float width[20];
int min[9];
char name[20];
In C Language, arrays starts at position 0. The elements of the array occupy adjacent
locations in memory. C Language treats the name of the array as if it were a pointer to the
first element This is important in understanding how to do arithmetic with arrays. Any item
in the array can be accessed through its index, and it can be accessed any where from with
in the program. So
m=height[0];
Initializing Arrays
Initializing of array is very simple in c programming. The initializing values are enclosed
within the curly braces in the declaration and placed following an equal sign after the array
name. Here is an example which declares and initializes an array of five elements of type
int. Array can also be initialized after declaration. Look at the following C code which
demonstrate the declaration and initialization of an array.
int myArray[5] = {1, 2, 3, 4, 5}; //declare and initialize the array in one statement
int studentAge[4];
studentAge[0]=14;
studentAge[1]=13;
studentAge[2]=15;
studentAge[3]=16;
#include <stdio.h>
void oneWay(void);
void anotherWay(void);
int main(void) {
printf("\noneWay:\n");
oneWay();
printf("\nantherWay:\n");
anotherWay();
}
antherWay:
i = 0 vect[i] = 1
i = 1 vect[i] = 2
i = 2 vect[i] = 3
i = 3 vect[i] = 4
i = 4 vect[i] = 5
i = 5 vect[i] = 6
i = 6 vect[i] = 7
i = 7 vect[i] = 8
i = 8 vect[i] = 9
i = 9 vect[i] = 10
*/
Here is a more complex program that will demonstrate how to read, write and traverse the
integer arrays
#include <stdio.h>
void intSwap(int *x, int *y);
int getIntArray(int a[], int nmax, int sentinel);
void printIntArray(int a[], int n);
void reverseIntArray(int a[], int n);
int main(void) {
int x[10];
int hmny;
do {
printf("Enter integer [%d to terminate] : ", sentinel);
scanf("%d", &temp);
if (temp==sentinel) break;
if (n==nmax)
printf("array is full\n");
else
a[n++] = temp;
}while (1);
return n;
}
#include <stdio.h>
int main()
{
int iMarks[4];
short newMarks[4];
iMarks[0]=78;
iMarks[1]=64;
iMarks[2]=66;
iMarks[3]=74;
for(i=0; i<4; i++)
newMarks[i]=iMarks[i];
for(j=0; j<4; j++)
printf("%d\n", newMarks[j]);
return 0;
}
To summarize, arrays are provides a simple mechanism where more than one elements of
same type are to be used. We can maintain, manipulate and store multiple elements of same
type in one array variable and access them through index.
Multidimensional Arrays
In C Language one can have arrays of any dimensions. To understand the concept
of multidimensional arrays let us consider the following 4 X 5 matrix
To access a particular element from the array we have to use two subscripts on for row
number and other for column number the notation is of the form X [i] [j] where i stands for
row subscripts and j stands for column subscripts. Thus X [0] [0] refers to 10, X [2] [1]
refers to 16 and so on In short multidimensional arrays are defined more or less in the same
manner as single dimensional arrays, except that for subscripts you require two squire two
square brackets. We will restrict our decision to two dimensional arrays.
The first example defines tables as a floating point array having 50 rows and 50 columns.
the number of elements will be 2500 (50 X50).
The second declaration example establishes an array line of type character with 24 rows
and 40 columns. The number of elements will be (24 X 40) 1920 consider the following
two dimensional array definition int values [3] [4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10. 11, 12, };
Values [0] [0] = 1 Values [0] [1] = 2 Values [0] [2] = 3 Values [0] [3] = 4
Values [1] [0] = 5 Values [1] [1] = 6 Values [1] [2] = 7 Values [1] [3] = 8
Values [2] [0] = 9 Values [2] [1] = 10 Values [2] [2] = 11 Values [2] [3] = 12
Here the first subscript stands for the row number and second one for column number. First
subscript ranges from 0 to 2 and there are altogether 3 rows second one ranges from 0 to 3
and there are altogether 4 columns.
Here is a sample program that stores roll numbers and marks obtained by a student side by
side in matrix
main ( )
{
int stud [4] [2];
int i, j;
for (i =0; i < =3; i ++)
{
printf ("\n Enter roll no. and marks");
scanf ("%d%d", &stud [i] [0], &stud [i] [1] );
}
for (i = 0; i < = 3; i ++)
printf ("\n %d %d", stud [i] [0], stud [i] [1]);
}
The above example illustrates how a two dimensional array can be read and how the values
stored in the array can be displayed on screen.
Integer Types
The "integral" types in C form a family of integer types. They all behave like integers and
can be mixed together and used in similar ways. The differences are due to the different
number of bits ("widths") used to implement each type — the wider types can store a
greater ranges of values.
char ASCII character at least 8 bits. Pronounced "car". As a practical matter char is
basically always a byte which is 8 bits which is enough to store a single ASCII character. 8
bits provides a signed range of -128..127 or an unsigned range is 0..255. char is also
required to be the "smallest addressable unit" for the machine — each byte in memory has
its own address.
short Small integer — at least 16 bits which provides a signed range of -32768..32767.
Typical size is 16 bits. Not used so much.
int Default integer — at least 16 bits, with 32 bits being typical. Defined to be the "most
comfortable" size for the computer. If you do not really care about the range for an integer
variable, declare it int since that is likely to be an appropriate size (16 or 32 bit) which
works well for that machine.
long Large integer — at least 32 bits. Typical size is 32 bits which gives a signed range of
about -2 billion ..+2 billion. Some compilers support "long long" for 64 bit ints.
The integer types can be preceded by the qualifier unsigned which disallows representing
negative numbers, but doubles the largest positive number representable. For example, a 16
bit implementation of short can store numbers in the range -32768..32767, while unsigned
short can store 0..65535. You can think of pointers as being a form of unsigned long on a
machine with 4 byte pointers. In my opinion, it’s best to avoid using unsigned unless you
really need to. It tends to cause more misunderstandings and problems than it is worth.
char Constants
A char constant is written with single quotes (‘) like ‘A’ or ‘z’. The char constant ‘A’ is
really just a synonym for the ordinary integer value 65 which is the ASCII value for
uppercase ‘A’. There are special case char constants, such as ‘\t’ for tab, for characters
which are not convenient to type on a keyboard.
int Constants
Numbers in the source code such as 234 default to type int. They may be followed by an
‘L’ (upper or lower case) to designate that the constant should be a long such as 42L. An
integer constant can be written with a leading 0x to indicate that it is expressed in
hexadecimal — 0x10 is way of expressing the number 16. Similarly, a constant may be
written in octal by preceding it with "0" — 012 is a way of expressing the number 10.
The sum may or may not be 1.0 exactly, and it may vary from one type of machine to
another. For this reason, you should never compare floating numbers to eachother for
equality (==) — use inequality (<) comparisons instead. Realize that a correct C program
run on different computers may produce slightly different outputs in the rightmost digits of
its floating point computations.
Comments
Comments in C are enclosed by slash/star pairs:
/* .. comments .. */
which may cross multiple lines. C++ introduced a form of comment started by two slashes
and extending to the end of the line: // comment until the line end The // comment form is
so handy that many C compilers now also support it, although it is not technically part of
the C language.
Along with well-chosen function names, comments are an important part of well written
code. Comments should not just repeat what the code says. Comments should describe
what the code accomplishes which is much more interesting than a translation of what each
statement does. Comments should also narrate what is tricky or non-obvious about a
section of code.
Variables
As in most languages, a variable declaration reserves and names an area in memory at run
time to hold a value of particular type. Syntactically, C puts the type first followed by the
name of the variable. The following declares an int variable named "num" and the 2nd line
stores the value 42 into num.
int num;
num = 42;
num 42
A variable corresponds to an area of memory which can store a value of the given type.
Making a drawing is an excellent way to think about the variables in a program. Draw each
variable as box with the current value inside the box. This may seem like a "beginner"
technique, but when I’m buried in some horribly complex programming problem, I
invariably resort to making a drawing to help think the problem through.
Variables, such as num, do not have their memory cleared or set in any way when they are
allocated at run time.Variables start with random values, and it is up to the program to set
them to something sensible before depending on their values.
Names in C are case sensitive so "x" and "X" refer to different variables. Names can
contain digits and underscores (_), but may not begin with a digit. Multiple variables can be
declared after the type by separating them with commas. C is a classical "compile time"
language — the names of the variables, their types, and their implementations are all
flushed out by the compiler at compile time (as opposed to figuring such details out at run
time like an interpreter).
float x, y, z, X;
Assignment Operator =
The assignment operator is the single equals sign (=).
i = 6;
i = i + 1;
The assignment operator copies the value from its right hand side to the variable on its left
hand side. The assignment also acts as an expression which returns the newly assigned
value. Some programmers will use that feature to write things like the following.
Truncation
The opposite of promotion, truncation moves a value from a type to a smaller type. In that
case, the compiler just drops the extra bits. It may or may not generate a compile time
warning of the loss of information. Assigning from an integer to a smaller integer (e.g..
long to int, or int to char) drops the most significant bits. Assigning from a floating point
type to an integer drops the fractional part of the number.
char ch;
int i;
i = 321;
ch = i; // truncation of an int value to fit in a char
// ch is now 65
The assignment will drop the upper bits of the int 321. The lower 8 bits of the number 321
represents the number 65 (321 – 256). So the value of ch will be (char)65 which happens to
be ‘A’.
The assignment of a floating point type to an integer type will drop the fractional part of the
number. The following code will set i to the value 3. This happens when assigning a
floating point number to an integer or passing a floating point number to a function which
takes an integer.
double pi;
int i;
pi = 3.14159;
i = pi; // truncation of a double to fit in an int
// i is now 3
Unfortunately, score will almost always be set to 0 for this code because the integer
division in the expression (score/20) will be 0 for every value of score less than 20. The fix
is to force the quotient to be computed as a floating point number…
i = 0;
while (i - 10) {
...
will execute until the variable i takes on the value 10 at which time the expression (i – 10)
will become false (i.e. 0). (we’ll see the while() statement a bit later)
Mathematical Operators
C includes the usual binary and unary arithmetic operators. See the appendix for the table
of precedence. Personally, I just use parenthesis liberally to avoid any bugs due to a
misunderstanding of precedence. The operators are sensitive to the type of the operands. So
division (/) with two integer arguments will do integer division. If either argument is a
float, it does floating point division. So (6/4) evaluates to 1 while (6/4.0) evaluates to 1.5 —
the 6 is promoted to 6.0 before the division.
+ Addition
- Subtraction
/ Division
* Multiplication
% Remainder (mod)
int i = 42;
int j;
j = (i++ + 10);
// i is now 43
// j is now 52 (NOT 53)
j = (++i + 10)
// i is now 44
// j is now 54
j = (i + 10);
i++;
i++;
j = (i + 10);
Now then, isn’t that nicer? (editorial) Build programs that do something cool rather than
programs which flex the language’s syntax. Syntax — who cares?
Relational Operators
These operate on integer or floating point values and return a 0 or 1 boolean value.
== Equal
!= Not Equal
> Greater Than
< Less Than
>= Greater or Equal
<= Less or Equal
To see if x equals three, write something like:
if (x == 3) ...
Pitfall = ==
An absolutely classic pitfall is to write assignment (=) when you mean comparison (==).
This would not be such a problem, except the incorrect assignment version compiles fine
because the compiler assumes you mean to use the value returned by the assignment. This
is rarely what you want
if (x = 3) ...
This does not test if x is 3. This sets x to the value 3, and then returns the 3 to the if for
testing. 3 is not 0, so it counts as "true" every time. This is probably the single most
common error made by beginning C programmers. The problem is that the compiler is no
help — it thinks both forms are fine, so the only defense is extreme vigilance when coding.
Or write "= � ==" in big letters on the back of your hand before coding. This mistake is an
absolute classic and it’s a bear to debug. Watch Out! And need I say: "Professional
Programmer’s Language."
Logical Operators
The value 0 is false, anything else is true. The operators evaluate left to right and stop as
soon as the truth or falsity of the expression can be deduced. (Such operators are called
"short circuiting") In ANSI C, these are furthermore guaranteed to use 1 to represent true,
and not just some random non-zero bit pattern. However, there are many C programs out
there which use values other than 1 for true (non-zero pointers for example), so when
programming, do not assume that a true boolean is necessarily 1 exactly.
Bitwise Operators
C includes operators to manipulate memory at the bit level. This is useful for writing
lowlevel hardware or operating system code where the ordinary abstractions of numbers,
characters, pointers, etc… are insufficient — an increasingly rare need. Bit manipulation
code tends to be less "portable". Code is "portable" if with no programmer intervention it
compiles and runs correctly on different types of computers. The bitwise operations are
typically used with unsigned types. In particular, the shift operations are guaranteed to shift
0 bits into the newly vacated positions when used on unsigned values.
Do not confuse the Bitwise operators with the logical operators. The bitwise connectives
are one character wide (&, |) while the boolean connectives are two characters wide (&&,
||). The bitwise operators have higher precedence than the boolean operators. The compiler
will never help you out with a type error if you use & when you meant &&. As far as the
type checker is concerned, they are identical– they both take and produce integers since
there is no distinct boolean type.
Graphics in C Language
In a C program, first step is to initialize the graphics drivers on the computer. This is done
using the initgraph method provided in graphics.h library. In the next few pages we will
discuss graphics.h library in details. Important functions in graphic.h library will be
discussed in details and samples programs will be provided to show the power of C
programming language.
Initgraph initializes the graphics system by loading the graphics driver from disk (or
validating a registered driver) then putting the system into graphics mode. Initgraph also
resets all graphics settings (color, palette, current position, viewport, etc.) to their defaults,
then resets graphresult to 0.
*graphdriver
Integer that specifies the graphics driver to be used. You can give graphdriver a value using
a constant of the graphics_drivers enumeration type whcih is listed in graphics.h. Normally
we use value as “0” (requests auto-detect). Other values are 1 to 10 and description of each
enumeration type is listed here.
*graphmode
Integer that specifies the initial graphics mode (unless *graphdriver = DETECT). If
*graphdriver = DETECT, initgraph sets *graphmode to the highest resolution available for
the detected driver. You can give *graphmode a value using a constant of the
graphics_modes enumeration type and description of each enumeration type is listed here.
*pathtodriver
Specifies the directory path where initgraph looks for graphics drivers (*.BGI) first.
After a call to initgraph, *graphdriver is set to the current graphics driver, and *graphmode
is set to the current graphics mode. You can tell initgraph to use a particular graphics driver
and mode, or to auto detect the attached video adapter at run time and pick the
corresponding driver. If you tell initgraph to auto detect, it calls detectgraph to select a
graphics driver and mode.
Normally, initgraph loads a graphics driver by allocating memory for the driver (through
_graphgetmem), then loading the appropriate .BGI file from disk. As an alternative to this
dynamic loading scheme, you can link a graphics driver file (or several of them) directly
into your executable program file.
Here is a simple program that initializes the graphics mode in C programming language and
print the line in graphics mode.
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
int main(void)
{
/* draw a line */
line(0, 0, getmaxx(), getmaxy());
/* clean up */
getch();
closegraph();
return 0;
}
The below program draws a circle in the current drawing color with its center at (150,150)
and the radius (100) given by radius.
Normally the screen which we see in DOS/Command Mode is in the text mode which
means it is meant for text only. And for graphics we need to initialize graphics mode using
initgraph() method defined in graphics.h?.
The circle command takes a X coordinate which means Vertical axis and Y coordinate
which means Horizontal axis. And the last one is the radius of the circle.
closegraph();
This function unloads the graphics drivers and returns the screen back to text mode.
/*A program to draw a space with stars*/
#include<graphics.h>
#include<stdio.h>
main()
{
int gd=DETECT,gm;
int i,x,y;
initgraph(&gd,&gm,"");
line(0,0,640,0);
line(0,0,0,480);
line(639,0,639,480);
line(639,479,0,479);
for(i=0;i<=1000;i++)
{
x=rand()%639;
y=rand()%480;
putpixel(x,y,15);
}
getch();
closegraph();
}
/* End of program */
Here a sample program to illustrate how to use BARS which are used for visual statistics.
The bar is filled using the current fill pattern and fill color. Bar method accepts parameters
i.e. left, top, right and bottom. The setfillstyle() method can be used to fill the bar with a
different color or pattern
#include <graphics.h>
#include <conio.h>
main() {
int gd=DETECT,gm,maxx,maxy,x,y,button;
initgraph(&gd,&gm,"");
line(80,150,200,150);
line(80,150,80,50);
settextstyle(1,HORIZ_DIR,1);
outtextxy(100,153,"<-X axis");
settextstyle(1,VERT_DIR,1);
outtextxy(60,50,"<-Y axis");
bar(100,100,120,150);
bar(130,120,150,150);
getch();
closegraph();
}
Minimum Distance between a Point and a
Line
This article describes the technique and gives the solution to finding the shortest distance
from a point to a line or line segment. The equation of a line defined through two points P1
(x1,y1) and P2 (x2,y2) is
P = P1 + u (P2 – P1)
The point P3 (x3,y3) is closest to the line at the tangent to the line which passes through
P3, that is, the dot product of the tangent and line is 0, thus
Substituting this into the equation of the line gives the point of intersection (x,y) of the
tangent as
x = x1 + u (x2 – x1)
y = y1 + u (y2 – y1)
The distance therefore between the point P3 and the line is the distance between (x,y)
above and P3.
Notes
The only special testing for a software implementation is to ensure that P1 and P2
are not coincident (denominator in the equation for u is 0)
If the distance of the point to a line segment is required then it is only necessary to
test that u lies between 0 and 1.
The solution is similar in higher dimensions.
Source code
//================
//
// DistancePointLine Unit Test
// Copyright (c) 2002, All rights reserved
//
// Damian Coventry
// Tuesday, 16 July 2002
//
// Implementation of theory by Paul Bourke
//
//================
#include <stdio.h>
#include <math.h>
typedef struct tagXYZ
{
float X, Y, Z;
}
XYZ;
float Magnitude( XYZ *Point1, XYZ *Point2 )
{
XYZ Vector;
Vector.X = Point2->X - Point1->X;
Vector.Y = Point2->Y - Point1->Y;
Vector.Z = Point2->Z - Point1->Z;
return (float)sqrt( Vector.X * Vector.X + Vector.Y * Vector.Y +
Vector.Z * Vector.Z );
}
int DistancePointLine( XYZ *Point, XYZ *LineStart, XYZ *LineEnd,
float *Distance )
{
float LineMag;
float U;
XYZ Intersection;
LineMag = Magnitude( LineEnd, LineStart );
U = ( ( ( Point->X - LineStart->X ) * ( LineEnd->X - LineStart->X
) ) +
( ( Point->Y - LineStart->Y ) * ( LineEnd->Y - LineStart->Y ) ) +
( ( Point->Z - LineStart->Z ) * ( LineEnd->Z - LineStart->Z ) ) )
/
( LineMag * LineMag );
The following will show how to compute this shortest line segment that joins two lines in
3D, it will as a biproduct identify parrallel lines. In what follows a line will be defined by
two points lying on it, a point on line “a” defined by points P1 and P2 has an equation
Pa = P1 + mua (P2 –
P1)
Pb = P3 + mub
(P4 – P3)
The values of mua and mub range from negative to positive infinity. The line segments between P1
P2 and P3 P4 have their corresponding mu
between 0 and 1.
There are two approaches to finding the shortest line segment between lines “a” and “b”.
The first is to write down the length of the line segment joining the two lines and then find
the minimum. That is, minimize the following
|| Pb – Pa ||2
|| P1 – P3 + mua (P2 –
P1) – mub (P4 – P3) ||2
The above can then be expanded out in the (x,y,z) components. There are conditions to be
met at the minimum, the derivative with respect to mua and mub must be zero. Note: it is
easy to convince
oneself that the above function only has one minima and no other minima or maxima.
These two equations can then be solved for mua and mub, the actual intersection points
found by substituting the values of mu into the original equations of the line.
An alternative approach but one that gives the exact same equations is to realize that the
shortest line segment between the two lines will be perpendicular to the two lines. This
allows us to write two equations for the dot product as
( P1 – P3 + mua (P2 –
P1) – mub (P4 – P3) ) dot
(P2 – P1) = 0
( P1 – P3 + mua (P2 –
P1) – mub (P4 – P3) ) dot
(P4 – P3) = 0
result is as follows
where
dmnop = (xm – xn)(xo –
xp) + (ym – yn)(yo – yp)
+ (zm – zn)(zo – zp)
typedef struct {
double x,y,z;
} XYZ;
/*
Calculate the line segment PaPb that is the shortest route
between
two lines P1P2 and P3P4. Calculate also the values of mua and
mub where
Pa = P1 + mua (P2 - P1)
Pb = P3 + mub (P4 - P3)
Return FALSE if no solution exists.
*/
int LineLineIntersect(
XYZ p1,XYZ p2,XYZ p3,XYZ p4,XYZ *pa,XYZ *pb,
double *mua, double *mub)
{
XYZ p13,p43,p21;
double d1343,d4321,d1321,d4343,d2121;
double numer,denom;
return(TRUE);
}
void far initgraph(int far *driver, int far *mode, char far
*path)
Here path is the actual path to the graphics library. You can give the path to this
library by giving the complete path, like “C:\\TC\\BGI”, where BGI is the graphics
library directory.
After initializing the graphics mode you can check for any error which may happen
while initializing the graphics mode. The function used to find out any errors is int
errorcode = graphresult() which returns the error code for the specific error.
If you pass this errorcode to grapherrormsg() function the, it will return the
complete description of the error message. And if the errorcode==grOk the you are
on the way to develop your first graphics program using C/C++.
If you are using Dev C++ compiler for your graphics programs then you can follow these
simple steps to configure your environment for graphics programming.
Function circle
Draws the circle on the screen using a point(x,y) and the radius for the circle.
Function line
void far line(int startx, int starty, int endx, int endy)
Function outtext
Function outtextxy
Function rectangle
Draws a rectangular box on the screen using the points given in the parameters.
void far rectangle(int left, int top, int right, int bottom)
What is a Function?
A function is a block of code that has a name and it has a property that it is reusable i.e. it
can be executed from as many different points in a C Program as required.
Function groups a number of program statements into a unit and gives it a name. This unit
can be invoked from other parts of a program. A computer program cannot handle all the
tasks by it self. Instead its requests other program like entities – called functions in C – to
get its tasks done. A function is a self contained block of statements that perform a coherent
task of same kind
The name of the function is unique in a C Program and is Global. It means that a function
can be accessed from any location with in a C Program. We pass information to the
function called arguments specified when the function is called. And the function either
returns some value to the point it was called from or returns nothing.
We can divide a long C program into small blocks which can perform a certain task. A
function is a self contained block of statements that perform a coherent task of same kind.
Structure of a Function
There are two main parts of the function. The function header and the function body.
Function Header
In the first line of the above code
Function Body
What ever is written with in { } in the above example is the body of the function.
Function Prototypes
The prototype of a function provides the basic information about a function which tells the
compiler that the function is used correctly or not. It contains the same information as the
function header contains. The prototype of the function in the above example would be like
The only difference between the header and the prototype is the semicolon ; there must the
a semicolon at the end of the prototype.
// table .cpp
// demonstrates simple function
# include
using namespace std;
void starline( );
into main ()
{
starline ( );
cout << "Data type Range" << endl;
starline ( );
cout << "char -128 to 127 " << endl
<< "short -32 ,768 to 32,767"<< endl
<< "int system independent: << endl
<< " long q-2,147,483,648 to 2,147,483,647" << endl;
starline ( );
return 0;
}
//""""""""""""""""""""""""..
//starline ( )
// function defintion
void starline ( )
{
for(into j=0;j<45; j++)
cout << "*" ;
cout << endl;
}
The output from the program looks like this
*************************************
Data type Range
*************************************
Char -128 to 127
Short -32,768 to 32,767
Into system dependent
Double -2,147,483,648 to 2,147,483,647
*************************************
Two reasons
1. Writing functions avoids rewriting the same code over and over. Suppose that there
is a section of code in a program that calculates area of a triangle. If, later in the
program we want to calculate the area of a different triangle we wont like to write
the same instructions all over again. Instead we would prefer to jump to a “section
of code” that calculates area and then jump back to the place from where you left
off. This section of code is nothing but a function.
2. Using functions it becomes easier to write programs and keep track of what they are
doing. If the operation of a program can be divided in to separate activities, and
each activity placed in a different function, then each could be written and checked
more or less independently. Separating the code in to modular functions also makes
the pro-gram easier to design and understand.
Function Declaration
Just as you can”t use a variable without first telling the compiler what it is, you also can”t
use a functions without telling the compiler about it, There are two ways to do this . The
approach we show here is to declare the function before it is called. The other approach is
to define it before it”s called. ; we”ll examine that next.) in the Table program, the
functions starline() is declared in the line.
void starline ( );
The declaration tells the compiler that at some later point we plan to present a function
called starline. The keyword void specifies that the function has no return value, and the
empty parentheses indicate that it takes no arguments.
Function declarations are also called prototypes, since they provide a model or blueprint for
the function. They tell the compiler,” a function that looks like this is coming up later in the
program, so it”s all right if you see references to it before you see the function itself.”
Starline();
This is all we need to call a function name,followed by parentheses. The syntax of the call
is very similar to that of declaration, except that the return type is not used. A semicolon
terminates the call. Executing the call statement causes the function to execute; that is,
control is transferred to the function, the statement in the function definition are executed,
and then control returns
to the statement following the function call.
Function Definition
Finally, we come to the functions its self, which is referred to as the functions definition,
The definition contains the actual code for the function. Here’s the definition for starline( ) .
void starline ( )
{
for ( intj=0, j < 45; j++ )
cout << "*" ;
cout << endl;
}
The definition consists of a line called the decelerator, followed by the function body , The
function body is composed of the statements that make up the function, delimited by
braces.
The decelerator must agree with the declaration: It must use the same function name, have
the same argument types in the same order( if there are arguments), and have the same
return type.
Notice that a semicolon does not terminate the decelerator. Figure shows the syntax of the
function declaration, function call, and function definition.
When the function is called, control is transferred to the first statement in the functions
body. The other statements in the function body are then executed, and when the closing
brace is encountered, control returns to the calling program.
main ( ){
message ( );
message ( ){
statement 1;
statement2;
statement 3;
4. Any function can be called from any other function even main ( ) can be called from
other functions. for e.g.
main ( ){
message ( );
message ( )
printf (” \n Hello”);
main ( );
main (){
message ( );
message ( );
message ( )
6. The order in which the functions are defined in a program and the order in which
they get called need not necessarily be same for e.g.
main ( );{
message 1 ( );
message 2 ( );
message 2 ( )
message 1 ( )
argentina ( )
Functions declaration and prototypes Any function by default returns an int value. If we
desire that a function should return a value other than an int, then it is necessary to
explicitly mention so in the calling functions as well as in the called function. for e.g
main ( )
{
float a,b,
printf ("\n Enter any number");
scanf ("\% f", &a );
b = square (a)
printf ("\n square of % f is % f", a,b);
}
square (float X)
{
float y;
Y = x * x;
return (y);
}
the sample run of this program is Enter any number 2.5 square of 2.5 is 6.000000 Here 6 is
not a square of 2.5 this happened because any C function, by default, always returns an
integer value. The following program segment illustrates how to make square ( ) capable of
returning a float value.
main ( )
{
float square ( );
float a, b;
printf ("\n Enter any number ");
scanf ("%f" &a);
b = square (a);
printf ("\n square of % f is % f, " a,
b);
}
float square (float x)
{
float y;
y= x *x;
return ( y);
}
sample run Enter any number 2.5 square of 2.5 is 6.2500000
PASSING CONSTANTS
As an exp, let”s suppose we decide that the starline ( ) function in the last exp is too rigid.
Instead of a function that always prints 45 asterisks, we want a function that will print any
character any number of times
Here is a program, TABLEARG, that incorporates just such a function. We use arguments
to pass the character to be printed and the number of times to print it .
// tablearg.cpp
// demonstrates funciotn arguments
# include < iostream>
using namespace std;
void repchar(char, int); //function declaration
in main ( )
{
repchar(" " " , 43);
cout << " Data type Range" < endl;
repchar ( "=", 23); //call to function
cout << " char -128 to 128" < endl
<< "short -32,768 to 32,767" < endl
<< " int system dependent " << endl
<< " double -2, 147,483,648 to 2,147,483,647" << endl;
repchar("-" , 43);
return 0;
}//""""""""""""""""""""""""""".
//repchar ( )
// funtion definiton
void repchar ( char ch , int n )
{
for ( into j=0; j<n; j++) //function body
cout < ch;
cout << endl;
}
The new function is called repchar ( ), Its declaration looks like this
The items in the parentheses are the data types of the argument that will be sent to repchar(
): char and int.
In a function call, specific values—– constants in this case “are inserted in the appropriate
place in the parentheses:
This statement instructs repchar ( ) to print a line of 43 dashes. The values supplied in the
call must be of the types specified in the declaration: the first argument, the “-” character ,
must be of type[ char; and the second arguments, the number 43 must be of type int. The
types in the definition must also agree.
Tells it to print a line of 23 equal signs. The third call again prints 43 dashes. Here”s the
output form TABLEARG.
“”””””””””””””””””””””””””””””
===============
char -128 to 127
The calling program supplies arguments such as “-” and 43 ,to the function. The variables
used within the functions to hold the argument values are called parameters; in repchar()
the are ch and n.These decelerator names ch and n, are used in the functions as they were
normal variables. Placing them in the decelerators is equivalent to defining them with the
statements like
Char ch;
Int n;l
When the function is called, its parameters are automatically initialized to the values passed
by the calling program.
PASSING VARIABLES
In the tablearg example the arguments were constants “-” 43,and so on. Lets look at an
example where variables, instead of constants ,are passed as arguments. This
program,VARARG,incorporates the same repchar()function as did tablearg,but let the user
specify the character and the number of times it should be repeated.
//vararg.cpp
//demonstrates variable arguments
# include <iostream>
using namespace std;
void repchar(char,int);
int main()
{
char chin;
int nin;
cout<<"enter a character:";
cin>>nin;
cout<<"enter a number of times to repeat it:";
cin>>nin;
repchar (chin,nin);
return 0;
}
//"""""""""""""""""""""""""""
//repchar ()
//function definition
void repchar(char ch,int n)
{
for(int j=0,j<n;j++)
cout<<ch;
cout<<end1;
}
Enter a character:+
++++++++++++++++
The data types of variables used as arguments must match those specified in the function
declaration and definition, just as they must for constant. That is chin must be a char and
nin must be an int.
//convert.cpp
//demonstrates return values, converts a pound to kg
#include <iostream>
using namespace std;
float lbstokg(float);
int main()
{
float lbs,kgs;
cout<<"enter your weight in pounds:";
cin>>lbs;
kgs=lbstokg(lbs);
cout<<"your weight in kg is "<<kgs<<end1;
return 0;
}
//"""""""""""""""""..
//lbstokg()
//converts pounds to kg
float lbstokg(float pounds)
{
float kg=0.453592*pounds;
return kg;
}
When a function returns a value. The data type of this value must be specified. The function
declaration does this by placing the data types, float in this case, before the function name
in the declaration and the definition. Functions in earlier program examples returned no
value, so the return type was void. In the above function lbstokg() returns type float, so the
declaration is
Float lbstokg(float);
The first float specifies the return type. The float in parentheses s specifies that an argument
to be passed to lbstokg() is also of type float.
CALL BY VALUE
In the preceding examples we have seen that whenever we called a function we have
always passed the values of variables to the called function. Such function calls are called
“calls by value” by this what it meant is that on calling a function we are passing values of
variables to it. The example of call by value are shown below ;
In this method the value of each of the actual arguments in the calling function is copied
into corresponding formal arguments of the called function. With this method the changes
made to the formal arguments in the called function have no effect on the values of actual
argument in the calling function. The following program illustrates this:
main ( )
{
int a = 10, b=20;
swapy (a,b);
printf ("\na = % d b = % d", a,b);
}
swapy (int x, int y)
{
int t;
t = x;
x = y;
y = t;
printf ( "\n x = % d y = % d" , x, y);
}
CALL BY REFERENCE
In the second method the addresses of actual arguments in the calling function are copied in
to formal arguments of the called function. This means that using these addresses we would
have an access to the actual arguments and hence we would be able to manipulate them the
following program illustrates this.
main ( )
{
int a = 10, b =20,
swapv (&a, &b);
printf ("\n a = %d b= %d", a, b);
}
swapr (int **, int * y)
{
int t;
t = *x
*x = *y;
*y = t;
}
The output of the above program would be a = 20 b =10
Pointers
Each memory location that we use to store the data hase an address in computre memory
(RAM). Computer Hardware i.e. CPU uses this addess to reference to a particular data
item. A pointer is a variable that stores the address of another variable.
A pointer is a variable that represents the location of a data item, such as a variable or an
array element. Pointers are used frequently in C, as they have a number of useful
applications. For example, pointers can be used to pass information back and forth between
a function and its reference point. Pointers provide a way to return multiple data items from
a function via function arguments to
be specified as arguments to a given function.
Pointers are also closely associated with arrays and therefore provide an alternate way to
access individual array elements.
Within the computer?s memory, every stored data item occupies one or more adjacent
memory cells. The number of memory cells required to store a data item depends on the
type of data item. For example, a single character will be stored in 1 byte of memory
integer usually requires two adjacent bytes, a floating point number may require four
adjacent bytes.
Declaring a Pointer
A pointer is declared just like we declare a variable. There is only one difference in
declaration is that we add an asterisk * infront of it to indicate that it’s a variable which is a
pointer. For example
int* i;
long* y;
int *i;
long *y;
You can also initialize the pointer to the default null value.
Here is a simple example that demonstrates the different aspects of the pointer operations.
#include <stdio.h>
int main(void){
int num=10;
int* pnum=NULL;
pnum = &num;
*pnum += 20;
printf("\nNumber = %d", num);
printf("\nPointer Number = %d", *pnum);
return 0;
}
Pointers are also closely associated with arrays and therefore provide an alternate way to
access individual array elements.
Within the computer?s memory, every stored data item occupies one or more adjacent
memory cells. The number of memory cells required to store a data item depends on the
type of data item. For example, a single character will be stored in 1 byte of memory
integer usually requires two adjacent bytes, a floating point number may require four
adjacent bytes.
Suppose V is a variable that represents some particular data item. The compiler will
automatically assign memory cells for this data item. The data item can be accessed if we
know the location of the first memory cell. The address of V?S memory location can be
determined by the expression & V, where & is a unary operator, called the address
operator, that evaluates the address of its operand.
PV = & V
This new variable is called a pointer to V, since it “Points” to the location where V is stored
in memory. Remember, however, that PV represents V?s address, not its value. Thus, Pv is
called pointer variable.
address of V value of V
PV V
Example :
The statement instructs the system to find a location for the integer quantity and puts the
value 179 in that location. Let us reassume that the system has chosen the address location
5000 for quantity.
Quantity Variable
179 Value
5000 Address
Representation of a Variable
Remember, since a pointer is a variable, its value is also stored in the memory in another
location.
The program instructions and global and static variables are stored in a region known as
permanent storage area and the local variables are stored in another area called stack. The
memory space that is located between these two regions is available for dynamic allocation
during execution of the program. The free memory region is called the heap. The size of the
heap keeps changing when program is executed due to creation and death of variables that
are local to functions and blocks. Therefore, it is possible to encounter memory “overflow”
during dynamic allocation process. In such situations, the memory allocations functions
mentioned above returns a NULL pointer.
Ptr is a pointer of type cast type. The malloc returns a pointer (of cast type) to an area of
memory with size byte – size.
Example :
X = ( int * ) malloc ( 100 * size of ( int )) ;
On successful execution of this statement, a memory space equivalent to “100 times the
size of an int” bytes is reserved and the address of the first byte of the memory allocated is
assigned to the pointer X of type int.
allocates 10 bytes of space for the pointer cptr of type char. This is illustrated below :
Cptr
Address of
first byte
10 bytes of Space
Remember, the malloc allocates a block of adjacent bytes. The allocation can fail if the
space in the heap is not sufficient to satisfy the request. If it foils, it returns a NULL. We
should therefore check whether the allocation is successful before using the memory
pointer.
Example :
Write a program that uses a table of integers whose size will be specified interactively at
run time. Program :
name, age and num. The calloc allocates memory to hold data for 30 such records. We
should check if the requested memory has been allocated successfully before using the ptr.
This may be done as follows:
if ( ptr = = NULL ){
Printf ( “Available memory not sufficient”) ;
exit ( 1 ) ;
}
follows :
Static int X [ 6 ] = { 1, 2, 3, 4, 5, 6 } ;
Suppose the base address of X is 1000 and assuming that each integer requires two bytes,
the five elements will be stored as follows :
BASE ADDRESS
The name X is defined as a constant pointer pointing to the first clement, x [0] and
therefore the value of X is 1000, the location whose X[0] is stored. That is ;
If we declare P as an integer pointer, then we can make the pointer P to point to the array X
by
P=X;
Now we can access every value of x using P+ + to more from one element to another. The
relationship between P and X is shown below :
The address of an element is calculated using its index and the scale factor of the data type.
For instance,
When handling array, instead of using array indexing, we can use pointers to access array
elements. Note that X(P+3) gives the value of X[3]. The pointer accessing method is more
faster than array indexing.
When an array is passed to a function as an argument, only the address of the first element
of the array is passed, but not the actual values of the array elements. The function uses this
address for manipulating the array elements. Similarly, we can pass the address of a
variable as an argument to a function in the normal fashion. When we pass addresses to a
function, the parameters receiving the addresses should be pointers. The process of calling
function using pointers to pass the address of variable is known as call by reference. The
function which is called by reference can change the value of the variable used in the call.
eg.
main ( ) {
int X ;
X = 40 ;
Change ( & X ) ;
Printf ( " %d", X ) ;
{
Change ( int * P )
{
* P = * P + 10 ;
}
When the function change is called, the address of the variable X, not its value, is passed
into the function change ( ). Inside change ( ), the variable P is declared as a pointer and
therefore P is the address of the variable X. The statement,
* P = * P + 10 ;
means add 10 to the value stored at address P. Since P represents the address of X, the
value of X is changed from 50. Therefore, the output of the program will be 50 not 40.
These, call by reference provides a mechanism by which the function can change the stored
values in the calling function.
1. Share a single memory location for a variable myVar1 and use the same location for
myVar2 of different data type when myVar1 is not required any more.
2. Use it if you want to user, for example, a long variable as two short type variables.
3. We don’t know what type of data is to be passed to a function, and you pass union
which contains all the possible data types.
Defining a Union
Union can be defined by the keyword union.
union myUnion{
int var1;
long var2;
};
Here we have defined a union with the name myUnion and it has two members i.e. var1 of
type int and var2 of type long
union myUnion{
int var1;
long var2;
}newUnion;
So newUnion will be the variable of type myUnion. We can also declare the union as
myUnion newUnion;
union myUnion{
int var1;
long var2;
}newUnion={10.5};
or we can initialize it as
newUnion.var1= 10;
In later stages we can also initialize the var2 as well but this will over write the var1 value.
Normally when we declare the union it is allocated the memory that its biggest member can
occupy. So here in our example newUnion will occupy the memory which a long type
variable can occupy.
What is a Structure
A structure is a convenient tool for handling a group of logically related data items.
Structure help to organize complex data is a more meaningful way. It is powerful concept
that we may after need to use in our program Design.
A structure is combination of different data types. Lets take the example of a book, if we
cant to declare a book we will be thinking about the name, title, authors and publisher of
the book and publishing year. So to declare a book we need to have some complex data
type which can deal with more than one data types. Lets declare a Book.
Defining a Structure
We can declare a structure to accommodate the book.
struct Book
{
char Name[100];
char Author[100];
char Publisher[80];
int Year;
};
The keyword struct defines a book, and each line with in the braces defines the elements of
the Book. Now when ever we create an instance of Book it will have all the elements of the
structure i.e. Name, Author, Publisher and Year.
Declaring a Structure
We can declare the structure just like union.
Book CProgrammingBook;
Initializing a Structure
Lets initialize the structure variable CProgrammingBook.
Book CProgrammingBook =
{
"Beginning VC++ 6",
"Ivor Horton",
"Wrox",
2001
};
CProgrammingBook.Year = 2002;
STRUCTURE
A structure is a convenient tool for handling a group of logically related data items.
Structure help to organize complex data is a more meaningful way. It is powerful concept
that we may after need to use in our program Design. A structure is combination of
different data types using the & operator, the beginning address of structure can be
determined. This is variable is of type structure, then & variable represent the starting
address of that variable.
STRUCTURE DEFINITION
A structure definition creates a format that may be used to declare structure variables
consider the following example.
Struct book-bank
{
Char title [20];
Char author [15];
int pages;
float price;
};
Here keyword Struct hold the details of four fields these fields are title, author, pages, and
price, these fields are called structure elements. Each element may belong to different types
of data. Here book-bank is the name of the structure and is called the structure tag. It
simply describes as shown below.
Struct book-bank
Pages integer
Price float
ARRAY OF STRUCTURES
Each element of the array itself is a structure see the following example shown below. Here
we want to store data of 5 persons for this purpose, we would be required to use 5 different
structure variables, from sample1 to sample 5. To have 5 separate variable will be
inconvenient.
#include <stdio.h>
main()
{
struct person
{
char name [25];
char age;
};
struct person sample[5];
int index;
char into[8];
for( index = 0; index <5; index ++)
{
print("Enter name;");
gets(sample [index]. name);
printf("%Age;");
gets(info);
sample [index]. age = atoi (info);
}
for (index = 0; index <5; index++)
{
printf("name = %5\n", sample [index].name);
printf("Age = %d \n", sample [index].age);
getch( );
}
}
The structure type person is having 2 elements: Name an array of 25 characters and
character type variable age
USING THE STATEMENT
Struct person sample[5]; we are declaring a 5 element array of structures. Here, each
element of sample is a separate structure of type person. We, then defined 2 variables into
index and an array of 8 characters, info. Here, the first loop executes 5 times, with the value
of index varying from 0 to 4. The first printf statement displays. Enter name gets( ) function
waits for the input string. For the first time this name you enter will go to sample[0]. name.
The second printf display age the number you type is will be 5 stored as character type,
because the member age is declared as character type. The function atoi( ) converts this into
an integer. atoi stands for alpha to integer. This will be store in sample[0] age. The second
for loop in responsible for printing the information stored in the array of structures.
This structure defines name, department, basic pay and 3 kinds of allowance. we can group
all the items related to allowance together and declare them under a substructure are shown
below:
struct salary
{
char name [20];
char department[10];
str uct
{
int dearness;
int hous_rent;
int city;
}
allowance;
}
employee;
The salary structure contains a member named allowance which itself is a structure with 3
members. The members contained in the inner, structure namely dearness, house_rent, and
city can be referred to as :
An inner-most member in a nested structure can be accessed by chaining all the concerned.
Structure variables (from outer-most to inner-most) with the member using dot operator.
The following being invalid.
typedef struct
{
char *name;
int acc_no;
char acc_types;
float balance;
} account;
main()
{
void change(account *pt);
static account person = {"David", 4323,?R?, 12.45};
printf("%s %d %c %.2f \n", person.
name,person. acc_type, person. acc_type,person.balance);
change(&person);
printf("%s %d %c %2f \n", person. name, person. acc_type,person.acc-type, person.
balance);
getch( );
}
. UNIONS
Unions, like structure contain members, whose individual data types may vary. These is
major distinction between them in terms of storage .In structures each member has its own
storage location, where as all the members of a union use the same location. Like
structures, a union can be declared using the keyword union is follows:
union item{
int m;
float x;
char c;
} code;
This declares a variable code of type union them. The union contains them members, each
with a different date type. However, we can use only one of them at a time. This is due to
the fact that only one location is allocated for a union variable, irrespective of its size. The
compiler allocates a piece of storage that is large enough to hold the largest variable type in
the union. In the declaration above, the member x requires 4 bytes which is the largest
among the members. The above figure shown how all the three variables share the same
address, this assumes that a float variable requires 4 bytes of storage. To access a union
member, we can use the same syntax that we as for structure members, that is,
code. m
code. x
code. c are all valid
Member variables, we should make sure that we can accessing the member whose value is
currently storage. For example
code. m = 565;
code. x = 783.65;
printf(“%d”, code. m); would produce erroneous output.
# include <stdio.h>
main( ){
union
{
int one;
char two;
} val;
val.one = 300;
printf("val. one = %d \n", val.one);
printf("val. two = %d \n", val.two);
}
The format of union is similar to structure, with the only difference in the keyword used.
The above example, we have 2 members int one and char two we have then initialized the
member ?one? to 300. Here we have initialized only one member of the union. Using two
printf statements, then we are displaying the individual members of the union val as:
As we have not initialized the char variable two, the second printf statement will give a
random value of 44.
The general formats of a union thus, can be shown as.
union tag {
member 1;
member 2;
---
---
member
m;
};
Storage-class and tag are optional variable 1, variable 2 etc, are union variable of type tag.
Declaring union and defining variables can be done at the same time as shown below:
# include <stdio.h>
# include <conio.h>
struct S{
int i;
char sz[4];
char *ptrC;
}s1, s2, s3;
void compare(void *, void *, int);
#define POPULATE(S,li,lsz,lptr) { S.i=li; memcpy(S.sz,lsz,4); S.sz[3]=0; S.ptrC = lptr; }
char * one = "one";
char * two = "two";
int main(int argc, char* argv[])
{
POPULATE(s1,12,"HI",one);
POPULATE(s2,12,"HI",one);
POPULATE(s3,12,"HI",two);
compare(&s1, &s2 , sizeof(s1) );
compare(&s1, &s3 , sizeof(s1) );
compare(&s1, &s3 , 8 );
return 0;
}
void compare(void *v1, void* v2, int size)
{
if( memcmp( v1, v2, size) == 0 ){
printf("Memory area is same type\n");
}
else{
printf("Memory area is different type\n");
}
return ;
}
The memcmp method needs a bit of extra caution because of memory alignment
considerations.
For example:
struct A
{
int n;
char c;
int m;
};
The memory layout of the struct A will be, on a 32 bit system with 4 byte alignment:
4 bytes for n;
1 byte for c;
3 unused bytes (garbage);
4 bytes for m;
If you use memcmp, it can be that the 4 + 1 + 4 used bytes are identical but that there is a
difference between the 3 garbage bytes. I don’t think in this
case you want your comparison function to return false.
If you have pointers in your structures, I suggest that you use a different structure for your
“raw” data and add the pointers later:
struct A
{
int n;
char c;
int m;
};
struct APTR
{
A a;
char* pt;
};
bool areEqualPtr (struct APTR a1, struct APTR a2)
{
if (!areEqual (a1.a, a2.a))
return false;
return !strcpy (a1.pt, a2.pt);
}
The C programming language provides input and output support using library functions,
which gives an advantage to system designers to tailor their input and output on their own.
1. Data can come from some location external to the program. Data moved from an
external location into RAM, where the program can access it, is called input. The
keyboard and disk files are the most common sources of program input.
2. Data can also be sent to a location external to the program; this is called output. The
most common destinations for output are the screen, a printer, and disk files.
Input sources and output destinations are collectively referred to as devices. The keyboard
is a device; the screen is a device, and so on. Some devices (the keyboard) are for input
only, others (the screen) are for output only, and still others (disk files) are for both input
and output. Whatever the device, and whether it’s performing input or output, C carries out
all input and output operations by means of streams.
What is a Stream?
A stream is a sequence of characters. More exactly, it is a sequence of bytes of data. A
sequence of bytes flowing into a program is an input stream; a sequence of bytes flowing
out of a program is an output stream. By focusing on streams, we don’t have to worry as
much about where they’re going or where they originated.
The major advantage of streams, therefore, is that input/output programming is device
independent. Programmers don’t need to write special input/output functions for each
device (keyboard, disk, and so on). The program sees input/output as a continuous stream
of bytes no matter where the input is coming from or going to.
Every C stream is connected to a file. In this context, the term file doesn’t refer to a disk
file. Rather, it is an intermediate step between the stream that the program deals with and
the actual physical device being used for input or output. For the most part, the beginning C
programmer doesn’t need to be concerned with these files, because the details of
interactions between streams, files, and devices are taken care of automatically by the C
library functions and the operating system.
Text Stream
A text stream consists only of characters, such as text data being sent to the screen. Text
streams are organized into lines, which can be up to 255 characters long and are terminated
by an end-of-line, or newline, character. Certain characters in a text stream are recognized
as having special meaning, such as the newline character.
Binary Stream
A binary stream can handle any sort of data, including, but not limited to, text data. Bytes
of data in a binary stream aren’t translated or interpreted in any special way; they are read
and written exactly as-is. Binary streams are used primarily with disk files.
Predefined Streams
ANSI C has three predefined streams, also referred to as the standard input/output files. If
you’re programming for an IBM-compatible PC running DOS, two additional standard
streams are available to you. These streams are automatically opened when a C program
starts executing and are closed when the program terminates. The programmer doesn’t need
to take any special action to make these streams available. Table lists the standard streams
and the devices they normally are connected with. All five of the standard streams are text-
mode streams.
Whenever we have to use the printf() or puts() functions to display text on-screen, we use
the stdout stream. Likewise, when we use gets() or scanf() to read keyboard input, we use
the stdin stream. The standard streams are opened automatically, but other streams, such as
those used to manipulate information stored on disk, must be opened explicitly.
These functions are listed in table below. This table doesn’t list all of C’s input/output
functions.
All these functions require that we include STDLIB.H. The function perror() may also
require STDLIB.H. The functions vprintf() and vfprintf() also require STDARGS.H. On
UNIX systems, vprintf() and vfprintf() may also require VARARGS.H. The compiler”s
Library Reference will state whether any additional or alternative header files are needed.
An Example
main()
{
char buffer[256];
puts(gets(buffer));
return 0;
}
On line 10, the gets() function is used to input a line of text from the keyboard (stdin).
Because gets() returns a pointer to the string, it can be used as the argument to puts(), which
displays the string on-screen (stdout). When run, this program inputs a line of text from the
user and then immediately displays the string on-screen.
Character Input
The character input functions read input from a stream one character at a time. When
called, each of these functions returns the next character in the stream, or EOF if the end of
the
file has been reached or an error has occurred. EOF is a symbolic constant defined in
STDIO.H as -1. Character input functions differ in terms of buffering and echoing.
1. Some character input functions are buffered. This means that the operating system
holds all characters in a temporary storage space until you press Enter, and then the
system sends the characters to the stdin stream. Others are unbuffered, meaning that
each character is sent to stdin as soon as the key is pressed.
2. Some input functions automatically echo each character to stdout as it is received.
Others don”t echo; the character is sent to stdin and not stdout. Because stdout is
assigned to the screen, that”s where input is echoed.
The uses of buffered, unbuffered, echoing, and nonechoing character input are explained in
the following sections.
int getchar(void);
The use of getchar() is demonstrated below. Notice that the putchar() function, explained in
detail, simply displays a single character on-screen.
#include <STDIO.H>
main()
{
int ch;
return 0;
}
This is what''s typed in.
This is what''s typed in.
On line 9, the getchar() function is called and waits to receive a character from stdin.
Because getchar() is a buffered input function, no characters are received until we press
Enter. However, each key we press is echoed (showed) immediately on the screen.
When we press Enter, all the characters we entered, including the newline, are sent to stdin
by the operating system. The getchar() function returns the characters one at a time,
assigning each in turn to ch.
Each character is compared to the newline character \n and, if not equal, displayed on-
screen with putchar(). When a newline is returned by getchar(), the while loop terminates.
The getchar() function can be used to input entire lines of text, as shown below. However,
other input functions are better suited for this task
#include <STDIO.H>
#define MAX 80
main()
{
char ch, buffer[MAX+1];
int x = 0;
buffer[x] = '\0';
printf("%s\n", buffer);
return 0;
}
This is a string
This is a string
This program is similar to the previous function in the way that it uses getchar(). An extra
condition has been added to the loop. This time the while loop accepts characters from
getchar() until either a newline character is reached or 80 characters are read. Each
character is assigned to an array called buffer. When the characters have been input, line 15
puts a null on the end of the array
so that the printf() function on line 17 can print the entered string.
On line 9, why was buffer declared with a size of MAX + 1 instead of just MAX? If we
declare buffer with a size of MAX + 1, the string can be 80 characters plus a null
terminator. So don”t forget to include a place for the null terminator at the end of the
strings.
int getch(void);
Because it is unbuffered, getch() returns each character as soon as the key is pressed,
without waiting for the user to press Enter. Because getch() doesn’t echo its input, the
characters aren”t displayed on-screen. Listing 14.4 illustrates the use of getch().
The following function uses getch(), which is not ANSI-compliant. There is no guarantee
that all compilers support non-ANSI functions.
main()
{
int ch;
return 0;
}
Testing the getch() function
When this program runs, getch() returns each character as soon as we press a key–it doesn”t
wait for us to press Enter. There”s no echo, so the only reason that each character is
displayed on-screen is the call to putchar(). To get a better understanding, add a semicolon
to the end of line 10 and remove line 11 (putchar(ch)). When we rerun the program, you
will find that nothing
we type is echoed to the screen. The getch() function gets the characters without echoing
them to the screen. We know the characters are being gotten because the original listing
used putchar() to display them.
Why does this program compare each character to \r instead of to \n? The code \r is the
escape sequence for the carriage return character. When we press Enter, the keyboard
device sends a carriage return to stdin. The buffered character input functions automatically
translate the carriage return to a newline, so the program must test for \n to determine
whether Enter has been pressed. The
unbuffered character input functions don”t translate, so a carriage return is input as \r, and
that”s what the program must test for.
The next function uses getch( ) to input an entire line of text. Running this program clearly
illustrates that getch( ) doesn”t echo its input
main()
{
char ch, buffer[MAX+1];
int x = 0;
buffer[x] = '\0';
printf("%s", buffer);
return 0;
}
Here's a string
Here's a string
Remember that getch() isn’t an ANSI-standard command. This means that your compiler
(and other compilers) might or might not support it. getch() is supported by Symantec and
Borland. Microsoft
supports _getch().
The getc() and fgetc() character input functions don”t automatically work with stdin.
Instead, they let the program specify the input stream. They are used primarily to read
characters from disk files. See Day 16 for more details.
The argument ch is the character to be returned. The argument *fp specifies the stream that
the character is to be returned to, which can be any input stream. For now, simply specify
stdin as the second argument: ungetc(ch, stdin);. The notation FILE *fp is used with
streams associated with disk files.
We can unget only a single character to a stream between reads, and can”t unget EOF at
any time. The function ungetc() returns ch on success and EOF if the character can”t be
returned to the stream.
Reading a Line
The line input functions read a line from an input stream. They read all characters up to the
next newline character ‘\n’. The standard library has two line input functions, gets() and
fgets().
gets() takes a pointer to type char as its argument and returns a pointer to type char. The
gets() function reads characters from stdin until a newline (\n) or end-of-file is encountered;
the newline is replaced with a null character, and the string is stored at the location
indicated by str.
The return value is a pointer to the string (the same as str). If gets() encounters an error or
reads end-of-file before any characters are input, a null pointer is returned.
Before calling gets(), we must allocate sufficient memory space to store the string. This
function has no way of knowing whether space pointed to by ptr is allocated; the string is
input and stored starting at ptr in either case. If the space hasn’t been allocated, the string
might overwrite other data and cause program errors.
char input[81];
main()
{
puts("Enter some text, then press Enter: ");
gets(input);
printf("You entered: %s\n", input);
return 0;
}
Enter some text, then press Enter:
This is a test
You entered: This is a test
In this example, the argument to gets() is the expression input, which is the name of a type
char array and therefore a pointer to the first array element. The array is declared with 81
elements in line 7. Because the maximum line length possible on most computer screens is
80 characters, this array size provides space for the longest possible input line (plus the null
character that gets()
adds at the end).
The gets() function has a return value. gets() returns a pointer to type char with the address
where the input string is stored. This is the same value that is passed to gets(), but having
the value returned to the program in this way lets your program test for a blank line.
Using the gets() return value to test for the input of a blank line.
/* Demonstrates using the gets() return value. */
#include <STDIO.H>
main()
{
/* Display instructions. */
return 0;
}
Enter text a line at a time, then press Enter.
Enter a blank line when done.
First string
You entered First string
Two
You entered Two
Asfia Firdaus
You entered Asfia Firdaus
Thank you and good-bye
If we enter a blank line (that is, if we simply press Enter) in response to line 18, the string
(which contains 0 characters) is still stored with a null character at the end. Because the
string has a length of 0, the null character is stored in the first position. This is the position
pointed to by the return value of gets(), so if we test that position and find a null character,
we know
that a blank line was entered.
The last parameter, FILE *fp, is used to specify the input stream. Simply specify the
standard input stream, stdin, as the stream argument.
The pointer str indicates where the input string is stored. The argument n specifies the
maximum number of characters to be input. The fgets() function reads characters from the
input stream until a newline or end-of-line is encountered or n – 1 characters have been
read. The newline is included in the string and terminated with a \0 before it is stored. The
return values of fgets() are the
same as described earlier for gets().
Strictly speaking, fgets() doesn’t input a single line of text (if you define a line as a
sequence of characters ending with a newline). It can read less than a full line if the line
contains more than n -1 characters. When used with stdin, execution doesn’t return from
fgets() until you press Enter, but only the first n-1 characters are stored in the string. The
newline is included in the string only if it falls within the first n-1 characters.
#include <STDIO.H>
#define MAXLEN 10
main()
{
char buffer[MAXLEN];
while (1)
{
fgets(buffer, MAXLEN, stdin);
if (buffer[0] == `\n')
break;
puts(buffer);
}
return 0;
}
Enter text a line at a time; enter a blank to exit.
Roses are red
Roses are
red
Violets are blue
Violets a
re blue
Programming in C
Programmi
ng in C
Is for people like you!
Is for pe
ople like
you!
Line 15 contains the fgets() function. When running the program, enter lines of length less
than and greater than MAXLEN to see what happens. If a line greater than MAXLEN is
entered, the first MAXLEN – 1 characters are read by the first call to fgets(); the remaining
characters remain in the keyboard buffer and are read by the next call to fgets() or any other
function that reads from stdin. The program exits when a blank line is entered (lines 17 and
18).
Formatted Input
The input functions covered up to this point have simply taken one or more characters from
an input stream and put them somewhere in memory. No interpretation or formatting of the
input has been done, and you still have no way to input numeric variables. For example,
how would you input the value 12.86 from the keyboard and assign it to a type float
variable? Enter the scanf() and fscanf() functions.
These two functions are identical, except that scanf() always uses stdin, whereas the user
can specify the input stream in fscanf(). This section covers scanf(); fscanf() generally is
used with disk file input.
scanf("%d", &x);
The first argument, “%d”, is the format string. In this case, %d tells scanf() to look for one
signed integer value. The second argument uses the address-of operator (&) to tell scanf()
to assign the input value to the variable x.
The scanf() format string can contain the following:
1. Spaces and tabs, which are ignored (they can be used to make the format string
more readable).
2. Characters (but not %), which are matched against non-white-space characters in
the input.
3. One or more conversion specifications, which consist of the % character followed
by special characters. Generally, the format string contains one conversion
specification for each variable.
The only required part of the format string is the conversion specifications. Each
conversion specification begins with the % character and contains optional and required
components in a
certain order. The scanf() function applies the conversion specifications in the format
string, in order, to the input fields. An input field is a sequence of non-white-space
characters that ends when the next white space is encountered or when the field width, if
specified, is reached. The conversion specification components include the following:
1. The optional assignment suppression flag (*) immediately follows the %. If present,
this character tells scanf() to perform the conversion corresponding to the current
conversion specifier but to ignore the result (not assign it to any variable).
2. The next component, the field width, is also optional. The field width is a decimal
number specifying the width, in characters, of the input field. In other words, the
field width specifies how many characters from stdin scanf() should examine for the
current conversion. If a field width isn’t specified, the input field extends to the next
white space.
3. The next component is the optional precision modifier, a single character that can be
h, l, or L. If present, the precision modifier changes the meaning of the type
specifier that follows it.
4. The only required component of the conversion specifier (besides the %) is the type
specifier. The type specifier is one or more characters that tell scanf() how to
interpret the input. These characters are listed and described in the table given
below. The Argument column lists the required type of the corresponding variable.
For example, the type specifier d requires int * (a pointer to type int).
Before seeing some examples of scanf(), we need to understand the precision modifiers.
The precision
modifiers.
Precision
Meaning
Modifier
When placed before the type specifier d, i, o, u, or x, the modifier h specifies
h that the argument is a pointer to type short instead of type int. On a PC, the
type short is the same as type int, so the h precision modifier is never needed.
When placed before the type specifier d, i, o, u, or x, the modifier l specifies
that the argument is a pointer to type long. When placed before the type
l
specifier e, f, or g, the modifier l specifies that the argument is a pointer to
type double.
When placed before the type specifier e, f, or g, the modifier L specifies that
L
the argument is a pointer to type long double.
When a call to scanf() is executed and the user has entered a single line, we can have three
situations. For these examples, assume that scanf(“%d %d”, &x, &y); is being executed; in
other words, scanf() is expecting two decimal integers. Here are the possibilities:
1. The line the user inputs matches the format string. For example, suppose the user
enters 12 14 followed by Enter. In this case, there are no problems.
2. scanf() is satisfied, and no characters are left over in stdin. The line that the user
inputs has too few elements to match the format string. For example, suppose the
user enters 12 followed by Enter. In this case, scanf() continues to wait for the
missing input. Once the input is received, execution continues, and no characters are
left over in stdin.
3. The line that the user enters has more elements than required by the format string.
For example, suppose the user enters 12 14 16 followed by Enter. In this case,
scanf() reads the 12 and the 14 and then returns. The extra characters, the 1 and the
6, are left waiting in stdin.
It is this third situation (specifically, those leftover characters) that can cause problems.
They remain waiting for as long as the program is running, until the next time the program
reads input from stdin. Then the leftover characters are the first ones read, ahead of any
input the user makes at the time. It’s clear how this could cause errors. For example, the
following code asks the user to input an integer and then a string:
Say, for example, that in response to the first prompt, the user decides to be precise and
enters 21.00 and then presses Enter. The first call to scanf() is looking for an integer, so it
reads the characters 21 from stdin and assigns the value 21 to the variable age. The
characters .00 are left waiting in stdin. The next call to scanf() is looking for a string. It
goes to stdin for input and finds .00 waiting there. The result is that the string .00 is
assigned to name.
A solution is to make sure there are no extra characters waiting in stdin before prompting
the user for input. We can do this by calling gets(), which reads any remaining characters
from stdin, up to and including the end of the line. Rather than calling gets() directly from
the program, we can put it in a separate function with the descriptive name of clear_kb().
#include <STDIO.H>
void clear_kb(void);
main()
{
int age;
char name[20];
clear_kb();
return 0;
}
void clear_kb(void)
When running this, enter some extra characters after the age, before pressing Enter. Make
sure the program ignores them and correctly prompts for the name. Then modify the
program by removing the call to clear_kb(), and run it again. Any extra characters entered
on the same line as your age are assigned to name
There is a second way through which we can clear the extra characters that were typed in.
The fflush() function flushes the information in a stream–including the standard input
stream. fflush() is generally used with disk files.
The next program uses the fflush() function instead of the clear_kb() function.
main()
{
int age;
char name[20];
return 0;
}
Enter your age.
21 and never older LOL!
Enter your first name.
Asfia
Your age is 21.
Your name is Asfia.
As can be seen in line 15, the fflush() function is being used. The prototype for the fflush()
function is as follows:
The stream is the stream to be flushed. In the above function, the standard input stream,
stdin, is being passed for stream.
scanf() Examples
It’s a powerful function, but it can be a bit confusing at times. Try it and see what happens.
Compile and run this program and then experiment by making changes to the scanf()
format strings.
//---------------------
//Output of the Program
//---------------------
This program starts by defining several variables in lines 9 through 13 for data input. The
program then goes through various types of data. Lines 17 through 21 print long integers
and a double. Line 23 calls the fflush() function to clear any unwanted characters from the
standard input stream. Lines 27 and 28 get the next value, a five-character integer. Because
there are width specifiers, the five-digit integer is split into two integers–one that is two
characters, and one that is three characters. Line 34 calls fflush() to clear the keyboard
again. The final example, in lines 36 through 44, uses the exclude character. Line 40 uses
“%[^ ]%s”, which tells scanf() to get a string but to stop at any spaces. This effectively
splits the input.
Play with this program, change it around a bit and see what happens ?
The scanf() function can be used for most of the input needs, particularly those involving
numbers (strings can be input more easily with gets()).
Screen Output
Screen output functions are divided into three general categories along the
same lines as the input functions.
1. Character output
2. Line output
3. Formatted output
This function writes the character stored in C to stdout. Although the prototype specifies a
type int argument, we pass putchar() a type char. We can also pass it a type int as long as its
value is appropriate for a character (that is, in the range 0 to 255). The function returns the
character that was just written, or EOF if an error has occurred.
#include <STDIO.H…
main()
{
int count;
return 0;
}
These two functions perform the same action–sending a single character to a specified
stream. putc() is a macro implementation of fputc().Its prototype is
The FILE *fp part might puzzle you. If wespecify stdout as the stream, fputc() behaves
exactly the same as putchar(). Thus, the following two statements are equivalent:
putchar(`x');
fputc(`x', stdout);
#include <STDIO.H>
main()
{
int x;
return 0;
}
This
is
a
short
message.
And this is the end!
This program declares an array of pointers. Lines 13 and 14 print each of the strings stored
in the message array.
The two functions printf() and fprintf() are identical, except that printf() always sends
output to stdout, whereas fprintf() specifies the output stream. fprintf() is generally used for
output to disk files.
The printf() function takes a variable number of arguments, with a minimum of one. The
first and only required argument is the format string, which tells printf() how to format the
output. The optional arguments are variables and expressions whose values we want to
display. Take a look at these simple examples:
1. The statement printf(“Hello, world.”); displays the message Hello, world. on-screen.
This is an example of using printf() with only one argument, the format string. In
this case, the format string contains only a literal string to be displayed on-screen.
2. The statement printf(“%d”, i); displays the value of the integer variable i on-screen.
The format string contains only the format specifier %d, which
tells printf() to display a single decimal integer. The second argument is the name of
the variable whose value is to be displayed.
3. The statement printf(“%d plus %d equals %d.”, a, b, a+b); displays 2 plus 3 equals
5 on-screen (assuming that a and b are integer variables with the values of 2 and 3,
respectively). This use of printf() has four arguments: a format string that contains
literal text as well as format specifiers, and two variables and an expression whose
values are to be displayed.
1. Zero, one, or more conversion commands that tell printf() how to display a value in
its argument list. A conversion command consists of % followed by one or more
characters.
2. Characters that are not part of a conversion command and are displayed as-is.
The third example’s format string is %d plus %d equals %d. In this case, the three %ds are
conversion commands, and the remainder of the string, including the spaces, is literal
characters that are displayed directly.
Now we can discuss the conversion command. The components of the command are given
here and explained next. Components in brackets are optional.
%[flag][field_width][.[precision]][l]conversion_char
The conversion_char is the only required part of a conversion command (other than the %).
Table lists the conversion characters and their meanings.
We can place the l modifier just before the conversion character. This modifier applies only
to the conversion characters o, u, x, X, i, d, and b. When applied, this modifier specifies
that the argument is a type long rather than a type int. If the l modifier is applied to the
conversion characters e, E, f, g, or G, it specifies that the argument is a type double. If an l
is placed before any other conversion character, it is ignored.
The precision specifier consists of a decimal point (.) by itself or followed by a number. A
precision specifier applies only to the conversion characters e, E, f, g, G, and s. It specifies
the number of digits to display to the right of the decimal point or, when used with s, the
number of characters to output. If the decimal point is used alone, it specifies a precision of
0.
The field-width specifier determines the minimum number of characters output. The field-
width specifier can be the following:
1. A decimal integer not starting with 0. The output is padded on the left with spaces
to fill the designated field width.
2. A decimal integer starting with 0. The output is padded on the left with zeros to fill
the designated field width.
3. The * character. The value of the next argument (which must be an int) is used as
the field width. For example, if w is a type int with a value of 10, the statement
printf(“%*d”, w, a); prints the value of a with a field width of 10.
If no field width is specified, or if the specified field width is narrower than the output, the
output field is just as wide as needed.
The last optional part of the printf() format string is the flag, which immediately follows the
% character. There are four available flags:
?-? This means that the output is left-justified in its field rather than right-justified, which is
the default.
?+? This means that signed numbers are always displayed with a leading + or -.
?#? This applies only to x, X, and o conversion characters. It specifies that nonzero
numbers are displayed with a leading 0X or 0x (for x and X) or a leading 0 (for o).
When we use printf(), the format string can be a string literal enclosed in double quotes in
the printf() argument list. It can also be a null-terminated string stored in memory, in
which case we pass a pointer to the string to printf(). For example, this statement:
The printf() format string can contain escape sequences that provide special control over
the output. Table below lists the most frequently used escape sequences. For example,
including the newline sequence (\n) in a format string causes subsequent output to appear
starting on the next screen line
printf() is somewhat complicated. The best way to learn how to use it is to look at examples
and then experiment on your own but don?t be alarmed, it?s easy ?
Some ways to use the printf() function.
/* Demonstration of printf(). */
#include <STDIO.H>
main()
{
float d1 = 10000.123;
int n, f;
printf("%5f\n", d1);
printf("%10f\n", d1);
printf("%15f\n", d1);
printf("%20f\n", d1);
printf("%25f\n", d1);
printf("%05f\n", d1);
printf("%010f\n", d1);
printf("%015f\n", d1);
printf("%020f\n", d1);
printf("%025f\n", d1);
puts("\n Press Enter to continue...");
fflush(stdin);
getchar();
return 0;
}
Outputting a number with different field widths.
10000.123047
10000.123047
10000.123047
10000.123047
10000.123047
Press Enter to continue...
Use the * field width specifier to obtain field width
from a variable in the argument list.
10000.123047
10000.123047
10000.123047
10000.123047
10000.123047
Press Enter to continue...
Include leading zeros.
10000.123047
10000.123047
00010000.123047
0000000010000.123047
000000000000010000.123047
Press Enter to continue...
Display in octal, decimal, and hexadecimal.
Use # to precede octal and hex output with 0 and 0X.
Use - to left-justify each value in its field.
First display column labels.
Decimal Octal Hexadecimal
1 01 0X1
2 02 0X2
3 03 0X3
4 04 0X4
5 05 0X5
6 06 0X6
7 07 0X7
8 010 0X8
9 011 0X9
10 012 0XA
11 013 0XB
12 014 0XC
13 015 0XD
14 016 0XE
15 017 0XF
16 020 0X10
17 021 0X11
18 022 0X12
19 023 0X13
Press Enter to continue...
Use the %n conversion command to count characters.
BinaryDecimalOctalHexadecimal
The last printf() output 29 characters.
1. Output sent to stdout can be sent to a disk file or the printer rather than to the
screen.
2. Program input from stdin can come from a disk file rather than from the keyboard.
We don’t code redirection into our programs; we specify it on the command line$ when we
run the program. In DOS, as in UNIX, the symbols for redirection are < and >.
Remember the first C program, HELLO.C? It used the printf() library function to display
the message Hello, world on-screen. As we now know, printf() sends output to stdout, so it
can be redirected. When we enter the program name at the command-line prompt, follow it
with the > symbol and the name of the new destination:
hello > destination
Thus, if we enter hello >prn, the program output goes to the printer instead of to the screen
(prn is the DOS name for the printer attached to port LPT1:). If we enter hello >hello.txt,
the output is placed in a disk file with the name HELLO.TXT.
When we redirect output to a disk file, be careful. If the file already exists, the old copy is
deleted and replaced with the new file. If the file doesn’t exist, it is created. When
redirecting output to a file, we can also use the >> symbol. If the specified destination file
already exists, the program output is appended to the end of the file.
#include <stdio.h>
main()
{
char buf[80];
gets(buf);
printf("The input was: %s\n", buf);
return 0;
}
This program accepts a line of input from stdin and then sends the line to stdout, preceding
it with The input was:. After compiling and linking the program, run it without redirection
(assuming that the program is named TRIAL) by entering TRIAL at the command-line
prompt. If we then enter I am teaching myself C, the program displays the following on-
screen:
If we run the program by entering TRIAL >test.txt and make the same entry, nothing is
displayed on-screen. Instead, a file named TEST.TXT is created on the disk. If we use the
DOS TYPE (or an equivalent) command to display the contents of the file:
type test.txt
We’ll see that the file contains only the line The input was: I am teaching myself C.
Similarly, if we had run the program by entering TRIAL >prn, the output line would have
been printed on the printer (prn is a DOS command name for the printer).
Just for the sake of it run the program again, this time redirecting output to TEST.TXT with
the >> symbol. Instead of the file’s getting replaced, the new output is appended to the end
of TEST.TXT. Give it a try ?
Redirecting Input
First we need a source file. Use the editor to create a file named INPUT.TXT that contains
the single line COMSATS Abbottabad. Now run the previous program by entering the
following at the DOS prompt:
The program doesn’t wait for you to make an entry at the keyboard. Instead, it immediately
displays the following message on-screen:
The stream stdin was redirected to the disk file INPUT.TXT, so the program’s call to gets()
reads one line of text from the file rather than the keyboard.
We can redirect input and output at the same time. Try running the program with the
following command to redirect stdin to the file INPUT.TXT and redirect stdout to
JUNK.TXT:
Redirecting stdin and stdout can be useful in certain situations. A sorting program, for
example, could sort either keyboard input or the contents of a disk file. Likewise, a mailing
list program could display addresses on-screen, send them to the printer for mailing labels,
or place them in a file for some other use.
Using stderr
One of C’s predefined streams is stderr (standard error). A program’s error messages
traditionally are sent to the stream stderr and not to stdout. Output to stdout can be
redirected to a destination other than the display screen. If stdout is redirected, the user
might not be aware of any error messages the program sends to stdout. Unlike stdout, stderr
can’t be redirected and is always connected to the screen (at least in DOS–UNIX systems
might allow redirection of stderr). By directing error messages to stderr, we can be sure the
user always sees them. We do this with fprintf():
We can write a function to handle error messages and then call the function when an error
occurs rather than calling fprintf():
error_message("An error has occurred.");
void error_message(char *msg)
{
fprintf(stderr, msg);
}
By using our own function instead of directly calling fprintf(), we provide additional
flexibility (one of the advantages of structured programming). For example, in special
circumstances we might want a program’s error messages to go to the printer or a disk file.
All we need to do is modify the error_message() function so that the output is sent to the
desired destination.
This output is printed by the printer. It won’t appear on-screen If DOS system has a printer
connected to port LPT1:, we can compile and run this program. It prints three lines on the
page. Line 14 sends an “\f” to the printer. \f is the escape sequence for a form feed, the
command that causes the printer to advance a page (or, in the case of a laser printer, to eject
the current page).
DOs and DON?Ts
1. DO use fprintf() to create programs that can send output to stdout, stderr, stdprn, or
any other stream.
2. DO use fprintf() with stderr to print error messages to the screen.
3. DO take advantage of the standard input/output streams that C provides.
4. DO understand the difference between echoed and nonechoed input.
5. DO understand the difference between buffered and unbuffered input
6. DO create functions such as error_message to make your code more structured and
maintainable.
7. DO take advantage of extended characters in your programs. When using extended
characters, you should try to be consistent with other programs.
8. DO use the gets() and scanf() functions instead of the fgets() and fscanf() functions
if you’re using the standard input file (stdin) only.
9. DON’T use stderr for purposes other than printing error messages or warnings.
10. DON’T ever try to redirect stderr.
11. DON’T use non-ANSI standard functions if portability is a concern
12. DON’T rename or change the standard streams unnecessarily.
13. DON’T try to use an input stream such as stdin for an output function such as
fprintf().
14. DON’T forget to check the input stream for extra characters.
Input from the keyboard arrives from the stream stdin. Using C’s standard library functions,
you can accept keyboard input character by character, a line at a time, or as formatted
numbers and strings. Character input can be buffered or unbuffered, echoed or unechoed.
Output to the display screen is normally done with the stdout stream. Like input, program
output can be by character, by line, or as formatted numbers and strings. For output to the
printer, you use fprintf() to send data to the stream stdprn.
When you use stdin and stdout, you can redirect program input and output. Input can come
from a disk file rather than the keyboard, and output can go to a disk file or to the printer
rather than to the display screen.
Finally, you learned why error messages should be sent to the stream stderr instead of
stdout. Because stderr is usually connected to the display screen, you are assured of seeing
error messages even when the program output is redirected.
These relational operators compare two values and return true or false after comparison.
We can use the relational operators to compare values of any basic data type, so all we need
is to modify the behavior of the program.
“The relational operators compare two values of any basic data type and return true or false
after comparison.”
The if statement by itself will execute a single statement or a group of statements when the
condition following if is true
If the condition is false then a group of statements can be executed using else statement
if(varName == 20)
printf ("Value of the variable is 20");
We can use the block to specify the statements to pre executed if the given condition is true
if(varName == 20){
printf ("Value of the variable is 20");
printf ("Print what ever you want!!!");
}
The for statement is started with the keyword for . There are three expressions which
appear with in a for statement.
1. Initializing Expression
2. Test Expression
3. Increment Expression
The while loop continues untill the specified condition is true. The general form of while
loop is
while(condition)
loop statement
The do-while loop is similar to the while loop in that the loop continues as long as the
specified loop condition remains true. The main difference is that the condition is checked
at the end of the do-while statement. So do-while loop is always executed at least once. Its
general form is
do{
loop statement
}while(condition)
The if Statement
The general form of if statement looks like this:
Here the keyword if tells the compiler that what follows, is a decision control instruction.
The condition following the keyword if is always enclosed within a pair of parentheses. If
the condition, whatever it is true, then the statement is executed. It the condition is not true
then the statement is not executed instead the program skips past it. The condition in C is
evaluated using C?s relational operators. The relational operators help us to build
expression which are either true or false
for e.q
X == Y X is equal to Y
X != Y X is not equal to Y
X >Y X is greater than Y
X <= Y X is less than or equal to Y
X >= Y X is greater than or equal to Y
Demonstration of if statement
main( )
{
int num;
Printf("Enter a number less than 10");
Scanf("%d", & num);
if(num < = 10)
Printf("The number is less than 10");
}
/* calculation of bonus */
main( )
{
int bonus, CY, Yoj, yr-of-ser;
Printf("Enter current year and year of joining");
Scanf("%d %d", Scy, Syoj);
yr-of-ser = CY-Yoj;
if(yr-ofser > 3)
{
bonus = 2500;
Printf("Bonus = Rs. %d", bonus);
}
}
If – Else statement
The if statement by itself will execute a single statement or a group of statements when the
condition following if is true. it does nothing when the condition is false. It the condition is
false then a group of statements can be executed using else statement. The following
program illustrates this
if (condition)
{
if (condition)
{
do this;
else
{
do this;
and this;
}
}
else
do this;
The parentheses after the while contains a condition so long as this condition remains true
all statements within the body of the while loop keep getting executed repeatedly for e.g.
do
{
this;
and this;
and this;
and this;
} while (this condition is true);
There is a minor difference between the working of while and do-while loops. The
difference is the place where the condition is tested. The while tests the condition before
executing any of the statements within the while loop. As against this the do-while tests the
condition after having executed the statements within the loop. for e.g.
main( )
{
while(5<1)
printf("Hello ");
}
In the above e.q. the printf will not get executed at all since the condition fails at the first
time itself. Now let?s now write the same program using a do-while loop.
main( ) {
do {
Printf ("itello ");
}
while
(5<1);
}
In the above program the printf( ) would be executed once, since first the body of the loop
us executed and then the condition is tested.
Now let us write the simple interest problem using the for loop
Logic: To test a number is prime or not, is to divide it successively by all numbers from 2
to one less than itself. It the remainder of any of the divisions is zero, the number is not a
prime. Following program implements this logic
main( )
{
int num, i;
printf("Enter a number");
scanf("%d", &num);
i=2
while (i < = num -1)
{
if (num%i= = 0)
{
printf("Not a prime number");
break;
}
i++
}
if(i = = num)
printf("Prime number");
}
main( )
{
int i,j;
for(i = 1; i< = 2; i++)
{
for(j=1; j<=2; j++)
{
if (i= =j)
continue;
printf("%d%d", i,j);
}
}
}
12
21
when the value of i equal to that of j, the continue statement takes the control to the for loop
(inner) bypassing rest of the statements pending execution in the for loop (inner).
What is a File?
Abstractly, a file is a collection of bytes stored on a secondary storage device, which is
generally a disk of some kind. The collection of bytes may be interpreted, for example, as
characters, words, lines, paragraphs and pages from a textual document; fields and records
belonging to a database; or pixels from a graphical image. The meaning attached to a
particular file is determined entirely by the data structures and operations used by a
program to process the file. It is conceivable (and it sometimes happens) that a graphics file
will be read and displayed by a program designed to process textual data. The result is that
no meaningful output occurs (probably) and this is to be expected. A file is simply a
machine decipherable storage media where programs and data are stored for machine
usage.
Essentially there are two kinds of files that programmers deal with text files and binary
files. These two classes of files will be discussed in the following sections.
Similarly, since text files only process characters, they can only read or write data one
character at a time. (In C Programming Language, Functions are provided that deal with
lines of text, but these still essentially process data one character at a time.) A text stream in
C is a special kind of file. Depending on the requirements of the operating system, newline
characters may be converted to or from carriage-return/linefeed combinations depending on
whether data is being written to, or read from, the file. Other character conversions may
also occur to satisfy the storage requirements of the operating system. These translations
occur transparently and they occur because the programmer has signalled the intention to
process a text file.
Binary files
A binary file is no different to a text file. It is a collection of bytes. In C Programming
Language a byte and a character are equivalent. Hence a binary file is also referred to as a
character stream, but there are two essential differences.
1. No special processing of the data occurs and each byte of data is transferred to or
from the disk unprocessed.
2. C Programming Language places no constructs on the file, and it may be read from,
or written to, in any manner chosen by the programmer.
Binary files can be either processed sequentially or, depending on the needs of the
application, they can be processed using random access techniques. In C Programming
Language, processing a file using random access techniques involves moving the current
file position to an appropriate place in the file before reading or writing data. This indicates
a second characteristic of binary files.
They a generally processed using read and write operations simultaneously.
For example, a database file will be created and processed as a binary file. A record update
operation will involve locating the appropriate record, reading the record into memory,
modifying it in some way, and finally writing the record back to disk at its appropriate
location in the file. These kinds of operations are common to many binary files, but are
rarely found in applications that process text files.
The file name is any valid DOS file name, and can be expressed in upper or lower case
letters, or even mixed if you so desire. It is enclosed in double quotes. For this example we
have chosen the name TENLINES.TXT. This file should not exist on your disk at this time.
If you have a file with this name, you should change its name or move it because when we
execute this program, its contents will be erased. If you don’t have a file by this name,
that is good because we will create one and put some data into it. You are permitted to
include a directory with the file name.The directory must, of course, be a valid directory
otherwise an error will occur. Also, because of the way C handles literal strings, the
directory separation character \ must be written twice. For example, if the file is to be stored
in the \PROJECTS sub directory then the file name should be entered as
“\\PROJECTS\\TENLINES.TXT”. The second parameter is the file attribute and can be
any of three letters, r, w, or a, and must be lower case.
Reading (r)
When an r is used, the file is opened for reading, a w is used to indicate a file to be used for
writing, and an a indicates that you desire to append additional data to the data already in an
existing file. Most C compilers have other file attributes available; check your Reference
Manual for details. Using the r indicates that the file is assumed to be a text file. Opening a
file for reading requires that the file already exist. If it does not exist, the file pointer will be
set to NULL and can be checked by the program.
Here is a small program that reads a file and display its contents on screen.
When a file is opened for writing, it will be created if it does not already exist and it will be
reset if it does, resulting in the deletion of any data already there. Using the w indicates that
the file is assumed to be a text file.
Here is the program to create a file and write some data into the file.
#include <stdio.h>
int main()
{
FILE *fp;
file = fopen("file.txt","w");
/*Create a file and add text*/
fprintf(fp,"%s","This is just an example :)"); /*writes data to the file*/
fclose(fp); /*done!*/
return 0;
}
Appending (a)
When a file is opened for appending, it will be created if it does not already exist and it will
be initially empty. If it does exist, the data input point will be positioned at the end of the
present data so that any new data will be added to any data that already exists in the file.
Using the a indicates that the file is assumed to be a text file.
Here is a program that will add text to a file which already exists and there is some text in
the file.
#include <stdio.h>
int main()
{
FILE *fp
file = fopen("file.txt","a");
fprintf(fp,"%s","This is just an example :)"); /*append some text*/
fclose(fp);
return 0;
}
Closing a file
To close a file you simply use the function fclose with the file pointer in the parentheses.
Actually, in this simple program, it is not necessary to close the file because the system will
close all open files before returning to DOS, but it is good programming practice for you to
close all files in spite of the fact that they will be closed automatically, because that would
act as a reminder to you of what files are open at the end of each program.
You can open a file for writing, close it, and reopen it for reading, then close it, and open it
again for appending, etc. Each time you open it, you could use the same file pointer, or you
could use a different one. The file pointer is simply a tool that you use to point to a file and
you decide what file it will point to. Compile and run this program. When you run it, you
will not get any output to the monitor because it doesn’t generate any. After running it,
look at your directory for a file named TENLINES.TXT and type it; that is where your
output will be. Compare the output with that specified in the program; they should agree!
Do not erase the file named TENLINES.TXT yet; we will use it in
some of the other examples in this section.
Now for our first program that reads from a file. This program begins with the familiar
include, some data definitions, and the file opening statement which should require no
explanation except for the fact that an r is used here because we want to read it.
#include <stdio.h>
main( )
{
FILE *fp;
char c;
funny = fopen("TENLINES.TXT", "r");
if (fp == NULL)
printf("File doesn't exist\n");
else {
do {
c = getc(fp); /* get one character from the file
*/
putchar(c); /* display it on the monitor
*/
} while (c != EOF); /* repeat until EOF (end of file)
*/
}
fclose(fp);
}
In this program we check to see that the file exists, and if it does, we execute the main body
of the program. If it doesn’t, we print a message and quit. If the file does not exist, the
system will set the pointer equal to NULL which we can test. The main body of the
program is one do while loop in which a single character is read from the file and output to
the monitor until an EOF (end of file) is detected from the input file. The file is then closed
and the program is terminated. At this point, we have the potential for one of the most
common and most perplexing problems of programming in C. The variable returned from
the getc function is a character, so we can use a char variable for this purpose. There is a
problem that could develop here if we happened to use an unsigned char however, because
C usually returns a minus one for an EOF – which an unsigned char type variable is not
capable of containing. An unsigned char type variable can only have the values of zero to
255, so it will return a 255 for a minus one in C. This is a very frustrating problem to try to
find. The program can never find the EOF and will therefore never terminate the loop. This
is easy to prevent: always have a char or int type variable for use in returning an EOF.
There is another problem with this program but we will worry about it when we get to the
next program and solve it with the one following that.
After you compile and run this program and are satisfied with the results, it would be a
good exercise to change the name of TENLINES.TXT and run the program again to see
that the NULL test actually works as stated. Be sure to change the name back because we
are still not finished with TENLINES.TXT.
File Handling
In C++ we say data flows as streams into and out of programs. There are different kinds of
streams of data flow for input and output. Each stream is associated with a class, which
contains member functions and definitions for dealing with that particular kind of flow. For
example, the if stream class represents the input disc files,. Thus each file in C++ is an
object of a particular stream class.
Stream classes
The ios class is the base class for the entire I/O hierarchy. It contains many constants and
member functions common to input and output operations of all kinds. The istream and
ostream classes are derived from ios and are dedicated to input and output respectively
Their member functions perform both formatted and unformatted operations. The iostream
class is derived from both istream and ostream by multiple inheritance, so that other classes
can inherit both of these classes from it. The classes in which we are most interested for file
I/O are ifstream for input files ofsteam for output files and fstream for files that will be used
for both input and output the ifstream and ofsteam classes are declared in the FSTREAM.H.
file.
getline( )
getine( )
read( )
Put( )
write( )
In the above program, we create an object called outfile, which is a member of the output
file stream class. We initialise it to the filename “fl.fil”. You can think of outfile as a user-
chosen logical name which is associated with the real file on disc called “fl.fil”. When any
automatic object (outfile is automatic) is defined in a function, it is created in the function
and automatically destroyed when the function terminates. When our main ( ) function
ends, outfile goes out of scope. This automatically calls the destructor, which closes the
file. It may be noticed that we do not need to close the file explicitly by any close-file
command. The insertion operator << is overloaded in ofsteam and works with objects
defined from ofstream. Thus, we can use it to output txt to the file. The strings are written
in the file “fl. fil? in the ASCII mode. One can see it from DOS by giving the type
command. The file “fl. fil” looks as shown below
What is a buffer?
A buffer is a temporary holding area in memory which acts as an intermediary between a
program and a file or other I/0 device. Information can be transferred between a buffer and
a file using large chunks of data of the size most efficiently handled by devices like disc
drives. Typically, devices like discs transfer information in blocks of 512 bytes or more,
while program often processes information one byte at a time. The buffer helps match these
two desperate rates of information transfer. On output, a program first fills the buffer and
then transfers the entire block of data to a hard disc, thus clearing the buffer for the next
batch of output. C++ handles input by connecting a buffered stream to a program and to its
source of input. similarly, C++ handles output by connecting a buffered stream to a
program and to its output target.
The put ( ) and get( ) functions are also members of ostream and istream. These are used to
output and input a single character at a time. The program shown below is intended to
illustrate the use of writing one character at a time in a file.
In this program, the length of the string is found by the strlen( ) function, and the characters
are output using put( function in a for loop. This file is also an ASCII file.
Reading Characters
The program shown below illustrates the reading of characters from a file.
This program uses a class by name employees and an object by name emp. Data can be
written only by the function inside the object. This program creates a binary data file by
name f3.fil.The write( ) function is used for writing. The write( ) function requires two
arguments, the address of the object to be written, and the size of the object in bytes. We
use the size of operator to find the length of the emp object. The address of the object must
be cast to type pointer to char.
It may be noticed that both read( )and write( functions have similar argument. we must
specify the address in which the disc input will be placed. We also use size of to indicate
the number of bytes to be read.