Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Command Processor. Objectives You will be able to Create and understand State Diagrams. Write a text based command processor with multilevel menus.

Similar presentations


Presentation on theme: "1 Command Processor. Objectives You will be able to Create and understand State Diagrams. Write a text based command processor with multilevel menus."— Presentation transcript:

1 1 Command Processor

2 Objectives You will be able to Create and understand State Diagrams. Write a text based command processor with multilevel menus. 2

3 3 State Diagram Officially called State Machine Diagram in UML 2.0 Statechart Diagram in UML 1.x State Diagram is the general term used in computer science.

4 4 State Diagram Typically represents a single object Unlike activity diagrams, which show all objects involved in a given use case. Cuts across use cases. Summarizes object’s behavior in all circumstances

5 5 State Diagrams State diagrams consist of States Transitions Events Actions

6 6 What is a state? If an object’s response to a given stimulus depends on what has happened previously, each different response corresponds to a different state. The state completely determines the effects of past events on the object’s behavior.

7 7 What is a state? Concept from finite automata theory In finite automata theory, state changes take place instantaneously. An external stimulus results in an output (potentially) a new state (potentially) Both the output and the new state can vary according to the current state of the system at the time of the event.

8 8 What is a state? Real world systems are not so clean cut. Actions in response to an event may take a significant amount of time. State changes may not be instantaneous. But... the concept of states and events is often a useful abstraction.

9 9 UML Notation for States State name Should indicate what has happened or what is being done

10 10 Transitions Show possible state changes For each state, which states can come next

11 11 Statechart Example Chart shows which transitions are possible Diagram says that you can start and stop the engine only in Park. My car can start in either Park or Neutral. Can kill engine in any gear, but can’t remove key except in park. Engine On Engine Off

12 12 What is an Event? A stimulus that causes the object to do something or affects its future behavior. Examples: keyboard input, mouse click Events result in actions and state transitions. Label state transitions with the events that cause them.

13 13 Command Processor In the Ticket Booth program we will need a command processor. Top level control object. Gets command from user. Text menu Invokes function to execute command Once the program has started up, everything that it does is in response to a command.

14 14 Command State Various sets of commands are valid at different times depending on what has been done. Each distinct set of valid commands corresponds to a distinct command state. Executing a command results in an action and possibly a new command state. We need a state diagram as part of the system design.

15 15 Command Processor Example Let's look at a small example of a command processor using states and cities. Get initial information from XML file. Permit user to add information using text menu based commands. Program maintains a small "data base" about states (Florida, Texas, etc. ) State name Capital city Other cities

16 16 Command Processor Example Download file Geography_Initial.zip http://www.csee.usf.edu/~turnerr/Object_Oriented_Design/Downloads/ 2016_04_15_Command_Processor/ http://www.csee.usf.edu/~turnerr/Object_Oriented_Design/Downloads/ 2016_04_15_Command_Processor/ Expand

17 Input File: states.xml 17

18 Examine the Source Code in Visual Studio main.cpp City.h,.cpp State.h,.cpp main.cpp Build and run 18

19 19 Program Running

20 20 Command Processor Now let's add the capablity for the user to add new information to the file. Text based menu Select one of a small number of choices Choices identified by number

21 21 New Operations Add State command Add City command Add to an existing state. In order to add a city we need to specify which state. Select State.

22 22 Menu Hierarchy Initial Command State Menu 1. Select State 2. Add State 3. Quit When user selects 1 Ask state. Remember as selected state. Enter new command state, State Selected. When users selects 2 Get new state info Add state. Enter new command state, State Selected with new state selected. When user selects 3 Update file and terminate.

23 23 Menu Hierarchy State Selected Menu 1. Add City 2. Change State 3. Quit When user selects 1 Get new city info. Add city to currently selected state. Remain in same command state. When user selects 2 Switch to Initial command state. When user selects 3 Update file and terminate.

