fputs() writes the string to the specified file stream starting at the current location, unless the stream is opened in append mode in which case it is written at EOF.
Sample program to simulate DOS COPY command
# include
The fclose() and fcloseall() flush the streams before closing the files. But if you want to flush the contents of streams without closing them, use the fflush() and flushall() functions.
The action of flushing depends upon the file type. A file opened for read will have its input buffer cleared, while a file opened for write will have its output buffer written to the file.
fflush()
Flush the buffer leaving the file stream open. returns 0 on success and EOF on failure.
flushall()
flush all buffers leaving files open. Returns the number of files flushed.
STANDARD STREAMS
Whenever a 'C' program starts execution under DOS five special file streams are opened automatically by the operating system. They are the standard input (stdin), the standard output(stdout), standard error(stderr), standard printer(stdprn) and the standard auxiliary(stdaux). The stdin is assigned to the keyboard, stdout and stderr are assigned to the monitor, stdprn is assigned to the first parallel printer port and stdaux is assigned to the first serial port. They are defined as fixed pointers of type FILE.
main()
{
FILE *in;
char buffer[81],filename[13];
printf("Enter file name to print : ");
gets(filename);
if((in=fopen(filename, "r"))==NULL)
{
fputs("File not found", stderr);
exit(1);
}
while(!feof(in))
{
if(fgets(buffer, 81, in))
{
fputs(buffer, stdprn);
}
} fclose(in);
}
CURRENT ACTIVE POINTER
In order to keep track of the position where I/O operations are to take place, a pointer is maintained in the FILE structure. Whenever a character is read from or written to the stream the current active pointer is advanced. Most of the I/O functions refer to current active pointer and update it after the input or output procedures on the stream.
ftell()
prototype : long int ftell(FILE *fp);
The ftell() returns a long int value which gives the position of current active pointer in the specified stream.
e.g.:- printf("Current position = %ld", ftell(fp));
SETTING CURRENT POSITION
Immediately after opening the stream the current active pointer position is set to zero and points to the first byte of the stream. Whenever a character is read from or written to the stream, the current active pointer is automatically advanced, the pointer may be set to any position other than the current pointer, at any time in the program.
rewind()
prototype : void rewind(FILE *fp);
Rewind() takes the current active pointer back to the beginning of the stream from any point on the stream. This function allows to restart the file without closing the file and reopening it.
fseek()
prototype : int fseek(FILE *fp, long int offset, int origin);
fseek() repositions the current active pointer by a specified number of bytes from either the start, the current position or the end of the stream, depending upon the position specified to the fseek(). The offset is the number of bytes beyond the file location given by origin. Origin must be one of the values 0,1 or 2 which represent three symbolic constants defined in stdio.h as follows
SEEK_SET or 0 - Beginning of file
SEEK_CUR or 1 - Current file pointer position
SEEK_END or 2 - End-of-file
A return value of zero means fseek() succeeded and non-zero value means failure.
e.g.:- fseek(fp, 0L, SEEK_SET);
The above example takes the pointer to the beginning of the stream which is equivalent to rewind(fp);
The offset may be positive, meaning move forwards or negative meaning move backwards.
e.g.:-
fseek(fp, 0L, 0); - go to beginning(rewind)
fseek(fp, 0L, 1); - stay at the current position
fseek(fp, 0L, 2); - go to the end-of-file, past the last character of the file
fseek(fp, 10L, 0); - move to 11th byte in the file
fseek(fp, 10L, 1); - move forward by 10 bytes
fseek(fp, -m, 1); - go backward by m bytes from the current position
fseek(fp, -m, 2); - go backward by m bytes from the end
When the operation is successful, fseek() returns a zero. If the program attempts to move the file pointer beyond the file boundaries an error occurs and fseek returns -1(non-zero).
fprintf() and fscanf()
The functions fprintf and fscanf perform I/O operations that identical to the familiar printf and scanf functions, except that they work on files.
syntax : fprintf(FILE *stream, "control string", arguments);
fprintf sends output to the specified file stream. fprintf returns the number of bytes output. In case of error, it returns EOF.
syntax : fscantf(FILE *stream, "control string", arguments);
fscanf performs a formatted input from the specified stream. Returns the number of input fields successfully scanned, converted and stored, the returned value does not include unstored scanned fields.
e.g.:- fscanf(fp, "%s %d", name, &age);
fprintf(stdout," %s -- %d", name, age);
BLOCK I/O
The block I/O functions are used to read or write continuous blocks of bytes from and to a file. Each block will generally represent a complex data structure, such as a structure or an array. For example, it is easier to read or write an entire block of data rather than reading or writing the individual components (i.e., structure members) within a block separately.
prototypes : size_t fread(void *buffer, size_t num_bytes, size_t count, FILE *stream);
size_t fwrite(void *buffer, size_t num_bytes, size_t count, FILE *stream);
The data type size_t is an ANSI 'C' addition to improve portability. It is predefined as an integer type large enough to hold sizeof() results. Usually it is equivalent to unsigned integer. For fread() buffer is a pointer to the region of memory that will receive the data item from the file. For fwrite(), buffer is a pointer to the information that will be written to the file.
The number of bytes to read or written is specified by num-bytes. The argument count determines how many items(each num-bytes in length) are read or written.
The fread() returns the number of items read. This value be less than count if the end-of-file is reached or an error occurs. The fwrite() returns the number of items written. This value will equal to count unless an error occurs.
As long as the file has been opened for binary operations, fread() and fwrite() can read and write any type of information.
e.g.:-
fread(&buffer, sizeof(buffer), 1, fp);
fwrite(&buffer, sizeof(buffer), 1, fp);
ARRAY OF POINTERS
The way there can be an array of ints or an array of floats, similarly there can be an array of pointers. Since a pointer variable always contains an address, an array of pointers would be nothing but a collection of addresses. The addresses present in the array of pointers can be addresses of different variables or addresses of arrays and array elements.
syntax : data_type *array_name[size of array];
eg:- int *arr[4]; an array of 4 integer pointers
float *price[10]; an array of 10 float pointers
Sample Programs: To show array of pointers can contain the addresses of different data items.
i)
main()
{
int *arr[4];
int a=10, b=20, c=30,d=40,x=0;
arr[0]=&a; arr[1]=&b; arr[2]=&c; arr[3]=&d;
for(x=0;x<4;x++)
{
printf("%u -- %d\n", arr[x], *(arr[x]) );
}
getch();
}
will print, The for loop in the program picks up the addresses present in
6784 - - 10 the elements of arr and prints the addresses present at there 6786 - - 20 and the values present at these addresses.
6788 - - 30 ( the addresses shown in the sample output are imaginary )
6790 - - 40
ii)
main() will print, 6202 - - 5101 - - 0, where
{ 6202 is the base address of the pointer
int arr[]={0,1,2,3,4}, *p[5]; array, p, 5101 is the base address
p[0]=a; p[1]=a+1; p[2]=a+2; p[3]=a+3; p[4]=a+4; of integer array, a stored in the first
printf("%u -- %u --%d",p,*p,*(*p) ); element of p, and 0 is the value stored
} in the first element of array a.
iii)
main() will print,
{ 6202 - - 5101 - - 0
int arr[]={0,1,2,3,4}, *p[5]; 6204 - - 5103 - - 1
p[0]=a; p[1]=a+1; p[2]=a+2; p[3]=a+3; p[4]=a+4; 6206 - - 5105 - - 2
for(i=0;i<5;i++) 6207 - - 5107 - - 3
printf("%u -- %u --%d",&p[i],p[i],*(p[i]) ); 6210 - - 5109 - - 4
}
iv)
main() will print,
{ 6202 - - 5101 - - 0
int arr[]={0,1,2,3,4}, *p[5]; 6204 - - 5103 - - 1
p[0]=a; p[1]=a+1; p[2]=a+2; p[3]=a+3; p[4]=a+4; 6206 - - 5105 - - 2
for(i=0;i<5;i++) 6207 - - 5107 - - 3
printf("%u -- %u --%d", p+i,*(p+i),*(*(p+i)) ); 6210 - - 5109 - - 4
}
v)
main()
{
int arr[]={0,1,2,3,4}, *p[5],**ptr; will print,
p[0]=a; p[1]=a+1; p[2]=a+2; p[3]=a+3; p[4]=a+4; 5101 - - 0
ptr=p; 6202 - - 5101 - - 0
printf("%u - - %d \n", a, *a); 6202 - - 5101 - - 0
printf("%u - - %u - - %d \n", p, *p, **p);
printf("%u - - %u - - %d \n", ptr, *ptr, **ptr);
}
vi)
main()
{
int a[3][3]={ 1,2,3,4,5,6,7,8,9 }, *ptr[3]; will print,
ptr[0]=a[0]; ptr[1]=a[1]; ptr[2]=a[2]; 1 - - 4 - - 7
for(i=0;i<3;i++) 1 - - 4 - - 7
printf("%d \t", *ptr[i] );
printf("\n");
for(i=0;i<3;i++)
printf("%d \t", *a[i] );
}
Array of pointers mainly used for storing several strings in memory.
e.g.:- char *name[]={ "joy", "srinivas", "jayaprakash", "antony", "hussain", "abijith"};
In the above example names[] is an array of 6 pointers. It contains addresses of given names. i.e., base address of "joy" is stored in names[0], base address of "antony" is stored in names[3] and so on.
If we used a two-dimensional array to store these names, where each row will be of equal lengths, it will take roughly 72 bytes in memory.
But by using the memory of pointers is strings will take only 41 bytes. Thus one reason to store to make more efficient use of available memory.
Another advantage is that easy manipulation of strings. e.g.:- exchange of positions of strings like in sorting of string arrays.
e.g.1:- string exchanging:
main()
{
char *names[]={"joy", "srinivas", "jayaprakash", "antony", "hussain", "abijith"};
char *temp;
printf("Before exchanging : ");
printf("%s - - %s", names[2], names[3] );
temp = names[2];
names[2] = names[3];
names[3] = temp;
printf("\n After exchanging : ");
printf("%s - - %s", names[2], names[3] );
getch();
}
will print,
Before exchanging : jayaprakash - - antony
After exchanging : antony - - jayaprakash
e.g. 2: sorting strings
main()
{
char *names[]={"joy", "srinivas", "jayaprakash", "antony", "hussain", "abijith"};
sort(names);
for(i=0; i<6; i++)
printf("%s \n", arr[i] );
getch();
}
sort( char *names[])
{
int i, j;
char *temp;
for(i=0; i<5; i++)
{
for(j=5; j>i; j--)
{
if(strcmp(names[j], names[j-1]) < 0)
{
temp=names[j];
names[j]=names[j-1];
names[j-1]=temp;
}
}
}
}
e.g.3 :- sorting strings
main()
{
char *names[]={"joy", "srinivas", "jayaprakash", "antony", "hussain", "abijith"};
sort(names);
for(i=0; i<6; i++)
printf("%s \n", arr[i] );
getch();
}
sort( char *names[])
{
int i,j;
char *temp;
for(i=0; i<5; i++)
{
for(j=5; j>i; j--)
{
if(strcmp(names[j], names[j-1]) < 0)
{
swap(&names[j], &names[j-1] );
}
}
}
}
swap(char *s1, char *s2)
{
char *temp;
temp = *s1;
*s1= *s2;
*s2= temp;
}
LIMITATION OF ARRAY OF POINTERS TO STRING
When we are using a two dimension array of characters we can either initialise the strings where we are declaring the array or receive(accept) the string using scanf(). However, when we are using an array of pointers to strings we can initialise the strings at the place where we are declaring the array, we cannot accept the strings from keyboard using scanf().
i.e., code like,
…………..
…………..
char *names[3];
printf("Enter a name : ");
scanf("%s", name[i] );
…………
…………
Doesn't work because when we are declaring the array it is containing garbage values, and it is wrong to send these garbage values to scanf() as the addresses where it should keep the strings received from the keyboard.
Write a function month_name(int n);, which returns a pointer to a character string containing the name of the nth month.
char *month_name(int n)
{
static char *name[]={ "Illegal Month Number", "January", "February", "March", "April", "May",\
"June", "July", "August", "September", "October", "November", "December"
};
return( (n<1 || n>12) ? name[0] : name[n]) ;
}
COMMAND LINE ARGUMENTS
Command line arguments are the information made available to the program by writing it after the program name on the command line of the operating system. The command line arguments are used to pass information into the main() when program begins executing.
main() can take two arguments usually called argc and argv and the information contained in the command line is passed on to the main() through these arguments, when main() is called up by the system.
The variable argc is an argument counter, which holds the number of arguments including the program name on the command line, and is an integer. The argv is an argument vector and represents an array of character pointers that point to the command line arguments. Any type of argument in the command line is treated as a string. The size of this array will be equal to the value of argc. You can access the individual arguments by indexing (subscripting) argv.
The first parameter in the command line is always the program name and therfore argv[0] always represents the program name, argv[1] points to the first argument and so on. The argcth element points to NULL.
syntax : main( int argc, char *argv[])
{
.......
......
}
for example, if we want to execute a program to copy the contents of a file named file1 to another file named file2, then the command line like,
C:\>DUP file1 file2
Where DUP is the executable program file name. Here argc is 3 and argv is as shown below,
Q). Write a program to simulate the ECHO command available under DOS
# include
main(int argc, char *argv[])
{
int i;
for(i=1; i
{
printf("%s\t",argv[i] );
}
}
OR
# include
main(int argc, char *argv[])
{
int i=1;
while(argv[i]!=NULL)
{
printf("%s\t",argv[i++] );
}
}
OR
# include
main(int argc, char *argv[])
{
int i=1;
while(i
{
printf("%s\t",*argv );
argv++;
}
}
if any numeric value contained in the command line arguments will also passed to the main() as a string. Therefore you must convert it to numeric before processing using library functions like atoi(), atol(), atof() etc.
Q. Write a program to print the specified no. of dots(.) .
/* dots.c */
# include
void main(int argc, char *argv[])
{
int i;
if(argc < 2)
{
printf("You must specify a number");
printf(" with the program name \n");
printf("Try again");
exit(1);
}
for(i=1; i<=atoi(argv[1]); i++)
putchar('.');
printf("%s completed", argv[0]);
putchar(7); /* to create a beep sound */
}
An example program execution, C:\> dots 20
A program with command line arguments should issue instructions, if the user attempts to run the program without proper information. The command line arguments give the program a professional appearance. It is not necessary that you should always use the variable names argc and argv. In place of them any other valid variable name can be used.
Q1. Write a program tail, which prints the last 'n' lines of the specified file. By default, n is 10. But it can be changed by an optional command line argument. ie., tail file1 should print the last 10 lines of file1, and tail file2 15 should print the last 15 lines of file2.
Q2. Write a program head, which prints the first n lines of the specified.(use command line arguments)
Q3. Write a program to simulate the DOS external command FILD which prints the lines of the given file that contains the given word. There are options that changes the default meaning.
n - line numbers before each line
c - only total no. of lines
i - ignore case difference
x - will print each line that doesn’t match the given word
FUNCTIONS RETURNING POINTERS
The way functions return an int, a float, a double or any other data type, it can also return a ointer(address). To make a function return a pointer it has to be mentioned in the calling function as well as in the function declaration (prototype).
Syntax: datatype *function-name (arguments);
eg: (1)
# include
main()
{
int *p;
int *function();
p=function;
printf("%u -- %d",p,*p);
}
s
int *function()
{
int i=20;
return(&i);
}
eg: (2)
# include
float *function(float *r);
main()
{
float p=45.67, q=28.94, *x;
c=&p;
printf("Before calling *x = %f\n",*x);
x=function(&p);
printf("After calling *x = %f\n",*x);
getch();
}
float *function(float *r)
{
r=r+1;
return(r);
}
eg: (3)
# include
char *addstring(char *s1, char *s2);
main()
{
char s1[30],s2[10], *ptr;
printf("Enter first string : "); gets(s1);
printf("Enter second string : "); gets(s2);
ptr=addstring(s1,s2);
printf("\nAfter addition S1 = %s",ptr);
getch();
}
char *addstring(char *s1, char *s2)
{
int i,j;
for(i=0; s1[i]!=NULL; i++); Version 1
for(j=0; s2[j]!=NULL; s1[i]=s2[j],i++,j++);
return s1;
}
char *addstring(char *s1, char *s2)
{
int i,j;
for(i=0; s1[i]!=NULL; i++); Version 2
for(j=0; (s1[i]=s2[j])!=NULL;i++,j++);
return s1;
}
char *addstring(char *s1, char *s2)
{
char *ptr=s1;
for(;*s1!=NULL;s1++);s1--; Version 3
for(;(*s1=*s2)!=NULL;s1++,s2++);
return ptr;
}
char *addstring(char *s1, char *s2)
{
char *ptr=s1;
for(;*s1++!=NULL;);s1--; Version 4
for(;(*s1++=*s2++)!=NULL;);
return ptr;
}
char *addstring(char *s1, char *s2)
{
char *ptr=s1;
for(;*s1++;); s1--; Version 5
for(;*s1++ = *s2++;);
return ptr;
}
POINTERS TO FUNCTIONS
Even though a function is not a variable it has a physical location in memory that can be assigned to a pointer. A function’s address is the entry point of the function. Because of this, a function pointer can be used to call a function.
In ‘C’, as each function is compiled, source code is transformed into object code and an entry point is established. When a call is made to a function while your program is running, a machine language call is made to this point. Therefore, if a pointer contains the address of a function’s entry point, it can be used to call that function.
To obtain the address of a function, use the function’s name without any parentheses and arguments.
syntax: datatype (*ptr)();
The above declaration tells that ptr is a pointer to a function which returns the specified datatype.
eg: int (*ptr)();
ptr = strcmp;
To invoke the function using function pointer use the syntax, (*ptr)();
eg: to invoke the strcmp function,
(*ptr)(string1,string2);
Sample Program (1) To show functions also have address
# include
main()
{
int show();
printf(“Address of function show = %u “,show);
show();
}
show()
{
printf(“This is a sample program”);
}
Sample Program (2) Using pointer to function
# include
int show();
main()
{
int (*ptr)();
ptr=show;
printf(“Address of function show = %u “,ptr);
(*ptr)(); /* to invoke the function show using the pointer to function */
}
show()
{
printf(“This is the second sample program”);
}
Sample Program (3) Comparing two strings for equality
# include
# include
void check( char *a, char *b, int (*cmp)() );
main()
{
char s1[80],s2[80];
int (*ptr)();
ptr=strcmp;
printf(“Enter first string : “); gets(s1);
printf(“Enter second string : “); gets(s2);
check(s1,s2,ptr);
}
void check(char *a, char *b, int (*cmp)() )
{
if( !(*cmp)(a,b) )
printf(“Equal”);
else
printf(“Not equal”);
}
UNIONS
A union is a memory location that is shared by two or more different variables, generally of different types, at different times. Defining a union is similar to defining a structure, using the keyword union.
syntax :
1>
Share with your friends: