Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

C++ Text Messaging Program

Options
  • 12-11-2002 11:56am
    #1
    Moderators, Arts Moderators, Recreation & Hobbies Moderators, Sports Moderators Posts: 9,523 Mod ✭✭✭✭


    Well,
    I'm trying to create a c++ prgogram which shall function like the text messaging section of a mobile phone.
    e.g....when you press "2" once you get "a"....press "2" twice to get "b", ...three times you get "c"....four times and you are back to "a".
    ...and also implement this for the other number keys.

    I know this is a relatively simple problem...I've been trying to use arrays but am having problems getting the whole thing working.

    Any suggestions would be welcome.


Comments

  • Registered Users Posts: 4,676 ✭✭✭Gavin


    what exactly have you tried so far ?
    apart from arrays that is :)


    Gav


  • Moderators, Arts Moderators, Recreation & Hobbies Moderators, Sports Moderators Posts: 9,523 Mod ✭✭✭✭BossArky


    Have a few counters...a counter for each key...

    e.g. counter_abc, counter_def, etc...and try to increment each one every time a number corresponding to this key is pressed...and mod it by 3...so that if you press a key 7 times it still knows to ref the first array element.

    then try to put a while loop to read through the arrays...while input != #

    tried to use getch() to get the characters from the keyboard and scroll through the array.


  • Closed Accounts Posts: 423 ✭✭Dizz


    Mebee somethin like....
    From an array of buttons (butt[]), associate an array (charXX[]) of x characters with a button (2D array). Use getch() or some other mechanism to trap keyboard events and map that event to the appropriate field in the array of buttons.

    Mebee...

    Dizz


  • Registered Users Posts: 1,391 ✭✭✭fatherdougalmag


    I know this topic has probably gone a bit stale but here's my 2c.

    Best way to do it would be to use a state machine. Everytime you hit a key (an event) you see what state you're in and depending on what state you're in you perform an action which moves you into a new state.

    It's probably overkill for such a small application but it's either that or have a rats nest of 'if' statements.

    I can provide sample sources if anyone wants


  • Registered Users Posts: 2,281 ✭✭✭DeadBankClerk


    You will find that cout'ing the backspace character could be very usefull.


  • Advertisement
  • Registered Users Posts: 1,391 ✭✭✭fatherdougalmag


    That's what I've done when the user hit's the same key in succession. The next pos it used when
    a) 1 second elapses since last key press or
    b) a different key is hit

    Thanks for the the tip anyway.

    I've just found this forum/site and I look forward to asking and answering questions!

    Bye for now ...


  • Moderators, Arts Moderators, Recreation & Hobbies Moderators, Sports Moderators Posts: 9,523 Mod ✭✭✭✭BossArky


    Ok, but what do you mean about the backspace characters being cout-ed?

    I have the first bit working....press the key and it cycles thru the array ...2 presses for B on the 2 key, etc....just wondering about the next bit....either press 1 to accept the selection...or press # to output the message.


  • Closed Accounts Posts: 120 ✭✭test999


    PM me with a snippet of the code, and I'll try and help,
    I used to be called eSecurity....


  • Registered Users Posts: 1,391 ✭✭✭fatherdougalmag


    Here's a clunky FSM version of the app. I ripped most of it from another project I've worked on.

    The important bit is KeyPadFSM which defines the actions that occur when an event is received in a certain state. It's quite legible (i.e. inefficient) but speed probably isn't of the essence with an application like this.

    I've only implemented digits 2 and 3 (letters a,b,c,d,e & f) so you'll have to extend it for the other digits. This means adding new actions to the table. Ideally, an FSM should have a matrix/2d array type structure which states along the top and events down the side (or vice versa). You could have a 2d array of function pointers and then reference the array with [state][event] offsets to call the function/action. Each action results in a change to a new state (or stay in the same state) and can then react to further events.

    Feel free to adapt, enhance, slag the code below.

    #include <stdio.h>
    #include <conio.h>
    #include <time.h>

    enum KEYPAD_STATE {
    IDLE,
    TWO_ONCE,
    TWO_TWICE,
    TWO_THRICE,
    THREE_ONCE,
    THREE_TWICE,
    THREE_THRICE,
    MAX_STATE
    };

    enum KEYPAD_EVENT {
    TWO_PRESSED,
    THREE_PRESSED,
    MAX_EVENT
    };
    #define QUIT_EVENT '1'

    typedef struct {
    int State;
    int Event;
    int (*fn)(int);
    } STATE_EVENT_ACTION_TUPLE;

    int Idle_TwoPressed(int);
    int TwoOnce_TwoPressed(int);
    int TwoTwice_TwoPressed(int);
    int TwoThrice_TwoPressed(int);

    int Idle_ThreePressed(int State);
    int ThreeOnce_ThreePressed(int State);
    int ThreeTwice_ThreePressed(int State);
    int ThreeThrice_ThreePressed(int State);

    STATE_EVENT_ACTION_TUPLE KeyPadFSM[] = {
    /* 1 */ {IDLE, TWO_PRESSED, Idle_TwoPressed },
    /* 2 */ {IDLE, THREE_PRESSED, Idle_ThreePressed },
    /* 3 */ {TWO_ONCE, TWO_PRESSED, TwoOnce_TwoPressed },
    /* 4 */ {TWO_ONCE, THREE_PRESSED, Idle_ThreePressed },
    /* 5 */ {TWO_TWICE, TWO_PRESSED, TwoTwice_TwoPressed },
    /* 5 */ {TWO_TWICE, THREE_PRESSED, Idle_ThreePressed },
    /* 6 */ {TWO_THRICE, TWO_PRESSED, TwoThrice_TwoPressed },
    /* 7 */ {TWO_THRICE, THREE_PRESSED, Idle_ThreePressed },
    /* 8 */ {THREE_ONCE, THREE_PRESSED, ThreeOnce_ThreePressed },
    /* 9 */ {THREE_ONCE, TWO_PRESSED, Idle_TwoPressed },
    /* 10 */ {THREE_TWICE, THREE_PRESSED, ThreeTwice_ThreePressed },
    /* 11 */ {THREE_TWICE, TWO_PRESSED, Idle_TwoPressed },
    /* 12 */ {THREE_THRICE, THREE_PRESSED, ThreeThrice_ThreePressed },
    /* 13 */ {THREE_THRICE, TWO_PRESSED, Idle_TwoPressed }
    };
    int CurrentState = IDLE;

    void main(void)
    {
    int Event = '\0';
    int time_last_key = 0, now = 0;
    int FSMSize = sizeof(KeyPadFSM) / sizeof(STATE_EVENT_ACTION_TUPLE);

    printf(" 1 2 3\n");
    printf("(quit) abc def\n");

    Event = getch();
    time_last_key = time(NULL);

    while (Event != QUIT_EVENT)
    {
    int i;

    // Map Event to zero-based enum value
    Event -= '2';

    for (i=0; i<FSMSize; i++)
    {
    if ((KeyPadFSM.State == CurrentState) && (KeyPadFSM.Event == Event))
    {
    CurrentState = (KeyPadFSM.fn)(CurrentState);
    break;
    }
    }

    Event = getch();
    now = time(NULL);

    if (now - time_last_key > 1)
    {
    CurrentState = IDLE;
    }

    time_last_key = now;
    }
    }

    int Idle_TwoPressed(int State)
    {
    printf("a");

    return TWO_ONCE;
    }

    int TwoOnce_TwoPressed(int State)
    {
    printf("\bb");

    return TWO_TWICE;
    }

    int TwoTwice_TwoPressed(int State)
    {
    printf("\bc");

    return TWO_THRICE;
    }

    int TwoThrice_TwoPressed(int)
    {
    printf("\ba");

    return TWO_ONCE;
    }

    int Idle_ThreePressed(int State)
    {
    printf("d");

    return THREE_ONCE;
    }

    int ThreeOnce_ThreePressed(int State)
    {
    printf("\be");

    return THREE_TWICE;
    }

    int ThreeTwice_ThreePressed(int State)
    {
    printf("\bf");

    return THREE_THRICE;
    }

    int ThreeThrice_ThreePressed(int State)
    {
    printf("\bd");

    return THREE_ONCE;
    }


  • Registered Users Posts: 2,281 ✭✭✭DeadBankClerk


    char backspace = 8; // ASCII 8 = backspace character

    if you "cout << backspace" you can delete the last character that you cout'ed, you will need to do this, since when you press 2 your program will cout << 'a', when you press 2 again you will need to cout << backspace << 'b'; to remove the 'a' and write a 'b'.


  • Advertisement
  • Moderators, Arts Moderators, Recreation & Hobbies Moderators, Sports Moderators Posts: 9,523 Mod ✭✭✭✭BossArky


    Ok ...the backspace sounds interesting alright, I'l try it out.

    That chunk of code looks a bit overly complex ....we're only supposed to use what we've been thought over the past 7/8 weeks...so I'll try and stick to arrays and ifs/whiles etc.

    PM, I must try that when I get some more time.

    Thanks for all your thoughts.


  • Registered Users Posts: 19,608 ✭✭✭✭sceptre


    You're not doing the Grad Dip in computing in UL are you? Sounds like the kind of thing Dermot Shinners-Kennedy would throw at grad dip students


  • Moderators, Arts Moderators, Recreation & Hobbies Moderators, Sports Moderators Posts: 9,523 Mod ✭✭✭✭BossArky


    yes in that class for a bit, doing music technology, but we have to sit in with them class for the programming things.

    will try and finish it off later.


  • Registered Users Posts: 1,391 ✭✭✭fatherdougalmag


    I thought that the FSM approach would be a bit overkill for a 'simple' little keypad app - never mind broaching the subject of FSMs with a music tech under-grad :)

    So here's a far simpler version using arrays:
    #include <stdio.h>
    #include <conio.h>
    #include <time.h>

    // This is where the digit/character assignments are held
    char Two[] = {'a', 'b', 'c', 0};
    char Three[] = {'d', 'e', 'f', 0};
    char Four[] = {'g', 'h', 'i', 0};
    char Five[] = {'j', 'k', 'l', 0};
    char Six[] = {'m', 'n', 'o', 0};
    char Seven[] = {'p', 'q', 'r', 's', 0};
    char Eight[] = {'t', 'u', 'v', 0};
    char Nine[] = {'w', 'x', 'y', 'z', 0};

    // A handy array which is referenced by the keystroke itself
    char *KeyPad[8] = {Two, Three, Four, Five, Six, Seven, Eight, Nine};

    // Keep track of the next character to display for each of the 8 digits
    unsigned short key_track[8] = {0,0,0,0,0,0,0,0};

    void main(void)
    {
    unsigned char key, last_key;
    unsigned char display;
    time_t now, last_key_press;

    printf(" 1 2 3\n");
    printf(" (quit) abc def\n\n");
    printf(" 4 5 6\n");
    printf(" ghi jkl mno\n\n");
    printf(" 7 8 9\n");
    printf(" pqrs tuv wxyz\n\n");
    printf(" # - delete\n\n");

    last_key = key = getch();
    last_key_press = time(NULL);

    // Keep going until we get a '1'
    while (key != '1')
    {
    // Make sure it's between 2 and 9 or it's a '#'
    if (((key <'2') || (key > '9')) && (key != '#'))
    {
    key = getch();
    continue;
    }

    if (key == '#') // backspace
    {
    printf("\b \b"); // delete char to the left
    key = getch();
    continue;
    }

    // Convert key-stroke to 0-based index which we can use
    // to reference the array
    key -= '2';

    // Record the time so we know whether to progress through
    // a digits letters or start back at the first letter
    now = time(NULL);

    // If it's been more than a second since the last key press
    // or a different key has been pressed, start back at the
    // first letter for that key
    if (((now - last_key_press) > 1) || (last_key != key))
    {
    key_track[key] = 0;
    }
    else // otherwise make the cursor go back a step so that
    { // the current char is overwritten
    printf("\b");
    }

    // Keep track of time
    last_key_press = now;

    // Wrap around
    if (KeyPad[key][key_track[key]] == 0)
    {
    key_track[key] = 0;
    }

    // Display the character
    printf("%c", KeyPad[key][key_track[key]]);

    // and move the cursor on to they next character
    key_track[key]++;

    last_key = key;

    key = getch();
    }
    }


Advertisement