You are on page 1of 4

Program 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<fstream.h> #include<iostream.h> #include<conio.h> #include<process.h> #include<string.h> #include<stdio.h> #include<values.h> fstream file, index; class student { private: char name[100],usn[20]; int m1,m2,m3; public: void getstuff(); void pack(); void marksdiv(char*,int); void lookup(); void realunpack(char*);

}; void student :: marksdiv(char *digits,int m1) { int r1,r2,q1,q2; r1=m1%100; q1=m1/100; digits[0]=q1+'0'; r2=r1%10; q2=r1/10; digits[1]=q2+'0'; digits[2]=r2+'0'; } void student :: getstuff() { cout<<"Enter the name : "; cin>>name; cout<<"Enter the USN : "; cin>>usn; cout<<"Enter the marks scored in the 3 tests : "; cin>>m1>>m2>>m3; } void student:: pack() { int i,j; char buffer[500],digits[3]; getstuff(); i=0; while(name[i]!='\0')

} buffer[i++]='|'; j=0; while(usn[j]!='\0') { buffer[i]=usn[j]; i++;j++; } buffer[i++]='|'; marksdiv(digits,m1); buffer[i++]=digits[0]; buffer[i++]=digits[1]; buffer[i++]=digits[2]; buffer[i++]='|'; marksdiv(digits,m2); buffer[i++]=digits[0]; buffer[i++]=digits[1]; buffer[i++]=digits[2]; buffer[i++]='|'; marksdiv(digits,m3); buffer[i++]=digits[0]; buffer[i++]=digits[1]; buffer[i++]=digits[2]; buffer[i]='\n'; for(j=0;j<=i;j++) file<<buffer[j]; index << i << '\n';

buffer[i]=name[i]; i++;

void student:: realunpack(char * buffer) { cout<<"NAME: " << strtok(buffer,"|") cout<<"USN: " << strtok(NULL,"|") << cout<<"MARKS1: " << strtok(NULL,"|") cout<<"MARKS2: " << strtok(NULL,"|") cout<<"MARKS3: " << strtok(NULL,"|") }

<< "\n" ; "\n"; << "\n"; << "\n"; <<"\n";

void student::lookup() { int rrn, cur, byte_acc=0, rec_count=1; char* buffer; cout << "enter RRN of student:"; cin >> rrn; if (rrn > 1) { while ((!index.fail()) && (rec_count <= rrn-1)) { index >> cur; byte_acc = byte_acc + cur + 2; rec_count++; } if (index.fail()) { cout << "RRN is greater than number of existing records\n"; return; } } file.seekg(byte_acc,ios::beg);

file.getline(buffer,MAXINT,'\n'); if (file.fail()) { cout << "couldnt get the required line from file\n"; return; } realunpack(buffer); return; void main() { int n,i; student a[5]; clrscr(); cout<<"Enter the record number (max 5)\n"; cin>>n; file.open("sumne.txt",ios::out); index.open("sumne.idx",ios::out|ios::binary); if(file.fail()) { cout<<"cannot open sumne.txt for writing\n"; getch(); exit(0); } if(index.fail()) { cout<<"cannot open sumne.idx for writing\n"; getch(); exit(0); } for(i=0;i<n;i++) a[i].pack(); file.close(); index.close(); file.open("sumne.txt",ios::in); index.open("sumne.idx",ios::in); if(file.fail()) { cout<<"cannot open sumne.txt for reading\n"; getch(); exit(0); } if(index.fail()) { cout<<"cannot open sumne.idx for reading\n"; getch(); exit(0); } a[0].lookup(); file.close(); index.close(); getch();

The way in which data is organized in a file in this program is very similar to that of Program 3. This is because here also we need to use variable-length records.

Therefore, the private data members of the student class will not change. But as usual, the public member functions will change a little bit. If we were to implement RRN on fixed-length records, then we would always know the length of all records as it is a constant. So, if we want to jump directly to the 5 th record in a file (RRN=5), we would do seekg((4 the length of a record) + 1) from the beginning of the file and access the required record directly. The addition of 1 at the end is to jump past the inter-record separator \n. But with variable-length records, we cannot estimate the length of each record exactly. Therefore, we have to store the length of each record someplace. Now, if we want to jump directly to the 5th record in the file, we have to add the lengths of each of the first 4 records along with their inter-record separators, then add 1 to this sum, and then use seekg() to jump to this position in the file. In this implementation, we are storing the length of each variable-length record of a data file into another file. We open 2 files in main(), one called sumne.txt for storing variable-length records, and the other called sumne.idx to store the length of each of these records. Now, we open the sumne.idx in write mode and binary mode, since we wish to store the length of each record as an integer, and not as a sequence of characters like we stored the marks of each student after characterizing it using marksdiv(). getstuff() and marksdiv() have the same functionality as before. pack() not only gets information for each student from the user using getstuff(), packs it into a buffer and writes this buffer to sumne.txt, but also writes the length (as an integer) of each record into sumne.idx. After packing information into the file, the control comes back to main() and the files are closed. The files are opened again in read mode, and now lookup() is called. We get the RRN from the user. If the RRN is 1, then we do not have to jump anywhere in the file because the file get pointer is already pointing at the right record. So we do not have to compute any byte offset. If RRN is greater than 1, say RRN=5, we get the first 4 entries from sumne.idx file and accumulate their sum in the variable byte_offset. This variable now has the cumulative length of the first 4 records. Each time we add the value 2 to this sum. This is because, whenever DOS sees a \n character in a file, it replaces this by 2 characters \r and \n, which are the carriage return and the line feed characters. Hence, there are 2 inter-record separators now one beside the other (and in all the earlier programs where \n is the inter-record separator). When jumping past records, we have to now jump past length of each record + 2. Each time we get a record from the file, we increment a counter rec_count so that we can stop at RRN-1. If it so happens that the EOF of sumne.idx occurs before RRN-1 record is gotten to, then it means that too big a RRN has been entered. For eg., this happens if there are only 10 records in our file and we want the 15 th RRN record. It is enough to check whether there is no more data in sumne.idx instead of in sumne.txt, as sumne.idx has an integer corresponding to each record in sumne.txt. After computing the appropriate byte offset, we jump to that record using seekg(), then get that record using getline(). We then send it to realunpack(), which has the same functionality as in earlier programs, to display the contents of the record.

You might also like