Google Answers Logo
View Question
 
Q: C++ program ( Answered,   0 Comments )
Question  
Subject: C++ program
Category: Computers > Programming
Asked by: bobty-ga
List Price: $120.00
Posted: 02 Apr 2003 21:25 PST
Expires: 02 May 2003 22:25 PDT
Question ID: 185259
This program should be pretty straight forward for the average
programming expert. Please keep the programs as simple as possible
while keeping with the specifications.  I will need two different
working  versions of both parts.  Part I should be able to run
individually from  Part II.  I am not able to write these programs
myself because of school, work, and kids.  (I've pretty much fallen
behind with everything!) I will check several times a day to check if
you have any comments or questions.  These programs are to be used in
a Unix environment.  It is extremely important that these programs are
completed by April 12, 2003.  This problem is not nearly as long or
difficult as it may look.  I cannot express how much I appreciate your
help.(Except for in terms of dollars, I guess!) Thank you


Part I:
This part looks at the way information is stored in fields and
records. The program will read a source file from a real life
application, extract the fields and print the result.


Specification of the source data

We will extracting data from the site
http://www.ntsb.gov/ntsb/query.asp. To get data, click on Database
Query. Then enter some information into the form. For example, set the
start date to 1/1/03 and set the state to California. Then click on
Submit Query.
When you get the search results, select the data (not header fields,
just the fields shown with a white background) and copy and paste into
a text editor. Since the search results give only a few records per
page, you should do this more than once.

It is important that you follow directions because when I test your
programs, I will be using a file generated in this manner. I will not
be using the same file as you.

Specification of the Problem

Your code should read in the input data, which as you will see has
variable length fields.
Your code should extract each field individually and write it to the
screen, and to disk.
The fields written should be fixed length fields. Thus it may be
necessary to truncate some fields.
The primary key is the Airplane Registration Number. We will assume
there are no duplicates. (Any duplicates should be ignored in future
labs.) This is a fixed length (6 character) field.
At the same time you should construct a data record (structure)
consisting of fixed length fields.
The record should be written to a file called datafile.txt. 
The records should be written one record at a time (not field by
field).
The required format for output to the screen is 
Sequence number (RRN) 
Primary key 
All other fields in the record in the same order as in the data file
(except for the primary key which has been moved to the front).
The output for one record should fit on one line. Fields should be
separated by '|' character.
The format for the output file should be similar, but omit the RRN and
'|'.
Note that in some cases the last two fields are omitted (Type of Air
Carrier Operation, Carrier Name). This should not cause a problem.
(Hint: I believe that the only possible values for Report Status are:
"Prel", "Fact", "Final".)
Your executable file should be named showdata. 
There should be no restriction on the number of records processed. 

Specification of the user interface

The file name should be taken from the command line. 
The command to produce the correct result should be showdata
rawdata.txt, if the input file is named rawdata.txt.

Implementation constraints

Extracting data from the input text file— no required structure.
However, keep in mind the structure of the input data file described
above. You must follow this specification, because that is how the
file used to test your program will be generated. You may not change
the input format.
Your input should be done in binary ("raw") mode. 
Keep in mind that this will be the front end of the code you will
write during the rest of the semester. Design for re-use.
The fields should be output as fixed length fields and the beginning
and end of the field should be clearly shown as described above.
The State should be considered as a separate field from the rest of
the Location.
If you develop your code in Windows, you should allow for either
Windows or UNIX type text files. The difference is in how the end of a
line is represented. Windows uses 0x0A0D (or is it 0x0D0A ?), UNIX
just 0x0D.
Incorrectly named programs or programs that do not take command line
arguments will not be accepted

Part II:We are going to build an indexed data storage and retrieval
system for the data used in Lab 2. This will include a batch load
function (from a text file), an index display function, an interactive
search feature and delete. We will use an Avail list for deleted
records.

The easiest way to implement these functions is to use one program for
each function. The programs should know the name of the file
structure. The only thing that needs to be passed to the program on
the shell command line is the argument for the command:


$ load data.txt   /* create the file structure */ 
$ list   /* outputs a list of all records */ 
$ search N1079U   /* program displays remaining args */ 
$ add N1079U   /* program prompts for remaining args */ 
$ delete N1079U   /* program displays, waits for yes */ 


Give some thought to sharing code among the six programs. Other
commands may also occur to you during implementation and verification.

Structure your code so that the index functions are separate from the
user interface and can easily be replaced!

Specification of the problem


A program load should translate a text file containing product records
to a file structure of your design. You should have two files, a
database file, a primary index. You have already solved the problem of
creating the data file in Lab 2. In Lab 3, we add the index function.
(For Lab 4, your index file will change but you should be able to use
the same database file structure.) The source file format is the same
as for Lab 2. Records with missing primary key should be omitted.

A program search should allow the user to find a record with a given
primary key and display the record's content.

A program list should display all records in order by the primary key.
The display should show the entire primary key, followed by the other
fields, which may be truncated. Each work should fit on a single line,
and there should be no blank lines in between. If this format is not
followed, the project will not be accepted.

A program add should allow the user to add a new record to the file
structure. This program should prompt for the other fields. Since we
are going to add records, your index should have more space allocated
to it than just what is necessary for the source text records. The
function should check for duplicate keys and output an error message
if encountered.

A program delete should allow the user to delete a record with a user
supplied primary key.

The delete function should place the deleted data record on an Avail
list. The Avail list should be kept in the deleted records in the data
file. The head pointer for the Avail list should be kept in the header
of the index file. Subsequent adds should re-use deleted data records
for new data. (Use your hex dump program from Lab 1 to verify that
this is so.)

Specification of the source data

You should use the same source data file as in Lab 2. 
Specification of the user interface

Each command that may be performed on the file structure should be
implemented in a separate program.

Each program should know the name of the file containing the records
in the file structure.

The key field should be taken from the command line. 
Each program should open the file structure, perform a single
operation, and close the file structure.

Implementation constraints

Each program should perform the action required and report the results
to the standard output.

Transfers to or from the database file should be implemented only with
open(...), read(...), write(...) and close(...) functions. (If using
C++ I/O, this corresponds to the unformatted I/O functions sgetn and
sputn.) There are no constraints on how the index file is read or
written.

The file structure transfer block size should be the size of four
records, for transfers to and from the database file. The file size
must be a multiple of this value. Only blocks corresponding to RRNs
which are a multiple of 4 should be accessed.

The functions that read and write the database should print out the
block accessed and also the record accessed within the block ONLY for
functions that access only a single record. (i.e., not for the list
function.)
Constraints on accessing the data file do not apply to the load
function since the constraints were not in effect for Lab 2. The code
you developed for Lab 2 may be directly reused.
The search for an item should be performed using a binary search in a
sorted index.

The binary search function should print out the locations examined by
the search.
The index file should be created by the load function and should be
stored in order by primary key.

You may select your own format for storing the index file.

Additions and deletions should be implemented by moving index entries
appropriately and storing a sorted index.

The avail list should be kept in the deleted data records. The key
should be set to a particular value, and the next field in the data
record should contain the RRN of the next list item. The remainder of
the data field should be set to blanks. The head of the avail list
should be kept in the header record of the index file.

Code may be written in either C or C++.

Suggested structure and required output


Reading and writing data records.
The block size is sufficient for 4 records. Only blocks corresponding
to RRNs which are a multiple of 4 should be accessed, and the
appropriate record should then be extracted. For read, your blockread
function is given an RRN and returns a pointer to the appropriate
record in the buffer. For blockwrite, the function is given an RRN and
a pointer to a record which is to be copied into the buffer. Every
write also involves a read, since three of the four records in the
block remain unchanged. The functions should print a brief descriptive
message of the operation, including block numbers (RRN of the start of
the block and RRN of the accessed record) whenever a block is read or
written, ONLY for functions that access only a single record. (i.e.,
not for the list function.)
Binary search in index
Given a key, the function returns two values, a location in the index
and a Boolean value indicating whether the key was found in the index.
The binary search should print each index location accessed (on one
line, please!).
Insert into index
Since the binary search has already found the correct location, this
value can be passed to the indexinsert function along with a key and
RRN. Following entries in the index are moved down to make room for
the new entry. The function should print the range of index entries
which are being moved (first and last only).
Delete from index
Since the binary search has already found the correct location, this
value can be passed to the indexdelete function. Following entries in
the index are moved back to remove the index entry. The function
should print the range of index entries which are being moved (first
and last only).
I suggest that common functions should be placed in an include file.

Testing


Please verify that all functions are working .

Structure of the index file (use hexdmp) 
Structure of the data file (use hexdmp) 
Correct functioning of all operations. Diagnostic print statements as
specified must be included.
Placing and removing records to/from the Avail list (use hexdmp to
verify).



Here is sample data for a Unix format:


