PROGRAM 7
// FILENAME: PROGRAM7.CPP AUTHOR: ANTHONY F. ORTIZ // HEADER FILES. #include #include #include #include #include #include #include #include #include #include #include "ourstr.h" ifstream INFILE; ofstream OUTFILE; // DECLARATION FOR A LINKED LIST CLASS CALLED LIST. template class LIST { protected: // THE LIST IS A LINKED LIST WITH A HEADER NODE. struct NODE { ETYPE ELEMENT; NODE * NEXT; // CONSTRUCTOR FOR NODE. NODE (ETYPE E = 0, NODE * N = 0): ELEMENT (E), NEXT (N) {} }; // THE HEADER. NODE *LIST_HEAD; // THE CURRENT POSITION NODE *CURRENT_POS; // DELETE AN ENTIRE LIST. void DELETE_LIST (); // DISABLE CALL BY VALUE. LIST (LIST & VALUE); public: // CONSTRUCTOR. LIST () : LIST_HEAD (new NODE), CURRENT_POS (LIST_HEAD) {} // DESTRUCTOR. virtual ~LIST () {DELETE_LIST ();} // DUPLICATE A LIST. const LIST & operator = (LIST & VALUE); // ADVANCE THE CURRENT POSITION. const LIST & operator ++ (); // CHECK IF CURRENT POSITION IS NOT NULL. int operator ! () const; // RETRIEVE ELEMENT IN THE CURRENT POSITION. const ETYPE & operator () () const; // RETURNS TRUE IF THERE IS A EMPTY LIST. int IS_EMPTY () const {return LIST_HEAD -> NEXT == 0;} // FIND AN ELEMENT IN THE LINKED LIST. virtual int FIND (const ETYPE & X); // FIND THE PREVIOUS ELEMENT IN A LINKED LIST. USED FOR DELETION. virtual int FIND_PREVIOUS (const ETYPE & X); // DETERMINE IF AN ELEMENT IS IN THE LIST. int IN_LIST (const ETYPE & X); // SET THE CURRENT POSITION TO THE FIRST ELEMENT. void FIRST () {if (LIST_HEAD -> NEXT != 0) CURRENT_POS = LIST_HEAD -> NEXT;} // SET THE CURRENT POSITION TO THE HEADER. void HEADER () {CURRENT_POS = LIST_HEAD;} // REMOVE AN ELEMENT FROM THE LINKED LIST. int REMOVE (const ETYPE & X); // INSERT AN ELEMENT INTO THE LINKED LIST (ON TOP). virtual void INSERT (const ETYPE & X); // INSERT AN ELEMENT INTO THE LINKED LIST (ON BOTTOM). virtual void INSERT_AS_FIRST_ELEMENT (const ETYPE & X); // PRINT THE LINKED LISTS. void PRINT (); }; // IMPLEMENTATION OF A LINKED LIST CALLED LIST. // DELETE AN ENTIRE LIST. HEADER ASSUMED. template void LIST :: DELETE_LIST () { NODE * P = LIST_HEAD -> NEXT, * TEMP; while (P != 0) { TEMP = P -> NEXT; delete P; P = TEMP; } delete LIST_HEAD; } // DUPLICATE A LIST. CURRENT POSITION BECOMES FIRST ELEMENT IN BOTH LISTS. template const LIST & LIST :: operator = (LIST & VALUE) { // DON'T COPY TO YOURSELF. if (this == & VALUE) return * this; DELETE_LIST (); CURRENT_POS = LIST_HEAD = new NODE; for (VALUE.FIRST (); !VALUE; ++VALUE) { CURRENT_POS -> NEXT = new NODE (VALUE (), CURRENT_POS -> NEXT); CURRENT_POS = CURRENT_POS -> NEXT; } CURRENT_POS -> NEXT = 0; FIRST (); VALUE.FIRST (); return *this; } // ADVANCE THE CURRENT POSITION. template inline const LIST & LIST :: operator ++ () { if (CURRENT_POS != 0) CURRENT_POS = CURRENT_POS -> NEXT; return * this; } // CHECK IF CURRENT POSITION IS NOT NULL. template inline int LIST :: operator ! () const { return CURRENT_POS != 0; } // RETRIEVE ELEMENT IN THE CURRENT POSITION. RETURN VALUE IS UNDEFINED // IF CURRENT POSITION IS NULL. template inline const ETYPE & LIST :: operator () () const { if (CURRENT_POS != 0) return CURRENT_POS -> ELEMENT; else return LIST_HEAD -> ELEMENT; } // ASSUMING USE OF HEADER NODE, FIND X. IF FOUND, RETURN TRUE AND SET // THE CURRENT POSITION. template int LIST :: FIND (const ETYPE & X) { NODE * P; for (P = LIST_HEAD -> NEXT; P != 0; P = P -> NEXT) { if (P -> ELEMENT == X) { CURRENT_POS = P; return 1; } } return 0; } // ASSUMING USE OF HEADER NODE, FIND X. IF FOUND, RETURN TRUE AND SET // THE CURRENT POSITION TO BEFORE X. template int LIST :: FIND_PREVIOUS (const ETYPE & X) { NODE * P; for (P = LIST_HEAD; P -> NEXT != 0; P = P -> NEXT) if (P -> NEXT -> ELEMENT == X) { CURRENT_POS = P; return 1; } return 0; } // DETERMINE IF ELEMENT IS IN THE LIST. template int LIST :: IN_LIST (const ETYPE & X) { return FIND (X); } // REMOVE X FROM THE LIST. RETURN NONZERO IF DELETION WAS SUCCESSFUL. // HEADER NODE IS ASSUMED. template int LIST :: REMOVE (const ETYPE & X) { NODE * CELL_TO_DELETE; if (FIND_PREVIOUS (X)) { CELL_TO_DELETE = CURRENT_POS -> NEXT; CURRENT_POS -> NEXT = CELL_TO_DELETE -> NEXT; delete CELL_TO_DELETE; return 1; } return 0; } // INSERT X AFTER THE CURRENT POSITION. X BECOMES THE CURRENT ELEMENT. // HEADER IMPLEMENTATION ASSUMED. template void LIST :: INSERT (const ETYPE & X) { NODE * P = new NODE (X, CURRENT_POS -> NEXT); if (P == 0) cout << "OUT OF SPACE." << endl; else { CURRENT_POS -> NEXT = P; CURRENT_POS = CURRENT_POS -> NEXT; } } // INSERT X BEFORE THE CURRENT POSITION. HEADER IMPLEMENTATION ASSUMED. template void LIST :: INSERT_AS_FIRST_ELEMENT (const ETYPE & X) { HEADER (); INSERT (X); } template void LIST :: PRINT () { NODE * P; int COUNT = 0; for (P = LIST_HEAD -> NEXT; P != 0; P = P -> NEXT) { COUNT = COUNT + 1; OUTFILE << P -> ELEMENT << "\n"; } } // CLASS DECLARATION FOR A SORTED LINKED LIST. template class SORTED_LIST : public LIST { public: virtual void INSERT (const ETYPE & X); virtual void INSERT_AS_FIRST_ELEMENT (const ETYPE & X) {cout << "ILLEGAL OPERATION FOR SORTED LIST.";} }; // CLASS IMPLEMENTATION FOR A SORTED LINKED LIST. // SORTED INSERTION. template void SORTED_LIST :: INSERT (const ETYPE & X) { for (NODE * P = LIST_HEAD; P -> NEXT != 0; P = P -> NEXT) if (P -> NEXT -> ELEMENT > X) break; CURRENT_POS = P; LIST :: INSERT (X); } // CLASS DECLARATION FOR OPEN HASHING. static const DEFAULT_SIZE = 10; template class HASH_TABLE { private: // SIZE OF HASHING TABLE. unsigned int H_SIZE; // LINKED LIST FOR EACH HASHING CELL. SORTED_LIST * THE_LISTS; // THE LAST LIST ACCESSED. unsigned int CURRENT_LIST; // ALLOCATE MEMORY FROM THE HEAP FOR THE LINKED LISTS. void ALLOCATE_LISTS (); // DISABLE BY VALUE. HASH_TABLE (HASH_TABLE & VALUE); public: // CONSTRUCTORS. HASH_TABLE (unsigned int INITIAL_SIZE = DEFAULT_SIZE); // DESTRUCTORS. ~HASH_TABLE () {delete [] THE_LISTS;} // HASH FUNCTION. HASH (const ETYPE & KEY, const int H_SIZE); // COPY A HASH TABLE USING '='. const HASH_TABLE & operator = (const HASH_TABLE & VALUE); // RETURN A CELL IN THE HASH TABLE. const ETYPE & operator () () const {return THE_LISTS [CURRENT_LIST] ();} // INITIALIZE HASH TABLE. void INITIALIZE_TABLE (); // INSERT ELEMENT INTO THE HASH TABLE (OPEN HASHING). void INSERT (const ETYPE & KEY); // REMOVE ELEMENT FROM THE HASH TABLE (OPEN HASHING). void REMOVE (const ETYPE & KEY); // FIND AN ELEMENT IN THE HASH TABLE (OPEN HASHING). int FIND (const ETYPE & KEY); // PRINT THE HASH FILE. void PRINT (); }; // CLASS IMPLEMENTATION FOR OPENING HASHING. // ALLOCATE MEMORY FROM THE HEAP FOR LINKED LISTS. template void HASH_TABLE :: ALLOCATE_LISTS () { THE_LISTS = new SORTED_LIST [H_SIZE]; if (THE_LISTS == 0) cout << "OUT OF SPACE!!"; } // CONSTRUCTOR. template HASH_TABLE :: HASH_TABLE (unsigned int INITIAL_SIZE) { H_SIZE = INITIAL_SIZE; ALLOCATE_LISTS (); } // HASH FUNCTION. template int HASH_TABLE :: HASH (const ETYPE & KEY, const int H_SIZE) { int SUM = 0; for (int I = 0; KEY [I] != '\0' ; I++) { SUM += KEY [I]; } return SUM % H_SIZE; } // INITIAILZE THE HASH TABLE. template void HASH_TABLE :: INITIALIZE_TABLE () { delete [] THE_LISTS; ALLOCATE_LISTS (); } // COPY HASH TABLE USING '='. template const HASH_TABLE & HASH_TABLE :: operator = (const HASH_TABLE & VALUE) { if (this != &VALUE) { delete [] THE_LISTS; H_SIZE = VALUE.H_SIZE; ALLOCATE_LISTS (); for (int I = 0; I < H_SIZE; I++) THE_LISTS [I] = VALUE.THE_LISTS [I]; } return * this; } // FIND AN ELEMENT IN THE HASH TABLE. template int HASH_TABLE :: FIND (const ETYPE & KEY) { unsigned int HASH_VAL = HASH (KEY, H_SIZE); if (THE_LISTS [HASH_VAL].FIND (KEY)) { CURRENT_LIST = HASH_VAL; return 1; } return 0; } // INSERT AN ELEMENT INTO THE HASH TABLE. template inline void HASH_TABLE :: INSERT (const ELEMENT_TYPE & KEY) { unsigned int HASH_VAL = HASH (KEY, H_SIZE); if (!THE_LISTS [HASH_VAL].IN_LIST (KEY)) THE_LISTS [HASH_VAL].INSERT (KEY); } // DELETE AN ELEMENT FROM THE HASH TABLE template inline void HASH_TABLE :: REMOVE (const ELEMENT_TYPE & KEY) { THE_LISTS [HASH (KEY, H_SIZE)].REMOVE (KEY); } // PRINT THE HASH TABLE. template void HASH_TABLE :: PRINT () { for (int I = 0; I <= H_SIZE - 1; I++) { OUTFILE << "\nHASH CELL " << I << "\n\n"; THE_LISTS [I].PRINT (); } } // THIS PROGRAM WILL GET THE ENVIRONMENT PATH USING THE C++ FUNCTION // GET_PATH. THEN, IT WILL EXTRACT THE DIRECTORIES FROM THE PATH. // AFTER GETTING THE DIRECTORIES, IT WILL MAKE A SERIES OF SYSTEM CALLS // TO DOS. EACH SYSTEM CALL WILL EXECUTE THE FOLLOWING COMMAND // "C:\DIR DIRECTORY /B > DIR.OUT. IN OTHER WORDS, PUT ALL FILES IN // THIS DIRECTORY INTO A FILE CALLED DIR.DOC. THEN, THE PROGRAM WILL // EXTRACT ALL THE FILES FROM DIR.DOC AND PUT THEM IN A OPEN HASH // TABLE. THE COLLISIONS WILL BE HANDLE BY HAVING A SORTED LINKED // LIST. THE USER WILL BE PROMPTED TO SEARCH FOR A FILE AND MAY // REPEAT THE SEARCH IF HE OR SHE LIKES. AFTER THE SEARCH, THE PROGRAM // WILL PUT THE HASH TABLE IN A OUT FILE. int main() { // HOLDS THE PATH. char * PATH; // HOLDS ALL DIRECTORY IN THE PATH VARIABLE. char DIRECTORY [10][15]; // HOLDS THE SYSTEM INSTRUCTION TO DOS. char SYSTEM_INSTRUCTION [25]; // HOLDS THE FILE NAME. string FILE_NAME; // HOLDS ALL THE FILES IN A HASH TABLE. HASH_TABLE FILE_HASH; // THESE VARIABLES WILL HELP TO EXTRACT THE DIRECTORY NAMES. int FLAG = 0; int COUNT = 0; int COUNT2 = 0; // CLEAR THE SCREEN. clrscr (); // GET THE PATH. PATH = getenv("PATH"); // EXTRACT THE DIRECTORY NAMES. for (int I = 1; PATH [I] != '\0'; I++) { if ((isalpha (PATH [I]) || isdigit (PATH [I])) && PATH [I + 1] != ':') { DIRECTORY [COUNT2][COUNT] = PATH [I]; COUNT = COUNT + 1; FLAG = 1; } else if (PATH [I] == ';') { DIRECTORY [COUNT2][COUNT] = '\0'; COUNT2 = COUNT2 + 1; COUNT = 0; FLAG = 0; } } // CALL THE DOS SYSTEM AND PUT THE FILES IN A DATA FILE CALLED // DIR.DAT. for (int J = 0; J < (COUNT2 - 1); J++) { strcpy (SYSTEM_INSTRUCTION, "DIR "); strcat (SYSTEM_INSTRUCTION, DIRECTORY [J]); strcat (SYSTEM_INSTRUCTION," /B > DIR.DAT"); system ("C:"); system (SYSTEM_INSTRUCTION); // THEN OPEN DIR.DAT FILE AND PUT EACH OF THE FILES INTO THE // OPEN HASH TABLE. INFILE.open ("C:\DIR.DAT", ios :: in); while (!INFILE.eof ()) { INFILE >> FILE_NAME; FILE_HASH.INSERT (FILE_NAME); } // CLOSE DATA FILE. INFILE.close (); } // CLEAR THE SCREEN AND DO SOME FILE SEARCHES. clrscr (); do { cout << "ENTER A FILE NAME. "; cin >> FILE_NAME; cout << "\n"; // DISPLAY A MESSAGE TO THE SCREEN TELLING THE USER WHETHER // THE FILE WAS FOUND. if (FILE_HASH.FIND (FILE_NAME)) { cout << FILE_NAME << " WAS FOUND.\n\n"; } else if (FILE_NAME != "STOP") { cout << FILE_NAME << " WAS NOT FOUND.\n\n"; } } while (FILE_NAME != "STOP"); // OPEN OUT FILE, PUT THE HASH TABLE IN THE OUT FILE, AND CLOSE // THE FILE. OUTFILE.open ("DIR.OUT", ios :: out); OUTFILE << "PATH = " << PATH << "\n\n"; FILE_HASH.PRINT (); return 0; } // FILENAME: OURSTR.H, OURSTR.CPP // SEE PROGRAM 12 (COMP251 PAGE). // DATA FILE: DIR.DAT VIRSCAN.EXE VIRSCAN.MSG VSTOP.MSG VIRUSCK.PIF VIRUSCK.BAT COMMAND.PIF HWCHECK.PIF MAKECU.PIF PS1_TODO.PIF START.BAT GRP.DAT VIRUSCK.HLP VIRSIG.LST VERV.EXE VSTOP.COM VIRUSCK.EXE BACKREST.EXE BACKREST.HLP DATETIME.EXE DATETIME.HLP DISPSEL.EXE DISPSEL.HLP HWCHECK.EXE HWSPECS.EXE HWSPECS.HLP MAKECU.EXE PS1LIB.DLL PS1LOGO.EXE PS1MENU.EXE PS1SETUP.EXE PS1TOOLS.EXE REFDISK.EXE REFDISK.HLP WINRESET.EXE WINRESET.HLP YOURSOFT.EXE YOURSOFT.HLP HWCHECK.DAT // OUTFILE: PROG7.OUT ENTER A FILE NAME. GRP.DAT GRP.DAT WAS FOUND. ENTER A FILE NAME. ANTHONY.DAT ANTHONY.DAT WAS NOT FOUND. ENTER A FILE NAME. ^C
BACK TO CS3240 PAGE.