Member.h は、テキストp.114に掲載。
Member.c は、テキストp.115に掲載。
LinkedList.h は、テキストp.337に掲載。
#ifndef ___LinkedList
#define ___LinkedList
#include "Member.h"
typedef struct __node {
Member data;
struct __node *next;
} Node;
typedef struct {
Node *head;
Node *crnt;
} List;
void Initialize(List *list);
Node *Search(List *list, const Member *x, int compare(const Member *x, const Member *y));
void InsertFront(List *list, const Member *x);
void InsertRear(List *list, const Member *x);
void RemoveFront(List *list);
void RemoveRear(List *list);
void RemoveCurrent(List *list);
void Clear(List *list);
void PrintCurrent(const List *list);
void PrintLnCurrent(const List *list);
void Print(const List *list);
void Terminate(List *list);
#endif
LinkedList.c
#include <stdio.h>
#include <stdlib.h>
#include "Member.h"
#include "LinkedList.h"
static Node *AllocNode(void)
{
return calloc(1, sizeof(Node));
}
static void SetNode(Node *n, const Member *x, const Node *next)
{
n->data = *x;
n->next = next;
}
void Initialize(List *list)
{
list->head = NULL;
list->crnt = NULL;
}
Node *Search(List *list, const Member *x, int compare(const Member *x, const Member *y))
{
Node *ptr = list->head;
while (ptr != NULL) {
if (compare(&ptr->data, x) == 0) {
list->crnt = ptr;
return ptr;
}
ptr = ptr->next;
}
return NULL;
}
void InsertFront(List *list, const Member *x)
{
Node *ptr = list->head;
list->head = list->crnt = AllocNode();
SetNode(list->head, x, ptr);
}
void InsertRear(List *list, const Member *x)
{
if (list->head == NULL)
InsertFront(list, x);
else {
Node *ptr = list->head;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = list->crnt = AllocNode();
SetNode(ptr->next, x, NULL);
}
}
void RemoveFront(List *list)
{
if (list->head != NULL) {
Node *ptr = list->head->next;
free(list->head);
list->head = list->crnt = ptr;
}
}
void RemoveRear(List *list)
{
if (list->head != NULL) {
if ((list->head)->next == NULL)
RemoveFront(list);
else {
Node *ptr = list->head;
Node *pre;
while (ptr->next != NULL) {
pre = ptr;
ptr = ptr->next;
}
pre->next = NULL;
free(ptr);
list->crnt = pre;
}
}
}
void RemoveCurrent(List *list)
{
if (list->head != NULL) {
if (list->crnt == list->head)
RemoveFront(list);
else {
Node *ptr = list->head;
while (ptr->next != list->crnt)
ptr = ptr->next;
ptr->next = list->crnt->next;
free(list->crnt);
list->crnt = ptr;
}
}
}
void Clear(List *list)
{
while (list->head != NULL)
RemoveFront(list);
list->crnt = NULL;
}
void PrintCurrent(const List *list)
{
if (list->crnt == NULL)
printf("着目ノードはありません。");
else
PrintMember(&list->crnt->data);
}
void PrintLnCurrent(const List *list)
{
PrintCurrent(list);
putchar('\n');
}
void Print(const List *list)
{
if (list->head == NULL)
puts("ノードがありません。");
else {
Node *ptr = list->head;
while (ptr != NULL) {
PrintLnMember(&ptr->data);
ptr = ptr->next;
}
}
}
void Terminate(List *list)
{
Clear(list);
}
LinkedListTest.c
#include <stdio.h>
#include "Member.h"
#include "LinkedList.h"
typedef enum {
TERMINATE, INS_FRONT, INS_REAR, RMV_FRONT, RMV_REAR, PRINT_CRNT,
RMV_CRNT, SRCH_NO, SRCH_NAME, PRINT_ALL, CLEAR
} Menu;
Menu SelectMenu(void)
{
int i, ch;
char *mstring[] = {
"先頭にノードを挿入", "末尾にノードを挿入", "先頭のノードを削除",
"末尾のノードを削除", "着目ノードを表示", "着目ノードを削除",
"番号で探索", "氏名で探索", "全ノードを表示",
"全ノードを削除",
};
do {
for (i = TERMINATE; i < CLEAR; i++) {
printf("(%2d) %-18.18s ", i+1, mstring[i]);
if ((i % 3) == 2) putchar('\n');
}
printf("( 0) 終了 :");
fflush(stdin);
scanf_s("%d", &ch);
} while (ch < TERMINATE || ch > CLEAR);
return (Menu)ch;
}
int main(void)
{
Menu menu;
List list;
Initialize(&list);
do{
Member x;
switch(menu = SelectMenu()) {
case INS_FRONT :
x = ScanMember("先頭に挿入", MEMBER_NO | MEMBER_NAME);
PrintMember(&x);
InsertFront(&list, &x);
break;
case INS_REAR:
x = ScanMember("末尾に挿入", MEMBER_NO | MEMBER_NAME);
InsertRear(&list, &x);
break;
case RMV_FRONT:
RemoveFront(&list);
break;
case PRINT_CRNT:
PrintLnCurrent(&list);
break;
case RMV_REAR:
RemoveRear(&list);
break;
case RMV_CRNT:
RemoveCurrent(&list);
break;
case SRCH_NO:
x = ScanMember("探索", MEMBER_NO);
if (Search(&list, &x, MemberNoCmp) != NULL)
PrintLnCurrent(&list);
else
puts("その番号のデータはありません。");
break;
case SRCH_NAME:
x = ScanMember("探索", MEMBER_NAME);
if (Search(&list, &x, MemberNameCmp) != NULL)
PrintLnCurrent(&list);
else
puts("その名前のデータはありません。");
break;
case PRINT_ALL:
Print(&list);
break;
}
} while (menu != TERMINATE);
Terminate(&list);
return 0;
}
Member.c
scanf() を scanf_s()に変更しているため、30行目の呼び出し部分に文字数上限の引数を追加する。
#include <stdio.h>
#include <string.h>
#include "Member.h"
int MemberNoCmp(const Member *x, const Member *y)
{
return x->no < y->no ? -1 : x->no > y->no ? 1 : 0;
}
int MemberNameCmp(const Member *x, const Member *y)
{
return strcmp(x->name, y->name);
}
void PrintMember(const Member *x)
{
printf("%d %s", x->no, x->name);
}
void PrintLnMember(const Member *x)
{
printf("%d %s\n", x->no, x->name);
}
Member ScanMember(const char *message, int sw)
{
Member temp;
printf("%sするデータを入力してください。\n", message);
if (sw & MEMBER_NO) { printf("番号:"); scanf_s("%d", &temp.no); }
if (sw & MEMBER_NAME) { printf("氏名:"); scanf_s("%s", temp.name, 20); }
return temp;
}



