Programming in C: Unit V: File processing

Function for Selecting a Record Randomly

Syntax with Example C Programs | File processing

In this section we will read about functions that are used to randomly access a record stored in a binary file. These functions include fseek (), ftell(), rewind (), fgetpos (), and fsetpos ().

FUNCTIONS FOR SELECTING A RECORD RANDOMLY

In this section we will read about functions that are used to randomly access a record stored in a binary file. These functions include fseek (), ftell(), rewind (), fgetpos (), and fsetpos ().

fseek()

The function fseek () is used to reposition a binary stream. The prototype of fseek() function which is defined in stdio.h can be given as

int fseek (FILE *stream, long offset, int origin);

fseek() is used to set the file position pointer for the given stream. The variable offset is an integer value that gives the number of bytes to move forward or backward in the file. The value of offset may be positive or negative, provided it makes sense. For example, you cannot specify a negative offset if you are starting at the beginning of the file. The origin value should have one of the following values (defined in stdio.h):

• SEEK_SET: to perform input or output on offset bytes from start of the file

• SEEK_CUR: to perform input or output on offset bytes from the current position in the file

• SEEK_END: to perform input or output on offset bytes from the end of the file

• SEEK_SET, SEEK_CUR and SEEK END are defined constants with value 0, 1, and 2, respectively.

Programming Tip: While using fseek(), if the third parameter is specified as SEEK_END, then you must provide a negative offset, otherwise it will try to access beyond EOF.

On successful operation, fseek() returns zero and in case of failure, it returns a non-zero value. For example, if you try to perform a seek operation on a file that is not opened in binary mode then a non-zero value will be returned.

fseek() can be used to move the file pointer beyond a file, but not before the beginning.

Note

If a file has been opened for update and later if you want to switch from reading to writing or vice versa, then you must use the fseek().

The fseek() is primarily used with binary files as it has limited functionality with text files.

25. Write a program to randomly read the nth records of a binary file.

#include <stdio.h>

#include <conio.h>

main()

{

typedef struct employee

{

int emp_code;

char name [20];

int hra;

int da;

int ta;

};

FILE *fp;

struct employee e;

int result, rec_no;

fp = fopen("employee.txt", "rb");

if (fp==NULL)

{

printf("\n Error opening file");

exit (1);

}

printf("\n\n Enter the rec_no you want to read: ");

scanf("%d", &rec_no);

if (rec_no >= 0)

{

/* from the file pointed by fp read a record of the specified record starting from the beginning of the file*/

fseek (fp, (rec_no-1) * sizeof (e), SEEK_SET);

result = fread (&e, sizeof (e), 1, fp);

if (result == 1)

{

printf("\n EMPLOYEE CODE: %d", e.emp_code);

printf("\n Name: %s", e.name);

printf("\n HRA, TA, and DA: %d %d %d", e.hra, e.ta, e.da);

}

else

printf("\n Record Not Found");

}

fclose(fp);

getch();

return 0;

}

Output

Enter the rec_no you want to read: 06

EMPLOYEE CODE: 06

Name: Tanya

HRA, DA and TA: 20000 10000 3000

26. Write a program to print the records in reverse order. The file must be opened in binary mode. Use fseek().

#include <stdio.h>

#include <conio.h>

main()

{

typedef struct employee

{

int emp_code;

char name [20];

int hra;

int da;

int ta;

};

FILE *fp;

struct employee e;

int result, i;

fp = fopen("employee.txt", "rb");

if (fp==NULL).

{

printf("\n Error opening file");

exit (1);

}

for (i=5;i>=0;i--)

{

fseek (fp, i* sizeof (e), SEEK_SET);

fread (&e, sizeof (e), 1, fp);

printf("\n EMPLOYEE CODE: %d", e.emp_code);

printf("\n Name: %s", e.name);

printf("\n HRA, TA and DA: %d %d %d", e.hra, e.ta, e.da);

}

fclose(fp);

getch();

return 0;

}

Output

EMPLOYEE CODE: 06

Name: Tanya

HRA, DA and TA: 20000 10000 3000

EMPLOYEE CODE: 05

Name: Ruchi

HRA, DA and TA: 10000 6000 3000

27. Write a program to edit a record in binary mode using fseek().

#include <stdio.h>

#include <conio.h>

main()

{

typedef struct employee

{

int emp_code;

char name [20];

int hra;

int da;

int ta;

};

FILE *fp;

struct employee e;

fp = fopen("employee.txt", "r+");

if (fp==NULL)

{

printf("\n Error opening file");

exit(1);

}

printf("\n Enter record no. to be modified: ");

scanf("%d", &rec_no);

fseek (fp, (rec_no-1)* sizeof (e), SEEK_SET);

fread (&e, sizeof (e), 1, fp);

printf("\n Enter modified name of the employee: ");

scanf("%s", e.name);

printf("\n Enter the modified HRA, TA, and DA of the employee: ");

scanf("%d %d %d", &e.hra, &e.ta, &e.da);

fwrite(&e, sizeof (e), 1, fp);

fclose (fp);

printf("\n Record Edited");

getch();

return 0;

}

Output

Enter record no. to be modified: 04

Enter the modified HRA, TA, and DA of the employee: 30000 1000 5000

Record Edited

ftell ()

