4年ぶりにC言語を復習をしたわけだが、どうにも使いづらいw
大学の3年で少し触っただけだw
なにせそれまでずっと PHP,C++,Python なんてオブジェクト指向言語しか弄ってないからだ。
連結リスト使うかも〜と、上の人。
で予習にスタックを組む俺。
取り敢えず以下のコードを見て欲しい。
予め断っておくが Objective-C でも C++ でもなく、C のコードである。
#include <stdio.h> #include "intstack.h" main() { int i; IntStack* stack = new_IntStack(); for(i=0;i<20;i++) { stack->push(stack,i+1); printf("Insert to stack val : %d\n",i+1); } printf("Stack counter is : %d\n",stack->getCount(stack)); for(i=0;i<5;i++) { printf("pop : %d\n",stack->pop(stack)); } delete_IntStack(stack); }
どう見ても C++ に汚染されたコードですw
一応残りのコードも晒しておく。
list.h
#ifndef __Node_H__ #define __Node_H__ typedef struct __node Node; struct __node { void* val; Node* next; }; Node* new_Node(); void* delete_Node(Node* this); #endif
list.c
#include <stdlib.h> #include <string.h> #include "list.h" Node* new_Node() { Node* this = (Node*)malloc(sizeof(Node)); if (this == NULL) return NULL; memset(this,0,sizeof(Node)); return this; } void* delete_Node(Node* this) { void* val = this->val; free(this); return val; }
new と delete を自前で宣言している。
スタック定義は以下。
stack.h
#ifndef __STACK_H__ #define __STACK_H__ #include "list.h" typedef struct __stack Stack; struct __stack { Node* top; int count; void (*push)(Stack*,void*); void* (*pop)(Stack*); int (*getCount)(Stack*); void (*clear)(Stack*); }; /* new と delete */ Stack* new_Stack(); void delete_Stack(Stack* this); /* コンストラクタとデストラクタ */ void Stack_init(Stack* this); void Stack_finish(Stack* this); /* クラス関数 */ void Stack_push(Stack* this,void* val); void* Stack_pop(Stack* this); int Stack_count(Stack* this); void Stack_clear(Stack* this); #endif
関数ポインタでクラス関数を無理やり宣言してる。
正直、生粋のC言語プログラマが見たら悲鳴上げるんじゃなかろうか?
stack.c
#include <stdlib.h> #include <string.h> #include "stack.h" Stack* new_Stack() { Stack* this = (Stack*)malloc(sizeof(Stack)); if(this == NULL) return NULL; memset(this,0,sizeof(Stack)); /* 関数の割り当て */ this->push = Stack_push; this->pop = Stack_pop; this->getCount = Stack_count; this->clear = Stack_clear; /* コンストラクタのコール */ Stack_init(this); return this; } void delete_Stack(Stack* this) { Stack_finish(this); free(this); } void Stack_init(Stack* this){} void Stack_finish(Stack* this) { Stack_clear(this); } void Stack_push(Stack* this,void* val) { Node* list = (Node*)malloc(sizeof(Node)); if (list == NULL) return; list->val = val; list->next = this->top; this->top = list; this->count++; } void* Stack_pop(Stack* this) { Node* top = this->top; if(top == NULL) return NULL; this->top = this->top->next; this->count--; return delete_Node(top); } int Stack_count(Stack* this) { return this->count; } void Stack_clear(Stack* this) { void* val; while ( (val = Stack_pop(this)) != NULL ) { /* * スタックの中に積まれたデータも削除 * そういう仕様 */ free(val); } }
特に言うことはなさげ。
ここからがキモい(自分で見てもキモい)。
intstack.h
#ifndef __INTSTACK_H__ #define __INTSTACK_H__ #include "stack.h" typedef struct __intstack IntStack; /* Stack を継承 */ struct __intstack { Stack* super; void (*push)(IntStack*,int val); int (*pop)(IntStack*); int (*getCount)(IntStack*); void (*clear)(IntStack*); }; /* new と delete */ IntStack* new_IntStack(); void delete_IntStack(IntStack* this); /* コンストラクタとデストラクタ */ void IntStack_init(IntStack* this); void IntStack_finish(IntStack* this); /* クラス関数(全てオーバーライド) */ void IntStack_push(IntStack* this,int val); int IntStack_pop(IntStack* this); int IntStack_count(IntStack* this); void IntStack_clear(IntStack* this); #endif
#include <stdlib.h> #include <string.h> #include "intstack.h" /* new と delete */ IntStack* new_IntStack() { IntStack* this = (IntStack*)malloc(sizeof(IntStack)); if(this == NULL) return NULL; memset(this,0,sizeof(IntStack)); /* 関数の割り当て */ this->push = IntStack_push; this->pop = IntStack_pop; this->getCount = IntStack_count; this->clear = IntStack_clear; /* 親クラスの生成 */ this->super = new_Stack(); /* コンストラクタのコール */ IntStack_init(this); return this; } void delete_IntStack(IntStack* this) { IntStack_finish(this); free(this); } /* コンストラクタとデストラクタ */ void IntStack_init(IntStack* this) {} void IntStack_finish(IntStack* this) { delete_Stack(this->super); } /* クラス関数(全てオーバーライド) */ void IntStack_push(IntStack* this,int val) { int* lpVal = (int*)malloc(sizeof(int)); *lpVal = val; this->super->push(this->super,(void*)lpVal); } int IntStack_pop(IntStack* this) { int val; int* lpVal = (int*)this->super->pop(this->super); val = *lpVal; free(lpVal); return val; } int IntStack_count(IntStack* this) { return this->super->getCount(this->super); } void IntStack_clear(IntStack* this) { this->super->clear(this->super); }
結論。
オブジェクト指向言語でなくても、きっとそれに近いコトはできるんだよ!
(手間隙掛かるけど)
今のところ private な継承で、オーバーライド(?)かけている。