Chapter 9

Files

CHAPTER OUTLINE
9.1 DATA AND INFORMATION

The ancient scratches on the rocks, writings on Ashoka pillars, the scriptures, and the caves of Ajanta and Ellora—all indicate that the human beings have a basic tendency to record information. The oldest records were made on clay tablets as long ago as 3700 BC. Most of the Indian scriptures were written on the thin sheets of bark of Bhojpatra, a tree found in the upper Himalayas. In second century AD, paper was developed in China. This event brought a revolution and the paper became a writing medium in whole of the world.

In an enterprise, whether it is a small shop at the corner of the street, a school or a large industry, it can be observed that each and every person uses lot of paper and a large amount of data and information exchange takes place. The workers deal with actual physical work and produce data whereas the managers deal with the information written on papers.

Let us now delve upon the terms data and information, especially in the context of files.

9.1.1 Data

The word data is a plural of datum, which means fact. Thus, data is a collection of facts and figures. It can be represented by symbols. For example, in a business house, data can be the name of an employee, his salary, number of hours worked, etc. Similarly in an educational institute, the data can be the marks of a student, roll numbers, percentage, etc.

9.1.2 Information

It is the data arranged in an ordered and useful form. Thus, the data can be processed so that it becomes meaningful and understandable (see Figure 9.1).

 

Processing of data into information

 

Fig. 9.1 Processing of data into information

 

For example, in Figure 9.2(a), the collection of characters and digits is meaningless by itself because it could refer to total marks and names of students, the house numbers and names of house owners, etc. Once the data is arranged in an order as shown in Figure 9.2(b), anybody can come to know that the data refers to names of persons and their corresponding ages. Therefore, this meaningful data can be called information.

 

Data and information

 

Fig. 9.2 Data and information

9.2 FILE CONCEPTS

Let us consider the information recorded in Figure 9.3. Each entry into the table shown in this figure is a set of three data items: Roll, Name, and Marks. The first entry states that the roll number and total marks of a student named Ajay are 001 and 50, respectively. Similarly, the second entry relates to a student named RAM whose roll number is 002 and total marks are 67.

 

File of records

 

Fig. 9.3 File of records

 

Each entry of the table is also known as a record of a student. The record can be defined as a set of related data items of a particular entity such as a person, machine, place, or operation. An individual data item within a record is known as a field.

Thus, the record of a student is made up of following three fields:

  1. Roll
  2. Name
  3. Marks

Let us assume that a particular class has 30 students. Now, the entire information of the class consisting of 30 records is referred to as a file. A file, therefore, consists of a number of records and each record consists of a number of items known as fields. The creation and maintenance of files is one of the most important activities in an organization. Depending upon its purpose, a file can be called by a specific name or type. The various types of files are tabulated in Table 9.1.

 

Table 9.1 Types of file

Type Purpose Examples
Master file Collection of records about an important activity. It may reflect the history of events or information which can be used as a source of reference. The master file is always kept up-to-date. These are fairly permanent files. Student fee file, Personnel file, Inventory file, Stock file.
Transaction file A temporary file with two purposes:
  1. collection of data about events as they occur and
  2. updation of master files.

These files are temporary in nature as these are deleted after master file is updated.

Fee receipt file, Purchase file, Sales invoice file.
Reference file This file contains information which is required for reference and changes periodically, i.e., price list, students’ attendance, share rates, etc. Student-attendance file, Share rates file.
Report file Data extracted from master files in order to prepare a report. Student detainee file, Scholarship file, Taxes file.
Sort file A working file of records to be ordered in a particular sequence. Merit list file.
Back up file A copy of a master or a transaction file made to ensure that a duplicate is available, if anything happens to the original. Stud-back up file, Data back up file.
Archival files Copies made for long-term storage of data maintained for future reference. These files are generally stored off-line, i.e., away from the computer centre. Security file, History file.

The arrangement of records in a file can be different for different situations. The file of records shown in Figure 9.3 can be arranged according to names instead of roll numbers, i.e., in alphabetical order. The rearranged file is shown in Figure 9.4.

 

File in alphabetical order

 

Fig. 9.4 File in alphabetical order

 

It may be noted here that in the file shown in Figure 9.3, the records were arranged according to Roll field whereas in the file shown in Figure 9.4, the records are arranged according to Name field. However, a record in both the files can be identified by the field called Roll. Basically, a field which is used to identify a particular record within a file is called as a key field. It is the key field according to which, generally, all records within a file are arranged.

The records in a file can be arranged in the following three ways:

  1. Ascending/Descending order: The records in the file can be arranged according to ascending or descending order of a key field. For example, the records in the file of Figure 9.3 are in ascending order of its Roll field.
  2. Alphabetical order: If a field is of string or character type, then this arrangement is used. For example, the records in the file of Figure 9.4 are in alphabetical order.
  3. Chronological order: In this type of order, the records are stored in the order of their occurrence, i.e., arranged according to dates or events. If the key field is a date, i.e., date of birth, date of joining, etc., then this type of arrangement is used. For example, the records of a file shown in Figure 9.5 are arranged according to date of birth (DOB).

 

File in chronological order

 

Fig. 9.5 File in chronological order

9.3 FILE ORGANIZATION

In a non-computerized company, the data and information are held on files kept in a paper filing system. If the company had a computer, the files would be held on computer storage. The former system is known as manual filing system and the latter is known as electronic data processing (EDP) filing system. The characteristics of a manual filing system are as follows:

  • Records are stored as documents in files using papers.
  • Records are arranged using a system of indices.
  • The files are handled and maintained by people.

The characteristics of EDP filing system are as follows:

  • Used in computer environment.
  • Files are stored on computer storage.
  • Records are sorted and arranged according to a key field.
  • The files are handled and maintained by specific programs written in a high level language such as PASCAL, C, software packages, etc.

The manual filing system is suitable for small organizations where fast processing and storage of data is not required. In the EDP filing system, large amount of data can be managed efficiently. The data storage and retrieval becomes very fast. It may be noted that in the manual filing system, the files are generally arranged in a meaningful sequence. The records are located manually by the person in charge of the files. However when the files are stored on the computer, the files have to be kept in such a way that the records can be located, processed, and selected easily by the computer program. The handling of files depends on both input and output requirements, and the amount of data to be stored. How best can the files be arranged for ease of access? This necessity has led to the development of a number of file organization techniques as listed below:

  1. Sequential file organization
  2. Direct access file organization
  3. Indexed sequential file organization
9.4 FILES IN ‘C’

All the programs that we have written so far have extensively used input and output statements. The scanf statement is used to input data from keyboard and printf statement to output or display data on visual display unit (VDU) screen. Thus, whenever some data is required in a program, it tries to read from the keyboard. The keyboard is an extremely slow device. For small amount of data, this method of input works well. But what happens when huge data is needed by a program? For example, a program which generates the merit list of joint entrance examination (JEE) may require data in the tune of 10,000 to 20,000 records. It is not possible to sit down and type such a large amount of data in one go. Another interesting situation is: what happens when the data or results produced by one program are required subsequently by another program? On the next day, the results may even be required by the program that produced them. Therefore, we need to have a mechanism such as files by virtue of which the program can read data from or write data on magnetic storage medium.

When the data of a file is stored in the form of readable and printable characters, then the file is known as a text file. On the other hand, if a file contains non-readable characters in binary code then the file is called a binary file. For instance, the program files created by an editor are stored as text files whereas the executable files generated by a compiler are stored as binary files. An introduction to files supported by ‘C’ is given in the following sections.

9.5 FILES AND STREAMS

In ‘C’, a stream is a data flow from a source to a sink. The sources and sinks can be any of the input/output devices or files. For input and output, there are two different streams called input stream and output stream as shown in Figure 9.6.

 

Stream I/O

 

Fig. 9.6 Stream I/O

 

We have already used the following formatted stream I/O functions in our previous programs:

 

Stream Description
     scanf                     standard input stream
     printf                     standard output stream

 

The standard source and sink are keyboard and monitor screen, respectively. These unformatted streams are initialized whenever the header file <stdio.h> is included in a program.

In fact, ‘C’ supports a very large number of I/O functions capable of performing a wide variety of tasks. The I/O system of ‘C’ is categorized into following three categories:

  1. The stream I/O system
  2. The console I/O system
  3. The low-level I/O system

Some of the important stream I/O functions are listed in Table 9.2.

 

Table 9.2 Some important stream I/O functions in ‘C

