線形リストでスタック #1
intをデータに持つ単方向連結の線形リストで実装するスタック。
先頭要素の追加と削除でpush/pop操作を実現する。
文字列から整数への変換にはatoiよりエラーを認識できるstrtolを用いた方がいいだろうと思う。
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct tagNode Node; struct tagNode { int data; Node *next; }; typedef enum { CMD_INVALID, CMD_TOOLONG, CMD_PUSH, CMD_POP, CMD_PRINT, CMD_QUIT } CmdType; typedef struct { CmdType type; int value; } Cmd; void init(Node *head); void push(Node *head, int data); void pop(Node *head); void print(Node *head); void get_cmd(Cmd *cmd); void init(Node *head) { head->next = NULL; } void push(Node *head, int data) { Node *n = malloc(sizeof(Node)); n->data = data; n->next = head->next; head->next = n; } void pop(Node *head) { Node *n = head->next; if (n == NULL) { puts("empty list"); } else { printf("%d\n", n->data); head->next = n->next; free(n); } } void print(Node *head) { Node *n; for (n = head->next; n != NULL; n = n->next) { printf("%d ", n->data); } putchar('\n'); } void get_cmd(Cmd *cmd) { char s[4096]; putchar('>'); if (fgets(s, sizeof s, stdin) == NULL) { cmd->type = CMD_QUIT; } else if (s[strlen(s) - 1] != '\n') { for (;;) { int c = getchar(); if (c == '\n' || c == EOF) break; } cmd->type = CMD_TOOLONG; } else { s[strlen(s) - 1] = '\0'; if (strncmp(s, "push ", 5) == 0) { cmd->type = CMD_PUSH; cmd->value = atoi(s + 5); } else if(strcmp(s, "pop") == 0) { cmd->type = CMD_POP; } else if(strcmp(s, "print") == 0) { cmd->type = CMD_PRINT; } else if(strcmp(s, "quit") == 0) { cmd->type = CMD_QUIT; } else { cmd->type = CMD_INVALID; } } } int main(void) { int quit_requested = 0; Node head; Cmd cmd; init(&head); do { get_cmd(&cmd); switch (cmd.type) { case CMD_PUSH: push(&head, cmd.value); break; case CMD_POP: pop(&head); break; case CMD_PRINT: print(&head); break; case CMD_QUIT: quit_requested = 1; break; case CMD_INVALID: puts("incomprehensible command"); break; case CMD_TOOLONG: puts("too long command"); break; default: puts("something strange..."); } } while (! quit_requested); return 0; }