'Sort.CPP'
!  Add: lt <  'Tags' (after   #include) to Compile. !
//------------------------  Pointer Hints ----------------------------------

#include stdio.h>  // Add ALL (less-than) 'Tags' (NO SHOW! in HTML)
#include stdlib.h>
#include string.h>
#include conio.h>          // getch()
#include string.h>
#include iostream.h>       // cin & cout
#include fstream.h>        // For file I/O

//---------------------------------------------------------------------------
// Dynamic Double-Linked List for QUICK Sorting of: 'Sort.txt' to 'Sorted.txt'
//---------------------------------------------------------------------------

ofstream outFile;           // For file out/in
#define MAX 155             // Max. charactors/line
int lineNumbers = 0;

struct node                 // Globals
{
   char* line;
   struct node* previous;
   struct node* next;
};
int build_list(struct node**, struct node**);
void show_ascending(struct node*);
void show_descending(struct node*);
void release_memory(struct node*);

main(void)
{
   int lines;
   struct node* head;
   struct node* tail;

   outFile.open("Sorted.txt",  ios::app);     // append to file

   cout << "\n Reading & (pointer) Sorting of: 'Sort.txt'...  ";
   
   // Pass 'Address-of' the (pointer)head/tail
   lines = build_list(&head, &tail);          /* Read: "sort.txt" */
   cout << " ( Sorted " << lineNumbers << " Lines. )" << endl << endl;

   if ( lines < 0 )
   {
      puts("\n NO File ? Memory allocation error.\n\n");
      getch();
      exit(-1);
   }
   puts("\n\n (Descending Order ~ Enter: 'D') ASCENDING Order ~ Press Return.\n");
   cout << " ";
   char letter = getchar();
   if( letter == 'D' || letter == 'd') show_descending(tail);
     else show_ascending(head);
   release_memory(head);

   outFile << "\n\n";                // REQUIRED to End All Lists
   cout << endl << endl << " Done.  Output to 'Sorted.txt'...";
   getch();
   return 1;
}
// Receive a 'pointer' to the (pointer)head/tail
build_list(struct node** p_head, struct node** p_tail)
{
   int a, n = 0;
   char buf[MAX];
   char* lineIN;
   FILE *fp;

   struct node  *start, *link, *fresh, *end;
// *p_head is the indirect store into the (pointer)head
   *p_head = NULL;
   *p_tail = NULL;

   if ( (fp = fopen("Sort.txt", "rb")) == NULL)
   {
      fprintf(stderr, "\n\n Bogus... Check 'Sort.exe' Folder for 'Sort.txt'\n\n");
      {
         fclose(fp);
	 return -1;
      }
    }
    while ( !feof(fp) )                     /* Read until EOF. */
    {
       fgets(buf, MAX, fp);
       if((lineIN = (char*)malloc(strlen(buf) + 1 )) == NULL)
       {
	      fclose(fp);
	      return -1;
       }
       buf[(strlen(buf) - 2)] = '\x0';    // Cut BAD '\r\n'
       strcpy(lineIN, buf);
       lineNumbers++;

       if(( fresh = (struct node*)malloc(sizeof(struct node))) == NULL)
       {
	      fclose(fp);
	      free(lineIN);
	      return -1;
       }
       fresh->line = lineIN;
       n++;

       if(*p_tail == NULL)
       {
	      fresh->next = NULL;
	      fresh->previous = NULL;
	      *p_head = fresh;
	      *p_tail = fresh;
       }
   //  *p_head is the indirect recall (contents) of the (pointer)head
       start = *p_head;               /* start at top of list */
       end   = *p_tail;

       if(strcmp(start->line, fresh->line) > 0)
       {
 	      fresh->next = start;         /* fresh head */
	      fresh->previous = NULL;
	      start->previous = fresh;
	      *p_head = fresh;
       }
       else if (strcmp(end->line, fresh->line ) < 0)
       {
              *p_tail = fresh;             /* fresh tail */
	      fresh->next = NULL;
	      fresh->previous = end;
	      end->next = fresh;
       }
       else                               // Insert 
       {
       link = *p_head;      // start at top of list 
	   
 /*       #===<====[3]==<==(PREV )
          #   #==[4]==>===>(FRESH)<===<===[5]==<==#
          #   #            ( NEXT)==>==[2]===#    #
          #  _#__                           _V__  #
        __V_(NEXT)-----[1]---------------->(LINK)_#__
       ( HEAD    )<---------------[3]------(     PREV)
 */
       for(a = 0; a < n-1; a++)
       {
	      link = link->next;          // Next Link  [1]
	      if(strcmp(link->line, fresh->line) >= 0)
	      {
	         fresh->next = link;                 // [2]
	         fresh->previous = link->previous;   // [3]
	         (link->previous)->next = fresh;     // [4]
	         link->previous = fresh;             // [5]
	         break;
  	      }
        }
     }
  }
  fclose(fp);
  return n;
}
void show_ascending(struct node* head)
{
   struct node *link;
   link = head;

   while( link != 0 )
   {
      outFile << link->line << endl;
      // printf(" %s\n", link->line);
      link = link->next;
   }
}
void show_descending(struct node* tail)
{
   struct node *link;
   link = tail;

   while( link != 0 )
   {
      outFile << link->line << endl;
      // printf(" %s\n", link->line);
      link = link->previous;
   }
}
void release_memory(struct node* head)
{
   struct node *link, *temp;

   link = head;
   while(link != 0)
   {
      free(link->line);
      link = link->next;
   }
   link = head;
   while(link != 0)
   {
      temp = link->next;
      free(link);
      link = temp;
   }
}