main.c 9.47 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/******************************************************************************
 *                               C PROGRAMMING                                *
 *                    BASIC EXERCISES - EXAMPLE SOLUTIONS                     *
 *                                                                            *
 *      Task_6.09:  Stack                                                     *
 *      Author:     Dominik Widhalm                                           *
 *      Email:      dominik.widhalm@technikum-wien.at                         *
 *      Date:       2017-08-22                                                *
 *                                                                            *
 ******************************************************************************/


/***** INCLUDES ***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/***** MACROS *****************************************************************/
// Maximum length of strings
#define STRING_MAX 40
// Maximum stack size
#define STACK_MAX 10


/***** TYPEDEFS ***************************************************************/
/* Enumeration type for push & pop return value */
28
typedef enum {OK, EMPTY, FULL, FAILED} retval_t;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/* Struct type for the single linked list */
typedef struct cmd {
        // Command (string)
        char command[STRING_MAX];
        // Pointer to next element
        struct cmd *next;
    } cmd_t;


/***** FUNCTION PROTOTYPES ****************************************************/
retval_t stack_push (cmd_t **head, char *command);
retval_t stack_pop (cmd_t **head, char *command);
void stack_print (cmd_t *head);


/***** LOCAL FUNCTIONS ********************************************************/
/******************************************************************************
 *      stack_push                                                            *
 *      @brief Function to push a command on the stack.                       *
 *                                                                            *
 *      This function first checks if the stack is full. If not, it pushes    *
 *      the given command on the stack (adding it as first element).          *
 *                                                                            *
 *      @param head             Pointer to pointer to the first stack element *
 *      @param command          Pointer to the desired command                *
54
 *      @retval OK              Pushing successful                            *
55
 *      @retval FULL            Pushing failed -- stack is full               *
56
 *      @retval FAILED          Pushing failed -- allocation failed           *
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 ******************************************************************************/
retval_t stack_push (cmd_t **head, char *command) {
    /* Temporary pointer to the current stack element */
    cmd_t *curr = *head;
    /* Temporary variable for the stack size */
    int size = 0;
    
    /* Retrieve the current stack size */
    while (curr != NULL) {
        /* Increase stack size counter */
        size++;
        /* Go to next element */
        curr = curr->next;
    }
    /* Check if stack maximum size is already reached */
    if (size >= STACK_MAX) {
        /* Stack is full, cannot push */
        return FULL;
    }
    
    /* Allocate memory for the new command */
    curr = (cmd_t*)malloc(sizeof(cmd_t));
79
80
81
82
83
    /* Check if memory allocation was successful */
    if (curr == NULL) {
        /* Return FAILED to caller */
        return FAILED;
    }
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
    /* Copy the command string */
    strcpy(curr->command,command);
    /* Set the pointers accordingly */
    curr->next = *head;
    *head = curr;
    
    /* Pushing successful */
    return OK;
}


/******************************************************************************
 *      stack_pop                                                             *
 *      @brief Function to pop a command from the stack.                      *
 *                                                                            *
 *      This function first checks if the stack is empty. If not, it pops     *
 *      the next command from the stack.                                      *
 *                                                                            *
 *      @param head             Pointer to pointer to the first stack element *
103
104
 *      @param command          Pointer to the read back command              *
 *      @retval OK              Popping successful                            *
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
 *      @retval FULL            Popping failed -- stack is empty              *
 ******************************************************************************/
retval_t stack_pop (cmd_t **head, char *command) {
    /* Temporary pointer to the current stack element */
    cmd_t *curr = *head;
    
    /* Check if stack is empty */
    if (curr == NULL) {
        /* Stack is empty, cannot pop */
        return EMPTY;
    }
    
    /* Get the command from the current top element */
    strcpy(command,(*head)->command);
    
    /* Remove first element from the stack */
    *head = curr->next;
    free(curr);
    
    /* Popping successful */
    return OK;
}


/******************************************************************************
 *      stack_print                                                           *
 *      @brief Function to print the current stack.                           *
 *                                                                            *
 *      This function prints the current content of the stack (recursively).  *
 *                                                                            *
 *      @param head             Pointer to the first stack element            *
 ******************************************************************************/
void stack_print (cmd_t *head) {
    /* Print list recursively */
    if (head != NULL) {
        /* Print current element */
        printf("-> \"%s\"\n",head->command);
        /* Call function with next element */
        stack_print(head->next);
    }
    /* A void function has nothing to return */
    return;
}


/***** MAIN ROUTINE ***********************************************************/
int main (void) {
    /*** Local Variables ***/
    cmd_t *head = NULL;
    cmd_t *next;
155
    retval_t ret;
156
157
158
159
160
161
162
163
164
165
166
167
168
    char select = 'x';
    char command[STRING_MAX];
    
    /* Do as long as the users wants to do an action */
    do {
        /* Ask the user to select an action */
        printf("\nWant do you want to do?\n");
        printf("(i) insert a command (push)\n");
        printf("(r) retrieve next command (pop)\n");
        printf("(p) print current stack\n");
        printf("(x) exit\n");
        printf("Input: ");
        /* Read in the user's input */
169
        scanf(" %c%*c",&select);
170
171
172
173
174
175
176
177
        
        /* Do required action */
        switch (select) {
            case 'i':
                /** Insert a command **/
                /* Ask the user to input the command */
                printf("Please enter the desired command: ");
                /* Read in the user's input */
178
                fgets(command,STRING_MAX,stdin);
179
180
                /* Remove trailing newline */
                strtok(command,"\n");
181
                /* (Try to) push the command on the stack */
182
183
184
185
186
187
                ret = stack_push(&head,command);
                /* Check if pushing was successful */
                if (ret == OK) {
                    /* Command has been successfully pushed */
                    printf("\nPUSHED\n\n");
                } else if (ret == FULL) {
188
189
190
                    /* Command cannot be pushed, stack is full */
                    printf("\nFAILED -- Stack is already full!\n\n");
                } else {
191
192
                    /* Command cannot be pushed, allocation error */
                    printf("\nFAILED -- Cannot allocate memory!\n\n");
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
                }
                /** Finished inserting **/
                break;
            case 'r':
                /** Retrieve next command **/
                /* (Try to) pop the next command from the stack */
                if (stack_pop(&head,command) == EMPTY) {
                    /* Cannot pop, stack is empty */
                    printf("\nFAILED -- Stack is empty!\n\n");
                } else {
                    /* Command has been successfully pushed */
                    printf("\nPOPPED: \"%s\"\n\n",command);
                }
                /** Finished retrieving **/
                break;
            case 'p':
                /** Print the current stack */
                if (head == NULL) {
                    printf("\n... Stack is empty ...\n\n");
                } else {
                    printf("\n... Current stack ...\n");
                    stack_print(head);
                    printf("\n");
                }
                /** Finished printing **/
                break;
        }
    } while (select != 'x');
    
    /* Release the allocated memory (use pointer "next" as helper) */
    while (head != NULL) {
        /* Save pointer to current element */
        next = head;
        /* Set head to the next element */
        head = next->next;
        /* Free memory of current element */
        free(next);
    }
    
    /* Notify the user about the termination of the program */
    printf("\nThe program will now be terminated...\n");
    
    return 0;                           /* Return with Success (0)            */
}
/******************************************************************************/