The ftell () function is used to know the current position of file pointer. It is at this position where the next input or ouput operation will be performed. The syntax of ftell (), defined in stdio.h, can be given as

long ftell (FILE *stream);

Here, stream points to the file whose file position indicator has to be determined. If successful, ftell () function returns the current file position (in bytes) for stream. However, in case of error, ftell () returns -1.

When using ftell (), error can occur either because of two reasons:

• First, using ftell() with a device that cannot store data (e.g., keyboard).

• Second, when the position is larger than that can be represented in a long integer. This will usually happen when dealing with very large files.

Look at the program code which illustrates the use of ftell ().

/*The program writes data to a file, saves the number of bytes stored in it in a variable n (by using ftell ()) and then re-opens the file to read n bytes from the file and simultaneously display it on the screen.*/

main ()

{

FILE *fp;

char c;

int n;

fp=fopen("abc", "w");

if(fp==NULL)

{

printf("\n Error Opening The File");

exit (1);

}

while ((c=getchar()) != EOF)

putc(c, fp);

n = ftell (fp);

fclose(fp);

fp=fopen("abc", "r");

if (fp==NULL)

{

printf("\n Error Opening The File");

exit (1);

}

while (ftell (fp) <n)

{

c= fgetc (fp);

printf("%c", c);

}

fclose(fp);

}

Output

abcdefghijkjdqjdh

Note

ftell () is useful when we have to deal with text files for which position of the data cannot be calculated.

rewind ()

rewind () is used to adjust the position of file pointer so that the next I/O operation will take place at the beginning of the file. It is defined in stdio.h and its prototype can be given as

void rewind (FILE *f);

rewind () is equivalent to calling fseek() with following parameters:

fseek (f, OL, SEEK_SET);

We have seen earlier that if a file is opened for writing and you want to read it later, then you have to close the existing file and reopen it so that data can be read from the beginning of the file. The other alternative is to to use the rewind (). Look at the program code given below which demonstrates the use of rewind ().

#include <stdio.h>

main()

{

FILE *fp;

char feedback [80];

int i=0;

fp = fopen("comments.txt", "w+");

if (fp==NULL)

{

printf("\n Error Opening The File");

exit (1);

}

printf("\n Provide comments on this book: ");

scanf("%s", feedback);

while (feedback [i] != '\0')

{

fputc(feedback [i], fp);

i++;

}

rewind (fp);

printf("\n Contents of the file are: ");

while (feof (fp)==0)

printf("%c", fgetc (fp);

fclose(fp);

return 0;

}

Output

Provide comments on this book: Good

Contents of the file are: Good

However, you must prefer to use fseek() equivalent code rather calling rewind () because it is impossible to determine if rewind () was successful or not.

fgetpos ()

The fgetpos () is used to determine the current position of the stream. The prototype of the fgetpos () as given in stdio.his

int fgetpos (FILE *stream, fpos_t *pos);

Here, stream is the file whose current file pointer position has to be determined. pos is used to point to the location where fgetpos () can store the position information. In simple words, fgetpos () stores the file position indicator of the given file stream in the pos variable. The pos variable is of type fpos_t which is defined in stdio.h and is basically an object that can hold every possible position in a FILE.

On success, fgetpos () returns zero and in case of an error a non-zero value is returned. The value of pos obtained through fgetpos () can be used by the fsetpos () to return to this same position.

fsetpos ()

The fsetpos () is used to move the file position indicator of a stream to the location indicated by the information obtained in 'pos' by making a call to the fgetpos (). Like fgetpos (), fsetpos () is defined in stdio.h and its prototype can be given as

int fsetpos (FILE *stream, const fpos_t pos);

Here, stream points to the file whose file pointer indicator has to be re-positioned. pos points to positioning information as returned by fgetpos.

On success, fsetpos () returns a zero and clears the EOF indicator. In case of failure it returns a non-zero value.

Programming Tip: An error will be generated if you try to place the file position indicator before the first byte of the file.

After the successful call to fsetpos (), the next operation on a stream in update mode may be input or output. Look at the program code given below which illustrates the use of fgetpos () ent and fsetpos () functions.

// The program opens a file and reads bytes at several different locations.

#include <stdio.h>

main()

{

FILE *fp;

fpost_pos;

char text [20];

fp = fopen("practise.c", "rb");

if (fp ==NULL)

{

printf("\n Error opening file");

exit(1);

}

/* Read some data and then check the position. */

fread (text, sizeof (char), 20, fp);

if (fgetpos (fp, &pos) != 0)

{

printf("\n Error in fgetpos () ");

exit(1);

}

fread(text, sizeof(char), 20, fp);

printf("\n 20 bytes at byte %ld: %s", pos, text);

/* Set a new random position and read more data */

pos = 90;

if (fsetpos (fp, &pos) != 0)

{

printf("\n Error in fsetpos ()");

exit(1);

}

fread (text, sizeof (char), 20, fp);

printf("\n 20 bytes at byte %ld: %s", pos, text);

fclose(fp);

}

Output

20 bytes at byte 20: #include <conio.h>

ma

20 bytes at byte 90: getch();

90 return 0;

}

Only use values for fsetpos() that are returned from fgetpos().

Programming in C: Unit V: File processing : Tag: : Syntax with Example C Programs | File processing - Function for Selecting a Record Randomly