Insertion Sort problem - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Insertion Sort problem

billsbills Posts: 1Member
Hi guys,

I basically have an array of records I am reading data into (Student Name, Mark, Module Number). I'm trying to use an insertion sort to order the records in descending order by Mark i.e. Highest first. However, at the moment my program is putting the correct record first, but losing all of the contents of the rest of the records. Also if i input my maximum number of records (6) the program just closes. I can't work out why either of these two things are happening.

Any help would be much appreciated. Cheers.

Here is the procedure where i've been trying to make the sort work.

And for infos sake heres my type definitions.

[italic]TYPE
TMarkRecord = RECORD
Name : STRING;
Mark : INTEGER;
Module : STRING;
END;

TMarkDB = RECORD
MRs : ARRAY[1..Top] OF TMarkRecord;
Size : INTEGER;
END;[/italic]


[code]{ REQUIRES TRUE}
{ RESULTS IF there is room in the database
user prompted for record details
and record is added to database
ELSE
message}
PROCEDURE User_Add_Record();

Var
Temp : TMarkRecord;
i,
j : Integer;
Q_Sorted : Boolean;

BEGIN
IF MarkDB.Size < Top THEN
BEGIN
WRITELN('Please type in a mark record as requested');
Get_MarkRecord_From_Prompt('Record for position ' + IntToStr(MarkDB.Size), Temp);
MarkDB.Size := MarkDB.Size + 1;
If MarkDB.Size = 1 Then
Begin
MarkDB.MRs[1] := Temp;
End
Else
Begin
i := 1;
Q_Sorted := FALSE;
While Not Q_Sorted DO
Begin
If Temp.Mark > MarkDB.MRs[i].Mark Then
Begin
For j := MarkDB.Size Downto i + 1 Do
Begin
MarkDB.MRs[j] := MarkDB.MRs[j + 1];
End;
MarkDB.MRs[i] := Temp;
Q_Sorted := TRUE;
End
Else
Begin
IF i = MarkDB.Size Then
Begin
MarkDB.MRs[i] := Temp;
Q_Sorted := TRUE;
End;
i := i + 1;
End
End
End
END
ELSE
BEGIN
WRITELN('Database is full');
END
END;
[/code]

I also have to do the same in a program which is essentially the same but is using pointers and linked lists. I'll add the code for that. Any help in the slightest would be really useful. Thank you in advance!

[code]{$APPTYPE CONSOLE}
PROGRAM PointerFileIOExample;

uses
SysUtils;

CONST
Top = 6;

TYPE
TMarkRecord = RECORD
Name : STRING;
Mark : INTEGER;
END;

TNodePtr = ^TNode;

TNode = RECORD
Data : TMarkRecord;
Next : TNodePtr;
END;

TMarkDB = RECORD
MRs : TNodePtr;
Size : INTEGER;
END;

VAR
MarkDB : TMarkDB;

{ REQUIRES TRUE }
{ RESULTS Menu printed out }
PROCEDURE Menu();

BEGIN
WRITELN;
WRITELN('*************Menu******************');
WRITELN('* (r)ead in record **');
WRITELN('* (p)rint database **');
WRITELN('* (s)ave database **');
WRITELN('* (l)oad database **');
WRITELN('* (m)enu **');
WRITELN('* e(x)it **');
WRITELN('*************Menu******************')
END {Menu};

{ REQUIRES TRUE}
{ RESULTS Prompts user with Prompt
AND Id = response to prompting}
PROCEDURE Get_Int_From_Prompt(Prompt : STRING;
VAR Int : INTEGER);

BEGIN
WRITE(Prompt, ' ==> ');
READLN(Int);
END {Get_Int_From_Prompt};

{ REQUIRES TRUE}
{ RESULTS Prompts user with Prompt
AND Str = response to prompting}
PROCEDURE Get_String_From_Prompt(Prompt : STRING; VAR Str : STRING);

BEGIN
WRITE(Prompt, ' ==> ');
READLN(Str);
END {Get_String_From_Prompt};

{ REQUIRES TRUE}
{ RESULTS MR written to screen}
PROCEDURE Print_MarkRecord(MR : TMarkRecord);

BEGIN
WRITELN('Mark ==> ', MR.Mark);
WRITELN('Name ==> ', MR.Name);
END {Print_MarkRecord};

{ REQUIRES TRUE}
{ RESULTS Prompts user for mark srecord
AND MR = response to prompting}
PROCEDURE Get_MarkRecord_From_Prompt(Prompt : STRING; VAR MR : TMarkRecord);

BEGIN
Get_Int_From_Prompt('Mark', MR.Mark);
Get_String_From_Prompt('Name', MR.Name);
END {Get_MarkRecord_From_Prompt};

{ REQUIRES TRUE}
{ RESULTS IF there is room in the database
user prompted for record details
and record is added to database
ELSE
message}
PROCEDURE User_Add_Record();