Prel
2/28/03 
Deer Valley, AZ 
Creitz, Robert D RV-3 
N87BC 
Nonfatal 
Part 91: General Aviation 
Prel
2/28/03 
COLCHANI, Bolivia 
Cessna 411 
CP-1885 
Fatal(1) 
NSCH Non-U.S., Commercial Taxi Aereo "Colibri" 
Fact
1/17/03 
Quito, Ecuador 
Fokker F28 
HC-BMD 
Nonfatal 
SCHD Non-U.S., Commercial Transportes Aereos Militares del Ecuador
(D.B.A. TAME)
Prel
1/17/03 
McMurdo Station, Antarctica
Bell 212 
N1079U 
Nonfatal 
Public Use 
Prel
1/17/03 
Yacuiba, Bolivia 
British Aerospace Jetstream 31 
CP-2404 
Nonfatal 
NSCH Non-U.S., Commercial Servicio Aereo Vargas Espana (D.B.A. SAVE) 
Prel
1/16/03 
Venice, LA 
Bell 206L-1 
N3194P 
Fatal(1) 
NSCH Part 135: Air Taxi & Commuter Air Logistics LLC 
Prel
1/16/03 
Indianapolis, IN 
Boeing 737-83N 
N303TZ 
Incident 
SCHD Part 121: Air Carrier AMERICAN TRANS AIR INC 
Prel
1/16/03 
Midway, UT 
Yakovlev YAK 52 
N2256J 
Fatal(2) 
Part 91: General Aviation 
Prel
1/16/03 
SALINAS, CA 
Cessna 152 
N25562 
Nonfatal 
Part 91: General Aviation 
Prel
1/15/03 
BRAWLEY, CA 
Cessna A188A 
N5638J 
Nonfatal 
Part 137: Agricultural 
Prel
1/15/03 
, PO 
Dassault Aviation Falcon 900EX 
N11WM 
Nonfatal 
Part 91: General Aviation 
Fact
1/15/03 
Stansted, United Kingdom 
McDonnell Douglas MD-11 
N583FE 
Nonfatal 
SCHD Non-U.S., Commercial FEDERAL EXPRESS CORP 
Fact
1/8/03 
Diyarbakir, Turkey 
British Aerospace RJ-100 
TC-THG 
Fatal(75) 
SCHD Unknown 
Prel
1/8/03 
Charlotte, NC 
Beech 1900 
N233YV 
Fatal(21) 
SCHD Part 121: Air Carrier AIR MIDWEST INC (D.B.A. US Airways Express)
Prel
1/1/03 
Milford, UT 
Aircraft Mfg & Dev. Co. (AMD) CH2000 
N8500R 
Nonfatal 
Part 91: General Aviation 
Prel
1/1/03 
Lansing, IL 
Air Command Commander Elite 
Fatal(1) 
Part 91: General Aviation 
Fact
1/3/03 
Alton, IL 
Cessna 182S 
N2724R 
Nonfatal 
Part 91: General Aviation 
Prel
1/3/03 
Santo Domingo, Dominican Republic 
Beech BE-60 
HI-774CT
Fatal(1) 
Non-U.S., Non-Commercial 
Prel
1/2/03 
New Port Richey, FL 
Hughes OH-6 
N317LC 
Nonfatal 
Public Use 
Prel
2/28/03 
Captiva Island, FL 
Beech 36 
N41VK 
Fatal(1) 
Part 91: General Aviation 
Fact
2/28/03 
Columbus, OH 
Cessna 152 
N170SU 
Nonfatal 
Part 91: General Aviation 
Prel
2/27/03 
Renfrew, PA 
Cessna 182G 
N3404S 
Fatal(1) 
Part 91: General Aviation 
Fact
2/27/03 
Jamaica, NY 
Aerospatiale Concorde 
F-BVFA 
Nonfatal 
SCHD Part 129: Foreign Air France Airlines 
Prel
2/26/03 
Blue Bell, PA 
Piper PA-44-180 
N711AV 
Nonfatal 
Part 91: General Aviation 
Prel
2/25/03 
Williamson, NY 
Cessna 150J 
N51126 
Nonfatal 
Part 91: General Aviation 
Prel
2/25/03 
Osteen, FL 
Cessna 172P 
N97890 
Fatal(1) 
Part 91: General Aviation 
Prel
2/25/03 
YOUNTVILLE, CA 
FIREFLY 11B 
N1501H 
Fatal(1) 
Part 91: General Aviation

Clarification of Question by bobty-ga on 02 Apr 2003 21:27 PST
Please highly comment the programs so that I can follow along.  Also,
please list the functions used and a description of what they do.
Thanks

Request for Question Clarification by studboy-ga on 02 Apr 2003 22:46 PST
How about separating this into two separate questions to make it
easier for us (and to allow two different researchers to work on it
simultaneously)?

Clarification of Question by bobty-ga on 03 Apr 2003 10:21 PST
I have no problem with having two different researchers to work on it.
 However, i would need to split the cost between the two.  I can
increase the payment if necessary. How do I set it up from here to
allow that? Part I and Part II are separate questions, but Part II
needs Part I in order to function.

Request for Question Clarification by theta-ga on 03 Apr 2003 14:06 PST
Hi bobty-ga,   
  Needed a few clarifications on the first part:
    - The format of the input text file: Each record has 7 fields,
every field on a seperate line.
       Q: Is there an empty line between two successive records?
       When I pasted the results from the search query into a text
file, I got an empty line after each record. But the sample input file
you provided does not seperate records in this way. Since you said
that the last field of the record is optional, which means that every
record can be 6 or 7 fields long, it would make the code a little less
complicated if there was a newline seperating each record. Otherwise,
we will just have to check the contents of the 7th field to see if it
is a new record or the old one.
    - In the question, you say that in some cases the last two fields
are omitted (Type of Air Carrier Operation, Carrier Name). However, in
the results, and your sample file, (Type of Air Carrier Operation,
Carrier Name) is just one field, the last one. So, I assume that only
the last field is optional, and every record will have atleast 6
fields.
      Q: Can you provide a sample query for which the results have
these fields missing? It would help to test out the solution.
    - Just wondering about the size of the fixed length fields. Did
you have any particular sizes in mind? Here are my estimates:
       Seq. Number  : 4 bytes [32 bit mumber]
       Regist. Num  : 6 chars
       Status       : 5 chars
       Date         : 8 chars
       Location     : 25 chars
       Make / Model : 40 chars
       Severity     : ?? chars [If its just Fatal/Nonfatal : 1 char]
       Type of Air Carrier Operation
       and Carrier Name (Doing Business As)  : 40 chars
       
     Q: I assume that the Seq. number field will be generated and
added by us?
     Q: You say that the output for each record should fit on 1 line
of the screen,i.e,80 characters. Since there are 8 fields, we get an
average size of 9 characters per field + 7 seperator '|' characters.
Is this OK?
            

     As for breaking up this questions into two, so that multiple
researchers can work on them, I am not very sure that it would help
much. As you pointed out, part II depends on the solution for Part 1.
I believe a single researcher can attempt both the parts easily.
   However, if you still want to break up the questions, follow these
steps:
     - Post a clarification here, specifying that only the answer to
part 1 should be posted here.
     - Post part 2 as a new question on Google Answers. Make sure that
it contains a link to this question.
     - Adjust the pricing of the questions accordingly.

     As for the pricing, I believe that you would get more responses
from researchers if you were to increase the list price. The solution
you require consists of 6 subprograms of average and above average
difficulty. Please take a look at the Google Answers Pricing
Guidelines (http://answers.google.com/answers/pricing.html)

Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 03 Apr 2003 22:51 PST
Hello Theta-ga:
Thank you for taking a look at my problem.  Here are the answers to
your questions

A new line should separate each field.  The average size of each field
that you suggested sounds fine.  Although a few of those fields, such
as seq. number, regist. num, and status can have a smaller field size.
 I tried making a query to find those last two fields missing, but it
was too difficult.  I think if you just deleted those two fields from
one of the records in the sample input file, it should work in the
same manner.  I’m sorry I am getting back to you so late, but I could
not access a computer for most of the day. That will not be a problem
the next few days and so I will respond to any questions much quicker.
 I also increased the amount to be paid.  Thanks for the tip.  Let me
know if I still don’t have a clue.  Again, thanks for looking.

Request for Question Clarification by theta-ga on 04 Apr 2003 03:45 PST
Hi bobty-ga,
   I am starting work on Part 1 of the question. Once you test out my
solution, I will move to Part 2. Expect some more queries coming your
way soon :-)
   
   As for the pricing, the average price we get for one of the
subprograms this size is $20. So, for your 6 subprograms, I had the
$120+ range in mind. However, I will leave the pricing issue up to
you. Check out the solutions I post, and if you find them worth it,
increase the price or add the difference as a tip. And if you don't
find the results good enough...well, that ain't gonna happen ;-)
Regards,
Theta-ga
:-)

Request for Question Clarification by theta-ga on 05 Apr 2003 12:52 PST
Hi bobty-ga,
  Here is the initial implementation of the solution to part 1 of your
question. The code contains extensive comments, so you should be able
to follow it easily. The main purpose of this release is to enable you
to test it out and ensure it works as expected. I will post a more
indepth explanation of its working when I post the final version.
  The solution consists of the following two files:
    - DBRecord.h: Contains the database record structure definition,
and also constants defining the database filename and field sizes.
This file will be reused for part 2 of this question
    - showdata.cpp: Contains code to parse the input file named at the
