Author Topic: Class Student using STL list ... AND ... C emulation using my Clist ...  (Read 11729 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Update:

you can contact me via this link ...

https://sites.google.com/site/andeveryeyeshallseehim/

(my/editor gmail link is on the 2nd page)



An other very common student request ...

Note the almost exact same code used for this program as for the vector program here ....
http://developers-heaven.net/forum/index.php/topic,2585.0.html
but with 'vector' changed to 'list' and ... #include <algorithm> is NOT needed here for a sort function, as the C++ library list ... comes with a list sort function built in ... Note this sort has just a slightly different sort function call for list.

The vector used ...

sort( v.begin(), v.end(), compareFunc );

but list just needs ...

lst.sort( compareFunc );

Code: [Select]
// 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;
}
« Last Edit: June 23, 2015, 07:12:02 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: Class Student using STL list ...
« Reply #1 on: July 29, 2011, 04:43:23 AM »
 An example of a data file used/produced by the above program ...

// file name :  fall.txt

Code: [Select]
Bob Jones,1
Suzy McQueen,2
Tim Horton,3
Bob Jones,4
Suzy McQueen,5
Jane Thomas,10
Jane Thomas,6

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
And here is the C emulation using my readWord.h, Clist.h, Clist_func's.h ...

Code: [Select]
/* 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;
}

Here is a link to the included files needed by the above C emulation ...

http://developers-heaven.net/forum/index.php/topic,2582.0.html
« Last Edit: June 21, 2015, 05:48:52 AM by David »