線形リストでスタック #3

さらにいくつかの操作を追加するパッチ。

--- #   #
+++ #   #
@@ -12,18 +12,22 @@
 };
 
 typedef enum {
-    CMD_INVALID, CMD_TOOLONG, CMD_PUSH, CMD_POP, CMD_PRINT, CMD_QUIT
+    CMD_INVALID, CMD_TOOLONG, CMD_PUSH, CMD_POP, CMD_PRINT, CMD_DELETE, CMD_APPEND, CMD_CLEAR, CMD_QUIT
 } CmdType;
 
 typedef struct {
     CmdType type;
     char value[NAME_SIZE];
+    int index;
 } Cmd;
 
 void init(Node *head);
 void push(Node *head, char *data);
 void pop(Node *head);
 void print(Node *head);
+void delete(Node *head, int index);
+void append(Node *head, char *data, int index);
+void clear(Node *head);
 void get_cmd(Cmd *cmd);
 
 void init(Node *head)
@@ -62,6 +66,58 @@
     putchar('\n');
 }
 
+void delete(Node *head, int index)
+{
+    Node *p = head, *n = head->next;
+    int i = 0;
+
+    for (;;) {
+        if (n == NULL) {
+            puts("invalid index");
+            break;
+        }
+        if (i == index) {
+            p->next = n->next;
+            free(n);
+            break;
+        }
+        p = n;
+        n = n->next;
+        i++;
+    }
+}
+
+void append(Node *head, char *data, int index)
+{
+    Node *n = head->next;
+    int i = 0;
+
+    for (;;) {
+        if (n == NULL) {
+            puts("invalid index");
+            break;
+        }
+        if (i == index) {
+            push(n, data);
+            break;
+        }
+        n = n->next;
+        i++;
+    }
+}
+
+void clear(Node *head)
+{
+    Node *n = head->next;
+
+    while (n != NULL) {
+        Node *p = n;
+        n = n->next;
+        free(p);
+    }
+    head->next = NULL;
+}
+
 void get_cmd(Cmd *cmd)
 {
     char s[4096];
@@ -88,6 +144,26 @@
             cmd->type = CMD_POP;
         } else if(strcmp(s, "print") == 0) {
             cmd->type = CMD_PRINT;
+        } else if(strncmp(s, "delete ", 7) == 0) {
+            cmd->type = CMD_DELETE;
+            cmd->index = atoi(s + 7);
+        } else if(strncmp(s, "append ", 7) == 0) {
+            char *p = s + 7;
+            while (*p != '\0' && *p != ' ') p++;
+            if (*p == '\0') {
+                cmd->type = CMD_INVALID;
+            } else {
+                *p = '\0';
+                cmd->index = atoi(s + 7);
+                if (strlen(p + 1) < NAME_SIZE) {
+                    cmd->type = CMD_APPEND;
+                    strcpy(cmd->value, p + 1);
+                } else {
+                    cmd->type = CMD_TOOLONG;
+                }
+            }
+        } else if(strcmp(s, "clear") == 0) {
+            cmd->type = CMD_CLEAR;
         } else if(strcmp(s, "quit") == 0) {
             cmd->type = CMD_QUIT;
         } else {
@@ -115,6 +191,15 @@
         case CMD_PRINT:
             print(&head);
             break;
+        case CMD_DELETE:
+            delete(&head, cmd.index);
+            break;
+        case CMD_APPEND:
+            append(&head, cmd.value, cmd.index);
+            break;
+        case CMD_CLEAR:
+            clear(&head);
+            break;
         case CMD_QUIT:
             quit_requested = 1;
             break;
@@ -128,5 +213,6 @@
             puts("something strange...");
         }
     } while (! quit_requested);
+    clear(&head);
     return 0;
 }