// Student_list.cpp // // this version 2015-06-23 //
// A simple example of processing Student records ...
// using a C++ STL list container to hold each 'Student' object
// See MENU below to see what this program does ...
// Note:
// * this program allows only unique student id's for each record
// * this program is set to update its file, (if there were any changes),
// before quitting
#include <iostream>
#include <iomanip> // re. setw(widthValue) stream manipulator
#include <fstream> // re. ostream, ofstream, ifstream objects
#include <sstream> // re. ostringstream object
#include <string>
#include <list>
#include <cctype> // re. tolower/toupper for case insensitive comparison
// Globals ...
const char* THIS_TERM = "fall.txt"; // file name for this term's records
const std::string MENU= "\n"
" 1. V iew all records in memory at present\n"
" 2. A dd a new student name and id\n"
" 3. S ort student records\n"
" 4. E dit/E rase a student record\n"
" 5. L oad in student records from file\n"
" 6. U pdate file with records currently in memory\n"
" 7. e X it program\n\n"
"Your choice (1..7) : ";
class Student
{
public:
// constructors ...
Student() {} // default ctor ...
Student( const std::string& nam, const std::string& num ) : name( nam ), id( num ) {}
// setters ...
void set_name( const std::string& nam ){ name = nam; }
void set_id( const std::string& num ) { id = num; }
// getters ...
std::string get_name() const { return name; }
std::string get_id() const { return id; }
private:
std::string name, // add any needed info here, just like in a C/C++ 'struct'
id;
// Note: this name comparison is case insensitive ...
friend bool compare_nocaseName( const Student&, const Student& );
friend bool compare_id( const Student& a, const Student& b );
friend std::ostream& operator << ( std::ostream& os, const Student& s )
{ return os << s.name << ", " << s.id; }
} ;
// friends defined here ... //
bool compare_id( const Student& a, const Student& b )
{ return a.id < b.id; }
// this name comparison (friend function) is NOT case sensitive ...
bool compare_nocaseName( const Student& a, const Student& b )
{
size_t i = 0, lenNameA = a.name.length(), lenNameB = b.name.length();
while( i < lenNameA && i < lenNameB
&& tolower(a.name[i]) == tolower(b.name[i]) )
++i ;
// ok ... now check end conditions ...
if( i < lenNameA )
{
if( i < lenNameB ) return tolower(a.name[i]) < tolower(b.name[i]) ;
else return false; // since i == lenNameB
}
// if reach here ... i == lenNameA ... so check ...
if( i < lenNameB ) return true; // since i == lenNameA
// else we have i == lenNameA && i == lenNameB ... so names equal
return a.id < b.id;
}
// functions used by main to process a list of Student records
int takeInStr( const std::string& msg );
void pauseForEnter();
// returns a valid iterator if ID is used already ... otherwise returns 'end()'
std::list< Student >::iterator existID( std::list< Student >& term, const std::string& ID );
// adds Student records to end of list of Student records ... 'term'
// gets input from keyboard ...
int newStud( std::list< Student >& term );
// shows (to console screen) all student records in list container ... 'term'
void viewStuds( const std::list< Student >& term );
// file all records in memory ... create/overwrite file with name 'THIS_TERM'
int fileStuds( const std::list< Student >& term );
// reads in all Student records from file 'THIS_TERM' ... if it exists
// returns -1 if no file exists; else returns the number of records read
int readStuds( std::list< Student >& term );
// returns 'true' if a record was edited or erased; otherwise returns false
bool editStud( std::list< Student > &term );
int main() ////////////////////////// BEGIN MAIN ///////////////////////////////
{
using namespace std;
// create a 'fall list' to hold student names and ids for the 'Fall Term'
// also holds number of records, via 'fall.size()'
list < Student > fall;
// now get all records from file ... if it exists ?
int count = readStuds( fall );
if( count >= 0 )
cout << count << " student record(s) read into memory ..." << endl;
else
cout <<"(The file will be created when some student records exist.)"
<<endl;
bool changes = false; // set file 'update flag' to initial value ...
for( ;; ) // loop forever ... until break ...
{
int reply = takeInStr( MENU );
if( reply == '1' || reply == 'V' ) // View ...
viewStuds( fall );
else if( reply == '2' || reply == 'A' ) // Add ... from keyboard
{
int numStuds = newStud( fall );
cout << endl << numStuds << " student record(s) added ..."
<< " The total number of student records now is "
<< fall.size() << endl;
if( numStuds ) // if >0 added ... update bool variable changes
changes = true;
}
else if( reply == '3' || reply == 'S' ) // Sort ... but DON'T update
// 'changes' unless 'data filed'
{
reply = takeInStr( "\nSort by id or name (i/n) ? " );
if( reply == 'I' )
{
fall.sort(compare_id); // using case sensitive id's to sort ...
cout << "Now sorted in memory by id. ";
}
else if( reply == 'N' )
{
fall.sort(compare_nocaseName); // using case insensitive names
cout << "Now sorted in memory by name. ";
}
else
{
cout << "Ok ... no new sort done here ...\n";
continue;
}
reply = takeInStr( "Update file (y/n) ? " );
if( reply == 'Y' )
{
fileStuds( fall );
changes = false;
cout << "File updated ...\n";
}
else cout << "File NOT updated ...\n";
}
else if( reply == '4' || reply == 'E' )
{
if( editStud( fall ) )
changes = true;
}
else if( reply == '5' || reply == 'L' ) // Load/Read file into memory ...
{
int condition = readStuds( fall );
if( condition >= 0 )
{
cout << "\nThere were " << condition
<< " student records read into memory from file." << endl;
changes = false;
}
}
else if( reply == '6' || reply == 'U' ) // Update file from memory ...
{
if( !changes )
cout << "\nNo changes to file ..." << endl;
else
{
reply = takeInStr( "Are you sure you want to update"
" the file (y/n) ? " );
if( reply == 'Y' )
{
if( fileStuds( fall ) != (int)fall.size() )
cout << "\nUNEXPECTED ERROR! NOT all records were filed!"
<< "\nTry again ... If Error persits call IT."
<< endl;
else
{
changes = false;// update file flag ...
cout << "File write operation confirmed." << endl;
}
}
}
}
else if( reply == '7' || reply == 'X' ) // eXit main show MENU/loop ...
{ // and ...
if( changes ) // then ...
{
reply = takeInStr( "Are you sure you want to update"
" the file (y/n) ? " );
if( reply == 'Y' )
{
static int trys = 0;
if( fileStuds( fall ) != (int)fall.size() )
{
cout << "\nUNEXPECTED ERROR! NOT all records were filed!"
<< "\nTry again ... If Error persits call IT."
<< endl;
++trys;
if( trys < 2 ) continue;
}
else
{
changes = false;// update file flag ...
cout << "File write operation confirmed." << endl;
}
}
}
break; // and do exit program routine ...
}
else
{
cout << "\nChoice NOT implemented yet ...\n";
} // end of if( reply == ? ) 'switch' structure ...
} // end of main 'forever loop' ...
// debug exit routine ...
ifstream ftest( THIS_TERM ); // recall 'THIS_TERM' is a Global variable
if( !ftest )
{
cout << "\nError attempting to open file " << THIS_TERM << " ...\n";
pauseForEnter();
}
else // if reach here ...
{
ftest.close(); // first close file found ok above ...
// then ... proceed ... to open the file in a system text editor ...
// if you have a Win OS ... show structure of file
if( 'Y' == takeInStr( "Show in notepad {y/n) ? " ) )
{
string tmpSee = "notepad ";
tmpSee += THIS_TERM;
system( tmpSee.c_str() );
}
}
} ///////////////////////////////// END MAIN ///////////////////////////////////
int takeInStr( const std::string& msg )
{
std::cout << msg << std::flush;
int reply = toupper( std::cin.get() );
std::cin.sync();
return reply;
}
void pauseForEnter()
{
takeInStr( "\nPress 'Enter' to continue ... " );
}
// returns a valid iterator if ID is used already ... otherwise returns 'end()'
std::list< Student >::iterator existID( std::list< Student >& term, const std::string& ID )
{
std::list < Student > :: iterator it;
for( it = term.begin(); it != term.end(); ++it )
if( it->get_id() == ID ) return it;
// else ...
return it; // returns term.end() ...
}
// adds Student records to end of list of Student records ... 'term'
// gets input from keyboard ...
int newStud( std::list< Student >& term )
{
std::cout << "\nEnter an empty record to exit this 'Input Loop' ..." << std::endl;
int count = 0;
std::string nam, num;
for( ;; ) // loop forever until break ...
{
std::cout << "\nID : ";
getline( std::cin, num );
if( existID( term, num ) != term.end() )
{
std::cout << "\nThat 'id' " << num << " already exits ... " << std::endl;
continue; // from the top of the forever loop right now
}
std::cout << "Name : ";
getline( std::cin, nam );
if( nam == "" || num == "")
break;
int reply = takeInStr( "Add or Redo (a/r) ? " );
if( reply != 'A' )
{
std::cout << "Aborted ..." << std::endl;
continue;
}
// ok ... create and add this record to the end of the list ...
term.push_back( Student( nam, num ));
++count;
std::cout << "Added " << count << " ..." << std::endl;
}
return count; // i.e. the count of added new students ...
}
// shows (to console screen) all student records in list container ... 'term'
void viewStuds( const std::list< Student >& term )
{
std::list < Student > :: const_iterator it;
int i = 0;
std::cout << std::endl; // leading blank line ...
for( it = term.begin(); it != term.end(); ++it )
{
std::ostringstream oss;
oss << "list(" << std::setw(3) << std::setfill('0') << ++i << "): " << *it;
std::cout << std::left << std::setw(39) /*<< setfill(' ')*/ << oss.str();
if( i % 2 == 0 ) std::cout << std::endl; // print 2 per line ...
}
if( i % 2 == 1 ) std::cout << std::endl; // if only a half line ... go to a new line
}
// file all records in memory ... create/overwrite file with name 'THIS_TERM'
int fileStuds( const std::list< Student >& term )
{
std::ofstream fout( THIS_TERM ); // recall 'THIS_TERM' is a Global variable
if( !fout )
{
std::cout << "\nError attempting to open file " << THIS_TERM << std::endl;
return -1; // report error condition ...
}
// else ...
std::list < Student > :: const_iterator it;
int i = 0;
for( it = term.begin(); it != term.end(); ++it, ++i )
fout << it->get_name() << "," << it->get_id() << std::endl;
fout.close();
if( i == (int)term.size() )
std::cout << "\nAll " << i << " records filed ok." << std::endl;
else
std::cout << "\nOnly " << i << " of " << term.size()
<< " records were written ..." << std::endl;
return i; // report success ... i.e. report count of records filed
}
// reads in all Student records from file 'THIS_TERM' ... if it exists
// returns -1 if no file exists; else returns the number of records read
int readStuds( std::list< Student >& term )
{
std::ifstream fin( THIS_TERM ); // recall THIS_TERM is a Global variable
if ( !fin )
{
std::cout << "Error attempting to open file " << THIS_TERM
<< " ... Perhaps it dosen't exist yet?" << std::endl;
return -1; // report error condition ...
}
// else ... check existing term.size() first before re-setting?
if( term.size() ) // i.e. if not == 0 ...
{
std::cout << "\nDo you want over-write the " << term.size();
int reply = takeInStr( " records in memory (y/n) ? " );
if( reply != 'Y' )
{
std::cout << "Aborted ... " << std::flush;
return 0;
}
// if reach here ...
std::cout << "Ok ... will over-write the " << term.size()
<< " records in memory ... " << std::flush;
}
// if reach here ...
term.clear(); // set to empty list
std::string nam, num;
int i;
for( i = 0; getline( fin, nam, ',' ); ++i ) // get 1st string (up to ',')
{
getline( fin, num, '\n' ); // then get rest of line (up to '\n')
term.push_back( Student(nam, num) ); // construct and add new Student
}
fin.close();
return i; // report success? ... i.e. return the record count ...
}
// returns 'true' if a record was edited or erased; otherwise returns false
bool editStud( std::list< Student > &term )
{
std::cout << "\nNote: just enter an empty record to exit this 'Edit/Erase Function'"
<< "\nOk ... now enter the ID of the student record to edit : " << std::flush;
std::string idStr, nam;
getline( std::cin, idStr );
std::list< Student >::iterator i, index;
i = existID( term, idStr );
if( i == term.end() )
{
std::cout << "This '" << idStr << "' does not exist." << std::endl;
return false;
}
// else ... show ... and ask if ok to edit ...
std::cout << "Name : " << i->get_name() << std::endl
<< "ID : " << i->get_id() << std::endl;
int reply = takeInStr( "Abort or Edit/Erase (a/e) ? " );
if( reply != 'E' )
{
std::cout << "Aborted ... " << std::endl;
return false;
}
reply = takeInStr( "\nDo you want to erase this record (y/n) ? " );
if( reply == 'Y' )
{
term.erase( i );
std::cout << "Erased ...\n";
return true;
}
// else ... ok ... so will edit id ... then name
std::cout << "\nOk ... will edit ... Recall ...\n"
<< "Just enter an 'empty string' to abort/exit this edit ... "
<< "\nEnter NEW ID : ";
getline( std::cin, idStr );
index = existID( term, idStr );
if( index != term.end() && index != i ) // exclude 'i' so can edit 'i'
{
std::cout << "\nThe ID '" << idStr << "' already exits ... " << std::endl;
return false; // exit to menu now ...
}
// ok ... get new name ...
std::cout << "Enter NEW Name : ";
getline( std::cin, nam );
if( nam == "" || idStr == "" )
{
std::cout << "Aborted ..." << std::endl;
return false;
}
reply = takeInStr( "Ok or Redo (o/r) ? " );
if( reply != 'O' ) // cap 'O' ... as in Ok
{
std::cout << "Aborted ..." << std::endl;
return false;
}
// ok ... so ... go ahead and edit
i->set_name( nam );
i->set_id( idStr );
std::cout << "Edited ..." << std::endl;
return true;
}
Bob Jones,1
Suzy McQueen,2
Tim Horton,3
Bob Jones,4
Suzy McQueen,5
Jane Thomas,10
Jane Thomas,6
/* Student_Clist.c */ /* this version 2015-06-20 */
/*
A simple example of processing Student records ...
using my Clist ... an emulation of the C++ library list container ...
to hold each 'Student' object/record/Clist_member
See MENU below to see what this program does ...
Note:
* this program allows only unique student id's for each record
* this program is set to update its file, (if there were any changes),
before quitting
*/
#include "readWord.h" /* includes stdio.h, stdlib.h, string.h, etc... */
/* Globals ... */
#define THIS_TERM "fall.txt" /* file name for this term's records */
#define MENU "\n" \
" 1. V iew all records in memory at present\n" \
" 2. A dd a new student name and id\n" \
" 3. S ort student records\n" \
" 4. E dit/E rase a student record\n" \
" 5. L oad in student records from file\n" \
" 6. U pdate file with records currently in memory\n" \
" 7. e X it program\n\n" \
"Your choice (1..7) : "
typedef struct myStudent
{
char* name;
char* id;
struct myStudent* next;
} Student ;
#define List Student /* equate */
typedef List* pList;
#define pStudent pList /* equate */
#define clearStudent clearLrec /* equate */
void clearStudent( pStudent p )
{
free( p->id );
free( p->name );
}
/* Ok ... now can ... */
#include "Clist.h"
/* ... and then can ... */
#include "Clist_func's.h"
/* Note: this name comparison is NOT case sensitive ...
Also note: if names are 'same' the sorts by id */
int cmpNamesIgnoreCase( const pStudent x, const pStudent y )
{
const char *a = x->name, *b = y->name;
int test;
while( *a && *b && tolower(*a) == tolower(*b) ) ++a, ++b ;
/* ok ... now check end conditions ... */
test = tolower(*a) - tolower(*b) ;
if( test ) return test;
/* else ... names equal since test == 0 above ... so ... */
return strcmp(x->id, y->id);
}
/* to permit sorting by id */
int cmpIDs( const pStudent a, const pStudent b )
{
return strcmp(a->id, b->id );
}
/* functions used by main to process a list of Student records */
int takeInChr( const char* msg );
char* takeInStr( const char* msg, const char* delimits );
void pauseForEnter();
pStudent existID( Clist* term, const char* ID );
int newStud( Clist* term );
void viewStuds( const Clist* term );
int fileStuds( const Clist* term );
int readStuds( Clist* term );
int editStud( Clist* term );
int sortAndFile( Clist* term );
int update( Clist* term );
int doExit( Clist* term );
char* toCapsOnFirstLets( char* str )
{
char* p = str;
char prev = ' ';
while( *p )
{
if( prev == ' ' ) *p = toupper( *p );
prev = *p;
++p;
}
return str;
}
int main() /* //////////// BEGIN MAIN /////////////////// */
{
FILE* ftest;
int count,
changes = 0, /* set file 'changes' flag to initial value */
done = 0;
/* create a 'fall list' to hold student names and ids for the 'Fall Term'
also holds number of records, via 'fall.size' */
Clist fall;
initClist( &fall );
/* now get all records from file ... if it exists ? */
count = readStuds( &fall );
if( count >= 0 )
printf( "%d student record(s) read into memory ...\n", count );
else
puts( "(The file will be created when some student records exist.)" );
while( !done )
{
switch( toupper( takeInChr( MENU ) ) )
{
case '1' : case 'V' : /* View ... */
viewStuds( &fall );
break;
case '2' : case 'A' : /* Add ... from keyboard */
{
int numNewStuds = newStud( &fall );
printf( "\n%d student record(s) added ... "
"The total number of student records now is %d\n",
numNewStuds, fall.size );
if( numNewStuds ) /* if >0 added ... update bool variable changes */
changes = 1;
}
break;
case '3' : case 'S' : /* Sort ... but DON'T update changes' unless 'data filed' */
{
int val = sortAndFile( &fall );
if( val == 2 ) changes = 0;
else if( val == 1 ) changes = 1;
}
break;
case '4' : case 'E' :
if( editStud( &fall ) ) changes = 1;
break;
case '5' : case 'L' : /* Load/Read file into memory */
{
int num = readStuds( &fall );
if( num >= 0 )
{
printf( "\nThere were %d student records read into memory "
"from file.\n", num );
changes = 0; /* reset so will match present file ... */
}
}
break;
case '6' : case 'U' : /* Update file from memory */
if( !changes )
puts( "\nNO changes ... so file NOT updated ..." );
else
if( update( &fall ) ) changes = 0;
break;
case '7' : case 'X' : /* eXit main show MENU/loop */
if( toupper( takeInChr( "DO YOU REALLY WANT TO EXIT (y/n) ? " ) ) == 'Y' )
{
done = 1;
if( changes ) /* and then ... */
if( !doExit( &fall ) )
done = 0; /* so will NOT exit for loop ... */
}
break;
default :
puts( "\nChoice NOT implemented yet ..." );
} /* end of if( reply == ? ) 'switch' structure ... */
} /* end of main 'forever loop' ... */
/* debug exit routine ... */
ftest = fopen(THIS_TERM, "r"); /* recall 'THIS_TERM' is a Global variable */
if( !ftest )
{
printf( "\nError attempting to open file %s ...", THIS_TERM );
pauseForEnter();
}
else /* if reach here ... */
{
fclose( ftest ); /* first close file found ok above ... */
/* then ... proceed ... to open the file in a system text editor ...
if you have a Win OS ... show structure of file */
if( 'Y' == toupper( takeInChr("Show in notepad (y/n) ? ") ) )
system( "notepad " THIS_TERM ); /* compiler concat's strings */
}
return 0;
} /* ///////////////////// END MAIN ///////////////////// */
int takeInChr( const char* msg )
{
int chr;
fputs( msg, stdout ); fflush( stdout );
chr = getchar();
if( chr != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
return chr;
}
void pauseForEnter()
{
takeInChr( "\nPress 'Enter' to continue ... " );
}
char* takeInStr( const char* msg, const char* delimits )
{
char c;
fputs( msg, stdout ); fflush( stdout );
return readWord( stdin, 32, delimits, &c );
}
/* returns a valid iterator if ID is used already ... otherwise returns 'end()' */
pStudent existID( Clist* term, const char* ID )
{
pStudent it;
for( it = term->start; it != NULL; it = it->next )
if( strcmp(it->id, ID) == 0 ) return it;
/* else ... */
return it; /* returns NULL ... */
}
/* adds Student records to end of list of Student records ... 'term'
gets input from keyboard ... */
int newStud( Clist* term )
{
int count = 0;
Student rec;
puts( "\nNote: Enter quit (for ID) to exit this 'Input Loop' ..." );
for( ; ; ) /* loop forever until break ... */
{
rec.id = takeInStr( "\nID (a string) : ", "\n" );
if( strcmp(rec.id, "quit") == 0 )
{
free(rec.id);
return count;
}
if( existID( term, rec.id ) != NULL )
{
printf( "\nThat 'id' %s already exits ...\n", rec.id );
free( rec.id );
continue; /* from the top of the forever loop right now */
}
rec.name = takeInStr( "Name : ", "\n" );
toCapsOnFirstLets( rec.name );
if( toupper( takeInChr( "Add or Redo (a/r) ? " ) ) != 'A' )
{
puts( "Aborted ..." );
clearStudent( &rec );
continue;
}
/* ok ... create and add this record to the end of the list ... */
push_backClist( term, &rec );
++count;
printf( "Added %d ...\n", count );
}
return count; /* i.e. the count of added new students ... */
}
/* shows (to console screen) all student records in list container ... 'term' */
void viewStuds( const Clist* term )
{
pStudent it;
int i = 0;
putchar( '\n' ); /* leading blank line ... */
for( it = term->start; it != NULL; it = it->next )
{
char buf[256];
sprintf( buf, "(%03d): %s, %s", ++i, it->name, it->id );
printf( "%-30s", buf );
if( i % 2 == 0 ) putchar( '\n' ); /* print 2 per line ... */
}
if( i % 2 == 1 ) putchar( '\n' ); /* if only a half line, go to a new line */
fflush( stdout );
}
/* file all records in memory ... create/overwrite file with name 'THIS_TERM' */
int fileStuds( const Clist* term )
{
FILE* fout = fopen( THIS_TERM, "w" ); /* recall 'THIS_TERM' is a Global variable */
if( !fout )
{
printf( "\nError attempting to open file %s\n", THIS_TERM );
return -1; /* report error condition ... */
}
else
{
pList it;
int i = 0;
for( it = term->start; it != NULL; it = it->next, ++i )
fprintf( fout, "%s,%s\n", it->name, it->id );
fclose( fout );
if( i == term->size )
printf( "\nAll %d records filed ok.\n", i );
else
printf( "\nOnly %d of %d records were written ...\n", i, term->size );
return i; /* report success ... i.e. report count of records filed */
}
}
/* reads in all Student records from file 'THIS_TERM' ... if it exists
returns -1 if no file exists; else returns the number of records read */
int readStuds( Clist* term )
{
int i;
char c;
Student rec;
FILE* fin = fopen( THIS_TERM, "r" ); /* recall THIS_TERM is a Global variable */
if( !fin )
{
printf( "Error attempting to open file %s"
" ... Perhaps it dosen't exist yet?\n\n", THIS_TERM );
return -1; /* report error condition ... */
}
/* else ... check existing term size first before re-setting? */
if( term->size ) /* i.e. if not == 0 ... */
{
printf( "\nDo you want over-write the %d", term->size );
if( toupper( takeInChr(" records in memory (y/n) ? ") ) != 'Y' )
{
fputs( "Aborted ... ", stdout ); fflush( stdout );;
return 0;
}
/* if reach here ... */
printf( "Ok ... will over-write the %d records in memory ... ",
term->size ); fflush( stdout );
}
/* if reach here ... */
clearClist( term ); /* set to empty list */
for( i = 0; (rec.name = readWord( fin, 32, ",", &c )); ++i ) /* get 1st string (up to ',') */
{
rec.id = readWord(fin, 8, "\n", &c); /* then get rest of line (up to '\n') */
push_backClist( term, &rec );
}
fclose( fin );
return i; /* report success? ... i.e. return the record count ... */
}
/* returns 1 if a record was edited or erased ... otherwise returns 0 */
int editStud( Clist* term )
{
pStudent i, index;
char *idStr, *nam;
const char* prompt = "\nOk ... will edit ... Recall ... "
"just enter quit to abort/exit this edit."
"\nEnter NEW ID : ";
const char* prompt2 = "\nNote: just enter quit to exit this 'Edit/Erase Function'"
"\nOk ... now enter the ID of the student record to edit/erase : " ;
idStr = takeInStr( prompt2, "\n" );
if( strcmp(idStr, "quit") == 0 )
{
free(idStr);
return 0;
}
i = existID( term, idStr );
if( i == NULL )
{
printf( "This '%s' does not exist.\n", idStr );
free( idStr );
return 0;
}
/* else ... show ... and ask if ok to edit ... */
printf( "Name : %s\n"
"ID : %s\n", i->name, i->id );
if( toupper( takeInChr("Abort or Edit/Erase (a/e) ? ") ) != 'E' )
{
puts( "Aborted ... " );
free( idStr );
return 0;
}
if( toupper( takeInChr("Do you want to erase this record (y/n) ? ") ) == 'Y' )
{
eraseClist( term, i );
puts( "Erased ..." );
free( idStr );
return 1;
}
/* else ... ok ... so will edit id ... then name */
free( idStr );
/* now get new id string ... */
idStr = takeInStr( prompt, "\n" );
if( strcmp(idStr, "quit") == 0 ) { free(idStr); return 0; }
index = existID( term, idStr );
if( index != NULL && index != i ) /* exclude 'i' so can edit 'i' */
{
printf( "\nThe ID '%s' already exits ...\n", idStr );
free( idStr );
return 0; /* exit to menu now ... */
}
/* ok ... get new name ... */
nam = takeInStr("Enter NEW Name : ", "\n" );
if( nam[0] == 0 || idStr[0] == 0 )
{
puts( "Aborted ..." );
free( nam ); free( idStr );
return 0;
}
if( toupper(takeInChr("Ok or Redo (o/r) ? ")) != 'O' ) /* upper case 'O' ... as in Ok */
{
puts( "Aborted ..." );
free( nam ); free( idStr );
return 0;
}
/* ok ... so ... go ahead and edit, but first ... */
clearStudent( i );
i->name = nam;
i->id = idStr;
puts( "Edited ..." );
return 1;
}
int sortAndFile( Clist* term )
{
int changes = 1;
switch( toupper( takeInChr( "\nSort by id or name (i/n) ? " )))
{
case 'I' :
msortClist( term, cmpIDs ); /* case sensitive id's in sort */
fputs( "Now sorted in memory by id. ", stdout );
break;
case 'N' :
msortClist( term, cmpNamesIgnoreCase ); /* case insensitive */
fputs( "Now sorted in memory by name. ", stdout );
break;
default:
puts( "Ok ... no new sort done here ..." );
changes = 0; /* were NO changes, file NOT updated */
}
if( changes )
{
if( toupper(takeInChr( "Update file NOW (y/n) ? " ) ) == 'Y' )
{
fileStuds( term );
puts( "File was updated ..." );
changes = 2; /* were changes BUT file was updated */
}
else puts( "File was NOT updated ..." );
}
return changes;
}
int update( Clist* term )
{
if( toupper( takeInChr( "Are you sure you want to update"
" the file (y/n) ? " ) ) == 'Y' )
{
if( fileStuds( term ) != term->size )
{
puts( "\nUNEXPECTED ERROR! NOT all records were filed!"
"\nTry again ... If Error persits call IT." );
return 0;
}
/* else ... */
puts( "File write operation confirmed." );
return 1;
}
/* else ... */
return 0;
}
int doExit( Clist* term )
{
int exitValue = 0;
if( toupper( takeInChr( "Update file before exiting (y/n) ? " ) ) == 'Y' )
{
static int trys = 0;
if( fileStuds( term ) != term->size )
{
puts( "\nUNEXPECTED ERROR! NOT all records were filed!"
"\nTry again ... If Error persists call 'IT department'." );
++trys;
if( trys == 2 ) exitValue = -1;
}
else
{
puts( "File write operation confirmed." );
exitValue = 1;
}
}
return exitValue;
}