2025
01
18
2012
06
24
自己参照型双方向リスト(C言語)
現在ゲーム中のユーザ管理するのにリスト構造使おうとちょっと作ったので置いておく。 自己参照型双方向リストです。
ソースコード
/* nex2t_list.c */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <netdb.h> #define RET_SUCCESS 0 #define RET_NO_ENTRY 1 #define RET_NO_MATCH_ENTRY 2 #define RET_NO_EXIST 0 #define RET_EXIST 1 #define DEBUG_LINE "------------------------------------------\n" typedef struct client_info { pid_t pid; char ip[NI_MAXHOST]; char port[NI_MAXSERV]; } cli_info_t; typedef struct client_info_node { struct client_info_node *next; struct client_info_node *prev; cli_info_t ent; } cli_info_node_t; typedef struct client_info_list { struct client_info_node *head; struct client_info_node *tail; } cli_info_list_t; void test(void); void create_info(cli_info_t *info, pid_t pid, const char ip[], const char port[]); void list_init(cli_info_list_t *list); void list_exit(cli_info_list_t *list); void list_add(cli_info_list_t *list, const cli_info_t *info); int list_del_head(cli_info_list_t *list); int list_del_tail(cli_info_list_t *list); int list_del_match_pid(cli_info_list_t *list, pid_t pid); int list_del_match_ip(cli_info_list_t *list, const char ip[]); int list_del_match_port(cli_info_list_t *list, const char port[]); int list_del_match(cli_info_list_t *list, const cli_info_t *info); int is_exist_cli_info_pid(const cli_info_list_t *list, pid_t pid); int is_exist_cli_info_ip(const cli_info_list_t *list, const char ip[]); int is_exist_cli_info_port(const cli_info_list_t *list, const char port[]); int is_exist_cli_info(const cli_info_list_t *list, const cli_info_t *info); void list_show(const cli_info_list_t *list); void list_show_match_pid(const cli_info_list_t *list, pid_t pid); void list_show_match_ip(const cli_info_list_t *list, const char ip[]); void list_show_match_port(const cli_info_list_t *list, const char port[]); void list_show_match(const cli_info_list_t *list, const cli_info_t *info); int main(void) { test(); return 0; } void create_info(cli_info_t *info, pid_t pid, const char ip[], const char port[]) { info->pid = pid; strcpy(info->ip, ip); strcpy(info->port, port); } void list_init(cli_info_list_t *list) { list->head = NULL; list->tail = NULL; } void list_add(cli_info_list_t *list, const cli_info_t *info) { cli_info_node_t *node; cli_info_node_t *node_tmp; node = (cli_info_node_t *)malloc(sizeof(cli_info_node_t)); node->ent.pid = info->pid; strcpy(node->ent.ip, info->ip); strcpy(node->ent.port, info->port); if (list->head == NULL) { /* first add */ list->head = node; list->tail = node; node->prev = NULL; node->next = NULL; } else { node_tmp = list->head; while (node_tmp->next != NULL) { node_tmp = node_tmp->next; } node_tmp->next = node; node->next = NULL; node->prev = node_tmp; list->tail = node; } } int list_del_head(cli_info_list_t *list) { cli_info_node_t *node_next_keep; if (list->head == NULL) { return RET_NO_ENTRY; } else if (list->head->next == NULL) { free(list->head); list->head = NULL; list->tail = NULL; } else { node_next_keep = list->head->next; free(node_next_keep->prev); list->head = node_next_keep; list->head->prev = NULL; } return RET_SUCCESS; } int list_del_tail(cli_info_list_t *list) { cli_info_node_t *node_prev_keep; if (list->tail == NULL) { return RET_NO_ENTRY; } else if (list->tail->prev == NULL) { free(list->tail); list->head = NULL; list->tail = NULL; } else { node_prev_keep = list->tail->prev; free(list->tail); list->tail = node_prev_keep; list->tail->next = NULL; } return RET_SUCCESS; } int list_del_match_pid(cli_info_list_t *list, pid_t pid) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_ENTRY; } node = list->head; do { if (i != 1) { node = node->next; } if (node->ent.pid == pid) { if ((node->prev == NULL) && (node->next == NULL)) { list->head = NULL; list->tail = NULL; } else if (node->prev == NULL) { list->head = node->next; node->next->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; node->prev->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } free(node); return RET_SUCCESS; } i++; } while (node->next != NULL); return RET_NO_MATCH_ENTRY; } int list_del_match_ip(cli_info_list_t *list, const char ip[]) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_ENTRY; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.ip, ip)) { if ((node->prev == NULL) && (node->next == NULL)) { list->head = NULL; list->tail = NULL; } else if (node->prev == NULL) { list->head = node->next; node->next->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; node->prev->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } free(node); return RET_SUCCESS; } i++; } while (node->next != NULL); return RET_NO_MATCH_ENTRY; } int list_del_match_port(cli_info_list_t *list, const char port[]) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_ENTRY; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.port, port)) { if ((node->prev == NULL) && (node->next == NULL)) { list->head = NULL; list->tail = NULL; } else if (node->prev == NULL) { list->head = node->next; node->next->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; node->prev->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } free(node); return RET_SUCCESS; } i++; } while (node->next != NULL); return RET_NO_MATCH_ENTRY; } int list_del_match(cli_info_list_t *list, const cli_info_t *info) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_ENTRY; } node = list->head; do { if (i != 1) { node = node->next; } if ((node->ent.pid == info->pid) && !strcmp(node->ent.ip, info->ip) && (!strcmp(node->ent.port, info->port))) { if ((node->prev == NULL) && (node->next == NULL)) { list->head = NULL; list->tail = NULL; } else if (node->prev == NULL) { list->head = node->next; node->next->prev = NULL; } else if (node->next == NULL) { list->tail = node->prev; node->prev->next = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; } free(node); return RET_SUCCESS; } i++; } while (node->next != NULL); return RET_NO_MATCH_ENTRY; } void list_show(const cli_info_list_t *list) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { printf("NO ENTRY.\n"); return; } node = list->head; do { if (i != 1) { node = node->next; } printf("[%d] pid:%d, ip:%s, port:%s\n", i++, node->ent.pid, node->ent.ip, node->ent.port); } while (node->next != NULL); } void list_show_match_pid(const cli_info_list_t *list, pid_t pid) { int i = 1, match_flag = 0; cli_info_node_t *node; if (list->head == NULL) { printf("NO_ENTRY.\n"); return; } node = list->head; do { if (i != 1) { node = node->next; } if (node->ent.pid == pid) { printf("[%d] pid:%d, ip:%s, port:%s\n", i, node->ent.pid, node->ent.ip, node->ent.port); match_flag = 1; } i++; } while (node->next != NULL); if (!match_flag) { printf("NO MATCH ENTRY pid:%d\n", pid); } } void list_show_match_ip(const cli_info_list_t *list, const char ip[]) { int i = 1, match_flag = 0; cli_info_node_t *node; if (list->head == NULL) { printf("NO_ENTRY.\n"); return; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.ip, ip)) { printf("[%d] pid:%d, ip:%s, port:%s\n", i, node->ent.pid, node->ent.ip, node->ent.port); match_flag = 1; } i++; } while (node->next != NULL); if (!match_flag) { printf("NO MATCH ENTRY ip:%s\n", ip); } } void list_show_match_port(const cli_info_list_t *list, const char port[]) { int i = 1, match_flag = 0; cli_info_node_t *node; if (list->head == NULL) { printf("NO ENTRY.\n"); return; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.port, port)) { printf("[%d] pid:%d, ip:%s, port:%s\n", i, node->ent.pid, node->ent.ip, node->ent.port); match_flag = 1; } i++; } while (node->next != NULL); if (!match_flag) { printf("NO MATCH ENTRY port:%s\n", port); } } void list_show_match(const cli_info_list_t *list, const cli_info_t *info) { int i = 1, match_flag = 0; cli_info_node_t *node; if (list->head == NULL) { printf("NO ENTRY\n"); return; } node = list->head; do { if (i != 1) { node = node->next; } if ((node->ent.pid == info->pid) && !strcmp(node->ent.ip, info->ip) && (!strcmp(node->ent.port, info->port))) { printf("[%d] pid:%d, ip:%s, port:%s\n", i, node->ent.pid, node->ent.ip, node->ent.port); match_flag = 1; } i++; } while (node->next != NULL); if (!match_flag) { printf("NO MATCH ENTRY pid:%d, ip:%s, port:%s\n", info->pid, info->ip, info->port); } } int is_exist_cli_info_pid(const cli_info_list_t *list, pid_t pid) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_EXIST; } node = list->head; do { if (i != 1) { node = node->next; } if (node->ent.pid == pid) { return RET_EXIST; } i++; } while (node->next != NULL); return RET_NO_EXIST; } int is_exist_cli_info_ip(const cli_info_list_t *list, const char ip[]) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_EXIST; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.ip, ip)) { return RET_EXIST; } i++; } while (node->next != NULL); return RET_NO_EXIST; } int is_exist_cli_info_port(const cli_info_list_t *list, const char port[]) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_EXIST; } node = list->head; do { if (i != 1) { node = node->next; } if (!strcmp(node->ent.port, port)) { return RET_EXIST; } i++; } while (node->next != NULL); return RET_NO_EXIST; } int is_exist_cli_info(const cli_info_list_t *list, const cli_info_t *info) { int i = 1; cli_info_node_t *node; if (list->head == NULL) { return RET_NO_EXIST; } node = list->head; do { if (i != 1) { node = node->next; } if ((node->ent.pid == info->pid) && !strcmp(node->ent.ip, info->ip) && (!strcmp(node->ent.port, info->port))) { return RET_EXIST; } i++; } while (node->next != NULL); return RET_NO_EXIST; } void list_exit(cli_info_list_t *list) { cli_info_node_t *node_tmp; cli_info_node_t *node_keep; if (list->head == NULL) { return; /* no entry */ } node_tmp = list->head; do { node_keep = node_tmp->next; free(node_tmp); node_tmp = node_keep; } while (node_tmp != NULL); } void test(void) { cli_info_list_t list; cli_info_t info; list_init(&list); printf("first list state.\n"); create_info(&info, 1003, "192.168.1.3", "10003"); list_add(&list, &info); create_info(&info, 1004, "192.168.1.4", "10004"); list_add(&list, &info); create_info(&info, 1005, "192.168.1.5", "10005"); list_add(&list, &info); create_info(&info, 1006, "192.168.1.6", "10006"); list_add(&list, &info); printf(DEBUG_LINE); list_show(&list); printf(DEBUG_LINE "\n"); printf("list_show_match test\n"); printf(DEBUG_LINE); list_show_match_pid(&list, 1005); list_show_match_pid(&list, 1007); list_show_match_ip(&list, "192.168.1.10"); list_show_match_ip(&list, "192.168.1.6"); list_show_match_port(&list, "10009"); list_show_match_port(&list, "10003"); create_info(&info, 1003, "192.168.1.5", "10003"); list_show_match(&list, &info); create_info(&info, 1003, "192.168.1.3", "10003"); list_show_match(&list, &info); printf(DEBUG_LINE "\n"); printf("is_exist_cli_info test (equal param list_show_match test)\n"); printf(DEBUG_LINE); printf("%d\n", is_exist_cli_info_pid(&list, 1005)); printf("%d\n", is_exist_cli_info_pid(&list, 1007)); printf("%d\n", is_exist_cli_info_ip(&list, "192.168.1.10")); printf("%d\n", is_exist_cli_info_ip(&list, "192.168.1.6")); printf("%d\n", is_exist_cli_info_port(&list, "10009")); printf("%d\n", is_exist_cli_info_port(&list, "10003")); create_info(&info, 1003, "192.168.1.5", "10003"); printf("%d\n", is_exist_cli_info(&list, &info)); create_info(&info, 1003, "192.168.1.3", "10003"); printf("%d\n", is_exist_cli_info(&list, &info)); printf(DEBUG_LINE "\n"); printf("list_add test\n"); printf(DEBUG_LINE); create_info(&info, 2003, "192.168.2.3", "20003"); list_add(&list, &info); create_info(&info, 2004, "192.168.2.4", "20004"); list_add(&list, &info); list_show(&list); printf(DEBUG_LINE "\n"); printf("list_del test\n"); printf(DEBUG_LINE); list_del_head(&list); list_del_tail(&list); list_show(&list); printf(DEBUG_LINE); list_del_match_pid(&list, 1003); list_del_match_pid(&list, 1004); /* del */ list_show(&list); printf(DEBUG_LINE); list_del_match_ip(&list, "192.168.1.5"); /* del */ list_del_match_ip(&list, "192.168.1.7"); list_show(&list); printf(DEBUG_LINE); list_del_match_port(&list, "10006"); /* del */ list_del_match_port(&list, "10005"); list_show(&list); printf(DEBUG_LINE); create_info(&info, 1003, "192.168.1.5", "10003"); list_del_match(&list, &info); create_info(&info, 2003, "192.168.2.3", "20003"); /* del */ list_del_match(&list, &info); list_show(&list); printf(DEBUG_LINE); list_exit(&list); }
コンパイル例
gcc -W -Wall -o nex2t_list nex2t_list.c
実行結果
./list first list state. ------------------------------------------ [1] pid:1003, ip:192.168.1.3, port:10003 [2] pid:1004, ip:192.168.1.4, port:10004 [3] pid:1005, ip:192.168.1.5, port:10005 [4] pid:1006, ip:192.168.1.6, port:10006 ------------------------------------------ list_show_match test ------------------------------------------ [3] pid:1005, ip:192.168.1.5, port:10005 NO MATCH ENTRY pid:1007 NO MATCH ENTRY ip:192.168.1.10 [4] pid:1006, ip:192.168.1.6, port:10006 NO MATCH ENTRY port:10009 [1] pid:1003, ip:192.168.1.3, port:10003 NO MATCH ENTRY pid:1003, ip:192.168.1.5, port:10003 [1] pid:1003, ip:192.168.1.3, port:10003 ------------------------------------------ is_exist_cli_info test (equal param list_show_match test) ------------------------------------------ 1 0 0 1 0 1 0 1 ------------------------------------------ list_add test ------------------------------------------ [1] pid:1003, ip:192.168.1.3, port:10003 [2] pid:1004, ip:192.168.1.4, port:10004 [3] pid:1005, ip:192.168.1.5, port:10005 [4] pid:1006, ip:192.168.1.6, port:10006 [5] pid:2003, ip:192.168.2.3, port:20003 [6] pid:2004, ip:192.168.2.4, port:20004 ------------------------------------------ list_del test ------------------------------------------ [1] pid:1004, ip:192.168.1.4, port:10004 [2] pid:1005, ip:192.168.1.5, port:10005 [3] pid:1006, ip:192.168.1.6, port:10006 [4] pid:2003, ip:192.168.2.3, port:20003 ------------------------------------------ [1] pid:1005, ip:192.168.1.5, port:10005 [2] pid:1006, ip:192.168.1.6, port:10006 [3] pid:2003, ip:192.168.2.3, port:20003 ------------------------------------------ [1] pid:1006, ip:192.168.1.6, port:10006 [2] pid:2003, ip:192.168.2.3, port:20003 ------------------------------------------ [1] pid:2003, ip:192.168.2.3, port:20003 ------------------------------------------ NO ENTRY. ------------------------------------------
検索用タグ C言語 双方向リスト 自己参照型
PR
2012/06/24 (Sun.) Comment(0) C言語
Comments