C New Unit-5
C New Unit-5
A pointer is a variable which contains the address in memory of another variable. We can
have a pointer to any variable type.
The unary operator & gives the “address of a variable''. The indirection or dereference
operator * gives the “contents of an object pointed to by a pointer''.
We must associate a pointer to a particular type. We can't assign the address of a short int
to a long int.
Initialization of C Pointer variable
Pointer Initialization is the process of assigning address of a variable to a pointer variable. It
contains the address of a variable of the same data type. In C language address operator &
is used to determine the address of a variable. The & (immediately preceding a variable
name) returns the address of the variable associated with it.
int a = 10;
int *ptr; //pointer declaration
ptr = &a; //pointer initialization
Pointer variable always points to variables of the same datatype. For example:
float a;
int *ptr = &a; // ERROR, type mismatch
int x = 1, y = 2;
int *ip;
ip = & x ;
x 1 y 2 ip 100
100 200 1000
y = *ip;
x 1 y 1 ip 100
100 200 1000
*ip = 3;
x 3 y 1 ip 100
100 200 1000
F i g. 4. 1 P o i nt e r, V a r i a b l e s a n d M e mo ry
Now the assignments x = 1 and y = 2 obviously load these values into the variables.
ip is declared to be a pointer to an integer and is assigned to the address of x (&x). So ip
gets loaded with the value 100.
Next y gets assigned to the contents of ip. In this example ip currently points to
memory location 100 -- the location of x. So y gets assigned to the values of x -- which is 1.
Finally, we can assign a value 3 to the contents of a pointer (*ip).
IMPORTANT: When a pointer is declared it does not point anywhere. You must set it
to point somewhere before you use it. So,
int *ip;
*ip = 100;
will generate an error (program crash!!). The correct usage is:
int *ip;
int x;
ip = &x;
*ip = 100;
++ip;
if Ptr1 and Ptr2 are properly declared and initialized pointers then, 'C' allows adding integers
to a pointer variable.
EX:
int a=5, b=10;
int *Ptr1,*Ptr2;
Ptr1=&a;
Ptr2=&b
If Ptr1 & Ptr2 are properly declared and initialized, pointers then 'C' allows to subtract
integers from pointers. From the above example,
If Ptr1 & Ptr2 are properly declared and initialize pointers, and both points to the elements
of the same type. "Subtraction of one pointer from another pointer is also possible".
NOTE: this operation is done when both pointer variable points to the elements of the same
array.
EX:
P2- P1 (It gives the number of elements between p1 and p2)
Pointer Increment and Scale Factor
We can use increment operator to increment the address of the pointer variable so that it
points to next memory location.
The value by which the address of the pointer variable will increment is not fixed. It
depends upon the data type of the pointer variable.
For Example:
int *ptr;
ptr++;
Int 2 Byte
Float 4 Byte
Double 8 Byte
Write a C program to compute the sum of all elements stored in an array Using
pointers.
Program
/*program to compute sum of all elements stored in an array */
#include<stdio.h>
#include<conio.h>
main ()
{
int a [10], i, sum=0,*p;
printf ("enter 10 elements \n");
for (i=0; i<10; i++)
scanf ("%d", & a[i]);
p = a;
for (i = 0; i<10; i++)
{
sum = sum+(*p);
p++;
}
printf ("the sum is % d", sum);
getch ();
}
Output
enter 10 elements
1
2
3
4
5
6
7
8
9
10
the sum is 55
Write a C program using pointers to determine the length of a character String.
Program
/*program to find the length of a char string */
#include<stdio.h>
#include<conio.h>
main ()
{
char str[20], *ptr ;
int l=0;
printf("enter a string \n");
scanf("%s", str);
ptr=str;
while(*ptr!='\0')
{
l++;
ptr++;
}
printf("the length of the given string is %d \n", l);
}
Output
enter a string
atnyla.com
the length of the given string is 10
Press any key to continue .
#include<stdlib.h>
int main()
{
int x = 4;
float y = 5.5;
//A void pointer
void *ptr;
ptr = &x;
// (int*)ptr - does type casting of void
// *((int*)ptr) dereferences the typecasted
// void pointer variable.
printf("Integer variable is = %d", *( (int*) ptr) );
// void pointer is now float
ptr = &y;
printf("\nFloat variable is= %f", *( (float*) ptr) );
return 0;
}
Another Example
#include"stdio.h"
int main()
{
int i;
char c;
void *the_data;
i = 6;
c = 'a';
the_data = &i;
printf("the_data points to the integer value %d\n", *(int*) the_data);
the_data = &c;
printf("the_data now points to the character %c\n", *(char*) the_data);
return 0;
}
After Swapping:
p = 20
q = 10
Press any key to continue . . .
The address of memory locationmandnare passed to the function swap and the
pointers*aand*baccept those values.
So, now the pointeraandbpoints to the address ofmandnrespectively.
When, the value of pointers are changed, the value in the pointed memory location also
changes correspondingly.
Hence, changes made to*aand*bare reflected inmandnin the main function.
This technique is known as Call by Reference in C programming.
Simple Example of Pointer to Function
Program
#include<stdio.h>
int add(int x, int y)
{
return x+y;
}
int main( )
{
int (*functionPtr)(int, int);
int s;
functionPtr = add; //
s = functionPtr(20, 45);
printf("Sum is %d",s);
getch();
return 0;
}
Output
Sum is 65
Explanation
It is possible to declare a pointer pointing to a function which can then be used as an
argument in another function. A pointer to a function is declared as follows,
type (*pointer-name)(parameter);
Example :
int (*add)(); //legal declaration of pointer to function
int *add(); //This is not a declaration of pointer to function
A function pointer can point to a specific function when it is assigned the name of the
function.
int add(int, int);
int (*s)(int, int);
sr = add;
sr is a pointer to a function sum. Now sum can be called using function pointer s with the
list of parameter.
sr(10, 20);
Function returning Pointer
A function can also return a pointer to the calling function. In this case you must be careful,
because local variables of function doesn't live outside the function. They have scope only
till inside the function. Hence if you return a pointer connected to a local variable, that
pointer be will pointing to nothing when function ends.
Program
This program will check who is larger among two number, it is not for quality checking
#include<stdio.h>
int* checklarger(int*, int*);
void main()
{
int num1 ;
int num2;
int *ptr;
printf("Enter Two number: \n");
scanf("%d %d",&num1,&num2);
ptr = checklarger(&num1, &num2);
printf("%d is larger \n",*ptr);
}
#include<stdio.h>
void checkString(char *a, char *b,
int (*cmp)(const char *, const char *));
int main(void)
{
char strng1[80], strng2[80];
int (*ptr)(const char *, const char *); /* function pointer */
ptr = strcmp; /* assign address of strcmp to ptr */
printf("Enter two strings.\n");
gets(strng1);
gets(strng2);
checkString(strng1,strng2,ptr); /* pass address of strcmp via ptr */
return 0;
}
Output 2:
Enter two strings.
atnyla
atnlla
Testing for equality.
Not Equal
Press any key to continue . . .
Explanation
First, examine the declaration for ptr in main( ). It is shown here:
When the program begins, it assigns ptr the address of strcmp( ), the standard string
comparison function. Next, it prompts the user for two strings, and then it passes pointers
to those strings along with ptr to check( ), which compares the strings for equality. Inside
checkString( ), the expression
(*cmp)(a, b)
calls strcmp( ), which is pointed to by cmp, with the arguments m and n. The parentheses
around *cmp are necessary. This is one way to call a function through a pointer. A second,
simpler syntax, as shown here, can also be used.
cmp(a, b);
The reason that you will frequently see the first style is that it tips off anyone reading your
code that a function is being called through a pointer (that is, that cmp is a function pointer,
not the name of a function). Also, the first style was the form originally specified by C.
Note that you can call checkString( ) by using strcmp( ) directly, as shown here:
The array initialization statement is familiar to us. The second statement, array name x is
the starting address of the array. Let we take a sample memory map as shown in figure
4.2.:
From the figure 4.2 we can see that the starting address of the array is 1000. When x is an
array, it also represents an address and so there is no need to use the (&) symbol before x.
We can write int *p = x in place of writing int *p = &x[0].
The content of p is 1000 (see the memory map given below). To access the value in x[0] by
using pointers, the indirection operator * with its pointer variable p by the notation *p can
be used.
M e mo ry
1000 11 x[ 0]
1002 22 x[ 1]
1004 33 x[ 2]
1006 44 x[ 3]
1008 55 x[ 4]
1010
F i g ur e 4. 2. M e mo ry ma p - Arr ay s
The increment operator ++ helps you to increment the value of the pointer variable by the
size of the data type it points to. Therefore, the expression p++ will increment p by 2 bytes
(as p points to an integer) and new value in p will be 1000 + 2 = 1002, now *p will get you
22 which is x[1].
Consider the following expressions:
*p++;
*(p++);
(*p)++;
How would they be evaluated when the integers 10 & 20 are stored at addresses 1000 and
1002 respectively with p set to 1000.
p++ : The increment ++ operator has a higher priority than the indirection operator * .
Therefore p is increment first. The new value in p is then 1002 and the content at
this address is 20.
*(p++): is same as *p++.
(*p)++: *p which is content at address 1000 (i.e. 10) is incremented. Therefore (*p)++ is
11.
Note that, *p++ = content at incremented address.
Example:
#include <stdio.h>
main()
{
int x[5] = {11, 22, 33, 44, 55};
int *p = x, i; /* p=&x[0] = address of the first element */
for (i = 0; i < 5; i++)
{
printf (“\n x[%d] = %d”, i, *p); /* increment the address*/
p++;
}
}
Output:
x [0] = 11
x [1] = 22
x [2] = 33
x [3] = 44
x [4] = 55
The meanings of the expressions p, p+1, p+2, p+3, p+4 and the expressions *p, *(p+1),
*(p+2), *(p+3), *(p+4) are as follows:
V a ria ble t v[ 0] t v[ 1] t v[ 2] t v[ 3] t v[ 4] t v[ 5]
V alu e ‘O’ ‘ N’ ‘ I’ ‘ D’ ‘ A’ ‘\ 0’
The statement:
char *p = tv; /* or p = &tv[0] */
Assigns the address 1000 to p. Now, we will write a program to find the length of the string
tv and print the string in reverse order using pointer notation.
Example:
#include <stdio.h>
main()
{
int n, i;
char tv[20] = “ONIDA”; /* p = 1000 */
char *p = tv, *q; /* p = &tv[0], q is a pointer */
q = p;
while (*p != ‘\0’) /* content at address of p is not null character */
p++;
n = p - q; /* length of the string */
--p; /* make p point to the last character A in the string */
printf (“\nLength of the string is %d”, n);
printf (“\nString in reverse order: \n”);
for (i=0; i<n; i++)
{
putchar (*p);
p--;
}
}
Output:
Length of the string is 5
String in reverse order: ADINO
Introduction:
C allows the programmer to create custom data types in five different ways. These are:
The structure, which is a collection of variables under one name.
Types created with typedef, which defines a new name for an existing type.
The union, which enables the same piece of memory to be defined as two or more types
of variables.
The enumeration, which is a list of symbols.
The bit-field, a variation of the structure, which allows easy access to the bits of a
word.
Structure:
For example: If I have to write a program to store Student information, which will have
Student's name, age, branch, permanent address, father's name etc, which included string
values, integer values etc, how can I use arrays for this problem, I will require something
which can hold data of different types together. In structure, data is stored in form
of records.
Defining a structure
struct keyword is used to define a structure.
struct defines a new data type which is a collection of primary and derived data
types.
Syntax:
◦ struct [structure_tag]
◦ {
//member variable 1
//member variable 2
//member variable 3 ...
◦ }[structure_variables];
As you can see in the syntax above, we start with the struct keyword, then it's
optional to provide your structure a name, we suggest you to give it a name, then
inside the curly braces, we have to mention all the member variables, which are
nothing but normal C language variables of different types like int, float, array etc.
After the closing curly brace, we can specify one or more structure variables, again
this is optional.
Note: The closing curly brace in the structure type declaration must be followed by a
semicolon(;).
Example of Structure:
◦ struct Student
◦ {
char name[25];
int age;
char branch[10]; //
Char gender; //F for female and M for male
◦ };
Here struct Student declares a structure to hold the details of a student which
consists of 4 data fields, namely name, age, branch and gender.
These fields are called structure elements or members.
Each member can have different datatype, like in this case, name is an array
of char type and age is of int type etc.
Student is the name of the structure and is called as the structure tag.
Declaring Structure Variables
It is possible to declare variables of a structure, either along with structure
definition or after the structure is defined.
Structure variable declaration is similar to the declaration of any normal variable of
any other datatype.
Structure variables can be declared in following two ways:
Declaring Structure variables separately
struct Student
{
char name[25];
int age;
char branch[10];
char gender; //F for female and M for male
}; struct Student S1, S2;
//declaring variables of struct Student
Declaring Structure variables with structure definition
struct Student
{
char name[25];
int age;
char branch[10]; //F for female and M for male
char gender;
}S1, S2;
Here S1 and S2 are variables of structure Student.
Accessing Structure Members
Like a variable of any other datatype, structure variable can also be initialized at
compile time.
struct Patient
{
float height;
int weight;
int age;
Char name[10];
}; struct Patient p1 = { 180.75 , 73, 23, “munwar” }; //initializationor,
struct Patient p1;
p1.height = 180.75; //initialization of each member separately
p1.weight = 73;
p1.age = 23;
P1.gender=‘F’;
Array of Structure
We can pass a structure as a function argument just like we pass any other variable
or an array as a function argument.
Example:
#include<stdio.h>
struct Student
{
char name[10];
int roll;
};
void show(struct Student st);
void main()
{
struct Student std;
printf("\nEnter Student record:\n");
printf("\nStudent name:\t");
scanf("%s", std.name);
printf("\nEnter Student rollno.:\t");
scanf("%d", &std.roll);
show(std);
}
void show(struct Student st)
{
printf("\nstudent name is %s", st.name);
printf("\nroll is %d", st.roll);
}
C Unions
This implies that although a union may contain many members of different types, it
cannot handle all the members at the same time. A union is declared using
the union keyword.
union item
{
int m;
float x;
char c;
}It1;
In the union declared above the member x requires 4 bytes which is largest
amongst the members for a 16-bit machine. Other members of union will share the
same memory address.
Syntax for accessing any union member is similar to accessing structure members,
union test
{
int a;
float b;
char c;
}t;
t.a; //to access members of union t
t.b;
t.c;
Example
#include <stdio.h>
union item
{
int a;
float b;
char ch;
};
int main( )
{
union item it;
it.a = 12;
it.b = 20.2;
it.ch = 'z';
printf("%d\n", it.a);
printf("%f\n", it.b);
printf("%c\n", it.ch);
return 0;
}
Arrays of Unions Variables
Like array of structures we can also create array of unions and access them in similar
way. When array of unions are created it will create each element of the array as
individual unions with all the features of union. That means, each array element will
be allocated a memory which is equivalent to the maximum size of the union
member and any one of the union member will be accessed by array element.
union category
int intClass;
char chrDeptId[10];
};
union category catg [10]; // creates an array of unions with 10 elements of union
type
Members of array of unions are accessed using ‘.’ operator on union variable name
along with the index to specify which array element that we are accessing.
catg[0].intClass = 10;
catg[5].chrDeptId = “DEPT_001”;
Here note that, each element of the union array need not access the same member
of the union. It can have any member of the union as array element at any point in
time. In above example, first element of the union array accesses intClass while 6th
element of union array has chrDeptId as its member.
In the below code, we have union embedded within a structure. We know, the fields of a
union will share memory, so in main program we ask the user which data he/she would like
to store and depending on the user choice the appropriate field will be used. By this way we
can use the memory efficiently.
#include <stdio.h>
struct student
{
union
{ //anonymous union (unnamed union)
char name[10];
int roll;
};
int mark;
};
int main()
{
struct student stud;
char choice;
printf("\n You can enter your name or roll number ");
printf("\n Do you want to enter the name (y or n): ");
scanf("%c",&choice);
if(choice=='y'||choice=='Y')
{
printf("\n Enter name: ");
scanf("%s",stud.name);
printf("\n Name:%s",stud.name);
}
else
{
printf("\n Enter roll number");
scanf("%d",&stud.roll);
printf("\n Roll:%d",stud.roll);
}
printf("\n Enter marks");
scanf("%d",&stud.mark);
printf("\n Marks:%d",stud.mark);
return 0;
}
Output
You can enter your name or roll number Do you want to enter the name (y or n) : y
Enter name: john
Name:john
Enter marks: 45
Marks:45
Structures inside Unions
Example for defining a structure inside union is given below :
#include<stdio.h>
int main() {
struct student
{
char name[30];
int rollno;
float percentage;
};
union details
{
struct student s1;
};
union details set;
printf("Enter details:");
printf("\nEnter name : ");
scanf("%s", set.s1.name);
printf("\nEnter roll no : ");
scanf("%d", &set.s1.rollno);
printf("\nEnter percentage :");
scanf("%f", &set.s1.percentage);
printf("\nThe student details are : \n");
printf("\name : %s", set.s1.name);
printf("\nRollno : %d", set.s1.rollno);
printf("\nPercentage : %f", set.s1.percentage);
return 0;
}
Enumerated Data Types
#include<stdio.h>
enum week
{
Mon=10, Tue, Wed, Thur, Fri=10, Sat=16, Sun
};
enum day
{
Mond, Tues, Wedn, Thurs, Frid=18, Satu=11, Sund
};
int main()
{
printf("The value of enum week: %d\t%d\t%d\t%d\t%d\t%d\t%d\n\n",Mon ,
Tue, Wed, Thur, Fri, Sat, Sun);
printf("The default value of enum day: %d\t%d\t%d\t%d\t%d\t%d\t%d",Mond ,
Tues, Wedn, Thurs, Frid, Satu, Sund);
return 0;
}
Output
The value of enum week: 10111213101617
The default value of enum day: 0123181112
In the above program, two enums are declared as week and day outside the main()
function
In the main() function, the values of enum elements are printed.
enum week
{
Mon=10, Tue, Wed, Thur, Fri=10, Sat=16, Sun
};
enum day
{
Mond, Tues, Wedn, Thurs, Frid=18, Satu=11, Sund
};
int main()
{
printf("The value of enum week: %d\t%d\t%d\t%d\t%d\t%d\t%d\n\n",Mon ,
Tue, Wed, Thur, Fri, Sat, Sun);
printf("The default value of enum day: %d\t%d\t%d\t%d\t%d\t%d\t%d",Mond ,
Tues, Wedn, Thurs, Frid, Satu, Sund);
}
Structure Union
You can use a struct keyword to You can use a union keyword to define a
define a structure. union.
Changing the value of one data Changing the value of one data member
member will not affect other data will change the value of other data
members in structure. members in union.
It enables you to initialize several It enables you to initialize only the first
members at once. member of union.
The total size of the structure is the The total size of the union is the size of
sum of the size of every data the largest data member
member.
It is mainly used for storing various It is mainly used for storing one of the
data types. many data types that are available.
It occupies space for each and every It occupies space for a member having
member written in inner parameters. the highest size written in inner
parameters.
You can retrieve any member at a You can access one member at a time in
time. the union.
Advantages of structure
Here are pros/benefits for using structure:
◦ Structures gather more than one piece of data about the same subject
together in the same place.
◦ It is helpful when you want to gather the data of similar data types and
parameters like first name, last name, etc.
◦ It is very easy to maintain as we can represent the whole record by using a
single name.
◦ In structure, we can pass complete set of records to any function using a
single parameter.
◦ You can use an array of structure to store more records with similar types.
Advantages of union
Here,
are pros/benefits for using union:
◦ It occupies less memory compared to structure.
◦ When you use union, only the last variable can be directly accessed.
◦ Union is used when you have to use the same memory location for two or
more data members.
◦ It enables you to hold data of only one data member.
◦ Its allocated space is equal to maximum size of the data member.
Disadvantages of structure
Files:
File is a bunch of bytes stored in a particular area on some storage devices like
floppy disk, hard disk, magnetic tape and cd-rom etc., which helps for the permanent
storage.
All files are closed automatically when the program terminates, but not when it crashes.
Each stream associated with a file has a file control structure of type FILE.
4.2.1. Streams:
Even though different devices are involved (terminals, disk drives, etc), the buffered file
system transforms each into a logical device called a stream. Because streams are device-
independent, the same function can write to a disk file or to another device, such as a
console. There are two types of streams:
Function Description
Most of these functions begin with the letter "f". The header file stdio.h provides the
prototypes for the I/O function and defines these three types:
typedef unsigned long size_t
typedef unsigned long fpos_t
typedef struct _FILE FILE
stdio.h also defines the following:
EOF -1 /* value returned at end of file */
SEEK_SET 0 /* from beginning of file */
SEEK_CUR 1 /* from current position */
SEEK_END 2 /* from end of file */
The latter three are used with fseek() function which performs random access on a file.
4.2.3. The File Pointer:
C treats a file just like a stream of characters and allows input and output as a
stream of characters. To store data in file we have to create a buffer area. This buffer area
allows information to be read or written on to a data file. The buffer area is automatically
created as soon as the file pointer is declared. The general form of declaring a file is:
FILE *fp;
FILE is a defined data type, all files should be declared as type FILE before they are used.
FILE should be compulsorily written in upper case. The pointer fp is referred to as the
stream pointer. This pointer contains all the information about the file, which is
subsequently used as a communication link between the system and the program.
A file pointer fp is a variable of type FILE that is defined in stdio.h.
4.2.4. Opening a File:
fopen() opens a stream for use, links a file with that stream and returns a pointer
associated with that file. The prototype of fopen() function is as follows:
Where, filename is a pointer to a string of characters that make a valid filename (and may
include a path specification) and mode determines how the file will be opened. The legal
values for mode are as follows:
Value Description
A file may be opened in text or binary mode. In most implementations, in text mode, CR/LF
sequences are translated to newline characters on input. On output, the reverse occurs. No
such translation occurs on binary files.
The following opens a file named TEST for writing:
FILE *fp;
fp = fopen ("test", "w");
However, because fopen() returns a null pointer if an error occurs when a file is opened, this
is better written as:
FILE *fp;
if ((fp = fopen ("test", "w")) == NULL)
{
printf("cannot open file\n");
exit(1);
}
4.2.5. Closing a File:
fclose() closes the stream, writes any data remaining in the disk buffer to the file, does a
formal operating system level close on the file, and frees the associated file control block.
fclose() has this prototype:
int fclose (FILE *fp);
A return value of zero signifies a successful operation. Generally, fclose() will fail only when
a disk has been prematurely removed or a disk is full.
4.2.6. Writing a Character:
Characters are written using putc() or its equivalent fputc(). The prototype for putc() is:
int putc (int ch, FILE *fp);
where ch is the character to be output. For historical reasons, ch is defined as an int, but
only the low order byte is used.
If the putc() operation is successful, it returns the character written, otherwise it returns
EOF.
4.2.7. Reading a Character:
Characters are read using getc() or its equivalent fgetc(). The prototype for getc() is:
int getc(FILE *fp);
For historical reasons, getc() returns an integer, but the high order byte is zero. getc()
returns an EOF when the end of file has been reached. The following code reads a text file
to the end:
do
{
ch = getc (fp);
} while(ch != EOF);
4.2.8. Using feof():
As previously stated, the buffered file system can also operate on binary data. When a file is
opened for binary input, an integer value equal to the EOF mark may be read, causing the
EOF condition. To solve this problem, C includes the function feof(), which determines when
the end of the file is reached when reading binary data.
The prototype is:
int feof (FILE *fp);
The following code reads a binary file until end of file is encountered:
while (! feof (fp))
ch = getc(fp);
Of course, this method can be applied to text files as well as binary files.
4.2.9. Working With Strings - fputs() and fgets():
In addition to getc() and putc(), C supports the related functions fputs() and fgets(), which
read and write character strings. They have the following prototypes:
int fputs (const char *str, FILE *fp);
char *fgets (char *str, int length, FILE *fp);
The function fputs() works like puts() but writes the string to the specified stream. The
fgets() function reads a string until either a newline character is read or length-1 characters
have been read. If a newline is read, it will be part of the string (unlike gets()). The
resultant string will be null-terminated.
4.2.10. rewind ():
rewind() resets the file position indicator to the beginning of the file. The syntax of rewind()
is:
rewind(fptr);
where, fptr is a file pointer.
4.2.11. ferror ():
ferror() determines whether a file operation has produced an error. It returns TRUE if an
error has occurred, otherwise it returns FALSE. ferror() should be called immediately after
each file operation, otherwise an error may be lost.
4.2.12. Erasing Files:
remove () erases a specified file. It returns zero if successful.
4.2.13. Flushing a Stream:
fflush () flushes the contents of an output stream. fflush() writes the contents of any
unbuffered data to the file associated with fp. It returns zero if successful.
size_t fread (void *buffer, size_t num_bytes, size_t count, FILE *fp);
size_t fwrite (const void *buffer, size_t num_bytes, size_t count, FILE *fp);
For fread(), buffer is a pointer to a region of memory which will receive the data from the
file. For fwrite(), buffer is a pointer to the information which will be written. The buffer may
be simply the memory used to hold the variable, for example, &l for a long integer.
fread() returns the number of items read. This value may be less than count if the end of
file is reached or an error occurs. fwrite() returns the number of items written.
One of the most useful applications of fread() and fwrite() involves reading and writing
user-defined data types, especially structures. For example, given this structure:
struct struct_type
{
float balance;
char name[80];
} cust;
The following statement writes the contents of cust:
fwrite (&cust, sizeof(struct struct_type), 1, fp);
4.2.15. fseek() and Random Access I/O:
Random read and write operations may be performed with the help of fseek(), which sets
the file position locator. The prototype is:
int fseek(FILE *fp, long numbytes, int origin);
in which numbytes is the number of bytes from the origin, which will become the new
current position, and origin is one of the following macros defined in stdio.h:
End-of-file SEEK_END
fseek() returns 0 when successful and a non-zero value if an error occurs. fseek() may be
used to seek in multiples of any type of data by simply multiplying the size of the data by
the number of the item to be reached, for example:
fseek (fp, 9*sizeof (struct list), SEEK_SET);
Which seeks the tenth address.
4.2.16. fprint() and fscanf():
fprint() and fscanf() behave exactly like print() and scanf() except that they operate with
files. The prototypes are:
int fprintf (FILE *fp, const char *control_string, ...);
int fscanf (FILE *fp, const char *control_string, ...);
Although these functions are often the easiest way to read and write assorted data, they are
not always the most efficient. Because formatted ASCII data is being written as it would
appear on the screen (instead of in binary), extra overhead is incurred with each call. If
speed or file size is of concern, use fread() and fwrite().
4.2.17. The Standard Streams:
Whenever a C program starts execution, three streams are opened automatically. These
are:
Standard input (stdin)
Standard output (stdout)
Standard error (stderr)
Normally, these streams refer to the console, but they may be redirected by the operating
system to some other device or environment. Because the standard streams are file
pointers, they may be used to provide buffered I/O operations on the console, for example:
putchar(char c)
{
putc(c, stdout);
}
4.3. Command Line Arguments:
Some times it is very useful to pass information into a program when we run it from the
command prompt. The general method to pass information into main() function is through
the use of command line arguments.
A command line argument is the information that follows the program’s name on the
command prompt of the operating system.
The first argument is argc (argument count) must be an integer value, which
represents the number arguments in the command prompt. It will always be at
least one because the name of the program qualifies as the first argument.
The second argument argv (argument vector) is a pointer to an array of strings.
The third argument env (environment data) is used to access the DOS
environmental parameters active at the time the program begins execution.
When an array is used as an argument to function, only the address of the array is passed,
not a copy of the entire array. When you call a function with an array name, a pointer to the
first element in the array is passed into a function. (In C, an array name without as index is
a pointer to the first element in the array).
Each of the command line arguments must be separated by a space or a tab. If you need to
pass a command line argument that contains space, you must place it between quotes as:
“this is one argument”
Dclaration of argv must be done properly, A common method is:
char *argv[];
That is, as a array of undetermined length.
The env parameter is declared the same as the argv parameter, it is a pointer to an array of
strings that contain environmental setting.
Example 4.3.1:
Example 4.3.2:
while(ch != EOF)
{
putchar(ch); /* print on screen */
ch = getc(fp); /* read another char */
}
Example 4.4.2:
Program on feof() to check for EOF condition in Binary Files. Specify filenames for input and
output at command prompt. The program copies the source file to the destination file. feof()
checks for end of file condition. The feof() can also be used for text files.
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
FILE *in, *out; /* file pointers */
char ch;
if(argc != 3)
{
printf("You forgot to enter the filenames\n");
exit(1);
}
if((in=fopen(argv[1], "rb"))==NULL) /* open source file */
{ /* for read binary */
printf("Cannot open source file\n");
exit(1);
}
Example 4.4.3:
Program on fputs(), fgets and rewind(). Strings are entered from keyboard until blank line is
entered. Strings are then written to a file called ‘testfile'. Since gets() does not store the
newline character, ‘\n’ is added before the string is written so that the file can be read more
easily. The file is then rewind, input and displayed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(void)
{
FILE *fp; /* file pointer */
char str[80];
rewind(fp); /* rewind */
while(! feof(fp)) /* read and display file */
{
fgets(str, 79, fp);
printf(str);
}
Example 4.4.4:
Program on fread() and fwrite() (for Data Types Longer than Byte) which writes, then reads
back, a double, an int and a long. Notice how sizeof () is used to determine the length of
each data type. These functions are useful for reading and writing user-defined data types,
especially structures.
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *fp;
double d=12.23;
int i=101;
long l=123023;
if((fp=fopen("testfile", "wb+"))==NULL) /* open for binary read & write */
{
printf("Cannot open file\n");
exit(1);
}
Example 4.4.5:
Program on fprintf() and fscanf(). Reads a string and an integer from the keyboard, writes
them to a file, then reads the file and displays the data. These functions are easy to write
mixed data to files but are very slow compared with fread() and fwrite().
#include <stdio.h>
#include <stdlib.h>
#include <exec/io.h>
void main (void)
{
FILE *fp;
char s[ 80];
int t;
if ((fp=fopen("testfile", "w"))==NULL) /* open for text write */
{
printf ("Cannot open file\n");
exit (1);
}
fscanf (fp,"%s%d",s,&t);
fprintf (stdout, "%s %d\n", s, t);
fclose (fp)
}