#include<iostream>
#include <windows.h>
using namespace std;
char* reverse(char* scopy) {
    int cnt{0};
    while(*scopy!=0)  {
        ++scopy;
        ++cnt;
    }
    char* rev = new char[cnt];
    for(int i = 0; i < cnt; ++i) {
        --scopy;
        rev[i] = *scopy;
    }
    delete [] scopy;
    return rev;
}

#define example 5
const int screenHt = 70;
string global = "variable";

char* reverseJE(char* s) {
    int n = 0;
    while(*s!=NULL) {
        n++;
        ++s;
    }
    char* r = new char[n+1];
    s--; /// back up from NUL character
    for(int i = 0; i < n; i++) {
        r[i]=*s--; ///s[n-1-i];
    }
    r[n]='\0';
    return r;
}

int menu() {
    int choice{0};
    cout<< "\n\nChoose a numbered code sample to see what it does: \n"
        << "1. \n\tchar* pc = 0;\n\tchar& rc = *pc;\n\tcout << pc << rc;\n\n"
        << "2. \n\tstring& rs = global;\n\n"
        << "3. \n\tint* pi = new int;\n\tcout << \"The value of pi is \" << pi;\n\n"
        << "4. \n\tchar* pc = new char;\n\tcout << pc;\n\n"
        << "5. \n\tchar* pc;\n\tcout << pc;\n\n"
        << "6. \n\tchar* pc;\n\twhile(*pc++!='e')\n\t\tcout << pc;\n\n";

    do {
        cout << "\n\nchoose: ";
        cin>>choice;
        if(choice<1 || choice>7) cout << "\nchoose again: ";
    } while(choice<1 || choice>7);
    return choice;
}
int main() {
    system("MODE 80,50");
    int choice{0};
    while(1) {
        choice = menu();
        switch (choice) {
        case 1 : {
            cout << "\nMidterm #2: Ooops! You've set a reference value to NULL.  Very bad!  A NULL reference cannot exist!~ That will likely crash!\n";
            try {
                char x{'a'};
                char* pc = &x;
                char& rc = *pc;
                cout << "\npc = " << pc;
                cout << "\nrc = " << rc;
                /*int y{1};
                int* pi = &y;
                int& ri = *pi;
                cout << "\npi = " << pi;
                cout << "\nri = " << ri;*/
            }
            catch(const std::exception& e) { cout << e.what();}
            cin.ignore();
            cin.get();
            break;
        }
        case 2 : {
            cout<<"\nMidterm #3: The declaration: string& rs, without initialization"
                <<"\nwill very likely crash your system...RAII, no I so no A so no no."
                <<"\n...you can't initialize to a literal either: string& rs = \"literal\" won't fly."
                <<"\nI created a globat variable, \"string global = \"variable\" and that works.";
            string& rs = global; ///note the need for initialization
            cin.ignore();
            cin.get();
            cout << string(screenHt, '\n');
            break;
        }
        case 3 : {
            cout << "\nVariation on Midterm #4: The code\n\n\tint* pi = new int;\n\tcout <<\"The value of pi is \" << pi;"
                 << "\n\nproduces\n\n";
            int* pi = new int;
            cout << "\tThe value of pi is " << pi ;
            cout << "\n\n...a memory address assigned by the compiler.";
            cin.ignore();
            cin.get();
            cout << string(screenHt, '\n');
            break;
        }
        case 4 : {
            cout << "\nMidterm #4: By contrast with the variation on Midterm #4: The code\n\tchar* pc = new char;\n\tcout <<\"The value of pc is \" << pc;"
                 << "\n\nproduces\n\n";
            char* pc = new char;
            cout << pc;
            cout<< "\nAn unitialized character of some sort or other..."
                << "\nif, by contrast, we had initialized \n\tpc = \"dog\";"
                << "\nwe'd get the output \"dog\", not, as in the previous case, a memory address."
                << "\nThis is a special aspect of the C-string type.\n";
                cin.ignore();
                cin.get();
                cout << string(screenHt, '\n');
            break;
        }
        case 5 : {
             cout <<"\nThe code\n\tchar* pc;\n\tcout <<\"The value of pc is \" << pc;";
             cout<<"\nMidterm #5: Accessing unallocated and uninitialized memory"
                 <<"\nwill very likely crash your system...RAII: if no I then no A, a no no!"
                 <<"\n...you could initialize to a literal: char* pc = \"dog\".";
            char* pc = "dog";
            cout << "\nThe value of pc is " << pc;
            cin.ignore();
            cin.get();
            cout << string(screenHt, '\n');
            break;
        }
        case 6 : {
            char* pc;
            while(*pc++!='e')
                cout << *pc;
            cin.ignore();
            cin.get();
            cout << string(screenHt, '\n');
            break;
        }
        case 7 : {
            cout << "\ncase 8: ";
            char* pc = "literal";
            cout << "\ninput = " << pc;
            cout << "\nreverse input = " << reverseJE(pc);
            cin.ignore();
            cin.get();
            cout << string(screenHt, '\n');
            break;
        }
        }
    }
}