24 24 Command Processor Display menu for current command state. Get user's selection. Invoke function to perform action for selected command. Update command state.

25 25 State Diagram

26 26 Class Menu A boundary class Part of the program's user interface. Menu object displays list of available commands. Prompts user for input to select command Gets input. Return text of selected command. Not concerned with executing the command. Separation of concerns. No knowledge of command_states.

27 27 Class Menu Menu Add_Command Get_Command Command command text * prompt text

28 28 Add Class Menu to Project

29 29 Add Class Menu to Project

30 30 Menu.h #pragma once #include class Menu { public: static const int MAX_COMMANDS = 10; private: std::string* commands[MAX_COMMANDS]; int nr_commands; const std::string prompt; public: Menu(const std::string& prompt_); ~Menu(void); void Add_Command(const std::string& cmd); const std::string* Get_Command(void) const; };

31 31 Menu.cpp #include #include "Menu.h" using namespace std; Menu::Menu(const string& prompt_) : nr_commands(0), prompt(prompt_) {} Menu::~Menu(void) { for (int i = 0; i < nr_commands; ++i) { delete commands[i]; } void Menu::Add_Command(const string& cmd) { assert(nr_commands < MAX_COMMANDS); commands[nr_commands++] = new string(cmd); }

32 const string* Menu::Get_Command(void) const { string cmd; int choice = 0; while (true) { cout << prompt << endl; for (int i = 0; i < nr_commands; ++i) { cout << (i+1) << ": " << *commands[i] << endl; } cout << endl; cout "; getline(cin, cmd); try { choice = stoi(cmd); } catch (exception ex) { choice = 0; } Menu.cpp

33 if ((choice nr_commands)) { cout << "Invalid choice\n"; cout << "Please try again\n\n"; continue; } return commands[--choice]; } Menu.cpp (continued) Build

34 Test Class Menu In main.cpp Comment out main() Add #include "menu.h" Add new main() from following slide. 34

35 35 main.cpp int main() { Menu* menu = new Menu("Enter command number"); menu->Add_Command("Select State"); menu->Add_Command("Add State"); menu->Add_Command("Quit"); while (true) { const string* cmd = menu->Get_Command(); cout << "\nCommand was " << *cmd << endl << endl; if (*cmd == "Quit") { break; } cout << "Normal termination\n"; cin.get(); } Build and run

36 36 Testing Class Menu

37 37 Testing Class Menu

38 38 Command Processing We need two menus. Initial State Selected Command state says which one to use. Command results in: Action Possibly new command state.

39 39 Command Processor Select Menu object based on command state. Use Menu object to get command Execute command. Update command state. Command Processor will be top level control Display menu for current state. Get command. Execute command.

40 40 Command Processor Add new class Command_Processor Only purpose is as home for a static method that will be the top level of control. Process_Commands. Define a private default constructor to show the intent that the class should never be instantiated.

41 41 Command_Processor.h #pragma once #include #include "Menu.h" enum Command_States { Initial, State_Selected, Done }; using namespace std; class Command_Processor { public: static void Process_Commands(); private: static const int NR_CMD_STATES = (int) Done + 1; static Command_States command_state; static Menu* menus[NR_CMD_STATES]; Command_Processor(void) {}; }; Private constructor ensures that class cannot be instantiated.

42 42 Command_Processor.cpp #include #include "Command_Processor.h" using namespace std; Command_States Command_Processor::command_state = Initial; void Command_Processor::Process_Commands() { cout << "Process_Commands starting\n"; while (command_state != Done) { // Execute next command cout << "Process_Commands running\n"; command_state = Done; } cout << "Process_Commands exiting\n"; } Start with a stub.

43 Test Command Processor Comment out current main() Add main() from next slide 43

44 44 main.cpp At top of file:... #include "Command_Processor.h"... New main int main(void) { Command_Processor::Process_Commands(); cout << "Normal Termination\n"; cin.get(); return 0; } Build and run.

45 45 Inital Stub Running

46 46 Command_Processor.cpp #include #include "Command_Processor.h" using namespace std; Command_States Command_Processor::command_state = Initial; Menu* Command_Processor::menus[NR_CMD_STATES]; Add to private area of Command_Processor.h static void Create_Menus(); static void Process_Initial_State_Cmd(const string& cmd); static void Process_State_Selected_Cmd(const string& cmd); Real Command Processor, with stubs for commands.

47 47 Command_Processor.cpp void Command_Processor::Create_Menus() { // Menu for Initial command state Menu* menu = new Menu("Enter command number"); menu->Add_Command("Select State"); menu->Add_Command("Add State"); menu->Add_Command("Quit"); menus[Initial] = menu; // Menu for State Selected menu = new Menu("Enter command number"); menu->Add_Command("Add City"); menu->Add_Command("Change State"); menu->Add_Command("Quit"); menus[State_Selected] = menu; }

48 48 Command_Processor.cpp void Command_Processor::Process_Commands() { cout << "Process commands starting\n"; Create_Menus(); while (command_state != Done) { const string* cmd = menus[command_state]->Get_Command(); switch (command_state) { case Initial: Process_Initial_State_Cmd(*cmd); break; case State_Selected: Process_State_Selected_Cmd(*cmd); break; case Done: break; // Can't happen } cout << "Command_Processor exiting\n"; }

49 // Process command in Initial command state void Command_Processor::Process_Initial_State_Cmd(const string& cmd) { if (cmd == "Select State") { // Select state cout << "Select State command\n"; command_state = State_Selected; } else if (cmd == "Add State") { // Add state cout << "Add State command\n"; command_state = State_Selected; } else { cout << "Quit command\n"; command_state = Done; }

50 50 Command_Processor.cpp // Process command in State Selected command state void Command_Processor::Process_State_Selected_Cmd(const string& cmd) { if (cmd == "Add City") { // Add City cout << "Add City command\n"; } else if (cmd == "Change State") { cout << "Change State command\n"; command_state = Initial; } else { cout << "Quit command\n"; command_state = Done; }

51 51 Running with Command Stubs

52 52 Implementing Select State Comment out current main.cpp Restore original main.cpp as shown on following slides On the following slides: Add code to get State information from XML file. Pass states array to Process_Commands. Let Process_Commands use states array as its database.

53 main.cpp #include #include "tinyxml.h" #include "City.h" #include "State.h" #include "menu.h" #include "Command_Processor.h" using namespace std; 53

54 54 main.cpp int main(void) { State* states[50]; int nr_states = 0; cout << "This is the Geography program\n\n"; nr_states = Get_Data(states); Display_Data(states, nr_states); Command_Processor::Process_Commands(states, &nr_states); cout << "Normal Termination\n"; cin.get(); return 0; }

55 55 Command_Processor.h #pragma once #include "Menu.h" #include "City.h" #include "State.h" enum Command_States { Initial, State_Selected, Done }; using namespace std; class Command_Processor { public: static void Process_Commands(State** states_, int* nr_states_); private: static const int NR_CMD_STATES = (int)Done + 1; static Command_States command_state; static Menu* menus[NR_CMD_STATES ]; Command_Processor(void) {}; static void Create_Menus(); static void Process_Initial_State_Cmd(const string& cmd); static void Process_State_Selected_Cmd(const string& cmd); static void Select_State(); static State** states; static int* nr_states; static State* selected_state; };

56 56 Command_Processor.cpp Add near top: State** Command_Processor::states = 0; int* Command_Processor::nr_states = 0; State* Command_Processor::selected_state = 0;... void Command_Processor::Process_Commands(State** states_, int* nr_states_) { cout << "Process commands starting\n"; states = states_; nr_states = nr_states_; Create_Menus();

57 New Method Select_State void Command_Processor::Select_State() { Menu* menu = new Menu("Select State"); for (int i = 0; i < *nr_states; ++i) { menu->Add_Command(states[i]->Name()); } const string* state_name = menu->Get_Command(); // Find state with this name for (int i = 0; i < *nr_states; ++i) { if (states[i]->Name() == *state_name) { selected_state = states[i]; command_state = State_Selected; return; } // Should never reach this point. cout << "Error in Command_Processor::Select_State()\n"; }

58 58 New Method Select_State Update Process_Initial_State_Cmd to call Select_State() void Command_Processor::Process_Initial_State_Cmd(const string& cmd) { if (cmd == "Select State") { // Select state //cout << "Select State command\n"; Select_State(); command_state = State_Selected; }

59 59 Selecting a State

60 60 Selecting a State When a state is selected we should tell the user which state it is. Output currently selected state name prior to State_Selected menu.

61 61 Process_Commands while (command_state != Done) { if (command_state == State_Selected) { cout << "Selected state is " Name() << endl; } const string* cmd = menus[command_state]->Get_Command(); switch (command_state) { case Initial: Process_Command_0(*cmd); break; case State_Selected: Process_Command_1(*cmd); break; case Done: break; // Can't happen }

62 62 Selecting a State

63 63 Add State and Add City Add to private section of Command_Processor.h: static void Add_State(); static City* Get_City();

64 64 Add City City* Command_Processor::Get_City() { string name; cout << "City name: "; getline(cin, name); City* city = new City(name); return city; } // Process command in State Selected command state void Command_Processor::Process_State_Selected_Cmd (const string& cmd) { if (cmd == "Add City") { City* city = Get_City(); selected_state->Add_City(*city); delete city; selected_state->Display(); } Add to Command_Processor.cpp

65 65 Add State void Command_Processor::Add_State() { string state_name; string capital_name; cout << "State name: "; getline(cin, state_name); cout << "Capital city name: "; getline(cin, capital_name); City* capital = new City(capital_name); State* state = new State(state_name, *capital); delete capital; states[(*nr_states)++] = state; selected_state = state; }

66 66 Process_Initial_State_Cmd // Process command in Initial command state void Command_Processor::Process_Initial_State_Cmd(const string& cmd) { if (cmd == "Select State") { Select_State(); command_state = State_Selected; } else if (cmd == "Add State") { Add_State(); command_state = State_Selected; } else { //cout << "Quit command\n"; command_state = Done; }

67 Adding States and Cities 67

68 68 Save Changes The DOM can output itself to a file. Requires updating the DOM. Easier to work with our own objects. Add code to output XML.

69 69 Comand_Processor.h Add to private section: static void Output_XML();

70 70 Command_Processor.cpp void Command_Processor::Output_XML() { ofstream outfile; outfile.open("states2.xml"); if (!outfile.is_open()) { cout << "Failed to open file for output\n"; return; } outfile \n"; for (int i = 0; i < *nr_states; ++i) { states[i]->Output_XML(outfile); } outfile \n"; outfile.close(); cout << "File states2.xml written\n"; }

71 71 Command_Processor.cpp // Process command in Initial command state void Command_Processor::Process_Initial_State_Cmd (const string& cmd) { if (cmd == "Select State") { Select_State(); } else if (cmd == "Add State") { Add_State(); command_state = State_Selected; } else { Output_XML(); command_state = Done; }

72 72 Command_Processor.cpp // Process command in State Selected command state void Command_Processor::Process_State_Selected_Cmd (const string& cmd) { if (cmd == "Add City") { City* city = Get_City(); selected_state->Add_City(*city); delete city; selected_state->Display(); } else if (cmd == "Change State") { cout << "Change State command\n"; command_state = Initial; } else { Output_XML(); command_state = Done; } Build and run

73 73 Program Running

74 74 Program Running

75 Output File 75


Download ppt "1 Command Processor. Objectives You will be able to Create and understand State Diagrams. Write a text based command processor with multilevel menus."

Similar presentations


Ads by Google