Function Purpose
fclose close a stream
feof test for end of file
flush flush a stream
fgctc read a character from a stream
fgetchar read a character from a stream
fgets read a string from a stream
fopen open a stream
fprintf send formatted data to a stream
fputc send a character to a stream
fputs send a string to a stream
fread read a block of data from a stream
fscanf read formatted data from a stream
fseek reposition a stream pointer
fwrite write a block of data to a stream
fputs send a string to a stream
getw read an integer from a stream
putw send an integer to a stream

 

Some of the important console I/O functions are listed in Table 9.3.

 

Table 9.3 Some important console I/O functions in ‘C’

Function Purpose
cgets read a string from the console
clrscr clear text window
cprintf write formatted data to the console
getch read a character from the console
getche read a character from the console and echo it
gotoxy move the cursor to a specified location
putch write a character to the console

 

Some of the low-level I/O functions are listed in Table 9.4.

 

Table 9.4 Some important low-level I/O functions in ‘C’

Function Purpose
chmode Change the mode a file
close Close the file
eof Test for end of file
file length Determine the length of a file in byte
lseek Move or read data of a file pointer
open Open a file
read Read data from a file
setmode Setmode of a file
write Write data to a file
9.6 WORKING WITH FILES USING STREAM I/O

An I/O stream is a sequence of characters f lowing from a source to a sink. When the data is read by a program from a device, the device becomes the source which places the data on the stream (see Figure 9.6). Obviously, the program becomes the sink that receives the data from the stream. While writing the data, the program and the device reverse the roles.

A stream is accessed by a stream pointer as shown in Figure 9.7. The stream pointer points to the beginning of a stream.

 

Working of a stream

 

Fig. 9.7 Working of a stream

 

A file is opened as a stream with the help of a pointer of type FILE. Having opened the file, it is accessed through a pointer in a fashion very similar to accessing an array of strings.

9.6.1 Opening of a File

A file can be opened in stream I/O by using function called fopen(). It takes two arguments: file name and type of operation (see Table 9.5). The fopen() function returns a pointer of type FILE.

 

Table 9.5 File opening mode

Mode Purpose
“r” Open a file for reading. If file does not exist, NULL is returned.
“w” Open a file for writing. It the file does not exist, a new file is created. If the file exists, the new content overwrites the previous contents.
“r+” Open the file for both reading and writing. If the file does not exist, NULL is returned.
“w+” Open the file for both reading and writing. If the file exists, the previous contents are overwritten by the new one.
“a” Open a file for appending. If the file exists, the new data is written at the end of the file else the new file is created.
“a+” Open the file for reading and appending. If the file does not exist, a new file is created.

Thus, a file (say “Myfile”) can be opened for reading by using the following steps:

STEP 1: Declare a pointer (say ptr) of type FILE i.e., FILE*ptr;