VAR
NextRec : TMarkRecord;
NewNodePtr : TNodePtr;
Cursor : TNodePtr;

BEGIN
IF MarkDB.Size < Top THEN
BEGIN
WRITELN('Please type in a mark record as requested');
MarkDB.Size := MarkDB.Size + 1;
Get_MarkRecord_From_Prompt('Record for position ' + IntToStr(MarkDB.Size), NextRec);
NEW(NewNodePtr);
NewNodePtr^.Data := NextRec;
NewNodePtr^.Next := NIL;
IF MarkDB.Size = 1 THEN
BEGIN
MarkDB.MRs := NewNodePtr;
END
ELSE
BEGIN
Cursor := MarkDB.MRs;
WHILE Cursor^.Next <> NIL DO
BEGIN
Cursor := Cursor^.Next;
END;
Cursor^.Next := NewNodePtr;
END
END
ELSE
BEGIN
WRITELN('Database is full');
END
END;

{ REQUIRES TRUE}
{ RESULTS IF there there are records in the database
database is printed to screen
ELSE
message}
PROCEDURE User_Print_DB();

VAR
Cursor : TNodePtr;
i : INTEGER;

BEGIN
IF MarkDB.Size > 0 THEN
BEGIN
i := 1;
Cursor := MarkDB.MRs;
WHILE Cursor <> NIL DO
BEGIN
WRITELN('Record in position ' , i, ' is ');
Print_MarkRecord(Cursor^.Data);
Cursor := Cursor^.Next;
i := i + 1;
END
END
ELSE
BEGIN
WRITELN('No records in database');
END
END;

{ REQUIRES TRUE}
{ RESULTS user prompted for file to save to
IF file exists
user is asked whether to overwrite
IF file does not exist OR user has agreed to overwrite
database is written to file}
PROCEDURE User_Save_DB();

VAR
FileName : STRING;
OverWrite : CHAR;
FileHandle : TextFile;
i : INTEGER;
Cursor : TNodePtr;

BEGIN
Write('Please type in the name of the file to save to ==> ');
ReadLn(FileName);
OverWrite := 'y';
IF FileExists(FileName) THEN
BEGIN
WRITELN(FileName, ' already exists');
WRITE('Do you want to overwrite it (y/n) ==> ');
READLN(OverWrite);
END;
IF OverWrite = 'y' THEN
BEGIN
AssignFile(FileHandle, FileName);
Rewrite(FileHandle);
Cursor := MarkDB.MRs;
FOR i := 1 TO MarkDB.Size DO
BEGIN
WRITELN(FileHandle, Cursor^.Data.Mark);
WRITELN(FileHandle, Cursor^.Data.Name);
Cursor := Cursor^.Next;
END
END;
CloseFile(FileHandle);
END;

{ REQUIRES TRUE}
{ RESULTS user prompted for file to save to
IF file exists
all records up to a maximum of top are loaded into the database
ELSE
message}
PROCEDURE User_Load_DB();

VAR
FileName : String;
FileHandle : TextFile;
Next : TMarkRecord;
i : INTEGER;
NewNodePtr : TNodePtr;
Cursor : TNodePtr;

BEGIN
Write('Please type in the name of the file to load ==> ');
ReadLn(FileName);
IF FileExists(FileName) THEN
BEGIN
AssignFile(FileHandle, FileName);
Reset(FileHandle);
i := 1;
WHILE NOT EOF(FileHandle) AND (i <= Top) DO
BEGIN
READLN(FileHandle, Next.Mark);
READLN(FileHandle, Next.Name);
NEW(NewNodePtr);
NewNodePtr^.Data := Next;
NewNodePtr^.Next := NIL;
IF i = 1 THEN
BEGIN
MarkDB.MRs := NewNodePtr;
END
ELSE
BEGIN
Cursor := MarkDB.MRs;
WHILE Cursor^.Next <> NIL DO
BEGIN
Cursor := Cursor^.Next;
END;
Cursor^.Next := NewNodePtr;
END;
i := i + 1;
END;
MarkDB.Size := i - 1;
CloseFile(FileHandle);
END
ELSE
BEGIN
WRITELN('No file ', FileName);
END
END;

{ REQUIRES TRUE }
{ RESULTS menu is printed and user is prompted repeatedly for
option which is executed, until after exit option
is encountered }
PROCEDURE Main_Loop();
VAR
Option : CHAR;
BEGIN
Option := 'm';
WHILE Option <> 'x' DO BEGIN
CASE Option OF
'r', 'R' : User_Add_Record();
'p', 'P' : User_Print_DB();
's', 'S' : User_Save_DB();
'l', 'L' : User_Load_DB();
'm', 'M' : Menu();
ELSE
WRITELN('Unidentified option')
END;
WRITELN; WRITE('Next option please ==> ');
ReadLn(Option);
END
END {Main_Loop};

BEGIN
MarkDB.Size := 0;
Main_Loop();
READLN;
END.[/code]

Comments

Sign In or Register to comment.