Learn Algorithms with
第一天 一級ADT (first-class data type)
我們前一天實現的ADT有這樣的特點,它只用來表示一個對象。我們可以像使用int一樣使用stack,我們聲明一個整數 int m;類似的可以聲明一個堆棧 stack sta;可惜的是,使用c語言,它不支持重載,我們沒有辦法給我們的ADT賦予* 、- 、+ 這樣的運算,但可以自己用函數實現。
一級ADT就是這樣的東西: 它可以有多個實例,我們可以用它來聲明變量,對這些變量賦以實例的值。
我們來做個復數的ADT:想想復數有實部和虛部兩部分,我們給兩個浮點數來表示數據,並給它以下面操作:初始化、訪問實部和虛部、乘法。
//file name : complex.h
typedef struct complex
{
float re;
float im;
};
complex init(float ,float);
float re(complex);
float im(complex);complex mult(complex ,complex);
實現它也並非難事:
//file name : complex.c
#include< stdlib.h>
#include< complex.h>
complex init(float m_re , float m_im)
{
complex c;
c.re=m_re;
c.im=m_im;
return c;
}
float re(complex m_c)
{
return m_c.re;
float im(complex m_c)
{
return m_c.im;
}
complex(complex fc,complex sc)
{
complex c;
c.re=fc.re*sc.re-fc.im*sc.im;
c.im=fc.re*sc.re+fc.im*sc.im;
return c;
}
試著使用一下,恩,everything runs good 。只是,和更好差些。讓我們回頭好好想想,我們辛辛苦苦分了倆文件實現一個復數的目的是什麼?對呀,抽象啊。怎麼抽象呢?數據封裝呗。封裝好了沒?還沒有。
typedef struct complex{
float re;
float im;
};
在complex.h中的上面幾句話,讓結構的數據完全暴露在了那些引用了complex.h的客戶眼裡。這樣用戶其實可以完全不用什麼init(float,float)了。直接complex c1 ;c1.re=2; c1.im=3;就達到了目的,我們必須面對現實,前面做的努力白費了。我可以很負責任的告訴你,如果以後程序有了變化,這些直接對數據的操作將讓你很頭疼,後果很嚴重。
現在為時不晚,讓我們來改善它,最方便的途徑:
在complex.h中不看不見結構定義!但是我們還必須聲明它,好像有些矛盾。找個替代品:
//file name : complex.h
complex init(float ,float);
float re(complex);
float im(complex);
complex mult(complex ,complex);
在實現中我們來定義結構:
//file name : complex.c
#include< stdlib.h>
#include< complex.h>
struct complex {float re;float im;};
Comp init(float m_re , float m_im)
{
Comp c=malloc(sizeof *c);
c->re=m_re;
c->im=m_im;return c;
}
float re(Comp m_c)
{
return m_c->re;
}
float im(Comp m_c)
{
return m_c->im;
}
Comp mult (Comp fc , Comp sc)
{
return init(re(fc)*re(sc)-im(fc)*im(sc),re(fc)*re(sc)+im(fc)*im(sc));
}
Better one 。有經驗的朋友已經在鄙視這個癡呆版的memory leak 復數了。事實是我也不知道如何給它