FS Lab Manual - 18ISL67-Updated
FS Lab Manual - 18ISL67-Updated
7 Write a program to read two lists of names and then match the
names in the two lists using Consequential Match based on a L3, L6
single loop. Output the names common to both the lists.
8 Write a program to read k Lists of names and merge them using k- L3, L6
File Structures Laboratory with mini project 18ISL67
1. Write a program to read series of names, one per line, from standard input and write
these names spelled in reverse order to the standard output using I/O redirection and
pipes. Repeat the exercise using input file specified by the user instead of the standard
input and output file specified by the user instead of the standard output.
#include<iostream.h>
#include<fstream.h>
#include<conio.h>
#include<string.h>
#include<process.h>
void main()
{
fstream fp1,fp2;
char fin[10],fout[10];
int ch,n,i;
char str[10],name[10][10];
clrscr();
for(;;)
{
cout<<"1:Std Input to Std Output 2:File to Std Output 3:File to File\n";
cout<<"Enter your Choice : ";
cin>>ch;
switch(ch)
{
case 1: cout<<"Enter Number of Records : ";
cin>>n;
cout<<"Enter "<<n<<" Names : ";
for(i=0;i<n;i++)
{
cin>>name[i];
}
cout<<"Reversed names are ... "<<endl;
for(i=0;i<n;i++)
{
strrev(name[i]);
cout<<name[i];
cout<<"\n";
}
break;
case 2: cout<<"Enter the Input Filename : ";
cin>>fin;
fp1.open(fin,ios::in);
while(!fp1.fail())
{
fp1>>str;
strrev(str);
cout<<str;
cout<<"\n";
}
fp1.close();
break;
case 3: cout<<"Enter the Input Filename : ";
cin>>fin;
cout<<"Enter the Output Filename : ";
cin>>fout;
fp1.open(fin,ios::in);
fp2.open(fout,ios::out);
while(!fp1.fail())
{
fp1>>str;
strrev(str);
Department of Information Science and Engineering Page 3
File Structures Laboratory with mini project 18ISL67
fp2<<str;
fp2<<"\n";
}
fp1.close();
fp2.close();
break;
default: exit(0);
}
}
}
Working :
Files are objects of the fstream class, so we first declare 2 file objects, one to be associated for
input and one to be associated for output. We use strrev() defined in string.h to reverse a
string pointed to by str.
Case 1: A set of names is read from the user via cin command, and these are reversed and
displayed onto the screen. File I/O is not used here.
Case 2: We create a file with a set of names in it such that each name is in a separate line. We
open the file in read mode using open() function of fstream class. We then check whether
this open operation actually worked by checking whether file.fail() returned 1 or 0. If it
returned 1, then the file could not be opened. This may be because the filename is given
incorrectly or maybe because we do not have read permission for that file. Otherwise, we go
ahead to access each line (hence each name) in the file using the file>>str statement until we
reach the end of file. file.fail() function also checks for the end of file. It returns 1 if end of file
is reached. Once we get each name into an array of characters str, we again use strrev(str)
to reverse this and display it on to the screen. After all file operations, we close the file with
file.close().
Case 3: The steps in Case 2 are repeated but instead of sending the reversed strings to the
screen, we send it to another file. But this file must first be opened in write mode with
open()and the flag ios::out .
Output of Program 1:
C:>tc>edit file.txt
abc
xyz
2. Write a C++ program to read and write student objects with fixed length records and
the fields delimited by”|”. Implement pack (), unpack(), modify(),and search methods.
#include<iostream.h>
#include<fstream.h>
#include<conio.h>
#include<string.h>
#include<process.h>
fstream fp;
int n=0;
char fname[10];
class student
{
private:
char usn[10], name[10], branch[5];
public:
void pack();
void unpack(char[]);
void display();
void search();
};
cout<<"Branch:"<<t<<endl;
}
void student::display()
{
char buffer[28];
int i,j;
if(n==0)
{
cout<<"No records to display";
return;
}
cout<<"\nFile Contents are \n";
fp.open(fname,ios::in);
for(i=1;i<=n;i++)
{
fp>>buffer;
unpack(buffer);
cout<<endl;
}
fp.close();
}
void student::search()
{
char buffer[28],temp[28];
char key[15];
char *usn;
int i,j,k,choice;
cout<<"Enter the USN to search: ";
cin>>key;
fp.open(fname,ios::in|ios::out);
for(i=1;i<=n;i++)
{
fp>>buffer;
strcpy(temp,buffer);
usn=strtok(temp,"|");
if(strcmp(key,usn)==0)
{
cout<<"\nRecord Found..\n";
unpack(buffer);
cout<<endl;
cout<<"\nDo you wish to modify?\n";
cout<<"\nEnter your choice \n 1.Yes \n 2.No\n";
cin>>choice;
if(choice==1)
{
fp.seekp(-27,ios::cur);
pack();
}
fp.close();
return;
}
}
cout<<"Record not found..!\n";
fp.close();
getch();
}
void main()
{
int i,ch;
student s1;
clrscr();
switch(ch)
{
case 1:
n++;
fp.open(fname,ios::app);
s1.pack();
fp.close();
break;
case 2:
s1.display();
break;
case 3:
s1.search();
break;
case 4:
exit(0);
Department of Information Science and Engineering Page 8
File Structures Laboratory with mini project 18ISL67
default:
cout<<"Invalid Choice..!\n";
}
}
}
Working
We are supposed to store information of many students in a file on the hard disk. For
each student, we get (from the user) and store his name, USN number and branch. Once we
create such a data file, we are supposed to display its contents and be able to search in the
file for a particular student’s information based on his USN number.
In this program, we are required to store this information in some fixed amount of
space, say in x bytes. When data is stored in this way, the data corresponding to each
student is called a “fixed-length record”. Since each character occupies 1 byte of space, we
can store x characters in x bytes. So as to be able to differentiate each of the fields, we store
an inter-field separator, which is specified in the question to be the | character. To
differentiate between 2 records, we have to store an inter-record separator, and we have
chosen the \n character to do this job. Hence, the structure of each fixed-length record that
we have defined is as follows:
In our implementation above, a total of 28 spaces or characters are allocated to store a record
in the file. The first 10 spaces are for storing the name and the next 10 spaces are for storing
the USN number of the student and 5 spaces for storing department. We are going to
frequently open and close files, so we do not want to pass around the file object as a
parameter to the various functions. Therefore we make the fstream object file as a global
parameter. We then define a class called student, into which we put the different fields in a
record as private members, and the functions that work on these fields as public member
functions. In pack(), we take an empty buffer of size 28 characters, populate it with a record
and then write this buffer to the file which we opened in main(). We read student usn, name,
branch from the user. Then using strcpy(buffer,usn), we copy usn entered by the user to the
buffer and concatenate the delimiter “|” to the buffer. Similarly it is repeated for name and
branch fields. We check length of the buffer, if the buffer length is less than 27 then # is
concatenated to the buffer.
Example: buffer contents after copying usn, name and branch fields with delimiter
a b c | 1 J B 0 1 | I S E | # # # # # # # # # # # # # /
0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
In buffer[27] position ‘/0’ end of the string null character is initialized. Then buffer contents
is written to the data file.
In unpack () function, buffer is used as a input parameter to the function. Buffer will contain
the record data in which each field needs to be extracted. Each field is separated by “|
delimiter. So to extract strtok function is used in the program. Strtok takes twp parameters,
string as first parameter and delimiter “|” as a second parameter a token for separating the
string.
char *t;
t= strtok(buffer,"|"); // splits the string into tokens ,
cout<<"USN:"<<t<<endl;
//For each subsequent call to get more tokens out of the string, you pass NULL.
t=strtok(NULL,"|");
cout<<"Name:"<<t<<endl;
t=strtok(NULL,"|");
The function of display() is implement to display file contents on output screen, opens the
data file in read mode using fp1.open(fname,ios::in); for reading, gets each record though
the statement file >> buffer and then stores in buffer, unpack(buffer) function is called for
the actual unpacking. In unpack(), we use strtok() repeatedly to retrieve all fields between
the inter-field separator characters | .
In search(), each record is retrieved from the data file and checked whether this is the USN
we are searching for. If it is not, then “record not found” is displayed. If it is, then we say
that search is a success, printout the contents of this record using unpack(), If the user
decides to modify this found record then,
pack() is called to read new record data. This is because we want to write the modified
record directly to the data file. Here sequential search is used.
1jb01|abc|ise##############
1jb02|mno|ise##############
File contents before modification:
1jb01|abc|ise##############
1jb03|jkl|mech#############
3. Write a C++ program to read and write student objects with Variable Length records
using any suitable record structures. Implement pack(), unpack(), modify(),and search
methods.
#include<iostream.h>
#include<stdlib.h>
#include<conio.h>
#include<stdio.h>
#include<fstream.h>
#include<string.h>
fstream fp1,fp2;
int n=0;
char fname[10];
class student
{
private:
char usn[15], name[15], branch[5];
public:
void pack(int);
void unpack(char[]);
void display();
void search();
};
void student::display()
{
char buffer[100];
int i,j;
cout<<"\nFile Contents are \n";
fp1.open(fname,ios::in);
for(i=1;i<=n;i++)
{
fp1>>buffer;
unpack(buffer);
}
fp1.close();
}
void student::search()
{
char buffer[100],temp[100];
char *usn;
char key[15];
int i,choice;
cout<<"\nEnter the USN to search : ";
cin>>key;
fp1.open(fname,ios::in);
fp2.open("out.txt",ios::out);
for(i=1;i<=n;i++)
{
fp1>>buffer;
strcpy(temp,buffer);
usn = strtok(buffer,"|");
if(strcmp(usn,key)==0)
{
cout<<"Record Found\n";
unpack(buffer);
cout<<"\n Do you wish to modify?"<<endl;
cout<<"\n1.Yes \n2.No : ";
cin>>choice;
Department of Information Science and Engineering P a g e 13
File Structures Laboratory with mini project 18ISL67
if(choice==1)
{
pack(2);
while(!fp1.fail())
{
fp1>>buffer;
fp2<<buffer<<"\n";
}
fp1.close();
fp2.close();
remove(fname);
rename("out.txt",fname);
return;
}
else
{
fp1.close();
fp2.close();
remove("out.txt");
}
}
else
{
fp2<<buffer;
fp2<<"\n";
}
}
cout<<"Record not found";
fp1.close();
fp2.close();
remove("out.txt");
}
void main()
{
int i,ch;
student s1;
clrscr();
cout<<"Enter the file name : ";
cin>>fname;
fp1.open(fname,ios::out|ios::trunc);
fp1.close();
for(;;)
{
cout<<"\n 1.Insert\n 2.Display\n 3.Search and Modify\n 4.Exit \n";
cout<<"Enter Your Choice\n";
cin>>ch;
Department of Information Science and Engineering P a g e 14
File Structures Laboratory with mini project 18ISL67
switch(ch)
{
case 1:
n++;
fp1.open(fname,ios::app);
s1.pack(1);
fp1.close();
break;
case 2:
s1.display();
break;
case 3:
s1.search();
break;
case 4:
exit(0);
default:
cout<<"Invalid Choice\n";
}
}
}
Working
We are supposed to store information of many students in a file on the hard disk. For
each student, we get (from the user) and store his name, USN and branch. Once we create
such a data file, we are supposed to display its contents and be able to search in the file for a
particular student’s information based on his USN number. In this program, we are required
to implement variable length records structure to store students’ data in to file on the hard
disk. Since each character occupies 1 byte of space, we can store x characters in x bytes. So as
to be able to differentiate each of the fields, we store an inter-field separator, which is
specified in the question to be the | character. To differentiate between 2 records, we have to
store an inter-record separator, and we have chosen the \n character to do this job. Hence,
the structure of each variable-length record that we have defined is as follows:
In the implementation above, file name say file1.txt is read from the user, already file1.txt
may contain some data so fp1.open(fname,ios::out|ios::trunc); fp1.close(); used to clear the
file existing contents. To store record into file variable ‘n’ is used keep track of how many
records are stored in file. fp1.open(fname,ios::app); is used to open the file in write and
append mode. Once the file is opened in append mode, then we can write data into the file,
pack ( ) is used to write students data into the file. In pack() with parameter equal to 1 is
used write students data into the file, since we need to use variable length record structure
buffer character array of size 100 bytes is taken to place fields and field delimiters as we read
students data from the user. Using strcpy function USN is placed in buffer, then strcat
function is used to append ‘|’ delimiter. Then similarly name and department is placed in to
the buffer by separating with ‘|’ delimiter using strcat function. After filling the buffer with
student USN, name, department with ‘|’ delimiters buffer is written into the file. Then \n is
written into file to end the record. Similarly pack () is called to add each student records.
The function of display() is implement to display file contents on output screen, opens the
data file in read mode using fp1.open(fname,ios::in); for reading, gets each record though
the statement file >> buffer and then stores in buffer, unpack(buffer) function is called for
the actual unpacking. In unpack(), we use strtok() repeatedly to retrieve all fields between
the inter-field separator characters | . Control comes back to main() and modify() is called.
The search() is implemented to search and modify based on USN, if user choice is to modify
then only particular record is modified otherwise only search and display record if found
else display record not found: We open the data file say file1.txt in read mode and a
temporary file out.txt in write mode. We search the data file sequentially for the search USN.
Let us say that the record with this USN is the 5th record in the file. As we are walking
through the records 1-4, we copy these into the out.txt one by one. When the search comes to
the 5th record, it finds the USN, prints the respective record’s details and asks the user
whether he wants to modify it. If the user says yes, then pack() is called to get the new
details of that student, then the new buffer is written directly to the out.txt. The remaining
lines in the file1.txt are then copied to out.txt and then both of them are closed. The outdated
file1.txt is deleted and the out.txt is renamed as file1.txt.
In search(), each record is retrieved from the data file and checked whether this is the USN
we are searching for. If it is not, then this record is copied into the temporary file. If it is, then
we say that search is a success, printout the contents of this record using unpack(), If the user
decides to modify this found record, pack() is called with parameter 2. This is because we
want to write the modified record directly to the temporary file. pack() decides whether to
write a buffer to the data file or temporary file depending on the parameter sent to it.
1jb01|abc|ise
1jb02|mno|ise
1jb01|abc|ise
1jb03|jkl|mech
4. Write a C++ program to read and write student objects with variable-length records
using any suitable record structure and to read from this file a student record using
RRN.
#include<iostream.h>
#include<stdlib.h>
#include<conio.h>
#include<values.h>
#include<stdio.h>
#include<fstream.h>
#include<string.h>
fstream fp;
int n=0;
char fname[10],index[10];
class student
{
private:
char name[15],usn[15],branch[5];
public:
void pack();
void unpack(char[]);
void display();
void searchbyrrn();
};
void student::pack()
{
char buffer[100];
cout<<"Enter the student USN, Name and Branch:";
cin>>usn>>name>>branch;
strcpy(buffer,usn);
strcat(buffer,"|");
strcat(buffer,name);
strcat(buffer,"|");
strcat(buffer,branch);
index[n-1] = fp.tellg();
fp<<buffer;
fp<<"\n";
}
cout<<"Name : "<<t<<endl;
t = strtok(NULL,'\0');
cout<<"Branch :"<<t<<endl;
}
void student::display()
{
char buffer[100];
int i,j;
cout<<"\nFile Contents are \n";
fp.open(fname,ios::in);
for(i=1;i<=n;i++)
{
fp>>buffer;
unpack(buffer);
}
fp.close();
}
void student::searchbyrrn()
{
int rrn;
char buffer[30];
cout << "\nEnter RRN of the record:";
cin>>rrn;
fp.open(fname,ios::in);
if(rrn > n-1)
{
cout <<"Record with RRN "<<rrn<<" was not found..\n";
fp.close();
return;
}
fp.seekg(index[rrn],ios::beg);
fp>>buffer;
unpack(buffer);
fp.close();
return;
}
void main()
{
int i,ch;
student s1;
clrscr();
cout<<"\nEnter the Filename:";
cin>>fname;
fp.open(fname,ios::out|ios::trunc);
Department of Information Science and Engineering P a g e 19
File Structures Laboratory with mini project 18ISL67
fp.close();
for(;;)
{
cout<<"\n 1.Insert \n 2.Display \n 3.Search By RRN \n 4.Exit \n";
cout<<"Enter your Choice:";
cin>>ch;
switch(ch)
{
case 1:
n++;
fp.open(fname,ios::out|ios::ate);
s1.pack();
fp.close();
break;
case 2:
s1.display();
break;
case 3:
s1.searchbyrrn();
break;
default:
exit(0);
}
}
}
Working:
RRN is a direct access method to access a record that emerges from viewing a file as a
collection of records rather than as a collection of bytes. If a file is a sequence of records, the
RRN of a record gives its position relative to the beginning of the file. The first record in a
file has RRN 0, the next has RRN 1 and so forth.
In general, given a fixed length record file where the record size is r, the byte offset of record
with a RRN of n is
Byte offset = n * r
The above program is to store and search records of variable length record, using RRN direct
access method. In the implementation above, file name say file1.txt is read from the user,
already file1.txt may contain some data so fp1.open(fname,ios::out|ios::trunc); fp1.close();
used to clear the file existing contents. To store record into file variable ‘n’ is used keep track
of how many records are stored in file. fp1.open(fname,ios::app); is used to open the file in
write and append mode. Once the file is opened in append mode, then we can write data
into the file, pack ( ) is used to write students data into the file. In pack() is used to write
students data into the file, since we need to use variable length record structure buffer
character array of size 100 bytes is taken to place fields and field delimiters as we read
students data from the user. Using strcpy function USN is placed in buffer, then strcat
function is used to append ‘|’ delimiter. Then similarly name and department is placed in to
the buffer by separating with ‘|’ delimiter using strcat function. After filling the buffer with
Department of Information Science and Engineering P a g e 20
File Structures Laboratory with mini project 18ISL67
student USN, name, department with ‘|’ delimiters buffer is written into the file. Then \n is
written into file to end the record. Similarly pack () is called to add each student records.
index array is used to store the length of each records fp.tellg() is used to access the offset of
the record.In function search(), user enters rrn and checks if rrn > n-1 (number of records) ,
then display “error message rrn is not found” otherwise using fp.seekg(index[rrn],ios::beg);
function it seeks fp directly to the beginning of the required record.
File Contents:
1|abc|ise
2|mno|ise
5. Write a C++ program to implement simple index on primary key for a file of student
objects. Implement add(), search(), delete() using the index.
#include<iostream.h>
Department of Information Science and Engineering P a g e 21
File Structures Laboratory with mini project 18ISL67
#include<process.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
fstream fp;
int recount=0;
char fname[10];
class student
{
private:
char usn[15];
char name[15];
char branch[5];
public:
void pack(char[]);
void unpack(char[]);
void display();
void insrec();
void delrec();
int search(char[]);
};
struct memindex
{
char key[15];
int offset;
};
memindex index[10];
void student::insrec()
{
char buffer[50],tem[20];
char *usn;
Department of Information Science and Engineering P a g e 22
File Structures Laboratory with mini project 18ISL67
int i,j,pos;
fp.open(fname,ios::out|ios::ate);
pack(buffer);
strcpy(tem,buffer);
usn=strtok(tem,"|");
pos=search(usn);
if(pos!=0)
{
cout<<"USN already Exists \n"<<endl;
fp.close();
return;
}
recount++;
strcpy(index[recount].key,usn);
index[recount].offset=fp.tellg();
fp<<buffer;
fp<<"\n";
memindex temp;
for(i=1;i<recount;i++)
{
for(j=1;j<recount;j++)
{
if(strcmp(index[j].key,index[j+1].key)>0)
{
strcpy(temp.key,index[j].key);
temp.offset=index[j].offset;
strcpy(index[j].key,index[j+1].key);
index[j].offset=index[j+1].offset;
strcpy(index[j+1].key,temp.key);
index[j+1].offset=temp.offset;
}
}
}
fp.close();
}
void student::display()
{
char buffer[50];
int i,j;
if(recount == 0)
{
cout<<"No Records to Display"<<endl;
return;
Department of Information Science and Engineering P a g e 23
File Structures Laboratory with mini project 18ISL67
}
cout<<"\t---------------"<<endl;
cout<<"\t Primary index"<<endl;
cout<<"\t---------------"<<endl;
cout<<"\t key\t"<<"offset"<<endl;
cout<<"\t---------------"<<endl;
for(i=1;i<=recount;i++)
{
cout<<"\t"<<index[i].key<<"\t"<<index[i].offset<<endl;
}
cout<<"File Contents are"<<endl;
fp.open(fname,ios::in);
for(i=1;i<=recount;i++)
{
fp.seekg(index[i].offset,ios::beg);
fp>>buffer;
unpack(buffer);
cout<<endl;
}
fp.close();
}
void student::delrec()
{
char usn[15];
int pos;
fp.open(fname,ios::out|ios::ate);
cout<<"\nEnter the USN:";
cin>>usn;
pos=search(usn);
if(pos==0)
{
cout<<"\nRecord not found";
return;
}
fp.seekg(index[pos].offset,ios::beg);
fp<<"*";
fp.close();
for(int i=pos;i<recount;i++)
{
strcpy(index[i].key,index[i+1].key);
index[i].offset=index[i+1].offset;
}
cout<<"Record Deleted Successfully"<<endl;
recount--;
}
void main()
{
char buffer[50];
student s1;
char usn[15];
int i,j,k,choice,pos;
clrscr();
cout<<"Enter the file name: ";
cin>>fname;
fp.open(fname,ios::out|ios::trunc);
fp.close();
for(;;)
{
cout<<endl;
cout<<" 1.Insert\n 2.Delete\n 3.Display\n 4.Search\n 5.Exit\n";
cout<<"Enter your choice\n";
cin>>choice;
switch(choice)
{
case 1:
Department of Information Science and Engineering P a g e 25
File Structures Laboratory with mini project 18ISL67
s1.insrec();
break;
case 2:
s1.delrec();
break;
case 3:
s1.display();
break;
case 4:
cout<<"\nEnter the USN to be searched:";
cin>>usn;
pos=s1.search(usn);
if(pos==0)
{
cout<<"Record not found..\n";
break;
}
fp.open(fname,ios::in);
fp.seekg(index[pos].offset,ios::beg);
fp>>buffer;
s1.unpack(buffer);
fp.close();
break;
default:
exit(0);
}
}
}
Working:
An index is a tool for finding records in a file. It consists of a key field on which the index is
searched and reference (offset) field that tells where to find the data file record associated
with a particular key.
Index Record file
Reference Address of
Key Actual data record
field record
1jb01 29 0 1jb02|abc|ise
1jb02 0 15 1jb03|xyz|ise
1jb03 15 29 1jb01|pqr|ise
1jb04 57 43 1jb05|mno|ise
1jb05 43 57 1jb04|asd|ise
In C++ program 5 implementation USN-based index (primary key) of the file in main
memory is implemented, where sorting, and hence searching, is faster. Such an index is
referred to as the primary index, because the USN is the primary key of the student
database. Once the index is sorted on USN, binary search can be used for searching. When
new records are inserted into the file, an appropriate entry is also added to the index in a
way so as to maintain the sorted order of the index. When a record is deleted from the file,
the corresponding entry in the index is also deleted and all the index entries below the
deleted entry are pushed up by one (still maintaining sorted order). We implement this
technique in this program. We first create a structure called memindex, which contains a
character field of 15 spaces to store a primary key (USN, in our case) and an integer field to
store the byte offset of each record in the file. When we access an index entry, we get the
byte offset of the record to which this index is pointing to, and we use seekg() to jump to the
record directly without walking through the file in a serial manner. We create 10 elements of
this list here, but if more than 10 records are to be indexed, then this number has to be
increased. To know how many index elements are present, we use a global variable called
recount and initialize it to 0 as the index is empty to start with.
In main(), we open a data file for writing and call insrec() only once for one student’s
information, along with the buffer in which it has to pack the information. The pack() gets
the data of this student from the user and packs it using the | as the inter-field separator and
the ‘\n’ as the inter-record separator. This packed buffer is then written to the data file. At
this point in the program, we know that there is only one record in the data file, since we
have allowed only one record to go to the file yet. Then populate the first primary index
entry with the USN and byte offset. This being the very first record, its byte offset is 0. We
increment the global variable recount by 1 because the index now has exactly one entry.
Now that one record is placed into the file and a corresponding entry is put into the index,
In insrec(), we open the data file in ate mode (append-to-end), so that whatever record we
write to the file gets added to the end of the file after setting the put pointer to the end. We
call pack() to pack a new buffer for us. We extract the USN field from buffer using strtok to
search the index to see whether the USN that is in this buffer already exists. If it does, we do
not insert the current record into the file and return to main(). If not, we continue with
insertion.
Since recount gives the total number of index entries, it is incremented by 1 to make space
for the new entry, and the USN and byte offset of the record to be inserted are written into
the newly created position in the index. The byte offset of the record being inserted is given
by tellg() which returns a long integer, so we have to typecast it to make it a normal integer.
After adding data into file each time index is sorted based USN using Bubble sorting
technique. To delete a record from the file, from the main() , delrec() is called, before
deleting a record file is opened in ate mode. User enter the USN of the record to be deleted,
then search () is called with the parameter USN, we use Binary searching technique search
the index to see whether such a USN actually exists or not. If USN does not exists, search ()
returns 0 otherwise the position of the USN found in index. If pos is 0 display “Record not
found” and return to main (). If pos is non-zero, we move the fp object to point to the
particular pos offset using fp.seekg(index[pos].offset,ios::beg); . Then “*” is placed to mark
that record is deleted. During deletion, we do not actually delete anything from the data file.
We just delete the index entry for that particular record. The index entry for the record we
want to delete is found in position i in the index. We pull up all entries from i+1 position by
1. Finally recount is decremented by 1.
Department of Information Science and Engineering P a g e 27
File Structures Laboratory with mini project 18ISL67
6. Write a C++ program to implement index on secondary key, the name, for a file of
student objects. Implement add(), search(), delete() using the secondary index.
#include<iostream.h>
#include<process.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdio.h>
fstream fp;
int recount=0;
char fname[10];
class student
{
private:
char name[15];
char usn[15];
char branch[5];
public:
void pack(char[]);
void unpack(char[]);
void display();
void insrec();
void delrec();
int search(char[]);
void sch_scn_index();
};
struct primaryindex
{
char pkey[15];
int offset;
};
struct secondaryindex
{
char skey[15];
char pkey[15];
};
student s1;
primaryindex pindex[20];
secondaryindex sindex[20];
void student::insrec()
{
char buffer[50],tem[20];
char *usn,*name;
int i,j,pos;
fp.open(fname,ios::out|ios::ate);
pack(buffer);
strcpy(tem,buffer);
usn=strtok(tem,"|");
name=strtok(NULL,"|");
pos=search(usn);
if(pos!=0)
{
cout<<"USN already present\n";
fp.close();
return;
}
recount++;
strcpy(pindex[recount].pkey,usn);
pindex[recount].offset=fp.tellg();
strcpy(sindex[recount].skey,name);
strcpy(sindex[recount].pkey,usn);
fp<<buffer;
fp<<"\n";
primaryindex temp;
for(i=1;i<recount;i++)
{
for(j=1;j<recount;j++)
{
if(strcmp(pindex[j].pkey,pindex[j+1].pkey)>0)
{
strcpy(temp.pkey,pindex[j].pkey);
temp.offset=pindex[j].offset;
strcpy(pindex[j].pkey,pindex[j+1].pkey);
pindex[j].offset=pindex[j+1].offset;
strcpy(pindex[j+1].pkey,temp.pkey);
pindex[j+1].offset=temp.offset;
}
}
}
fp.close();
}
void student::display()
{
char buffer[50];
int i,j;
fp.open(fname,ios::in);
if(recount == 0)
{
cout<<"No Records to Display"<<endl;
fp.close();
return;
}
cout<<"\t---------------"<<endl;
cout<<"\t Primary index"<<endl;
cout<<"\t---------------"<<endl;
cout<<"\t key "<<"offset"<<endl;
cout<<"\t---------------"<<endl;
for(i=1;i<=recount;i++)
{
cout<<"\t"<<pindex[i].pkey<<"\t"<<pindex[i].offset<<endl;
}
cout<<"\t----------------------"<<endl;
cout<<"\t Secondary index"<<endl;
cout<<"\t----------------------"<<endl;
cout<<"\t sec-key\t"<<"pri-key"<<endl;
cout<<"\t-----------------------"<<endl;
for(i=1;i<=recount;i++)
{
cout<<"\t"<<sindex[i].skey<<"\t\t"<<sindex[i].pkey<<endl;
}
cout<<"\t------------------------"<<endl;
cout<<"File Contents are"<<endl;
for(i=1;i<=recount;i++)
{
fp.seekg(pindex[i].offset,ios::beg);
fp>>buffer;
unpack(buffer);
}
fp.close();
}
void student::delrec()
{
char usn[15];
int pos,j;
cout<<"\nEnter the usn:";
cin>>usn;
fp.open(fname,ios::out|ios::ate);
pos=search(usn);
if(pos==0)
{
cout<<"\n Record not found";
fp.close();
return;
}
fp.seekg(pindex[pos].offset,ios::beg);
fp<<"*";
fp.close();
for(int i=pos;i<recount;i++)
{
strcpy(pindex[i].pkey,pindex[i+1].pkey);
pindex[i].offset=pindex[i+1].offset;
}
j=1;
while(strcmp(sindex[j].pkey,usn)!=0)
{
j++;
}
for(i=j;i<recount;i++)
{
strcpy(sindex[i].skey,sindex[i+1].skey);
strcpy(sindex[i].pkey,sindex[i+1].pkey);
}
cout<<"Record deleted successfully"<<endl;
recount--;
}
void student::sch_scn_index()
{
char buffer[50];
char name[15];
int i,j;
int pos,flag=0;
fp.open(fname,ios::in);
cout<<"Enter the secondary key(name) \n";
cin>>name;
for(i=1;i<=recount;i++)
{
if(strcmp(sindex[i].skey,name)==0)
{
flag=1;
pos=search(sindex[i].pkey);
fp.seekg(pindex[pos].offset,ios::beg);
fp>>buffer;
unpack(buffer);
}
}
if(flag==0)
{
cout<<"Record not found";
}
fp.close();
}
default:
exit(0);
}
}
}
Working:
Secondary Index: It contains secondary key and primary key as reference. In this program,
name is used as the Secondary key and USN is used as the reference for the secondary key.
When a record is inserted in the data file, the USN is extracted from the record and an entry
is made in the primary index along with the byte offset of the record. The name is extracted
and an entry is made in the secondary index with USN as the reference. Primary index is kept
in sorted order by USN.
Deletion of a record results in the deletion of the corresponding entry from both the primary
index and the secondary index.
Search by USN: User enters USN to be searched as the key. Binary search is applied on the
primary index to search for the USN. If USN is found, we get the byte offset and file stream
object moves to the particular position to retrieve the record related of that USN from record
file.
Search by name: User enters the Name to be searched. Linear search is applied to the
secondary index to search for the name. If the name is found then, the USN for the particular
name is retrieved from secondary index using USN byte offset is accessed from primary index,
once we get the byte offset then file stream object is moved to the particular position to retrieve
the record related of that USN from record file.
7. Write a C++ program to read two lists of names and then match the names in the two
lists using Cosequential Match based on a single loop. Output the names common to
both lists.
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
fstream fp1,fp2,fp3;
void match()
{
char buffer1[100],buffer2[100];
int i,j;
fp1.open("names1.txt",ios::in);
fp2.open("names2.txt",ios::in);
fp3.open("match.txt",ios::out);
fp1>>buffer1;
fp2>>buffer2;
else if(strcmp(buffer1,buffer2)<0)
{
fp1>>buffer1;
}
else
{
fp2>>buffer2;
}
}
}
void main()
{
clrscr();
match();
getch();
}
Working:
We want to output the names common to the two files Names1.txt and names2.txt shown
in table below. This operation is called as match operation or an intersection. Assume
that the lists are sorted in ascending order.
Kiran Chethan
Ranjith Mahesh
Umesh Ranjith
We begin by reading the initial names from each files and find they match. We output the
first name of names1.txt to match.txt as a name matches. Then we read the next names
each file. Now next name in names1.txt is less than names2.txt, we are trying to match
name “Ajay” and “Amar”, since it is less, we scan down in names1.txt and read next
name “chethan”. Now we are trying to match “chethan” and “Amar”. Name in
names1.txt is greater than name in names2.txt. So scan down in names2.txt. read next
name that is “bharath” in names2.txt. Now we are trying to match “chethan” and
“bharath”, Name in names1.txt is greater than name in names2.txt. So scan down in
names2.txt. read next name that is “chethan” in names2.txt. Now we are trying to match
“chethan” and “chethan”, it matches output the name of names1.txt to match.txt. Then
we read the next names from each file.
Contents of names1.txt
abc
def
jkl
mno
Contents of names2.txt
def
mno
xyz
Contents of match.txt
def
mno
8. Write a C++ program to read k Lists of names and merge them using k-way merge
algorithm for k=8.
#include<iostream.h>
#include<fstream.h>
#include<conio.h>
#include<string.h>
#include<process.h>
void main()
{
char name[20][20];
int i,low;
fstream fp1;
fstream fp[10];
fp[1].open("n1.txt",ios::in);
fp[2].open("n2.txt",ios::in);
fp[3].open("n3.txt",ios::in);
fp[4].open("n4.txt",ios::in);
fp[5].open("n5.txt",ios::in);
fp[6].open("n6.txt",ios::in);
fp[7].open("n7.txt",ios::in);
fp[8].open("n8.txt",ios::in);
fp1.open("merge.txt",ios::out);
for(i=1;i<=8;i++)
{
fp[i]>>name[i];
}
for(;;)
{
low=1;
for(i=1;i<=8;i++)
{
if(strcmp(name[i],name[low])<0)
{
low=i;
}
}
if(strcmp(name[low],"~")==0)
{
fp1.close();
for(i=1;i<=8;i++)
{
fp[i].close();
}
exit(0);
}
else
{
fp1<<name[low];
fp1<<"\n";
cout<<name[low]<<"\n";
fp[low]>>name[low];
if(fp[low].fail())
{
strcpy(name[low],"~");
}
}
}
}
Physical file:A file as seen by the operating system, and which actually exists on secondary
storage.
Logical file:A file as seen by a program.
3. Explain open function of fstream class with syntax?
fd = open(filename,flags[,pmode]);
fd-file descriptor
The following flags can be bitwise ored together for the access mode:
O_RDONLY : Read only
O_WRONLY : Write only
O_RDWR : Read or write
O_CREAT : Create file if it does not exist
O_EXCL : If the file exists, truncate it to a length of zero, destroying its contents.
(used only with O_CREAT)
O_APPEND : Append every write operation to the end of the file
O_TRUNC : Delete any prior file contents
direction Description
ios::beg offset counted from the beginning of the stream
ios::cur offset counted from the current position
Reading
The C++ read function is used to read data from a file for handle level access.
The read function must be supplied with (as an arguments):
a. The source file to read from
b. The address of the memory block into which the data will be stored
c. The number of bytes to be read(byte count)
The value returned by the read function is the number of bytes read.
Read function:
Writing
The C++ write function is used to write data to a file for handle level access.
The write function must be supplied with (as an arguments):
a. The logical file name used for sending data
b. The address of the memory block from which the data will be written
c. The number of bytes to be write
The value returned by the write function is the number of bytes written.
Write function:
I/O redirection is used to change a program so it writes its output to a regular file rather than to
stdout.
In both DOS and UNIX, the standard output of a program can be redirected to a file with
the > symbol.
In both DOS and UNIX, the standard input of a program can be redirected to a file with
the < symbol.
The notations for input and output redirection on the command line in Unix are
Simple indexing can be useful when the entire index can be held in memory.
Changes (additions and deletions) require both the index and the data file to be changed.
Updates affect the index if the key field is changed, or if the record is moved.
An update which moves a record can be handled as a deletion followed by an addition.
15. Explain the key-sorting techniques and their limitations
Keysorting is a way to sort medium size files.
Description of the Method
Read each record sequentially into memory, one by one
Save the key of the record, and the location of the record, in an array (KEYNODES).
After all records have been read, internally sort the KEYNODES array of record keys and
locations.
Using the KEYNODES array, read each record back into memory a second time using direct
access.
Limitations of the Keysort Method
Keysort is only possible when the KEYNODES array is small enough to be held in memory.
Each record must be read twice: once sequentially and once directly.
The direct reads each require a seek.
If the original file and the output file are on the same physical drive, there will also be a
seek for each write.
Keysorting is a way to sort medium size files.
16. Explain the concept of B-Trees in multilevel indexing
Tree structured indexes such as B-trees are a scalable alternative to simple indexes. A multiway
tree in which all insertions are made at the leaf level. New nodes at the same level are created
when required by node overflow, and new nodes at the parent level are created when required by
the creation of new nodes.
17. Explain the limitations of binary searching and internal sorting?
Binary searching requires more than one or two accesses.
More than one or two accesses is too many.
Keeping a file sorted is very expensive.
An internal sort works only on small files.
18. Explain the operations required to maintain the index files?
Create empty index file and data files
Load index file into memory before using it
Rewrite the index file from memory after using it
Add records to data file
Delete records from data file
Update records in data file