main.c 8.87 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
28
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
/******************************************************************************
 *                               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 */
typedef enum {OK, EMPTY, FULL} retval_t;
/* 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 *      @retval FULL            Pushing failed -- stack is full               *
 ******************************************************************************/
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));
    /* 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 *
97
98
 *      @param command          Pointer to the read back command              *
 *      @retval OK              Popping successful                            *
99
100
101
102
103
104
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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
 *      @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;
    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 */
        scanf(" %c",&select);
        
        /* 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 */
                scanf("%s",command);
                /* (Try to) push the command on the stack */
                if (stack_push(&head,command) == FULL) {
                    /* Command cannot be pushed, stack is full */
                    printf("\nFAILED -- Stack is already full!\n\n");
                } else {
                    /* Command has been successfully pushed */
                    printf("\nPUSHED\n\n");
                }
                /** 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)            */
}
/******************************************************************************/