STEP 2: Open the file using a stream I/O function called fopen().

             ptr = fopen (“Myfile”, "r”);

The above statement requests the system to open a file called “myfile” in read mode and assigns its pointer to ptr.

A file can be closed by a function called fclose() which takes one argument of type FILE.

Thus, the file (“Myfile”) can be closed by the following statement:

fclose (ptr);

9.6.2 Unformatted File I/O Operations

An opened file can be read or written by the following set of unformatted I/O functions:

     fget(), get(), fgetchar()

     getw(), fputc(), putc()

     fputchar(), fputs(), putw()

A brief description of each function has already been provided in Table 9.2.

Let us consider a situation wherein we desire to create a file called “message.dat” containing the following text:

“When one apple fell, Newton was disturbed;
but when he found that all apples fell;
it was gravitation and he was satisfied”.

The file “message.dat” would be opened with the help of fopen() function and the function fputs() would be used to write a line in the file. The fputs() function requires two arguments as shown below:

fputs (<string>, <file-pointer>)

where <string> is string of characters to be written in the file; and

<file-pointer> is the pointer to the file in which the text is to be written.

The required program is given below:

  #include <stdio.h>
  main()
  {
    FILE *ptr;
    ptr = fopen (“message.dat”, "w”);
  
    if (!ptr)
    {
      printf (“
 The file cannot be opened”);
      exit(1);
  }
  fputs(“When an apple fell, Newton was disturbed
”, ptr);
  fputs(“but when he found that all apples fell, 
”, ptr);
  fputs(“it was gravitation and he was satisfied”, ptr);
  fclose(ptr);
  }

The above program is simple wherein the first statement of function main() declares a pointer to a FILE and in the second statement a file called “message.dat” is opened in write mode. The next compound statement checks whether the operation was successful or not. Rest of the statements write the text, line by line in the file. The last statement closes the file.

A string from a file can be read by a function called fgets(). This function requires three arguments as shown below:

fgets (<string>, n, <file-pointer>)

where <string> is the character string, i.e., an array of char in which a group of characters from the file would be read.

n is the number of characters to be read from the file. The function reads a string of characters until the first new line (“ ”) character is encountered or until the number of characters read is equal to n – 1.

<file-pointer> is the pointer to the file from which the text is to be read.

The end of a file can be detected by a function called feof(<file.pointer>). This function can be used in a situation where a program needs to read whole of the file. For example, the following program uses feof() and fgets() functions to read the “message.dat” file till the end of the file is encountered. The strings read from the file are displayed on the screen.

  #include<stdio.h>
  main()
  {
     char text[80];
     FILE*ptr;
     ptr = fopen(“message.dat”, "r”);
     if(!ptr)
     {
      printf(“
 the file cannot be opened”);
      exit(1);
     }
     while(!feof(ptr))
     {
        fgets(text, 80, ptr);
        printf(“ %s”, text);
     }
     fclose(ptr);
  }

Similarly, the functions fgetc() and fputc() functions can be used to read from or write a character to a file. The function fputc() takes two arguments, i.e., a character variable, and the file pointer whereas the function fgetc() takes only one argument, i.e., the file pointer.

For example, ch=fgetc(ptr) reads a character in ch from a file pointed by the pointer called ptr.

fputc(ch, ptr) writes a character stored in ch to a file pointed by the pointer called ptr.

Example 1: Write a program that copies the file called “message.dat” to another file called “new.dat”.

 

Solution: The above program can be written by using the following steps.

Steps

  1. Open “message.dat” for reading.
  2. Open “new.dat” for writing.
  3. Read a character from “message.dat”. If the character is “eof”, then go to step 5 else step 4.
  4. Write the character in “new.dat”. Go to step 3.
  5. Close “message.dat” and “new.dat”.

The required program is given below:

  #include <stdio.h>
  #include <conio.h>
  main()
  {
     FILE *ptr1, *ptr2;
     char ch;
     ptr1 = fopen(“message.dat”, “r”);
     if (!ptr1)
    {
    printf (“
 The file %s cannot be opened”, "message.dat”);
    exit(1);
  }

  ptr2 = fopen(“new.dat”, "w”);
  if (!ptr2)
  {
      printf (“
 The file %s cannot be opened”, "new.dat”);
      exit(1);
    }
    clrscr();
    while (!feof(ptr1))
    {
      ch = fgetc (ptr1);
      fputc( ch, ptr2);
    }
    fclose (ptr1);
    fclose (ptr2);
  }

The efficacy of the above program can be verified by opening the “new.dat” either in notepad or in the Turbo-C editor.

It may be noted that till now we have used programs which are rigid in nature, i.e., the programs work on particular files. For instance, the above program works on “message.dat” and “new.dat” files and will not work with other files. This situation can be easily handled by taking the name of the file from the user at run time. Consider the program segment given below:

  .
  .
  .
  char filename [20];
  FILE *ptr;
  printf(“
 Enter the name of the file to open for reading)”; 
  scanf(“%s”, filename);
  ptr = fopen(filename, "r”);
  .
  .
  .

The above program asks the user for the name of the file to be opened giving freedom to the user to opt for any of the available files or to provide altogether a new name for a file.

Example 2: Write a program that asks from the user for the file to be opened and then displays the contents of the file.

 

Solution: The required program is given below:

  #include <stdio.h>
  #include <conio.h>
  main()
  {
    char filename[20], ch;
    FILE *ptr;
    printf(“
 Enter the name of the file to be opened for reading:”);
    scanf(“%s”, filename);
    ptr = fopen(filename, "r”);
    if (!ptr)
    {
     printf (“
 The file %s cannot be opened”, filename);
     exit(1);
    }
    clrscr();
    while ((ch=fgetc(ptr)) != EOF)
      printf (“%c”, ch);
    fclose (ptr);
  }
Sample Input: Enter the name of the file to be opened for reading: new.dat
  Output: When an apple fell, Newton was disturbed;
but when he found that all apples fell;
it was gravitation and he was satisfied.

 

It may be noted that in the above program, instead of feof(), the keyword EOF has been used to detect the end of file. This is another method of doing the same thing. In fact, it is especially useful where a file has to be read character by character as was the case in the above program.

Example 3: Write a program that reads a file of numbers and sorts the numbers in ascending order. The sorted numbers are stored in a new file.

 

Solution: Assume that the input file (say “datafile.dat” contains the numbers which need to be sorted. The getw() function would be used to read the numbers from the file into an array of integers called List. The sorted list of numbers would be finally stored in an output file (say “sorted file.dat”).

The required program is given below:

  /* This program reads a file of numbers, sorts them and
  writes the sorted list into a new file */
  
  void sort (int List[100], int N);
  #include <stdio.h>
  main()
  {
    FILE *infile, *outfile;
    int List[100];
    int i, j, Num;
    char input_file[20], output_file[20];
    printf(“
 Enter the name of Input file:”);
    scanf(“%s”, input_file);
    printf(“
 Enter the name of output file:”);
    scanf(“%s”, output_file);
    infile = fopen (input_file, "r”);
    if (! infile)
    {
     printf (“
 The file %s cannot be opened”, input_file);
     exit(1);
    }
    outfile = fopen (output_file, "w”);
    if (! outfile)
    {
     printf (“
 The file %s cannot be opened”, output_file);
     exit(1);
    }
    /* read the input file */
    i = -1;
    while (!feof(infile))
    { i++;
    Num = getw(infile);
    /* Do not include EOF */
    if(!feof(infile)) List[i] = Num;
    }
    /* Sort the list */
    sort(List, i);
    /* write into the output file */
    for (j = 0; j <= i; j++)
      putw(List[j], outfile);
    fclose(infile);
    fclose(outfile);
  }
  void sort (int List[100], int N)
  {
    int i, j, small, pos, temp;
    for (i = 0; i < N − 1; i++)
    {
     small = List[i];
     pos = i;
     for (j = i + 1; j < N; j++)
    {
      if (List [j] < small)
     {
      small = List[j];
      pos = j;
     }
    }
    temp = List[i];
    List[i] =List[pos];
    List[pos] = temp;
   }
  }

Note: The files created in the above program cannot be verified by opening them in normal text editor like notepad. The reason is that the functions getw() and putw() read/write the numbers in a file with a format different from text format.

Therefore, a file consisting of numbers can be read by getw() function. In fact, following program can be used to create the datafile.dat.

  #include <stdio.h>
  main()
  {
    FILE *ptr;
    int val, i;
    ptr = fopen(“datafile.dat”, "w”);
    do
    {
     printf (“
 Enter a value”);
     scanf (“%d”, &val);
     if (val != −9999) putw(val, ptr);
    }
    while (val != −9999);
    fclose(ptr);
  }

The numbers are written in the file as long as system does not encounter −9999, a number used to identify the end of the list.

Similarly, the following program can be used to see the contents of a file (say “sortedfile.dat”)

  #include <stdio.h>
  main()
  {
    FILE *ptr;
    int val, i;
    ptr = fopen(“sortedfile.dat”, "r”);
    printf (“
”);
    while (!feof (ptr))
    {
     val =getw(ptr);
     if (!feof(ptr)) printf (“%d ”, val); /*Do not print EOF*/
    }
    fclose(ptr);
  }

It may be further noted that both the programs take care that the EOF (a number) does not get included into the list of numbers, being manipulated by them.

9.6.3 Formatted File I/O Operations

‘C’ supports fscanf() and fprintf() functions to read or to write from files. The general format of these functions is given below:

fscanf (<file pointer>, <format string>, <argument list>);

fprintf (<file pointer>, <format string>, <argument list>);

 

where <file pointer> is the pointer to the file in which I/O operations are to be done.

<format string> is the list of format specifiers, i.e., %d, %f, %s, etc.

<argument list> is the list of arguments.

Example 4: Write a program that takes a list of numbers from the user through standard input device, i.e., keyboard. The number −9999 marks the end of the list. The list is then written on a user defined file by using fprintf() function.

 

Solution: The required program is given below:

  #include stdio.h
  main()
  {
    FILE *ptr;
    int val, i;
    char outfile[20];
    printf(“
 Enter the name of the file :”);
    scanf(“%s”, outfile);
    ptr = fopen(outfile, "w”);
    do
    {
    printf (“
 Enter a value”);
    scanf (“%d”, &val);
    if (val != −9999) fprintf(ptr, “%d ”, val);
   }
   while (val != −9999);
   fclose(ptr);
  }

Example 5: Use the file created in Example 4. Read the list of numbers contained in the file using fscanf() function. Print the largest number in the list.

 

Solution: The numbers from the file would be read one by one and compared for getting the largest of them. After EOF, the largest would be displayed.

The required program is given below:

  #include stdio.h
  main()
  {
    FILE *ptr;
    int val, i, large;
    char infile[20];
    printf(“
 Enter the name of the file:”);
    scanf(“%s”, infile);
    ptr = fopen(infile, "r”);
    printf(“
 The list is ...”);
    large = −9999;
    while (1)
    {
     fscanf(ptr,"%d”, &val);
     if (feof(ptr)) break;
     printf (“%d ”, val);
     if (large < val) large = val;
    }
    printf(“
 The largest is: %d”, large);
    fclose(ptr);
  }

Sample output:

Enter the name of the file: Mydata.dat
The list is 12 34 56 78 32 41 21 13
The largest is: 78.

9.6.4 Reading or Writing Blocks of Data in Files

A block of data such as an array or a structure can be written in a file by using fwrite() function. Similarly, the block of data can be read from the file using fread() function.

The general formats of fread() and fwrite() functions are given below:

fread(<address of object>, <size of object>, <number of items>, <file pointer>);

fwrite(<address of object>, <size of object>, <number of items>, <file pointer>);

 

where <address of object> is the address or pointer to the object from which the data is to be read/ written on the file and vice versa.

<size of object> is computed by the function sizeof() and included in the argument list

<number of items> is the number of data items to be read or written. Generally, it is set as 1.

<file pointer> is the pointer to the file from which data is to be read or written.

Let us now try to write the following structure into a file (say test.dat):

  struct stud {
    char name [20];
    int roll;
  };

The following statements can be used to do the required task:

  FILE *ptr;
  struct stud {
     char name [20];
     int roll;
  };
  struct stud ob = {"Ram”, 101};
  ptr = fopen (“test.dat”, "w”);
  fwrite (& ob, sizeof (struct stud), 1, ptr);
  fclose (ptr);

A similar code can be written to read the structure from a file.

A complete program that writes a structure into a file and then reads and displays it, is given below:

  #include <stdio.h>
  main()
  { FILE *ptr;
    struct stud {
      char name[20];
      int roll;
    };
    struct stud ob1;
    struct stud ob ={"Ram”,101};
    ptr = fopen(“test.dat”, "w”);
    fwrite (&ob, sizeof (struct stud), 1, ptr);
    fclose(ptr);
    ptr = fopen(“test.dat”, "r”);
    fread (&ob1, sizeof (struct stud), 1, ptr);
    fclose(ptr);
    printf (“
 %s”, ob1.name);
    printf (“
 %d”, ob1.roll);
  }

Example 6: Write a program that creates a file called “Marks.dat” and writes the records of all the students studying in a class.

 

Solution: The required program is given below:

  #include <stdio.h>
  struct student {
     char name[20];
     int roll;
     int marks;
};
main()
{    FILE * ptr;
     struct student studob;
     int t = sizeof (struct student);
     ptr = fopen (“marks.dat”, "w”);
     printf (“
 Enter the student data terminated by roll = −9999”);
     while (1)
     {
       printf (“
Name:”); scanf(“%s”, studob.name);
       printf (“
Roll:”); scanf(“%d”, &studob.roll);
       if (studob.roll == −9999) break;
       printf (“
marks:”); scanf(“%d”, &studob.marks);
       fwrite(&studob, t, 1, ptr);
     }
     fclose (ptr);
  }

Example 7: A file called “Marks.dat” contains the records of students having the following structure:

  struct student
  {
    char name [20];
    int roll;
    int marks;
  };

Write a program that reads marks and creates the following two files:

  1. Pass.dat” should contain the roll numbers of students scoring more than or equal to pass-marks stored in a variable called pass_marks.
  2. FAIL.dat” should contain the roll numbers of students scoring below the pass_marks.

Solution: The required program is given below:

  #include <stdio.h>
  struct student {
   char name[20];
   int roll;
   int marks;
  };
  main()
  { FILE * ptr, *p, *f;
  struct student studob;
  int pass_marks;
  int t = sizeof (struct student);
  ptr = fopen (“marks.dat”, "r”);
  p = fopen(“pass.dat”, "w”);
  f = fopen (“fail.dat”, "w”);
  printf (“
 Enter the passing parks :”);
  scanf (“%d”, &pass_marks);
  while (!feof(ptr))
  {
     fread(&studob,t,1,ptr);
     if (feof(ptr)) break;
     if( studob.marks >= pass_marks)
       fprintf (p, "%d ”, studob.roll);
     else
       fprintf (f,"%d ”, studob.roll);
  }
  fclose (ptr);
  fclose (p);
  fclose(f);
  }

Example 8: Write a program that opens the “pass.dat” and “fail.dat” files created in the program in Example 7 and displays two separate lists of roll numbers who have passed and failed in the examination.

 

Solution: The required program is given below:

  #include <stdio.h>
  main()
  { int roll;
  FILE *p, *f;
  p = fopen(“pass.dat”, "r”);
  if (! p)
  {
       printf (“
 The file %s cannot be opened”, "pass.dat”);
       exit(1);
  }
  f = fopen (“fail.dat”, "r”);
  if (! f)
  {
      printf (“
 The file %s cannot be opened”, "fail.dat”);
      exit(1);
  }
  printf (“
 The list of pass students :”);
  while (! feof(p))
  {
      fscanf(p,"%d”, &roll);
      if (!feof(p)) printf (“%d ”, roll);
      roll = getch();
  }
  printf (“
 The list of fail students :”);
  while (! feof(f))
  {
      fscanf(f,"%d”, &roll);
      if (!feof(f)) printf (“%d ”, roll);
  }
  fclose (p);
  fclose(f);
  }
  }
9.7 SEQUENTIAL FILE ORGANIZATION

This file organization is the simplest way to store and retrieve records of a file. In this file, the records are stored in a meaningful order according to a key field. The first record in the order is placed at the beginning of the file. The second record is stored right after the first, the third after the second, and so on. However, the records may be ordered in ascending or descending order by the key field which can be numeric (such as student roll number) or alphabetic (such as student name). It may be noted that the order never changes afterwards. The arrangement of records in a sequential file is shown in Figure 9.8.

 

Arrangement of records in a file

 

Fig. 9.8 Arrangement of records in a file

 

Since all records in the file are stored sequentially by position, the records can be identified by the key field only.

9.7.1 Creating a Sequential File

The sequential file can be created on a storage device (magnetic tape or disk) by the following three steps:

  1. A name for the file is chosen. The system is requested to open a file on the storage device with the chosen file name.
  2. The records for the file are input sequentially one by one into the computer which in turn stores them in the order of their arrival on to the file.
  3. After all the records are transferred into the file, the system is requested to close the file.

A flow chart for this process is given in Figure 9.9. The above mentioned steps are carried out with the help of a program written in a high level language. All the high level languages, such as BASIC, FORTRAN, PASCAL and ‘C’, support sequential files.

 

Creation of a sequential file

 

Fig. 9.9 Creation of a sequential file

9.7.2 Reading and Searching a Sequential File

Suppose student data of an engineering college is maintained in a file (say “stud.dat”)

Let us assume that on a particular day, the principal of the school requires some information from the file called stud.dat. Now, the obvious step is to read the file to get the required information. The read operation for a sequential file is explained below.

To read a sequential file, the system always starts at the beginning of the file and the records are read one by one till the required record is reached or end of the file is encountered. The end of the file (EOF) indicates that all the records in the file have been read. For instance, if the desired record happens to be 50th one in a file, the system starts at the first record and reads ahead one record at a time until the 50th is reached.

The reading of a file involves the following operations:

  1. Open the file.
  2. Read a record.
  3. Check if the record is the desired one. If yes, then display information and perform step 6.
  4. Check for the end of the file (EOF). If yes, then perform step 6.
  5. Go to step 2.
  6. Close the file.

A flow chart for the reading of file is given in Figure 9.10.

 

Reading sequential file

 

Fig. 9.10 Reading sequential file

 

The step 3, i.e., check if the record is the desired one is carried out by matching the key field of the record read from the file with the key field of the desired record. For example, if the principal desires the information about a student whose roll number is 125 then the ROLL field of each record read from the file will be compared with the value 125. The process will be repeated till a record with ROLL equal to 125 is encountered.

9.7.3 Appending a Sequential File

The append operation is done with a view of adding more records to an existing file. In this operation, the file is opened and is read record by record, till EOF is encountered. The new records which are to be added to the file are then written into the file. Once all the records have been added, the file is closed. Thus, the following operations are done for the purpose of appending a file:

  1. Open the file for append operation.
  2. Read the file till EOF is encountered.

  3. Read the record to be added.
  4. Write the record on the file.
  5. Close the file.

A flow chart for appending of a file is given in Figure 9.11.

 

Appending a sequential file

 

Fig. 9.11 Appending a sequential file

Example 9: Write a program that creates a sequential file of records of students who are players of different games. The structure of student record is given below:

  struct student
  {
  char name [20]
    int roll;
    char class [5];
    char game [15];
  };

Solution: The required program that creates the file (say “Play_Master.dat”) is given below:

  /* This program creates a sequential file */
  
  #include <stdio.h>
  struct student {
    char name[20];
    int roll;
    char class[5];
    char game[15];
  };
  main()
  {
     FILE *ptr;
     char myfile[15];
     int t = sizeof(struct student);
     struct student studrec;
     printf(“
 Enter the name of the file:”);
     scanf(“%s”, myfile);
     ptr = fopen (myfile, "w”);
     printf(“
 Enter the records of the students one by one”);
     studrec.roll = 0;
     while (studrec.roll != −9999)
     {
       printf(“
Name:”); fflush(stdin); gets(studrec.name);
       printf(“
Roll:”); scanf(“%d”, &studrec.roll);
       printf(“
Class:”); fflush(stdin); gets(studrec.class);
       printf(“
Game:”); fflush(stdin); gets(studrec.game);
       if (studrec.roll != −9999)
        fwrite(&studrec, t, 1, ptr);
     }
     fclose (ptr);
  }

Example 10: Write a program that uses “Play_Master.dat” created in Example 9. For a given game, it displays the data of all the students who play that game.

 

Solution: The required program is as follows:

  /* This program searches a sequential file */
  #include <stdio.h>
  struct student {
    char name[20];
    int roll;
    char class[5];
    char game[15];
  };
  main()
  {
    FILE *ptr;
    char game[15], myfile[15];
    int t = sizeof(struct student);
    struct student studrec;
    printf(“
 Enter the name of the file to be opened”);
    scanf(“%s”, myfile);
    ptr = fopen (myfile, "r”);
    printf(“
 Enter the name of the game:”);
    fflush(stdin);
    gets(game);
    fread(&studrec,t,1,ptr);
    while (!feof(ptr))
    {
     if (! strcmp(game, studrec.game))
     { printf(“
Name =%s”, studrec.name);
     printf(“
Roll =%d”, studrec.roll);
     printf(“
class =%s”, studrec.class);
     printf(“
Game =%s”, studrec.game);
    }
    fread(&studrec,t,1,ptr);
    }
    fclose(ptr);
 }

Example 11: Write a program that opens the “Play_Master.dat” file and appends records in the file till the roll = –9999 is encountered.

 

Solution: The required program is given below:

  /* This program appends records in a sequential file */
  #include <stdio.h>
  struct student {
    char name[20];
    int roll;
    char class[5];
    char game[15];
  };
  main()
  {
    FILE *ptr;
    char myfile[15];
    int t = sizeof(struct student);
    struct student studrec;
    printf(“
 Enter the name of the file:”);
    scanf(“%s”, myfile);
    ptr = fopen (myfile, "r+”);
    printf(“
 Enter the records to be appended ”);
    while (!feof (ptr))
     fread(&studrec,t,1,ptr);
    studrec.roll=0;
    while (studrec.roll !=−9999)
    {
     printf(“
Name:”); fflush(stdin); gets(studrec.name);
     printf(“
Roll:”); scanf(“%d”, &studrec.roll);
     printf(“
Class:”); fflush(stdin); gets(studrec.class);
     printf(“
Game:”); fflush(stdin); gets(studrec.game);
     if (studrec.roll != −9999)
      fwrite(&studrec, t, 1, ptr);
    }
    fclose (ptr);
  }

It may be noted that in the above program, the file was opened in “r+” mode. In fact, the same job can be done by opening the file in “a”, i.e., append mode. The program that uses this mode is given below:

  /* This program appends records in a sequential file */
  #include <stdio.h>
  struct student {
    char name[20];
    int roll;
    char class[5];
    char game[15];
  };
  main()
  {
    FILE *ptr;
    char myfile[15];
    int t = sizeof(struct student);
    struct student studrec;
    printf(“
 Enter the name of the file:”);
    scanf(“%s”, myfile);
    ptr = fopen (myfile, "a”);
    printf(“
 Enter the records to be appended”);

    studrec.roll = 0;
    while (studrec.roll != −9999)
    {
      printf(“
Name:”); fflush(stdin); gets(studrec.name);
      printf(“
Roll:”); scanf(“%d”, &studrec.roll);
      printf(“
Class:”); fflush(stdin); gets(studrec.class);
      printf(“
Game:”); fflush(stdin); gets(studrec.game);
      if (studrec.roll != −9999)
        fwrite(&studrec, t, 1, ptr);
    }
    fclose (ptr);
  }

Example 12: Modify the program written in Example 11 so that it displays the contents of a file before and after the records are appended to the file.

 

Solution: A function called show() would be used to display the contents of the file. The required program is given below:

  /* This program displays the contents before and after it appends records in a sequential file */
  
  #include <stdio.h>
  void show(FILE *p, char x[15]);
  struct student {
    char name[20];
    int roll;
    char class[5];
    char game[15];
  };
  main()
  {
    FILE *ptr;
    char myfile[15];
    int t = sizeof(struct student);
    struct student studrec;
    printf(“
 Enter the name of the file:”);
    scanf(“%s”, myfile);
    printf(“
 The Records before append”);
    show(ptr, myfile);
    ptr = fopen (myfile, "a”);
    printf(“
 Enter the records to be appended ”);
    studrec.roll=0;
    while (studrec.roll !=−9999)
    {
      printf(“
Name:”); fflush(stdin); gets(studrec.name);
      printf(“
Roll:”); scanf(“%d”, &studrec.roll);
      printf(“
Class:”); fflush(stdin); gets(studrec.class);
      printf(“
Game:”); fflush(stdin); gets(studrec.game);
      if (studrec.roll != −9999)
        fwrite(&studrec, t, 1, ptr);
    }
    fclose (ptr);
    printf(“
 The Records after append”);
    show(ptr, myfile);
  }
  void show(FILE *p, char myfile[15])
  {
    struct student studrec;
    p=fopen(myfile, "r”);
    fread(&studrec, sizeof(studrec),1,p);
    while (!feof(p))
    {
      printf (“
Name:”); fflush(stdout); puts(studrec.name);
      printf(“
Roll:”); printf(“%d”, studrec.roll);
      printf(“
Class:”); fflush(stdout); puts(studrec.class);
      printf(“
Game:”); fflush(stdout); puts(studrec.game);
      fread(&studrec, sizeof(studrec),1,p);
    }
    fclose(p);
  }

9.7.4 Updating a Sequential File

The updation of a file means that the file is made up-to-date with the latest changes relating to it. The original file is known as a master file or old master file and the temporary file which contains the changes or transactions is known as transaction file. Examples of transactions are making purchases, payment for purchases, total sales in the day, etc.

In order to update a sequential file, the transactions are sorted according to the same key used for the old master file, i.e., both the files are sorted in the same order on the same key. Thus, the master file and the transaction file become co-sequential. A new file called new master file is opened for writing. The old master file and the transaction file are merged according to the following logic:

“The key of the record from the transaction file is compared with key of the record from the old master file. If identical, the transaction record is written on the new master file. Otherwise, the master record is written on the new master file’’.

 

Transaction processing

 

Fig. 9.12 Transaction processing

Example 13: A file called old master of a bank contains the records of saving fund A/C of its customers in ascending order of account numbers. The format of the record is given below:

  Name
  Acnt_No
  Balance_Amt

A file called transaction file contains the details about transactions done in A/C on a particular day. It also contains the records in the ascending order of A/C numbers. Each record of that file has the following format:

  Acnt_No
  Trans_type
  Trans_amt

The field Trans-amt contains the amount withdrawn or deposited to the account depending upon the value of Trans-type being 0 or 1, respectively. Write a program that reads the two files and does the transaction processing giving a third file called new master.

 

Solution: In this program, the following menu would be displayed so that the possible actions can be conveniently carried out by the user:

    Menu
    Create old master file   0
    Create transaction file  1
    Generate new master file 2
    Show contents of a file  3
    Quit                     4

The required program is given below:

  /* This program maintains the saving A/C of a bank */

  #include <stdio.h>
  #include <conio.h>
  struct Acnt_Rec {
    char name [20];
    int Acnt_No;
    float Balance_Amt;
  };
  struct Trans_Rec {
    int Acnt_No;
    int Trans_type;
    float Trans_Amt;
  };
  void creat_T(char Trans[15]);
  void creat_O(char O_master[15]);
  void creat_N(char O_master[15],char Trans[15], char N_master[15]);
  void showfile(char fname[15],int f_type);
  main()
  {
  struct Acnt_Rec Acntob;
  struct Trans_Rec Transob;
  char O_master[15], N_master[15], Trans[15], fname[15];
  int choice, f_type;
  /* Show Menu */
   do
  { clrscr();
    printf(“
Menu”);
    printf (“
”);
    printf (“
 Create Old master file   0”);
    printf (“
 Create Transaction file  1”);
    printf (“
 Create New master file   2”);
    printf (“
 Show Contents of a file  3”);
    printf (“
 Quit                     4”);
    printf (“
 Enter your choice:”); scanf (“%d”, &choice);
    switch (choice)
    {
    case 0: clrscr();
        printf (“
 Enter the name of the file”);
        fflush(stdin); gets(O_master); creat_O(O_master);
        break;
    case 1: clrscr();
        printf (“
 Enter the name of the file”);
        fflush(stdin); gets(Trans); creat_T(Trans);
        break;
    case 2: clrscr();
        printf (“
 Enter the name of Old master file”);
        fflush(stdin); gets(O_master);
        printf (“
 Enter the name of New master file”);
        fflush(stdin); gets(N_master);
        printf (“
 Enter the name of Transaction file”);
        fflush(stdin); gets(Trans);
        creat_N(O_master,Trans, N_master);
        break;
    case 3: printf (“
Enter the name of the file to be displayed”);
        fflush(stdin); gets(fname);
        printf (“
 Enter 0/1 for Master/Transaction”);
        scanf (“%d”, &f_type); showfile(fname,f_type);
        break;
    }
    }
    while (choice != 4);
  }
  void creat_O(char O_master[15])
  {
    FILE *ptr;
    struct Acnt_Rec Aob;
    int t = sizeof(Aob);
    ptr = fopen (O_master,"w”);
    printf(“
 Enter the records one by one terminated by A/c = −9999”);
    Aob.Acnt_No=0;

    while (Aob.Acnt_No != −9999)
    {
      printf (“
Name:”); fflush(stdin); gets(Aob.name);
      printf (“
A/C No:”); scanf(“
%d”, &Aob.Acnt_No);
      printf (“
Balance Amount:”); scanf(“
%f”, &Aob.Balance_Amt);
      if (Aob.Acnt_No != −9999) fwrite (&Aob,t,1,ptr);
    }
      fclose(ptr);
  }
  void creat_T(char Trans[15])
  { FILE *ptr;
    struct Trans_Rec Aob;
    int t = sizeof(Aob);
    ptr = fopen (Trans,"w”);
    printf (“
 Enter the records one by one terminated by A/c = −9999”);
    Aob.Acnt_No=0;

    while (Aob.Acnt_No != −9999)
    {
     printf (“
 A/C No:”); scanf(“
%d”, &Aob.Acnt_No);
     printf (“
 Transaction Type (0/1):”); scanf(“
%d”, &Aob.Trans_type);
       printf (“
 Transaction Amount:”); scanf(“
%f”, &Aob.Trans_Amt);
       if (Aob.Acnt_No != -9999) fwrite (&Aob,t,1,ptr);
    }
    fclose(ptr);
  }

  void creat_N(char O_master[15],char Tran[15], char N_master[15])
  {
    FILE *Old, *New, *Trans;
    struct Acnt_Rec Oob;
    struct Trans_Rec Tob;
    int t1, t2;
    t1 = sizeof (struct Acnt_Rec);
    t2 = sizeof(struct Trans_Rec);
       /* open files */
    Old = fopen(O_master, "r”);
    Trans = fopen(Tran, "r”);
    New = fopen(N_master, "w”);
 
      /* perform transaction processing */
  fread(&Oob,t1,1,Old);
  fread(&Tob,t2,1,Trans);
  while (!feof(Old) && !feof(Trans))
    {
      if (Oob.Acnt_No < Tob.Acnt_No)
      {fwrite (&Oob,t1,1,New);
      fread(&Oob,t1,1,Old);
      }
     else
      {
        while ((Oob.Acnt_No == Tob.Acnt_No ) && !feof(Trans))
        {
          if (Tob.Trans_type == 0)
          Oob.Balance_Amt = Oob.Balance_Amt − Tob.Trans_Amt;
          else
          Oob.Balance_Amt =Oob.Balance_Amt + Tob.Trans_Amt;
         fread(&Tob,t2,1,Trans);
      }
      fwrite (&Oob,t1,1,New);
      fread(&Oob,t1,1,Old);
     }
  }
       /*Copy rest of the file*/
  while (!feof(Old))
  {
   fwrite (&Oob,t1,1,New);
   fread(&Oob,t1,1,Old);
  }
       /*Close files */
 fclose(Old);
 fclose(New);
 fclose(Trans);
}
void showfile(char fname[15],int f_type)
{   FILE *ptr;
    char ch;
    struct Acnt_Rec Aob;
    struct Trans_Rec Tob;
    int t1 = sizeof (Aob);
    int t2 = sizeof(Tob);
    if (f_type == 0)
    {
      ptr = fopen (fname, "r”);
      fread (&Aob,t1,1,ptr);
      while(!feof(ptr))
      {
        printf (“
Name:”); fflush(stdout); puts(Aob.name);
        printf (“
A/C No:”); printf(“
%d”, Aob.Acnt_No);
        printf (“
Balance Amount:”); printf(“
%f”, Aob.Balance_Amt);
        fread (&Aob,t1,1,ptr);
        ch = getch();
      }
    }
    else
    { ptr = fopen (fname, "r”);
      fread (&Tob,t2,1,ptr);
      while(!feof(ptr))
      {
       printf (“
 A/C No:”); printf(“
%d”, Tob.Acnt_No);
       printf (“
 Transaction Type:”); printf(“
%d”, Tob.Trans_type);
       printf (“
 Transaction Amount:”); printf(“
%f”, Tob.Trans_Amt);
       fread (&Tob,t2,1,ptr);
       ch = getch();
     }
    }
    fclose(ptr);
  }
9.8 DIRECT FILE ORGANIZATION

The direct files allow records to be read or written on to a file without proceeding sequentially from the beginning. In this organization, the records are not stored in sequence. To read or write, an address is first calculated by applying a mathematical function to the key field of the record. The record is then stored at the generated address. The mathematical function is called a Hash function.

However, a poor form of direct access can be obtained in ‘C’ files by using the fseek() function. With the help of this function, the stream file pointer can be positioned at a particular record. It takes three arguments as shown below:

fseek (<file pointer>, <offset>, <start-position>)

where   <file pointer> is the pointer to the file.

            <start position> is the start position of the file. It can have either of the following values

 

      Value Meaning
      0 The starting position is the beginning of the file.
      1 Use the current file pointer as the starting position.
      2 The starting position is the end of the file.

 

<Offset> is the offset, i.e., how much the pointer should advance from the starting position.

From Figure 9.13, it may be noted that file pointer (ptr) is positioned at the beginning of the file because the start position is equal to 0 (zero). The offset (i.e., 4) would move the file pointer to the fourth record.

 

The working of fseek(ptr, 4, 0) function.

 

Fig. 9.13 The working of fseek(ptr, 4, 0) function.

 

Similarly, the fseek(ptr, 9, 2) suggests that from the end of the file move back by 9 records.

Thus, it is a relative file organization wherein the records are accessed directly in relation with the starting point, specified within the file. The offset is usually computed by the following formula:

offset = record number × size of a record

Example 14: Write a program that creates a file of room data of a hotel having following structure. The rooms are numbered starting from 1.

  struct room
  {
    int room_no;
    char room type;
    char status;
  };

where room type may take value S/D, i.e., single bed or double bed. Similarly, status may take value A/N, i.e., available or not available. Use fseek() function to display the information about a particular room of the hotel.

 

Solution: The required program is given below:

  /* This program uses fseek() function to search records in a file */
  
  #include <stdio.h>
  struct room {
    int room_no;
    char room_type;
    char room_status;
  };
  main()
  { FILE *ptr;
    char filename[20];
    int t = sizeof(struct room);
    struct room rob;
    int no_of_rooms, i, choice;
    printf (“
 Enter the name of the file”);
    fflush(stdin); gets(filename);
    printf(“
 Enter the number of rooms”);
    scanf(“%d”,&no_of_rooms);
    /* create the file */
    ptr = fopen(filename, "w”);
    printf (“
 Enter the room data one by one”);
    for (i =1; i<=no_of_rooms; i++)
    { rob.room_no=i;
    printf (“
 Room No. %d:”, i);
    printf(“
 Room_Type (S/D):”);
    fflush(stdin); scanf (“%c”, &rob.room_type);
    rob.room_type=toupper(rob.room_type);

    printf(“
 Room_Status (A/N):”);
    fflush(stdin); scanf (“%c”, &rob.room_status);
    rob.room_status = toupper (rob.room_status);
    fwrite (&rob,t,1,ptr);
    }
    fclose(ptr);
    ptr = fopen(filename, "r”);
    /*search a record */
    do
    {
      printf(“
 Menu”);
      printf(“
”);
      printf(“
 Display info 1”);
      printf(“
 Quit 2”);
      printf(“
 Enter your choice”);
      scanf(“%d”, &choice);
      if (choice == 1)
      {
        printf(“
 Enter the room no.”);
        scanf(“%d”, &i);
        fseek(ptr, (i − 1) * t, 0);
        fread(&rob, t, 1, ptr);
        clrscr();
        printf(“
 Room No.= %d”, rob.room_no);
        printf(“
 Room Type = %c”, rob.room_type);
        printf(“
 Room Status= %c”, rob.room_status);
      }
     else
       break;
}
while (1);
fclose (ptr);
}

The characteristics of a relative file are given below:

  • A relative file has fixed length records.
  • Al records in the file are written and accessed with the help of a record number.
  • Unless the record number for a record within the file is known, one cannot gain access to the information that the record contains.
  • The file is open for both writing and reading operations at once.

The advantages of direct files are given below :

  • Any record can be directly accessed.
  • File processing and updation activities can be performed without the creation of new master file.
  • Speed of record processing in case of large files is very fast as compared to sequential files.
  • The files can be kept up-to-date because on-line updation is possible.

  • Concurrent processing of several files is possible. For example, when a sale is recorded in a company, the account receivable can be posted on one file and simultaneously the inventory withdrawal can also be written on another file.
9.9 INDEXED SEQUENTIAL ORGANIZATION

A very large number of applications require a mixture of sequential and direct processing. For example, in an inventory control system, it is desired that at regular intervals the transactions be processed sequentially in a file and if needed, make direct accesses inquiries into the same file. File organization using the Indexed Sequential Access Method (ISAM) provide the essential benefits of both the sequential and random methods.

The indexed organization is similar to a telephone directory wherein one can retrieve a telephone number by using an index provided at the beginning. In this organization, the records of the file are stored sequentially in blocks on the disk. Each block can store a specified amount or set of of records. The records in this file can be accessed through an index. An index is a separate file from the original file. Each entry into the index contains only two items of data: the value of the keyfield of last record in the block and its corresponding starting block address (see Figure 9.14 ).

 

Indexed sequential organization

 

Fig. 9.14 Indexed sequential organization

9.9.1 Searching a Record

To search a specified record in an indexed sequential file, the index is first searched to find the block in which the key of the required record is present. When index entry is found, the address of the corresponding block containing the record on the disk is noted and then whole of the block is brought in the

main memory. Once the block is brought inside the main memory, the record is searched sequentially in the block.

It may be noted from Figure 9.14 that each entry in the index contains the highest key value for any record in the block and the starting address of the block. Now if we want to search a record with key value 376, then the index is searched first. The first entry (110) of the index is compared with the search key (376). Since 110 is the highest key value in its corresponding block and it is less than the search key (376), the comparison with next entry is done. The comparison continues till it reaches to third entry and it is found that the key of the entry (417) is larger than the search key (376). Thus it is established that the required record should be on its corresponding block. The block’s starting address is 4127. Now the access is made to disk address 4127 and the block is brought into the main memory. The search key is compared with key of the first record of the block (370). Then it moves on to the second record and the process is repeated till it reaches to the third record (key = 376). The keys match establishing the fact that the required record has been found. Now, it can perform the desired operation on the record such as display the contents, print certain values, etc.

9.9.2 Addition/Deletion of a Record

When records are added to an already existing indexed sequential file, the system inserts them at proper places so as to retain the sequential nature of each block. For example, assume that records with keys 217 and 371 are to be added into the file shown in Figure 9.14. The record with key 217 is searched into the file and its exact location where the record is to be inserted i.e. in the block starting with address 4130 and after the record with key value 216. Figure 9.15 shows that the record with key 217 has been inserted after record with key 216 and the rest of the records have been moved down to create space for the incoming record.

 

Operations on indexed sequential file

 

Fig. 9.15 Operations on indexed sequential file

 

The addition of record (371) will push the record (417) out of the Block 3. The reason being that the block is already full, and to accommodate the incoming record (371) the record from the extreme end has to leave the block. The overflowed record is then stored in a separate block known as overflow block. The deletion of a record from the file is logical deletion, i.e., the record is not physically or actually deleted from the file but it is marked with special characters to indicate that the record is no longer accessible. For example, if the records with key value 002 and 219 are to be deleted then these records are searched in the file. If they are found then the records are marked with special characters (<> in our case) (see Figure 9.15 ). The presence of ‘< >’ in a record indicates that the record has been deleted.

The modifications in a record involves the following steps

  1. Search the record
  2. Read the record
  3. Change the record
  4. Rewrite the changed record in its original location.

The ISAM files are very flexible in the sense that they can be processed either sequentially or randomly, depending on the requirements of the user.

9.9.3 Storage Devices for Indexed Sequential Files

The magnetic disks are the most suitable storage media for Indexed sequential files. The ISAM files are mapped on to the cylinders of the disk. We know that the index file consists of three parts: index, main file (data part), and overflow area. A cylinder on the disk is accordingly divided into three parts: index area, prime area, and overflow area as shown in Figure 9.16

 

ISAM on a cylinder of a magnetic disk

 

Fig. 9.16 ISAM on a cylinder of a magnetic disk

  • Index area: The first track in each cylinder is reserved for an index. This index describes the storage of records on the various tracks of the cylinder.
  • Prime area (Data tracks): The various records of the file are written on this area on a cylinder always starting from the 2nd track. The records are recorded sequentially along the various tracks. The highest key on the track and the track address are entered into the index.
  • Overflow area: The area is created to accommodate the overflowed records in the file. The overflow area is generally the last track on the same cylinder. This area is unoccupied at the time of creation of file.

9.9.4 Multilevel Indexed Files

If the file is so large that it cannot be accommodated on one cylinder then the records of the file are stored on many cylinders. To handle this situation, a separate index known as cylinder index is maintained to indicate how records are distributed over a number of cylinders. Therefore, we have a hierarchy of indices in the form of multilevel index as shown in Figure 9.17. The cylinder index has entries consisting of two parts: the highest key value on the cylinder and the cylinder number.

 

Multilevel indexed file

 

Fig. 9.17 Multilevel indexed file

 

To search a record in a multi level index file, the cylinder index is first searched to find the cylinder on which the record is stored. Once the cylinder is known then the track index is searched to find the block on which the record is residing. Rest of the process is same as in the case of single level indexed file.

The advantages of indexed files are as follows:

  • Provides good flexibility for users who need both direct accesses and sequential progressing with the same file.
  • It makes rapid access possible over the indexes.
  • Interactive processing is possible.

The disadvantages of indexed files are as follows:

  • ISAM files generate excessive overflows, and vacant storage locations are created.
  • Extra storage space is required for the index especially when multilevel indexes are maintained.
  • The overflow areas sometimes overflow to other cylinders and thus cause much read/write head movement making the access very slow. Therefore, the file has to be reorganized and indexes rearranged accordingly. This is a time consuming process.
9.10 CHOICE OF FILE ORGANIZATION

The choice of a file organization depends on the nature of a given application. How a data file is used, determines which particular file organization method is appropriate for it. The following factors play an important part in the selection of a file organization.

  1. Activity ratio: A record is said to be active if it requires processing in a file. The portion containing records in a file that requires processing is called as activity of a file. The ratio of number of active records and the total number of records in the file is known as activity ratio

    image

    A sequential file can be used if the activity ratio is high, i.e., more than 60–70 per cent. On the other hand, if the activity ratio is very low, then the direct file can be chosen. The indexed sequential files are less efficient than the direct files for low activity. A comparison between the various files organizations is shown in Figure 9.18.

  2. Response time: The response time can be defined as the amount of time elapsed between a demand for processing and its completion. The response time of a sequential file is always very long because it involves both the waiting time i.e. until a batch of transaction is run and the processing time. The direct and indexed sequential files have a faster response time.

    The direct files allow quick retrieval of records. Generally faster response time is comparatively more expansive. Since the direct and indexed files are more up to date, the added cost per transaction is justified.

  3. Volatility: It is the measure of percentage of records added to or deleted from a file during its use over a period of time. Since each file organization requires different methods to add or delete records, the volatility becomes a very important factor as far as file processing and its organization is concerned.

    In a direct file, the process for adding and deleting records is simple and time saving compared to a sequential file. The indexed sequential files are also very volatile. The direct or indexed files have a problem of reorganization and overflow overheads.

  4. Size: The amount of processing required for a file is directly proportional to its size. The size of a file is determined in terms of total number of records in the file. The size of a record is measured in terms of total number of characters in the record.

    Small files do not require any painstaking design. On the other hand large ones require careful design. A small sequential file may be stored on a direct access device to avoid waiting time, i.e., mounting and dismounting of tapes is avoided. Large sequential files are to be stored on a tape.* As far as direct files are concerned, the size has no relevance

  5. Integration: Generally, a business organization maintains integrated file system that allows online updation of interdependent files. Random and indexed organization allow all the files affected by a particular transaction to be updated online. Sequential files are not suitable for such system of files.
  6. Security: A back up is taken during every run of a sequential file. Therefore a sequential file stored is more secured. In fact, sequential files processing provide automatic data backup. The data stored in direct and indexed files are comparatively not secured. Special techniques such as frequent mirroring of disks, are used to insure file integrity. On the other hand the magnetic tapes are more prone to physical damage.

 

Impact of file activity ration on a file type

 

Fig. 9.18 Impact of file activity ration on a file type

9.11 GRADED PROBLEMS

Problem 1: A macro processor is a text substitution program where macro consists of a macro name and its definition as shown below:

 

Macro name Macro definition (replacement text)
YMCA YMCA institute of Engineering

The macro processor replaces all occurrences of macro name in a document by its corresponding definition. Write a program that takes a text in which the macros are defined at the beginning by the statements such as given below. The definitions end by the keyword “MEND”

 

#define CE Computer Engineering
#define PC Personal computer
MEND
<text of the document>

 

The program implements the macro processor, i.e., reads the macros and their definitions and does the text substitution for each macro call.

 

Solution: The following data structures would be employed to do the required task:

  1. A structure to store a macro name and its definition.
    struct macro
    {
        char Name [10];
        char Mdef [50];
    };
  2. An array of structures of type macro to store all macro definitions.
    struct macro Mlist [15]

The program would require the following functions:

Function Description
1. get-taken() : to read a word from the input text document.
2. build-Mtable() : to build a table of macro names and definitions using the array of structure, i.e., Mlist [ ].
3. writeout() : write the output to the output text file.

A complete program that does the required task is given below:

/* This program implements a macro processor, a text substitution
program */
#include <stdio.h>
struct macro /* to store a macro */
{
    char Mname[10];
    char Mdef[50];
};
FILE *infile, *outfile;
/* A function to build Macro table */
void build_Mtable(struct macro list[15], FILE *ptr);
/* function to read a word from input text file */

void get_token (FILE *infile, char token[20], char *break_point , int
*flag);
char inputfile[15], outputfile[15];
/* function to write a word to output text file */
void writeout(FILE *outfile, char token[20],char ch, struct macro Mlist[15]);
main()
{
    char token[20];
    char break_point;
    int flag, j;
    char ch;
    struct macro Mlist[15] ;
    printf (“
 Enter the name of input file:”);
    fflush(stdin); gets(inputfile);
    printf (“
 Enter the name of output file:”);
    fflush(stdin); gets(outputfile);
    infile = fopen(inputfile, "r”);
    outfile = fopen(outputfile, "w”);
    build_Mtable(Mlist, infile);
    flag = 0;
    clrscr();
    /* flag == 3 indicates EOF encountered */
    while (!feof(infile) && flag != 3)
    { flag=0;
    token[0] =’’;
    ch= ’';
    get_token(infile, token, &ch, &flag);
    writeout(outfile, token, ch, Mlist);
    }
    fclose(infile);
    fclose(outfile);
} /* end of main */

void get_token(FILE * infile, char token[30], char *break_pt, int *flag)
{ int i;
    char ch;
    i = −1;
    while (!(*flag))
    { ch = fgetc(infile); if (ch == EOF) { *flag = 3; return; }
    switch(ch)
    {     /* break points for words or tokens */
     case ’
’:
     case ’ ’ :
     case ’,’ : /* flag == 1 indicates that a break point occurred */
     case ’.’ :
     case ’;’ : *break_pt = ch; *flag = 1; token[++i] = ’’;
      break;
    default: token[++i] = ch;
    }
    }
} /* end of get_token */

void build_Mtable(struct macro list[15], FILE *ptr)
{ char token[20], ch1, temp[2];
int i;
token[0]=’’;
i =-1;
while (strcmp(token,"MEND”))
{ int flag = 0;
char ch =’';
get_token(ptr,token, &ch, &flag);
if (!strcmp(token, "define”))
{ i++;
flag=0;
ch=’';
get_token(ptr,token, &ch, &flag);
strcpy (list[i].Mname, token);
list[i].Mdef[0]=’’;
while (ch != ’
’)
{ flag=0;
ch =’';
get_token(ptr,token, &ch, &flag);
strcat(list[i].Mdef , token);
if (ch != ’
’)
{ temp[0] = ch;
temp [1] =’’;
strcat(list[i].Mdef , temp);
}
}
}
}
i++; /* Marks the end of the macro list*/
strcpy (list[i].Mname,"END”);
} /* end of build_Mtable */

void writeout(FILE *outfile,char token[20], char ch, struct macro Mlist[15])
{
      int i = 0;
      while (strcmp(Mlist[i].Mname, "END”))
      {
      /* replace macro by its definition */
      if (!strcmp(Mlist [i].Mname, token ))
      { fputs(Mlist[i].Mdef, outfile);
      fputc(ch, outfile);
      return;
      };
      i++;
    }
    fputs(token, outfile);
    fputc(ch, outfile);
  }

Sample Input:

#define ce Computer Engineering
#define ymca YMCA Institute of Engineering
#define aks A. K. Sharma
#define fbd Faridabad
#define MDU Maharishi Dayanand University, Rohtak
MEND

ymca is an Institute situated in fbd. It is a Government of Haryana institute. It is affiliated to MDU. The institute is rated as the best engineering college in the state of Haryana. The ce department is the largest department of the institute. aks works in ce department as a Professor.

Sample Output:

YMCA Institute of Engineering is an Institute situated in Faridabad. It is a Government of Haryana institute. It is affiliated to Maharishi Dayanand University, Rohtak. The institute is rated as the best engineering college in the state of Haryana. The Computer Engineering department is the largest department of the institute. A.K. Sharma works in Computer Engineering department as a Professor.

Note: The program does not perform syntax checking, i.e., if the terms “define” and “MEND” are misspelled, the program will go hey wire.

Problem 2: Statements in BASIC language are written in such a manner that each statement starts with an integer number as shown below:

  10 REM This is a sample statement
  20 input A, B
  30 goto 150
  :
  :
  :
  100 If (x y) goto 20

Write a program that reads a file of a BASIC program. For a given offset, it adds the offset to all the statement numbers. The arguments of the goto statements should also be modified to keep the program consistent. In fact, this type of activity is done by a loader, i.e., when it loads a program into the main memory for execution, it adds the offset of the address of the main memory to all address modifiable parts of the program such as to goto or jump statements and the like.

Solution: The get_token() and writeout() functions of previous program would be used in this pro-gram to read a token and to write the tokens to a given file. The following functions of stdlib.h would be used to convert a string to integer and vice versa

 

(1) <int> atoi (string) : This function takes a string of characters and converts it into an equivalent integer.
(2) void itoa (int, string, <radix>) : This function converts an integer to an equivalent string. Radix is the radix of the integer such as 2, 10 depending upon the number being binary or decimal.

The required program is given below:

/* This program implements a relative loader */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* function to read a word from input text file */
void get_token (FILE *infile, char token[20], char *break_point , int
*flag);
char inputfile[15], outputfile[15];
/* function to write a word to output text file */
void writeout(FILE *outfile,char token[20],char ch);
main()
{
    FILE *infile, *outfile;
    char token[20];
    char last_token[20]="”; 
    char break_point;
    int flag, j, temp;
    int offset;
    char ch, ch1;
    printf (“
 Enter the name of input file:”);
    fflush(stdin); gets(inputfile);
    printf (“
 Enter the name of output file:”);
    fflush(stdin); gets(outputfile);
    printf (“
 Enter the value of offset (int):”);
    scanf(“%d”, &offset);
    infile = fopen(inputfile, "r”);
    outfile = fopen(outputfile, "w”);
    flag = 0;
    clrscr();
    ch1 = ’
’;
    /* flag == 3 indicates EOF encountered */
    while (!feof(infile) && flag != 3)
    { flag=0;
    token[0] =’’;
    ch= ’';
    get_token(infile,token, &ch, &flag);
    /* Check if it is a number appearing at the
    beginning of a line or as argument of
    goto statement */
    if ((isdigit (token [0]) && ch1 ==’
’ ) || (isdigit (token [0]) &&
    (!strcmp(last_token, "goto”))) )
    { temp = atoi(token);
    temp = temp + offset;
    itoa(temp,token,10);
    }
    writeout(outfile,token,ch);
    ch1 = ch;
    strcpy(last_token ,token);
    }
    fclose(infile);
    fclose(outfile);
} /* end of main */

void get_token(FILE * infile, char token[30], char *break_pt, int *flag)
{int i;
char ch;
i = -1;
while (!(*flag))
{ ch = fgetc(infile); if (ch == EOF) { *flag = 3; return; }
switch(ch)
{ /* break points for words or tokens */
case ’
’:
case ’ ’:
case ’,’: /* flag == 1 indicates that a break point occurred */
case ’.’:
case ’;’: *break_pt = ch; *flag = 1; token[++i] = ’’;
     break;
default : token[++i] = ch;
}
}
} /* end of get_token */

void writeout(FILE *outfile,char token[20], char ch)
{
    fputs(token, outfile);
    fputc(ch, outfile);
}

Sample input:

   10 Rem this is a loader
   20 Input A, B
   30 If (A 20) goto 20
   40 C 5 A 1 5 * 20;
   50 if (C 50) goto 100
   60 C 5 C 1 B
   70 go to 50
   100 stop
Value of offset 5 50

Sample output:

   60 Rem this is a loader
   70 Input A, B
   80 If (A 20) goto 70
   90 C 5 A 1 5 * 20;
   100 if (C 50) goto 150
   110 C 5 C 1 B
   120 go to 50
   150 stop
EXERCISES
  1. What are the different methods of opening a file? Explain in brief.
  2. Differentiate between fwrite() and fput() functions.
  3. How can the end of a file be detected? Explain in brief.
  4. Write a program which counts the number of record in a given file.
  5. Give suitable declarations for the following files:
    1. A file containing components where each component consists of the following information
      Name: 20 characters
      Code: integer type
      NET: float type
    2. A text file called Book.
  6. Write a program which creates an exact copy of a given file called Ofile in the form of a new file called Nfile. Choose appropriate component type for this problem.
  7. Write a program which counts the number of times a given alphabet stored in variable ch appears in a text file.
  8. Write a program which searches a given file for a record equal to an input value of empcode. The component record structure of the file is as given below:

     

    image

     

    Choose appropriate data types wherever necessary.

  9. Write a program which reads a text file called document and generates a table of frequency count of alphabets appearing in the text. The output should be displayed in the following form:

    Frequency count

    Alphabet
    Count
    A
    B
    C
    .
    .
    .
    Z
  10. A student record is defined as given in Example 5. Write a program which reads a file of such records (say class-file) and prints the result in the following format:
    S. No. Condition No. of Students
    1
    Marks < 50%
    xx
    2
    Marks > 50% and < 60%
    xx
    3
    Marks >= 60% and < 75%
    xx
    4
    Marks >= 75% and < 90%
    xx
    5
    Marks >= 90
    xx

    (Assume Max marks in each subject = 100).

  11. What is EOF? Explain its utility.
  12. Modify Example 11 such that it generates a list of students who secure more than 80 per cent marks.
  13. Write an interactive menu driven ‘C’ program to create a text file and then display the file. Create another text file by converting each line of the newly created text file into a lowercase string. Display the newly created file. In case number of lines exceeds 22, file should be displayed one screen at a time.
  14. Write an interactive menu driven ‘C’ program to create a text file and then display the file. Create another text file by reversing each line of the newly created text file. Display the newly created file. In case number of lines exceeds 22, file should be displayed one screen at a time.
  15. Explain relative files in detail.
  16. Explain indexed sequential organization.
  17. Write an explanatory note on multilevel indexed files.
  18. Define file activity ratio, response time, and volatility.
  19. How records are edited or deleted from an indexed file?
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.227.102.50