二次ポインタは一方向チェーンを削除します。

2724 ワード

今夜ここで文章を見ました。http://coolshell.cn/articles/8990.htmlテキストはコードの断片を与えています。実践の原則に基づいて、またチェーンを復習して、コードを書きました。
#include <stdio.h>
#include <stdlib.h>

typedef struct _node {
	int n;
	struct _node *next;
} node;

typedef int (* remove_fn)(node const *n);

node *create_link();
void destory_link(node *head);
void print_link(node *head);
int should_remove(node const *n);
node *remove_if(node *head, remove_fn should_remove);
void remove_if2(node **head, remove_fn should_remove);

int main() {
	node *head = create_link();
	print_link(head);
	//head = remove_if(head, should_remove);
	remove_if2(&head, should_remove);
	print_link(head);
	destory_link(head);
	return 0;
}

node *create_link() {
	node *head = malloc(sizeof(node));
	if (head == NULL) {
		printf("malloc head failed
"); return NULL; } head->n = 0; head->next = NULL; node *pre = head; for (int i=1; i<10; i++) { node *cur = malloc(sizeof(node)); if (cur == NULL) { printf("malloc node %d failed
", i); return NULL; } pre->next = cur; cur->n = i; cur->next = NULL; pre = cur; } return head; } void destory_link(node *head) { node *cur = head; while (cur) { node *next = cur->next; free(cur); cur = next; } } void print_link(node *head) { node *cur = head; while (cur) { printf("%d\t", cur->n); cur = cur->next; } printf("
"); } int should_remove(node const *n) { if (n == NULL) { return 0; } return (n->n)%2 == 0; } node *remove_if(node *head, remove_fn should_remove) { for (node *pre = NULL, *cur = head; cur;) { node * const next = cur->next; if (should_remove(cur)) { if (pre) { pre->next= next; } else { head = next; } free(cur); } else { pre = cur; } cur = next; } return head; } void remove_if2(node **head, remove_fn should_remove) { for (node **cur = head; *cur;) { node *entry = *cur; if (should_remove(entry)) { *cur = entry->next; free(entry); } else { cur = &(entry->next); } } }
コンパイルして実行してください1zrj@zrj-desktop:~/c$ gcc -g -std=gnu99 link.c && ./a.out20    1    2    3    4    5    6    7    8    931    3    5    7    9実は道理は複雑ではありません。自分でコードを二回読めば分かります。このような書き方は確かに巧妙で、しかも可読性においても、実はそれほど落ちていません。
まとめ:
ここで詳しく知ってください。関数の指針の使い方です。typedef  int  (* remove_fn)(node  const  *n); ,remove_fn 。呼び出しint  should_remove(node  const  *n); should_remove 。