commandline, display its contents on the screen, and also to write
them to disk.
  You can download the ZIP file containing the code from :
      (http://www31.brinkster.com/tanm/GA/showdata.zip)
    
   The database record contains the following eight(8) fixed length
fields:
    1. Registration Number
    2. Report Status
    3. Date
    4. City
    5. State [seperate field as specified in the question]
    6. Airplane Make/Model
    7. Severity
    8. Aircraft carrier operation type
    The last field is optional. All fields are stored as fixed length
strings.

    I have subjected the code to the following tests:
    - Successfully tested with both Unix and DOS/Windows input text
files. The files contained 50 records, and were created as per your
instructions in the question above. The Unix files use the linefeed
character('\n') to denote the end of line, while DOS/Windows use the
carriage return-linefeed combination("\r\n") to denote the end of
line. This program works by ignoring all occurances of the carriage
return ('\r') character(since it is not part of our input data
anyway), and using the linefeed('\n') character as the end of line
marker.
    - Successfully tested with file containing some records not
seperated by an empty line. If the program is unable to find an empty
line after a record, it skips ahead in the input file until it finds
one. It then starts reading the next record from there.
    - Successfully tested with files containing incomplete records. If
a record contains a missing field(except for the last field which is
optional), it is not written to the database file.

   Please test out the program yourself and tell me about any areas
that I have missed out on, or that may need more work. Note that the
error checking/recovering code may at times make the program
(slightly)difficult to follow. I will be interested to know whether
you would want me to tone down on the error checks or increase them.
Also, it would be helpful if you could tell me what compiler and
platform you are using for you tests.
   I will be waiting for any suggestions/questions you may have.
Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 05 Apr 2003 22:15 PST
Hi Theta-ga,
Thank you for answering so quickly. The program is running just fine.
For the records that have a missing field, the record should still be
written to the database file.  For the missing record, blank spaces 
or "none" should be inserted.  For my test I am using the GNU C
compiler. If you could tone down the error checks slightly, that would
be helpful.  Thank you for your help. I hope it is not too difficult.
I will add a tip after completion.

Request for Question Clarification by theta-ga on 06 Apr 2003 03:36 PDT
Hi bobty-ga,
  As per your instructions, I removed the checks for an empty line
while reading the record. Now if an empty line is detected, the field
is filled with null '\0' characters. Of course, the Reg No. field
cannot be null, since it is the primary key.
  You can test the program with your query file, replacing some of the
fields with empty lines.
  A problem came to light while removing these error checks. If the
line containing the city and state name is empty, that record will be
read incorrectly. I can fix this by adding some error checks and
modifying the code a little, but have so far refrained from this due
to your desire for minimal error checking in the code.
  If you are looking for simplicity, I recommend removing all input
file validation code from the program. It then becomes the users
responsibility to ensure that the input file they provide is in the
right format. The program just reads the first 7 lines of text into
the record, skips the following empty line and continues, withour
performing any error checking at all. Note that if the input file is
not in the expected format, the database will be filled with
gibberish.
You can get the modified code here:
  (http://www31.brinkster.com/tanm/GA/shwdata2.zip)
  Test out the code, and tell me what you want. I will be waiting for
your suggestions.
Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 06 Apr 2003 14:03 PDT
Hi Theta-ga,
After checking the program, I think the best thing to do is to go
ahead with the error checks.  It should be the responsibility of the
program to deal with records with incorrect format.  The user should
not have to modify the records to make sure they are in correct
format.  Please proceed with using error checks.  You are doing above
and beyond my expectations. Thank you so much.

Request for Question Clarification by theta-ga on 06 Apr 2003 19:56 PDT
Hi bobty-ga,
  This is just to inform you that I will be out of town, on some
personal work, the whole of today and tomorrow. Hope to be back with
an updated implementation of Part 1 tomorrow night.
Regards,
Theta-ga
:-)

Request for Question Clarification by theta-ga on 08 Apr 2003 06:48 PDT
Hi bobty-ga,
  Here is the latest version of showdata. Now contains a new function
to deal with the city name and the various problems that may occur in
extracting it. The other functions have been (very slightly)
simplified. The package also contains the input file(Windows format) I
use to test the code. It contains 49 records, many with missing
fields, and extra blank lines seperating them. As of now, only two
fields are compulsory in a record. They are:
  - The status field. This is used to detect that a new record has
started.
  - The reg. no field. It is the primary key and cannot be empty.

You can download the code here:
  (http://www31.brinkster.com/tanm/GA/shwdata3.zip)

Waiting for your comments.
Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 08 Apr 2003 10:24 PDT
Hi Theta-ga,
Part I is working perfectly. Thank you so much. I'm sorry I made you
modify it so many times.  I think it is safe to move on to Part II!

Request for Question Clarification by theta-ga on 09 Apr 2003 11:35 PDT
Hi bobty-ga,
  That's absolutely all right, we aim to please. :-)
  Have already begun on Part 2. Should have the first draft for you soon.
Regards,
Theta-ga
:-)

Request for Question Clarification by theta-ga on 11 Apr 2003 17:07 PDT
Hi bobty-ga,
   Some bad news. :-(
   Emergencies at the work front have meant that I have spent most of
this week travelling out of town. In fact, I'm leaving again in a
couple of hours and will be out of communication for the next couple
of days. While I have completed a large part of Q2, under the current
circumstances, I will not be able to deliver it by your April 12th
deadline.
   If you are able to extend your deadline, I can get Q2 completed and
post it here. Otherwise, I have posted the current codebase here [
http://www31.brinkster.com/tanm/GA/P2.zip ]. You can download it and
test it out. Most of the components work as desired, although I have
not subjected them to any extensive testing. I am not posting this as
an answer, since  you will most likely desire some changes, and I will
not be able to respond to your requests before the deadline.
   My heartfelt apologies for any inconvenience caused.
Regards,
Theta-ga

Clarification of Question by bobty-ga on 13 Apr 2003 12:49 PDT
Hi Theta-ga,
I can extend the deadline to April 15th. Do you think you'll be able
to complete Part 2 by then? I look forward to hearing from you.

Clarification of Question by bobty-ga on 13 Apr 2003 18:30 PDT
Hi Theta-ga,
I am having problems with part 1. I am recieving the following errors:
g++ showdata.cpp -o showdata    
showdata.cpp: In function `int main(int, char**)':
showdata.cpp:60: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:62: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:67: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:69: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:70: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:71: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:72: invalid conversion from `unsigned char*' to `char*'
showdata.cpp:79: invalid conversion from `unsigned char*' to `char*'
make: *** [showdata] Error 1

This is the makefile that I wrote:
showdata: showdata.cpp DBRecord.h
	g++ showdata.cpp -o showdata	

Could you please either tell me what I am doing wrong while trying to
compile or fix the problem with the program. Thank you. I desperately
need part I done as soon as possible.  Part II I can wait until April
15 for right now. Thank you

Clarification of Question by bobty-ga on 13 Apr 2003 23:03 PDT
hi bobty-ga,
I was able to fix the problem with the program by making the following
changes:
In showdata.cpp: #include <DBRecord.h> was changed to "DBRecord.h"
In DBRecord.h: all the unsigned int were changed to int.   
               all the unsigned char were changed to char.

There is still one problem that I am having.  It seems as though the
last record in the input file is being cut off and therefore is not
showing up in the output file.  Could you please fix this problem.
Thank you so much.

Clarification of Question by bobty-ga on 13 Apr 2003 23:19 PDT
Hi theta-ga,
sorry, never mind about that last problem. everything seems to be
working fine now :)

Request for Question Clarification by theta-ga on 15 Apr 2003 11:11 PDT
Hi bobty-ga,
   Just got back today.
   I see that you extended your deadline, but there's just one little
problem... It's already April 15th in my timezone!! :-(
   Have you compiled and tested the code for Part 2 that I posted
before leaving? While I was not able to test it out fully, the initial
modules that I tested(load,list,add) seemed to be working all right.
Please test out the code and see what changes need to be made. I'll
try to find some free time and do some more testing of my own.
Regards,
Theta-ga

Clarification of Question by bobty-ga on 15 Apr 2003 12:02 PDT
Hi theta-ga,
I have not had a chance to test Part II yet.  I will do that tonight.
I can extend the deadline further(like a day or two, more if
absolutely necessary), but the sooner the better! Thank you.

Request for Question Clarification by theta-ga on 17 Apr 2003 05:04 PDT
Hi bobty-ga,
  Have you checked out the code yet? Any changes needed?
Regards,
Theta-ga

Request for Question Clarification by theta-ga on 17 Apr 2003 12:12 PDT
Hi bobty-ga,
  Taking advantage of a lull in the proceedings, I went over the code
for Part 2. Found a bunch of bugs, and fixed them :-)
  You can download and test the latest version here:
     [ http://www31.brinkster.com/tanm/GA/Part2-v2.zip ]
  The ZIP archive also contains the input file[query.txt - containing
80 records] that I am using for my tests.
  As far as I can tell, the main work seems to have been finished. The
various modules are working as required by the question. Check them
out yourself and tell me if I have missed out on anything. If it works
all right for you, I'll post a cleaned up and better commented version
as the answer.
  Hope this is not too late.
Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 19 Apr 2003 12:03 PDT
Hi bobty-ga, 
I did get a chance to test the code.  Everything seems fine right now,
although I haven't had a chance to do any extensive tests due to a
family emergency.  Hopefully by Monday I can let you know if anything
needs to changed/added.  Thank you.

Request for Question Clarification by theta-ga on 23 Apr 2003 05:50 PDT
Hi bobty-ga,
   I trust that you have had time to test out the code. Do you require
any more changes to be made, or should I post it as the answer?
Regards,
Theta-ga
:-)

Clarification of Question by bobty-ga on 23 Apr 2003 10:38 PDT
Hi theta-ga,
I'm sorry I haven't responded in a while.  Unfortunately, I've had to
deal with a few family problems the last few days and I still have not
gotten a chance to test the code. I will do this today and hopefully
let you know the status by tonight or tomorrow morning. Again, I'm
sorry and I really appreciate your patience.

Clarification of Question by bobty-ga on 27 Apr 2003 22:29 PDT
Hi Theta-ga,
I finally finished testing out Part II.  Everything is working great!!
Thank you so much for everything.  Your work was exactly what I
needed.  I was wondering if I could ask you to do one last program. I
have included the specifications below.  (It has a lot to do with Part
I and Part II) If you do not think you can finish this before this
posting expires, I can post it as another problem.  If you do not wish
to do this program at all, then thanks for completing Part I and Part
II.  I will add the extra payment as a tip after completion if you
choose to do this final part.


For this part I need to build an indexed data storage and retrieval
system for the data used in Parts 1 and 2. This will include a batch
load function (from a text file), an index display function, an
interactive search feature and delete. We will use an Avail list for
deleted records. After evaluating the memory requirements of the
previous version, it is decided that the primary index shall be a
B-Tree.

The easiest way to implement these functions is to use one program for
each function. The programs should know the name of the file
structure. Then the only thing that needs to be passed to the program
on the shell command line is the argument for the command.


$ load data.txt   /* create the file structure */ 
$ list   /* outputs a list of all records */ 
$ search N1079U   /* program displays remaining args */ 
$ add N1079U   /* program prompts for remaining args */ 
$ delete N1079U   /* program displays, waits for yes */ 


Given the difficulty of interpreting a B-Tree data structure, also
prepare a program that displays the B-Tree data structure:

$ btree /* show the B-tree structure */

If your code for Part I was well-structured, you can replace the
simple index functions with the B-tree functions without having to
make any other changes.

Specification of the problem

The source file format is the same as for Part II. Records with
missing primary key should be omitted.
A program load should translate a text file containing product records
to a file structure of your design. You should generate two files, a
database file and an B-tree file. You should use the same database
file structure as in Parts I and II.


The structure of the data file is the same as in Part II.

A program search should allow the user to find a record with a given
primary key and display the record's content.

A program list should display all records in order by the primary key.
The display should show the entire primary key, followed by the other
fields, which may be truncated. Each record should fit on a single
line, and there should be no blank lines in between. This format must
be followed.
A program add should allow the user to add a new record to the file
structure. This program should prompt for the other fields.

A program delete should allow the user to delete a record with a user
supplied primary key.

The delete function should place the deleted data record on an Avail
list. The Avail list should be kept in the deleted records in the data
file. The head pointer for the Avail list should be kept in the header
of the index file. Subsequent adds should re-use deleted data records
for new data.

The add and delete functions should make use of avail lists for both
the database file and the B-tree file.

There should be no limitation on the number of records in the
database.

A program btree should allow the user to display the structure of the
B-Tree, showing all pages.

The display of a B-Tree page should display: 
The B-Tree page number 
The value of each key in the page. 
The value of each B-Tree page pointer (e.g., address, byte offset,
RRN).

Each B-Tree page should take up only one line on the screen to make it
easier to view the entire tree at once, with no blank lines in
between.

The B-Tree should be displayed in tree traversal order, root first, or
a level at a time. Displays in page number order or other
non-specified order will not be accepted.


Specification of the source data

You should use the same source data format as in Parts I and II. 
The source files given are not ordered by the primary key. 

Specification of the user interface

Each command that may be performed on the file structure should be
implemented in a separate program.

Each program should know the name of the file containing the records
in the file structure.

The key field should be taken from the command line. 
Each program should open the file structure, perform a single
operation, and close the file structure.

Implementation constraints

Each program should perform the action required and report the results
to the standard output.

The primary index should be a B-Tree maintained in an index file. 
The B-Tree should be of order 5. 
The B-Tree should implement both splitting and redistribution logic in
the B-Tree for both insertion and deletion.
All B-Tree algorithms should be recursive (as shown in the notes).
This includes the list and B-Tree display functions.
The search , add , and delete functions should display the page
numbers of the B-tree pages accessed and the RRN of the data blocks
accessed.
Transfers to or from the database file should be implemented only with
open(...), read(...), write(...) and close(...) functions. (If using
C++ I/O, this corresponds to the unformatted I/O functions sgetn and
sputn.)

The data record size may be any reasonable size.

The file structure transfer block size should be the size of four
records, for transfers to and from the database file. The file size
must be a multiple of this value. Only blocks corresponding to RRNs
which are a multiple of 4 should be accessed. This simulates accessing
an actual disk file.

The transfer block size for the index file should be one B-Tree page.
This simulates accessing an actual disk file.

The functions that read and write the database should print out the
block accessed and also the record accessed within the block ONLY for
functions that access only a single record. (i.e., not for the list
function.)
Two avail lists should be maintained, one for records deleted from the
database, and another for freed B-tree pages. Subsequent insertions or
B-tree splits should use space from the avail list if possible.
The avail list should be kept in the deleted data records. The key
should be set to "****************" or equivalent, and the next field
in the data record should contain the RRN of the next list item. The
remainder of the data field should be set to blanks. The B-tree avail
list should also be maintained within the unused pages. The heads of
the avail lists should be kept in the header record of the B-tree
file.



Required structure


Reading and writing data records.
The block size is sufficient for 4 records. Only blocks corresponding
to RRNs which are a multiple of 4 should be accessed, and the
appropriate record should then be extracted. For read, your blockread
function is given an RRN and returns a pointer to the appropriate
record in the buffer. For blockwrite, the function is given an RRN and
a pointer to a record which is to be copied into the buffer. Every
write also involves a read, since three of the four records in the
block remain unchanged. The functions should print a brief descriptive
message of the operation, including block numbers (RRN of the start of
the block and RRN of the accessed record) whenever a block is read or
written, ONLY for functions that access only a single record. (i.e.,
not for the list function.) Note that for the load function you may
use a simpler block write.

Request for Question Clarification by theta-ga on 28 Apr 2003 04:58 PDT
Hi bobty-ga,
  Thanks for the opportunity to answer another question, but I'm
afraid my current commitments force me to decline the offer. We just
started on a new project at work two weeks ago, and that is going to
keep me occupied for most of the coming month. As you can see, I'm in
no position to meets any deadlines whatsoever. :-(
  However, if you post a seperate question, I am sure that one of the
many talented programmers at Google Answers will be glad to take it
up.
 Hope to be of service to you again in the future.
Regards,
Theta-ga
:-)
Answer  
Subject: Re: C++ program
Answered By: theta-ga on 28 Apr 2003 07:47 PDT
 
Hi bobty-ga,
   Since you are satisfied with the solutions for Part I and Part II
of your question, I am posting them as the answer. You can download
the final C source code from:
    [ http://www31.brinkster.com/tanm/GA/bobty-ga.zip ]
    
   The code for Part I is the same one you tested earlier. The code
for Part II has been somewhat cleaned up and is now better commented.
No implementation changes were made, so it should work exactly as it
did before.

   Although I am unable to take up your new question (see my previous
posting), I am sure you will have no problems in finding other GA
Researchers to take up the challenge. While the functions in the
'index.h' file for Part II will need to be implemented from scratch,
the remaining code for Part II should require only minor
modifications.

  If you require any more information, or need any changes to be made
to the code, just ask for a clarification.

Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 04 May 2003 14:56 PDT
Hi Theta-ga,
I ran into some problems when trying to compile part II on a Unix
machine.  Here is a list of errors that I recieved:
g++ load.cpp -o load
In file included from DBFuncs.h:20,
                 from load.cpp:7:
Index.h:12:16: io.h: No such file or directory
In file included from DBFuncs.h:20,
                 from load.cpp:7:
Index.h: In function `int OpenIndexFile()':
Index.h:63: `O_BINARY' undeclared (first use this function)
Index.h:63: (Each undeclared identifier is reported only once for each
function
   it appears in.)
Index.h:66: `filelength' undeclared (first use this function)
Index.h:73: `lseek' undeclared (first use this function)
Index.h:74: `write' undeclared (first use this function)
Index.h: In function `int CloseIndexFile()':
Index.h:86: `close' undeclared (first use this function)
Index.h: In function `int IndexAddEntry(char*, int)':
Index.h:118: `read' undeclared (first use this function)
Index.h:122: `stricmp' undeclared (first use this function)
Index.h: In function `bool IndexGetEntry(int, IndexEntry&)':
Index.h:219: `eof' undeclared (first use this function)
In file included from load.cpp:7:
DBFuncs.h:22:77: io.h: No such file or directory
make: *** [load] Error 1

Here is my makefile:
target: load list search delete add 

load: load.cpp
	g++ load.cpp -o load

list: list.cpp
	g++ list.cpp -o list

search: search.cpp
	g++ search.cpp -o search

delete: delete.cpp
	g++ delete.cpp -o delete

add: add.cpp
	g++ add.cpp -o add

I tried to fix the problems myself but was not able to.  I would
really appreciate it if you could do this for me, other wise I cannot
get the code to work where I really need it.  Thank you.

Clarification of Answer by theta-ga on 05 May 2003 08:14 PDT
Hi bobty-ga,
   Here's where we run headlong into platform incompatibilities.
   - Apparently UNIX systems do not have an 'io.h' header file.
Instead you must include the following headers:
          #include<unistd.h>
          #include<sys/types.h>

   - The next error we come to, is about 'O_BINARY' being undeclared.
Well, it is!! Unix by default reads files in binary mode, so many Unix
systems do not define the 'O_BINARY' flag. However you will need this
flag if you compile for the DOS/Windows platform. We can get around
this error, by adding the following lines to Index.h, after the
#includes:
     #ifndef O_BINARY
        #define O_BINARY 0
     #endif

  - The final problem we face, is that of the missing `stricmp()'
function. Some UNIX systems define the functions strcasecmp() and
strncasecmp() instead of strcmp()/stricmp(). It appears that your
system is one of these. To get around this error, just add the
following code after the #includes:
          #define stricmp strncasecmp

Hope this helps.
Try making these changes and call me if any new errors pop up. :-)
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 05 May 2003 10:40 PDT
Hi theta-ga, 
sorry for bothering you again. I made the changes that you recommended
and it seemed to fix most of those errors, however I am still
recieving the following error:
g++ load.cpp -o load
In file included from DBFuncs.h:20,
                 from load.cpp:7:
Index.h: In function `int OpenIndexFile()':
Index.h:72: `filelength' undeclared (first use this
function)
Index.h:72: (Each undeclared identifier is reported
only once for each function 
   it appears in.)
/usr/include/string.h: In function `int
IndexAddEntry(char*, int)':
/usr/include/string.h:71: too few arguments to
function `int strncasecmp(const 
   char*, const char*, unsigned int)'
Index.h:128: at this point in file
Index.h: In function `bool IndexGetEntry(int,
IndexEntry&)':
Index.h:225: base operand of `->' is not a pointer
/usr/include/string.h: In function `int
BinarySearch(int, int, char*)':
/usr/include/string.h:71: too few arguments to
function `int strncasecmp(const 
   char*, const char*, unsigned int)'
Index.h:274: at this point in file

Please let me know how to fix these errors. Thank you so much for your
continued help.

Request for Answer Clarification by bobty-ga on 05 May 2003 13:20 PDT
Hello again,
Slight problem! The program for partI needs to be slightly modified. 
It turns out that the input file does not have a blankline in between
records.  The input file should look just like the input file that I
posted above.  Therefore, new records should be able to be
distinguished by recognizing the status field.  This field always has
"Prel", "Fact" or "Final" inside.  Therefore whenever the program
encounters any of those three, it should start a new record rather
than by a blank line.  I would appreciate it if you could please make
these changes.  These changes should also be updated for partII.
Please do not forget to read the post right above this one. It is in
regards to part II. Thank you so much.

Request for Answer Clarification by bobty-ga on 05 May 2003 23:01 PDT
Hello theta-ga,
I've been trying to fix the errors myself and I have been able to
reduce them somewhat.  After doing a little research I found that I
should use strncmp instead of stricmp.  This is basically how it
should be implemented:

int strncmp(const char *s1, const char *s2, size_t n);

In Index.h, I replaced this and used sizeof regNo (for the third
argument) for both cases of strncmp. This reduced my errors to the
following, which I still have not been able to figure out:
g++ load.cpp -o load
In file included from DBFuncs.h:20,
                 from load.cpp:7:
Index.h: In function `int OpenIndexFile()':
Index.h:72: `filelength' undeclared (first use this function)
Index.h:72: (Each undeclared identifier is reported only once for each
function
   it appears in.)
Index.h: In function `bool IndexGetEntry(int, IndexEntry&)':
Index.h:225: base operand of `->' is not a pointer
make: *** [load] Error 1

PLEASE help me with this part and modifying the code to Part I as I
stated in the above posting.  I need these to be done very soon and
very badly! I really appreciate your quick responses. Thank you.

Request for Answer Clarification by bobty-ga on 06 May 2003 15:39 PDT
Hi theta-ga,
I desperately need these programs to work. Please try to fix them as
soon as you can.  I wouldn't sound so desperate if I wasn't!!  I've
been trying to make the necessary changes myself but so far have
failed miserably.  Please help!

Clarification of Answer by theta-ga on 08 May 2003 11:24 PDT
Hi bobty-ga,
 Ok. here are the latest round of bug fixes:
  - filelength() : Again a function defined in io.h for DOS/Windows,
but as it is neither POSIX nor ANSI C++, not available on many Unixes.
To get around it, we will have to code our own filelength function:
    int filelength(int handle)
    {
      //Store current pos
      int cur = lseek(handle,0,SEEK_CUR);

      // Move to end of file
      int len = lseek(handle,0,SEEK_END);

      // Reset file pointer to initial pos
      lseek(handle, cur, SEEK_SET);

      // Return file length
      return len;
    }

 - As for the error "base operand of `->' is not a pointer", I have
not used '->' in the code for the finction IndexGetEntry(). The
function contains an IndexEntry variable named idxEntry, all of whose
members are accessed using the "." member operator. Just go through
your version of IndexGetEntry and replace all "->" operators with "."
. That should fix the error.

Hope this helps. I will be posting a new version of the showdata/load
modules soon.

Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 08 May 2003 14:36 PDT
Hi theta-ga, 
I was wondering where exactly I should implement the int
filelength(int handle)?  As for the error "base operand of `->' is not
a pointer", nowhere in the code can'->' be found, however this error
still persists!  I believe these are the only errors, and so hopefully
nothing new will pop up after fixing them.  Thanks for taking the time
to fix the errors. :)

Clarification of Answer by theta-ga on 09 May 2003 07:26 PDT
Hi bobty-ga,
   Since Index.h is complaining about filelength(), implement it in
this file. Remember to add a function prototype for filelength() at
the beginning of the file.
   As for the 'base pointer' error, it may be caused by parsing errors
due to thr presence of the filelength() error. Once the filelength()
error is fixed, this too should go away. If it doesnt, please post the
code causing the error here so i can check it out.
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 10 May 2003 00:29 PDT
Hi theta-ga, 
I do not think that I am implementing the filelength correctly because
I same to be getting the following error.
Index.h: In function `int filelength(int)':
Index.h:62: `int filelength(int)' used prior to declaration
Index.h: In function `bool IndexGetEntry(int, IndexEntry&)'

Below is the code for Index.h:

#ifndef __index_h__
#define __index_h__

#include "DBRecord.h"
#include <sys/stat.h>
#include <stdio.h>
#include<unistd.h> 
#include<sys/types.h> 
#include <fcntl.h>
#include <string.h>
#include "DBFuncs.h"

#ifndef O_BINARY 
#define O_BINARY 0 
#endif
  #define strncmp strncasecmp  
//------------------------------------------------------------------------------

const char IDX_FILENAME[]="dbIndex.idx";   //Index filename
const int LEN_AVAILHEADER = sizeof(DBRecord);    //Size of Avail list
header


// This is the structure of an entry in the index file
// Contains the reg no and record number for each record
struct IndexEntry
{
  char regNo[9];
   int rrn;
};

// Used to mark areas in the Database file, that have been deleted
struct DeletedRecord
{
  char id[8];    // identifies the record as a deleted record
  int next ; // rrn of next deleted block in list
  char buf[sizeof(DBRecord)-8-sizeof(int)]; //filler to make this
record exactly
                                                 // the same size as
DBRecord
};
int indexFileHandle = -1;
int currentIndexEntry = -1;

//------------------------------------------------------------------------------

int AvailGetRRN(); //Gets a free record from the avail list
bool AvailAddRecord(int rrn); // Adds a deleted record onto the avail
list

int BinarySearch(int start, int end, char *regNo); // searches for a
matching regNo

int OpenIndexFile();// Globally opens the index file. Makes sure
thatevery file contains an Avail list header
int IndexAddEntry( char regNo[SZ_REGNO+1], int blockPos); // Add
record entry to index
bool IndexGetEntry(int num, IndexEntry& idxEntry);  //  read record
entry from index
bool IndexSearch( char* regNo, int &idxLoc); //uses the BinarySearch
fn


int OpenIndexFile()
{
   if( indexFileHandle < 0)
      indexFileHandle = open(IDX_FILENAME, O_RDWR|O_CREAT|O_BINARY,
S_IREAD|S_IWRITE);

  int idxHandle = OpenIndexFile();
   // file size is incorrect
   if(indexFileHandle>=0 && filelength(idxHandle) < LEN_AVAILHEADER)
   {
	 // Write an empty Avail list header to the file
     DeletedRecord header;
     memset(&header,0,sizeof(header));
	 strcpy(header.id ,"HEADER");
     header.next =0;
     lseek(indexFileHandle, 0, SEEK_SET);
     write(indexFileHandle,&header,sizeof(header));
   }

   return indexFileHandle;
}

//Closes the global Index file handle
int CloseIndexFile()
{
  close(indexFileHandle);
  indexFileHandle = -1;
  return 0;
}

int IndexAddEntry(char regNo[SZ_REGNO+1], int blockPos)
{
  IndexEntry idxnewEntry, idxoldEntry;
  
  //Fill with 0's
  memset(&idxnewEntry,0,sizeof(IndexEntry));
  memset(&idxoldEntry,0,sizeof(IndexEntry));

  strcpy(idxnewEntry.regNo, regNo);
  idxnewEntry.rrn  = blockPos;

  int idxHandle = OpenIndexFile();
  int handle = OpenIndexFile();
  // Seek to beginning of the index
  lseek(handle, LEN_AVAILHEADER, SEEK_SET);
  int totalRecords =  (filelength(idxHandle) -
LEN_AVAILHEADER)/sizeof(IndexEntry);

  int pos = 1;
  for(pos=1;pos<=totalRecords;pos++)
  {
    read(handle, &idxoldEntry, sizeof(idxoldEntry));
    // Using strncmp() to compare reg nums, as it ignores case while
	// performing comparision. An interesting result with string 
	// comparision functions is that "N99" evaluates to greater than
"N189"
    if(strncmp(idxoldEntry.regNo, idxnewEntry.regNo, sizeof regNo)>0)
    {
       lseek(handle,-(long)(sizeof(IndexEntry)),SEEK_CUR);

       if(pos<=totalRecords)
        {

          // shift items down
          printf("\nIndex Add: Shifting down index items %d to
%d.",pos, totalRecords);

          for(int i =pos; i<=totalRecords;i++)
          {
           read(handle,&idxoldEntry,sizeof(IndexEntry));
           lseek(handle,-(long)(sizeof(IndexEntry)), SEEK_CUR);
           write(handle,&idxnewEntry, sizeof(idxnewEntry));

           idxnewEntry = idxoldEntry;
          }
        }
      break;
      }
    }
  // Write record at the end of the file
  write(handle,&idxnewEntry, sizeof(idxnewEntry));

  return pos;
}

bool IndexDeleteEntry(int idxLoc)
{
  char indexFileHeader[LEN_AVAILHEADER];
  IndexEntry idxEntry;

  CloseIndexFile();

  FILE *oldIndex = fopen(IDX_FILENAME,"r+b");

  //Open new temp index file
  FILE *newIndex = fopen("idx.new","w+b");

  //Copy header to new file
  fread(indexFileHeader,LEN_AVAILHEADER,1,oldIndex);
  fwrite(indexFileHeader,LEN_AVAILHEADER,1,newIndex);

  for(int i=1;!feof(oldIndex);i++)
  {
    fread(&idxEntry,sizeof(IndexEntry),1, oldIndex);
    if(i != idxLoc && !feof(oldIndex))
       fwrite(&idxEntry,sizeof(IndexEntry),1, newIndex);
  }

  //close files
  fclose(oldIndex);
  fclose(newIndex);

  //Delete old Index
  remove(IDX_FILENAME);
  //Rename temp file to new index
  rename("idx.new",IDX_FILENAME);

  return true;
}

bool IndexGetEntry(int num, IndexEntry& idxEntry)
{
  int idxHandle = OpenIndexFile();

  int totalRecords = (filelength(idxHandle)
-LEN_AVAILHEADER)/sizeof(IndexEntry);

  // Is num a valid index entry number?
  if(num<1 || num>totalRecords)
    return false;

  do
  {
   //Position filepointer
   lseek(idxHandle, (num-1)*sizeof(IndexEntry)+LEN_AVAILHEADER,
SEEK_SET );

   read(idxHandle,&idxEntry,sizeof(idxEntry)); // read index entry
   num++;
  }
  while((idxEntry.rrn==0) && (!feof(idxHandle)));
   return true;
}

// IndexSearch(): Searches the index for the specified record entry
bool IndexSearch( char regNo[SZ_REGNO+1], int &idxLoc)
{
  int idxHandle =OpenIndexFile();

  int start = 1;
  int end = (filelength(idxHandle) -
LEN_AVAILHEADER)/int(sizeof(IndexEntry));

  if(end<start)
    return false;
   printf("\nBinarySearch [");
  idxLoc = BinarySearch(start,end, regNo);
  printf("]");
  if(idxLoc<=0)
    return false;

  return true;
}

// A binary search implementation for the IndexSearch() function
int BinarySearch(int start, int end, char regNo[SZ_REGNO+1])
{
 while(start<=end)
  {
    int mid = (start+end)/2;
    IndexEntry idxEntry;
    int cmp;
    if(!IndexGetEntry(mid, idxEntry))
        return 0;
	// Display records accessed while searching
    printf("-%d-",mid);
    cmp=strncmp(idxEntry.regNo,regNo, sizeof regNo); // compare reg
nums
    if(cmp==0)
      return mid;
    if(cmp>0)
      end = mid-1;
    else
      start = mid+1;
  }
  return 0;
}

int AvailGetRRN()
{
	
  struct DeletedRecord header, *ptr;

  memset(&header,0,sizeof(header));

  int handle = OpenIndexFile();

  // Seek to the top of the file
  lseek(handle,0,SEEK_SET);
  read(handle,&header, sizeof(header));

  if(header.next==0) // if avail list is empty
    return -1;

  // Otherwise traverse the avail list
  int freenode = header.next;
  // Read the next field of the deleted record and store in header
  ptr = (DeletedRecord*)blockread(header.next);
  header.next = ptr->next;
  // Write header back to index file
  lseek(handle,0, SEEK_SET);
  write(handle,&header, sizeof(header));

  return freenode; // return pos of the free record in the database
}
bool AvailAddRecord(int rrn)
{
  DeletedRecord header,delRec,curNode, *ptr;
  // Set to 0
  memset(&delRec,0,sizeof(DeletedRecord));
  memset(&curNode,0,sizeof(DeletedRecord));
  memset(&header,0,sizeof(DeletedRecord));

  // All deleted records are marked with the string "DELETE"
  strcpy(delRec.id,"DELETE");

  // Read Avail list header
  int handle = OpenIndexFile();
  lseek(handle,0, SEEK_SET);
  read(handle,&header, sizeof(header));

  if(header.next==0 || header.next>rrn)
  {
     //Swap
	 int temp = rrn;
     delRec.next = header.next;
     header.next = rrn;

     //Update header
     lseek(handle,0, SEEK_SET);
     write(handle,&header,sizeof(header));
  }
  else
  {
   int current = header.next;
   while(current !=0)
   {
     ptr = (DeletedRecord*) blockread(current);
     curNode = *ptr;
     if(curNode.next>rrn || curNode.next==0)
         break;
     current = curNode.next;
   }
   delRec.next = curNode.next;
   curNode.next = rrn;
   blockwrite(current,(DBRecord*) &curNode);
  }
  // Mark record as deleted
  blockwrite(rrn, (DBRecord*)&delRec);

  return true;
}

#endif

In file included from DBFuncs.h:20,
                 from load.cpp:7:
DBFuncs.h: In function `DBRecord* blockread(int)':
DBFuncs.h:64: `filelength' undeclared (first use this function)
DBFuncs.h:64: (Each undeclared identifier is reported only once for
each
   function it appears in.)
//---------------------------------------------------------------------------
// Contains functions for reading, writing and adding records to the
database
//---------------------------------------------------------------------------

#ifndef __DBFUNCS_H__
#define __DBFUNCS_H__

// Function prototypes
  DBRecord* blockread(int rrn);
  int blockwrite(int rrn, DBRecord *rec);
  int DBAdd(DBRecord& rec);

// Forward declarations
  int AvailGetRRN();
  int IndexAddEntry( char regNo[SZ_REGNO+1], int blockPos);
  bool IndexSearch( char regNo[SZ_REGNO+1], int &idxLoc);

// Includes
#include "DBRecord.h"
#include "Index.h"
#include <sys/stat.h> // -|
#include<unistd.h> 
#include<sys/types.h> //  |- for open(), read(), write() & related
constants
#include <fcntl.h>    // -|
#include <memory.h> // for memset()
#include <stdio.h>  // for printf()

#ifndef O_BINARY 
#define O_BINARY 0 
#endif

// Record buffer, used by blockread and write
DBRecord blockBuffer[4];

bool EnableInfoMessages = true; // default is messages enabled

// Prevents the blockread() and blockwrite() functions from displaying
// the information messages. Used by the list component
//void DisableInfoMessages()


 //bool EnableInfoMessages = false;




// Function blockread(): returns the specified record from the
database
//       This functions reads the contents of the databse 4 records at
a time
// and extracts the reqd record from the block read.
// NOTE: The user uses 1 based indexing for the records, which the
function
//      converts to 0 based indexing internally for convenience.
// Arguments: The record number to be read. The first record has the
rec no of 1.
// Returns: pointer to a block of memory containing the specified
record.
DBRecord* blockread(int rrn)
{
  
  // Open the database file
  int handle = open(DB_FILENAME,O_RDONLY|O_CREAT|O_BINARY,
S_IREAD|S_IWRITE);

  int totRecs = filelength(handle)/sizeof(DBRecord); // Get total num
of records in the database
  // If rec no is less than 1 or more than the tot num of recs, error!
  if(rrn<=0 || rrn>totRecs)
    return NULL;

  rrn=rrn-1; // Convert rec no to 0 based
  int blockNum = (rrn)/4; // Calculate the block no. in which the
record lies
  if(EnableInfoMessages) // Check if we can show messages
     printf("\nReading Block %d to get record %d.",blockNum+1, rrn+1);

  // Read the specified block of 4 records
  lseek(handle,blockNum*sizeof(DBRecord)*4,SEEK_SET); 
  read(handle,&blockBuffer, sizeof(DBRecord)*4);

  close(handle);

  return &blockBuffer[rrn%4]; // return a pointer to thr reqd record
}



// Function blockwrite(): writes the specified record into the
database
//       at the specified record position. The function writes a block
of
//       4 records to the databse at a time.
// Arguments: 
//     int rrn: The position in the database at which the record is to
be added.
//              If the specified position is less than 1, the record
is appended
//              to the end of the database
//     DBRecord *rec: Pointer to the record to be written
// Returns: 
//     The position at which the record was added to the database.
int blockwrite(int rrn, DBRecord *rec)
{
  bool found=false;
  int handle = open(DB_FILENAME,O_RDWR|O_CREAT|O_BINARY,
S_IREAD|S_IWRITE);
  int totRecs = filelength(handle)/sizeof(DBRecord);

  if(( rrn/4)>(totRecs/4) || rrn<=0)
  {
    // add record at end of file
    //first see if the last block has some empty space
    if((totRecs/4) >= 1)
    {
      lseek(handle,(long)(sizeof(DBRecord))*-4,SEEK_END);
      blockread(totRecs);
      for(int i=0;i<4;i++)
        if(blockBuffer[i].regNo[0] == '\0') // If the record is empty
        {
		  // add new record
          blockBuffer[i]=*rec;
          rrn=totRecs-4+i+1; // store the new record's position
          found=true;
          break;
        }
    }
    if(!found)
    { 
	  // Add record to the end of the database
      lseek(handle,0,SEEK_END);
      memset(blockBuffer,0,sizeof(DBRecord)*4);
      blockBuffer[0]=*rec;
      rrn = totRecs+1;
    }
  }
  else
  {  
	 //Add record to the specified pos
     blockread(rrn);
     rrn-=1; // convert to 0 based indexing
     blockBuffer[rrn%4] = *rec;
     lseek(handle,(rrn/4)*sizeof(DBRecord)*4, SEEK_SET);
     rrn+=1;
  }

  if(EnableInfoMessages)
    printf("\nWriting Block %d to update record %d.",rrn/4+1,rrn);

  //write to disk
  write(handle,blockBuffer,sizeof(DBRecord)*4);
  close(handle);
  return rrn;
}



// Function DBAdd(): Add a record to the database. Used by the load
and add modules.
//        The function checks if the Avail list(of deleted records)
contains an entry
//        and writes the new record at the position it specifies. If
the Avail list is
//        empty, the new record is added at the end of the database.
// Arguments:
//       DBRecord& rec: record whose contents are to be added to the
database
// Returns: The position at which the record was written into the
database
int DBAdd(DBRecord& rec)
{
    int tmpLoc;

   // Does a record with the same reg no already exist in the
database?
   if(IndexSearch(rec.regNo,tmpLoc) )
      return -1; // error! duplicate record

   // Get empty record position from the Avail list
   int rrn = AvailGetRRN();
   // Write the record at the position specified
   rrn=blockwrite(rrn,&rec);
   IndexAddEntry(rec.regNo, rrn); // Add new record entry to index

   return rrn; // The position at which the record was written
}



#endif


Also I recently found out that it is an error to do do an feof() on an
index file handle.  Apparently that can't be done because foef only
works with streams.  ie types defined as FILE*.The way to check eof
when you do a read() is to look at the value it returns.  read()
returns the number of bytes read so if that is 0 then you know that
you have reached the end of file. Below are the codes for Index.h and
DBFuncs.h that are causing the errors.  The lines with errors have
comments next to them indicating that there is an error there.

Clarification of Answer by theta-ga on 10 May 2003 08:12 PDT
Hi bobty-ga,
    I have updated code for Part I and the load module from Part II,
as per your requirements. You can download the updated code, and the
test input file I used from:
    [http://www31.brinkster.com/tanm/GA/update-noemptylines.zip]

    As for the filelength error, you are still getting this error
because you haven't added the function prototype for the filelength()
function at the beginning of the index.h file. To simplify your task,
I have created a seperate header 'utility.h' which you should include
in all your files that require the filelength() function. You can
download the utility.h header from:
    [http://www31.brinkster.com/tanm/GA/utility.h]
Now, this is what you have to do to get rid of the filelength()
problem:
  - Put 'utility.h' in the same dir as your other Part II files
  - In every file that gives the filelength error(DBFuncs.h and
Index.h) add the following include statement:
        #include "utility.h"
  - Do not add the filelength() function implementation to any other
file(like Index.h or DBFuncs.h)

As for the feof() thing, what you say is correct. For the POSIX file
functions(open,read etc.) we use the eof() function instead of the
feof() function to detect end of file. I see that you have changed the
eof() function call in the second last line of the IndexGetEntry()
function to a feof() call. Change it back to eof() and another error
will be gone.

Hope this helps.
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 10 May 2003 23:08 PDT
Hi theta-ga,
Thank you so much for making the changes.  The filelength() error is
now gone.  I changed the feof() back to eof() as you suggested, but I
am recieving this error:
Index.h: In function `bool IndexGetEntry(int, IndexEntry&)':
Index.h:228: `eof' undeclared (first use this function)
Index.h:228: (Each undeclared identifier is reported only once for
each
   function it appears in.)

This is the only error we are recieving. Hopefully we are almost done!
 I just want to thank you for your persistence in making sure that
everything works exactly how I want.
Sincerely,
bobty

Clarification of Answer by theta-ga on 11 May 2003 07:25 PDT
Hi bobty-ga,
   eof() appears to be another one of those unportable functions. As a
quick fix, add this custom implementation of eof() to the 'utility.h'
header file.

  int eof(int handle)
  {
      //Store current pos 
      int cur = lseek(handle,0,SEEK_CUR); 
 
      // Move to end of file 
      int len = lseek(handle,0,SEEK_END); 
 
      // Reset file pointer to initial pos 
      lseek(handle, cur, SEEK_SET); 
 
      if(cur>=len)
         return 1; //EOF reached
     
      return 0; //EOF not reached
  }

Just add this code after the filelength() function and before the
#endif line in 'utility.h'.
As a more permanent fix, I will try converting index.h to use file I/O
functions from stdio.h which are more portable than those in unistd.h
. But that will have to wait till I can find some more free time.
Hope this helps.
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 11 May 2003 12:44 PDT
Hi theta-ga,
There are two problems with the program.  I am now recieving the
following error in list.cpp.  This error has never shown up before.
list.cpp: In function

`int list()':
list.cpp:40: `idxEntry' undeclared (first use this function)
list.cpp:40: (Each undeclared identifier is reported only once for
each
   function it appears in.)
list.cpp:59:2: warning: no newline at end of file
make: *** [list] Error 1

Here is the code for list.cpp: (I put a comment next to the line with
the error so that it will be quicker for you to find)

#include "DBRecord.h" //Contains the record structure and some defined
constants
#include "DBFuncs.h"  // for blockread()
#include "Index.h"    // for IndexGetEntry() and the IndexEntry
structure
#include <stdio.h>    // for printf()

// Lists the contents of the database
int list();

// Function main()
int main(int argc, char* argv[])
{  
  list(); // List the contents of the database

  return 0;
}

// Function: list() - Lists the contents of the database, one record
//                    per line.
// Arguments: none
// Returns: -1 on error.
int list()
{
  DBRecord *recBlock, rec;
 // IndexEntry idxEntry;

  // Normally, blockread() and blockwrite() display a message on every
  // database access. But we dont wnat any access messages to be 
  // displayed during a list. So we call a fn to disable the messages.
  DisableInfoMessages(); 

  int i=1;
  // As long as an index entry is present, read it
  while(IndexGetEntry(i, idxEntry)) //LINE 40 ERROR
  {
	// Read in the record specified by the index entry
	// blockread() returns a pointer to internal memory.
    recBlock = fread(idxEntry.rrn);
    if(recBlock==NULL)
    {
      printf("\nUnable to read database!! Exiting!");
      return -1;
    }
    rec = *recBlock; // Copy contents of the internal memory 
	// Display the record in one line
    printf("\n%6.6s|%5.5s|%8.8s|%10.10s|%2.2s|%10.10s|%8.8s|%15.15s",
             rec.regNo, rec.status, rec.date, rec.city,
            rec.state, rec.planeMake, rec.severity, rec.opType);
    i++;
  }
  return 0;
}

Another problem is that when I try to run load, add, delete, or
search, I recieve the following message: Segmentation Fault (core
dumped)
I don't really understand what this means or why this is happening. 
As of now the load, add, delete, and search are compiling fine, but
the above line is the only output when I try to run these files.

Clarification of Answer by theta-ga on 12 May 2003 08:49 PDT
Hi bobty-ga, 
  The error about the idxEntry variable is occurring because the
second line of the list() function, which contains the declaration of
the idxEntry variable, has been commented out. Just remove the
comment, and the error will go away. The actual line is this:
     IndexEntry idxEntry;

As for the segmentation error, it sounds like a memory error, but I
need more information before I can get rid of it. Exactly at which
step of the program does this error occur? If you have access to a
debugger, you could step through the module and find out the exact
line of code causing the error. Also, which version of Unix are you
running the code on?

Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 12 May 2003 19:38 PDT
Hi theta-ga,
I was not able to find the error.  I have posted the code below: (I
did not inlcude DBFuncs.h, Index.h, or Load.cpp.)

//---------------------------------------------------------------------------
// Add a new record to the database

//---------------------------------------------------------------------------


#include "DBRecord.h" // Contains the record structure and some
defined constants
#include "DBFuncs.h"  // for DBAdd()

#include <stdio.h>    // for printf(), scanf(), fflush()

#include <memory.h>   // for memset()

#include <string.h>   // for strncpy()





// Function main()

int main(int argc, char* argv[])

{

  // We should have only one other argument - the input filename

  if( argc != 2)

  {

    printf("\nIncorrect number of arguments!!"

           "\nUsage: %s <RecordNumber>",argv[0]);

    return -1;

  }



  DBRecord rec;

  memset(&rec,0, sizeof(rec));

  

  // Get the reg num given at the commandline

  strncpy(rec.regNo, argv[1],SZ_REGNO);

  rec.regNo[SZ_REGNO] = '\0'; // last char should be '\0'



  // Ask user to input the rest of the record

  printf("\nPlease provide the following data for the new record:" \

         "\nStatus : ");

  fflush(stdin);

  scanf("%5s", &rec.status);

  printf("\nDate : ");

  fflush(stdin);

  scanf("%8s", &rec.date);

  printf("\nCity : ");

  fflush(stdin);

  scanf("%10s",&rec.city);

  printf("\nState : ");

  fflush(stdin);

  scanf("%2s",&rec.state);

  printf("\nMake : ");

  fflush(stdin);

  scanf("%15s",&rec.planeMake);

  printf("\nSeverity : ");

  fflush(stdin);

  scanf("%8s",&rec.severity);

  printf("\nCarrier Type & Operation : ");

  fflush(stdin);

  scanf("%20s",&rec.opType);



  // Add rec to database

  if( DBAdd(rec) == -1) //Was addition successful

    printf("\nError: A record with this reg. no. already exists in the
database.");


  return 0;

}



//---------------------------------------------------------------------------
//Deletes the specified record

//---------------------------------------------------------------------------
#include "DBRecord.h" // for the SZ_REGNO constant

#include "DBFuncs.h"  // for DBDelete()

#include <stdio.h>    // for printf()

#include <memory.h>   // for memset()

#include <string.h>   // for strncpy()





// Deletes the specified record

bool DBDelete(char reg[SZ_REGNO+1]);







// Function main()

int main(int argc, char* argv[])

{

  // We should have only one other argument - the input filename

  if( argc != 2)

  {

    printf("\nIncorrect number of arguments!!"

           "\nUsage: %s <RegisterationNumber>",argv[0]);

    return -1;

  }



  // Get the reg num entered at the commandline 

  // We use strncpy() instead of strcpy() to prevent

  // buffer overruns.

  char regNo[SZ_REGNO+1];

  strncpy(regNo,argv[1],SZ_REGNO);

  regNo[SZ_REGNO] = '\0';   // terminate with a '\0'





  // Call func. to delete the record

  if(DBDelete(regNo))

    printf("\nThe specified record was successfully deleted.");

  else

    printf("\nThe record was not deleted.");



  return 0;

}







// DBDelete: Deletes the record with the specified reg no from the
database
//           It also deletes the specified record's index entry, and
also
//           adds the record to the avail list

// Arguments: The registeration num of the record

// Returns: true or false depending on whether deletion was successful
or not
bool DBDelete(char reg[SZ_REGNO+1])

{

   int idxLoc;

   IndexEntry idxEntry;

   DBRecord rec, *ptr;

   char ch[2];



  //Search for the record

  if(!IndexSearch(reg, idxLoc))

  {

    printf("\nThe record was not found in the index.");

    return false;

  }



  // If found, get the rrn for the record

  IndexGetEntry(idxLoc, idxEntry);



  //read the specified record

  ptr = blockread(idxEntry.rrn);



  //copy the record read

  rec = *ptr;



  // Display the record

  printf("\nThis is the record you specified:"\

         "\nRegisteration Number : %s"        \

           "\nStatus: %s"                     \

           "\nDate : %s"                      \

           "\nCity : %s"                      \

           "\nState : %s"                     \

           "\nMake : %s"                      \

           "\nSeverity : %s"                  \

           "\nCarrier Type & Operation : %s"  \

           "\n\nAre you sure you want to delete this record [Y/N]? ",
            rec.regNo, rec.status, rec.date, rec.city,

            rec.state, rec.planeMake, rec.severity, rec.opType);

  fflush(stdin);

  scanf("%1s",ch); // read one character

  if(ch[0]=='y' || ch[0]=='Y')

  {

    // delete index entry

    IndexDeleteEntry(idxLoc);

    // Add the record to the AvailList

    AvailAddRecord(idxEntry.rrn);



    // return ok

    return true;

  }

  return false;

}

//---------------------------------------------------------------------------
// Showdata.cpp : Contains the implementation for Part 1 of bobty-ga's
question
//---------------------------------------------------------------------------


#include "DBRecord.h" //Contains the record structure and some defined
constants
#include "DBFuncs.h"  // for blockread()

#include "Index.h"    // for IndexGetEntry() and the IndexEntry
structure
#include <stdio.h>    // for printf()





// Lists the contents of the database

int list();



// Function main()

int main(int argc, char* argv[])

{

  

  list(); // List the contents of the database



  return 0;

}





// Function: list() - Lists the contents of the database, one record

//                    per line.

// Arguments: none

// Returns: -1 on error.

int list()

{

  DBRecord *recBlock, rec;

  IndexEntry idxEntry;



  // Normally, blockread() and blockwrite() display a message on every
  // database access. But we dont wnat any access messages to be 

  // displayed during a list. So we call a fn to disable the messages.
 // DisableInfoMessages(); 



  int i=1;

  // As long as an index entry is present, read it

 // while(IndexGetEntry(i, idxEntry))

 // {

	// Read in the record specified by the index entry

	// blockread() returns a pointer to internal memory.

    //recBlock = fread(idxEntry.rrn);

    //if(recBlock==NULL)

   // {

     // printf("\nUnable to read database!! Exiting!");

     // return -1;

   // }

    rec = *recBlock; // Copy contents of the internal memory 

	// Display the record in one line

    printf("\n%6.6s|%5.5s|%8.8s|%10.10s|%2.2s|%10.10s|%8.8s|%15.15s",
             rec.regNo, rec.status, rec.date, rec.city,

            rec.state, rec.planeMake, rec.severity, rec.opType);

    i++;

  //}



  return 0;

}

//---------------------------------------------------------------------------
// Searches the database for a record containing the specified

// registeration number, and displays this record if found.

//---------------------------------------------------------------------------


#include "DBRecord.h" //Contains the record structure and some defined
constants
#include "Index.h"

#include <stdio.h>  // for printf(), fopen(), fwrite(), fclose(),
getc()
#include <memory.h> // for memset()

#include <string.h> // for strlen()





// returns true if the specified record was found in the databse

bool DBSearch(DBRecord&, unsigned&);







// Function main()

int main(int argc, char* argv[])

{

  // We should have only one other argument - the input filename

  if( argc != 2)

  {

    printf("\nIncorrect number of arguments!!"

           "\nUsage: %s <RecordNumber>",argv[0]);

    return -1;

  }



  unsigned recPos;

  // Get the reg num entered at the commandline 

  // We use strncpy() instead of strcpy() to prevent

  // buffer overruns.

  DBRecord rec;

  strncpy(rec.regNo,argv[1],SZ_REGNO);

  rec.regNo[SZ_REGNO] = '\0';





  if( DBSearch(rec, recPos) ) // if record found

  {

    printf("\n\nReg. No.: %s"

           "\nStatus: %s"

           "\nDate : %s"

           "\nCity : %s"

           "\nState : %s"

           "\nMake : %s"

           "\nSeverity : %s"

           "\nCarrier Type & Operation : %s\n",

            rec.regNo, rec.status, rec.date, rec.city,

            rec.state, rec.planeMake, rec.severity, rec.opType);

  }

  else

    printf("\nNo record matching this record number was found in the
database.");


  return 0;

}







// Function DBSearch: Searches for the record with the specified reg.
no.
//                    and returns the position at which it was found

// Arguments:

//   DBrecord rec: The function searches for the reg. no. specified by
the regno field of this structure.
//                        If the rec. is found, the remaining fields
of this structure are filled in
//   unsigned recPos: If the record is found, its position in the
database is stored in this variable
// Returns: 

//     true if the record was found, false otherwise.

//     If the record was found, the contents of the variables rec and
recPos
//     are also updated(as explained above)

bool DBSearch(DBRecord& rec,unsigned& recPos )

{

  int idxLocation;



  // Check if a record with the specified regno exists in the index

 if(!IndexSearch(rec.regNo, idxLocation))

    return false; // record not found!



  IndexEntry idxEntry;

  // Get the index entry pertaining to the record we are searching for
  IndexGetEntry(idxLocation, idxEntry);





  DBRecord *ptr;

  ptr = blockread(idxEntry.rrn); // returns a pointer to internal
memory


  recPos = idxEntry.rrn; // return the record position in the database
  rec = *ptr; // Copy the record from blockread()'s internal memory

  

  return true;

}


//------------------------------------------------------------------------
// Contains oft used functions that do not belong in other headers

//------------------------------------------------------------------------
#ifndef __utility_h__

#define __utility_h__



#include <unistd.h>  

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>





//Returns length in bytes of the file who's handle is passed as an
argument
int filelength(int handle) 

{ 

      //Store current pos 

      int cur = lseek(handle,0,SEEK_CUR); 

 

      // Move to end of file 

      int len = lseek(handle,0,SEEK_END); 

 

      // Reset file pointer to initial pos 

      lseek(handle, cur, SEEK_SET); 

 

      // Return file length 

      return len; 

} 





  int eof(int handle) 

  { 

      //Store current pos  

      int cur = lseek(handle,0,SEEK_CUR);  

  

      // Move to end of file  

      int len = lseek(handle,0,SEEK_END);  

  

      // Reset file pointer to initial pos  

      lseek(handle, cur, SEEK_SET);  

  

      if(cur>=len) 

         return 1; //EOF reached 

      else

      return 0; //EOF not reached 

  } 



#endif

Request for Answer Clarification by bobty-ga on 13 May 2003 00:01 PDT
Hi Theta-ga,
I think that the problem may possibly be with OpenIndexFile() in
Index.h.  I recieve this warning in the gdb debugger:
Program received signal SIGSEGV, Segmentation fault.
0x10e2c in _Z13OpenIndexFilev ()

Clarification of Answer by theta-ga on 15 May 2003 07:56 PDT
Hi bobty-ga,
   I was going over the source for the index.h file that you had
posted earlier, and I noticed a change you have made to the
OpenIndexFile() function. Specifically, you added the line:
   int idxHandle = OpenIndexFile(); 
This will result in OpenIndexFile() called in an infinite loop,
obtaining a new file handle in every execution. This could be the
reason for the SIGSEGV error. Remove this line from the function and
make sure that the rest of the code for OpenIndexFile() is the same as
the original code I posted as the answer.
Try out the program now, and tell me if the error still persists.
Hope this helps.
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 18 Oct 2003 12:02 PDT
Hello theta-ga,
How are you?  I wanted to thank you so much for helping me a few
months ago.  You did a very thorough job and you were very patient
with me and my project. I know I must of been a bit of a pain with my
several "answer clarification" requests.  Since you were so great, I
was actually wondering if you would have the time to do another
project for me.  It's actually almost identical to the one you did for
me a few months ago.  The only difference is that it is for a
different database.  The specifications are almost exactly the same. 
In fact, you can just tweak the code that you already previously wrote
to make it work for this current database.  I would really appreciate
your help.  If you agree, I will post the question with "theta-ga
only" on the subject line.  I will post the code you wrote for me last
time as well along with the specifications.  Again, thanks for your
help and I hope to hear from you soon.
Sincerely,
bobty

Clarification of Answer by theta-ga on 22 Oct 2003 16:55 PDT
Hi bobty-ga,
   Great to have you back!  :-)
   I have a long weekend coming up right now, so I'll try to tackle
your latest question. Post the new question, and I'll take a look.
Please post the link to the source code instead of the contents of the
files itself. The way the code gets reformatted on posting makes it a
pain to use.  :-)
   If I'm unable to make any headway this weekend, I'll open up the
question to other researchers so they can have a go at providing you
the solution.
Regards,
Theta-ga
:-)

Request for Answer Clarification by bobty-ga on 22 Oct 2003 22:17 PDT
Hi theta-ga,
I'm so glad to hear from you.  I was afraid that you were no longer
doing work for googleanswers and so I  posted my question earlier
today under Computers/Programming.  I don't think any other researcher
has tried to tackle the problem, and so its all yours!  The subject
line is "C/C++ program".  I am not sure how to post the link to the
code.  Please tell me how to do this, and I will do so right away. 
Again, thank you so much for tackling my question.  I don't think the
question will be too tough for you, since you virtually did the same
thing for me once already! Hope to hear from you soon.
Sincerely,
bobty-ga

Request for Answer Clarification by bobty-ga on 27 Oct 2003 16:17 PST
Hello theta-ga,
I was wondering if you were able to take a look at my question.  I
received an e-mail saying that a comment was added to it, but when I
went to the question I found nothing.  Thank you for your help.

sincerely,
bobty-ga

Clarification of Answer by theta-ga on 06 Dec 2003 08:31 PST
Sorry bobty-ga, by the time I was able to take a look at your
question, it had already been cancelled.
Would have posted sooner, but work keeps me away from GA these days. 
Hope to see you again.
Regards,
Theta-ga
Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy