fork download
  1. /*******************************************************************************************
  2.  * File Name : Lab1.c
  3.  * Description : This file is the skeleton for Lab 1.
  4.  * Instructions: Complete the state machine as indicated in the comments inside each state.
  5.  * Implement the functions declared below and use them to complete the state machine.
  6.  * Do not modify any function declaration.
  7.  * Do not modify the main function nor any global declaration or definition.
  8.  * Any code above line 146 should not be modified.
  9.  * The output should look as follows:
  10.  * Program started!
  11.  * Stack empty or invalid.
  12.  * a b c
  13.  * a b c 1 2 3
  14.  * popped item: 3
  15.  * popped item: 2
  16.  * a b c 1
  17.  * a b c 1 x y z
  18.  * a b c 1 x y z
  19.  * Program ended!
  20.  *******************************************************************************************/
  21.  
  22. /******************************************************************************************
  23.  * Student Name:
  24.  * Student Number:
  25.  *
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <stdint.h>
  30. #include <string.h>
  31. #include <stdbool.h>
  32.  
  33. #define STACK_SIZE 200
  34. #define BUFFER_SIZE 10
  35.  
  36. /**
  37.  * Brief: Structure to hold stack index and stack data
  38.  */
  39. typedef struct {
  40. int8_t index;
  41. char stackData[STACK_SIZE];
  42. } stack_t;
  43.  
  44. /**
  45.  * Brief: Enum to represent type of command.
  46.  */
  47. typedef enum {
  48. COMMAND_NONE = 0,
  49. COMMAND_EXIT,
  50. COMMAND_PUSH,
  51. COMMAND_POP,
  52. COMMAND_PRINT,
  53. } command_t;
  54.  
  55. /**
  56.  * Brief: Structure to hold the parameters passed to the state machine
  57.  */
  58. struct StateMachineParameters {
  59. command_t command;
  60. char input[BUFFER_SIZE];
  61. } parameters[] = {
  62. {.command = COMMAND_NONE}, // Run START_STATE
  63. {.command = COMMAND_NONE}, // Run INITIALIZATION_STATE
  64. {.command = COMMAND_PRINT}, // Expect an error message
  65. {.command = COMMAND_PUSH, .input = "abc"},
  66. {.command = COMMAND_PRINT}, // Expect "abc"
  67. {.command = COMMAND_PUSH, .input = "123"},
  68. {.command = COMMAND_PRINT}, // Expect "abc123"
  69. {.command = 100, .input = "qwerty"}, // Parameters should be neglected
  70. {.command = COMMAND_POP}, // Pop out one item: '3'
  71. {.command = COMMAND_POP}, // Pop out one item: '2'
  72. {.command = COMMAND_PRINT}, // Expect "abc1"
  73. {.command = COMMAND_PUSH, .input = "xyz"},
  74. {.command = COMMAND_PRINT}, // Expect "abc1xyz"
  75. {.command = COMMAND_EXIT}, // Expect "abc1xyz"
  76. };
  77.  
  78. // Function prototypes
  79. int runStateMachine(struct StateMachineParameters parameters);
  80. bool pushIntoStack(char* pStack, int8_t* pStackIndex, char inputData);
  81. bool popFromStack(char* pStack, int8_t* pStackIndex, char* pOutputData);
  82. void printOutStackContents(char* pStack, int8_t stackIndex);
  83. bool isStackEmpty(int8_t stackIndex);
  84. bool isStackFull(int8_t stackIndex);
  85. void resetStack(char* pStack, int8_t* pStackIndex);
  86.  
  87. int main() {
  88. int i;
  89.  
  90.  
  91. for (i = 0; i < sizeof(parameters) / sizeof(parameters[0]); i++) {
  92. runStateMachine(parameters[i]);
  93. runStateMachine(parameters[0]); // Go back to WAIT_FOR_COMMAND_STATE
  94. }
  95.  
  96. return 0;
  97. }
  98.  
  99. /**
  100.  * Brief: This function runs a state machine that accepts commands as arguments
  101.  * in order to push/pop data into/from a stack structure defined locally and displays its contents.
  102.  */
  103. int runStateMachine(struct StateMachineParameters parameters) {
  104. static stack_t stack;
  105. static char inputString[BUFFER_SIZE]; // Stores the user's input string
  106.  
  107. static enum {
  108. START_STATE,
  109. INITIALIZATION_STATE,
  110. WAIT_FOR_COMMAND_STATE,
  111. PUSH_TO_STACK_STATE,
  112. POP_FROM_STACK_STATE,
  113. PRINT_STACK_CONTENTS_STATE,
  114. FINISH_STATE
  115. } state = START_STATE;
  116.  
  117. switch (state) {
  118. case START_STATE: {
  119. printf("Program started!\n");
  120. state = INITIALIZATION_STATE;
  121. break;
  122. }
  123.  
  124. case INITIALIZATION_STATE: {
  125. // Reset stack then go to wait for command state
  126. resetStack(stack.stackData, &stack.index);
  127. state = WAIT_FOR_COMMAND_STATE;
  128. break;
  129. }
  130.  
  131. case WAIT_FOR_COMMAND_STATE: {
  132. // Extract the command embedded in the parameter passed and switch to the
  133. // corresponding state as shown below:
  134. // COMMAND_PUSH -> go to PUSH_TO_STACK_STATE
  135. // COMMAND_POP -> go to POP_FROM_STACK_STATE
  136. // COMMAND_PRINT -> go to PRINT_STACK_CONTENTS_STATE
  137. // COMMAND_EXIT -> go to FINISH_STATE
  138. // Program should neglect any other input
  139. switch (parameters.command) {
  140. case COMMAND_PUSH:
  141. state = PUSH_TO_STACK_STATE;
  142. break;
  143. case COMMAND_POP:
  144. state = POP_FROM_STACK_STATE;
  145. break;
  146. case COMMAND_PRINT:
  147. state = PRINT_STACK_CONTENTS_STATE;
  148. break;
  149. case COMMAND_EXIT:
  150. state = FINISH_STATE;
  151. break;
  152. default:
  153. // Neglect invalid commands
  154. break;
  155. }
  156. break;
  157. }
  158.  
  159. case PUSH_TO_STACK_STATE: {
  160. // Push the data available in input string into the stack
  161. // Check for overflow condition
  162. // After all data is pushed, go back to WAIT_FOR_COMMAND_STATE
  163. strncpy(inputString, parameters.input, BUFFER_SIZE);
  164. for (int i = 0; i < strlen(inputString); i++) {
  165. if (!pushIntoStack(stack.stackData, & stack.index, inputString[i])) {
  166. printf("Stack full. Overflow.\n");
  167. state = WAIT_FOR_COMMAND_STATE;
  168. return 0;
  169. }
  170. }
  171. state = WAIT_FOR_COMMAND_STATE;
  172. break;
  173. }
  174.  
  175. case POP_FROM_STACK_STATE: {
  176. // Pop out one element from the stack and display the popped out data,
  177. // then go back to WAIT_FOR_COMMAND_STATE
  178. char outputData;
  179. if (popFromStack(stack.stackData, &stack.index, &outputData)) {
  180. printf("Popped item: %c\n", outputData);
  181. }
  182. state = WAIT_FOR_COMMAND_STATE;
  183. break;
  184. }
  185.  
  186. case PRINT_STACK_CONTENTS_STATE: {
  187. // Display the stack contents without popping out the data, however,
  188. // in case the stack is empty, print out a suitable message.
  189. // Then go back to WAIT_FOR_COMMAND_STATE.
  190. printOutStackContents(stack.stackData, stack.index);
  191. state = WAIT_FOR_COMMAND_STATE;
  192. break;
  193. }
  194.  
  195. case FINISH_STATE: {
  196. // Perform the same steps done in PRINT_STACK_CONTENTS_STATE except exit the state machine instead of
  197. // going back to WAIT_FOR_COMMAND_STATE.
  198. printOutStackContents(stack.stackData, stack.index);
  199. printf("Program ended!\n");
  200. return 0;
  201. }
  202.  
  203. default:
  204. state = START_STATE;
  205. break;
  206. }
  207.  
  208. return 0;
  209. }
  210.  
  211. bool pushIntoStack(char* pStack, int8_t* pStackIndex, char inputData) {
  212. if (*pStackIndex < STACK_SIZE - 1) {
  213. pStack[++(*pStackIndex)] = inputData;
  214. return true;
  215. } else {
  216. return false; // Stack is full
  217. }
  218. }
  219.  
  220. bool popFromStack(char* pStack, int8_t* pStackIndex, char* pOutputData) {
  221. if (*pStackIndex >= 0) {
  222. *pOutputData = pStack[(*pStackIndex)--];
  223. return true;
  224. } else {
  225. return false; // Stack is empty
  226. }
  227. }
  228.  
  229. void printOutStackContents(char* pStack, int8_t stackIndex) {
  230. if (stackIndex >= 0) {
  231. printf("Stack contents:");
  232. for (int i = 0; i <= stackIndex; i++) {
  233. printf(" %c", pStack[i]);
  234. }
  235. printf("\n");
  236. }
  237.  
  238. else {
  239. printf("Stack empty or invalid.\n");
  240. }
  241. }
  242.  
  243. bool isStackEmpty(int8_t stackIndex) {
  244. return stackIndex == -1;
  245. }
  246.  
  247. bool isStackFull(int8_t stackIndex) {
  248. return stackIndex == STACK_SIZE - 1;
  249. }
  250.  
  251. void resetStack(char* pStack, int8_t* pStackIndex) {
  252. *pStackIndex = -1;
  253. memset(pStack, 0, STACK_SIZE);
  254. }
Success #stdin #stdout 0s 5408KB
stdin
45
stdout
Program started!
Stack empty or invalid.
Stack empty or invalid.
Stack empty or invalid.
Stack empty or invalid.
Stack empty or invalid.
Stack empty or invalid.
Program ended!