前言:一篇好文章的誕生,需要你不斷地搜集資料、整理思路,本站小編為你收集了豐富的c語言函數主題范文,僅供參考,歡迎閱讀并收藏。
指導教師:__________ 成績:__________
實驗四 函數
一、 實驗目的
1、掌握函數定義、調用和聲明的方法
2、掌握實參和形參之間的傳遞方式
3、函數的嵌套調用
二、 實驗內容
1、 寫一個函數,將兩個字符串連接。(習題8.6)
2、 編寫一個函數,由實參傳來一個字符串,統計此字符串中字母、數字、空格和其他字符的個數,在主函數中輸入字符串以及輸出上述的結果。(習題8.9)
3、 請將實驗三中的實驗內容三改正后,再改寫成函數形式(排序部分)。
物理實驗報告 ·化學實驗報告 ·生物實驗報告 ·實驗報告格式 ·實驗報告模板
關鍵詞 多態性;面向對象;函數重載;運算符重載
中圖分類號TP39 文獻標識碼A 文章編號 1674-6708(2011)40-0196-02
0 引言
多態性是面向對象程序設計的重要特征之一,它與封裝性和繼承性共同組成面向對象的程序設計的三大基本特征,在函數重載中,同一個函數名可對應若干種不同的實現,依據函數參數的類型、個數和順序來確定某個實現。在運算符重載中,同一個運算符對應著很多種功能,這些功能是通過函數來定義的,依據操作數的類型來確定應選運算符的功能。我們接觸的還有另一種是指同樣的消息被不同類的對象接受時產生完全不同的實現,該情況大多產生在多類繼承中不同類中的相同說明的成員函數的多態行為。其中多態性分為專用多態和通用多態,專用多態分為強制多態和重載多態;通用多態分為參數多態和包含多態。其中重載是實現C++多態性的一種十分重要的機制,成為重載多態,即為程序正文中相同作用域內的同一個標識符賦予不同的操作語義,實質上就是實現了程序空間到代碼空間的一對多映射。
1 函數重載
簡單地說函數重載就是賦給同一個函數名多個含義。在我們學的C++中函數重載分為普通函數的重載和成員函數的重載,也就是說我們所學的函數重載可以以兩種不同的方式來實現,就是我們所說的普通函數的重載和成員函數的重載。
1.1 普通函數的重載
例1:
#include
float min(float x,float y){return x>y?x:y;}//求2個浮點型小數的最小值
float min(float x,float y,float z) {return x>y?(x>z?x:z):(y>z?y:z);}
//求3個浮點型小數的最小值
void main( )
{
cout
}
運行的結果:1.2,3.2
上一例題中,兩個函數都是普通的函數重載,由于主函數中調用的兩個函數對應的參數個數不同,所以通過形參和實參的結合,我們得到了運行的結果。
1.2 成員函數的重載
例2:
#include
class A
{
public:
A( ): a(0){cout
A(int x): a(x){cout
private:int a;
};
void main( )
{ A a1,a2(3); }
運行結果為: Default Constructing 0
Constructing 3
這是一個很常見的習題,該函數調用了構造函數的兩種形式,有參和無參,對應于主函數中帶有不同形式參數的函數,我們得到不同的結果。
2 運算符重載
運算符重載就是就是賦予已有的運算符多重含義,即多種功能。C++語言中通過重新定義運算符,使它能夠用于特定類的對象執行的特定的功能。一般情況下運算符重載有兩種形式,重載為類的成員函數和重載為有元函數兩種。
2.1 重載為類的成員函數
例1:
#include
class complex
{
Public:complex(){real=imag=0;}
complex(double r,double i){real=r;imag=I;}
complex operator +(const complex &c);
complex operator -(const complex &c);
friend void print(const complex &c);
Private:double real,imag;
};
inline complex complex::operator +(const complex &c)
{return complex (real+c.rael,imag+c.imag);}
inline complex complex::operator -(const complex &c)
{return complex (real-c.rael,imag-c.imag);}
void print (const complex &c);
{
if (c.imag
cout
else
cout
}
void main()
{
complex c1(2.0,3.0),c2(4.0,-2.0),c3;
c3=c1+c2;
print(c3);
cout
c3=c1-c2;
cout
print(c3);
}
執行該程序的輸出結果:
c1+c2=6+1i;
c1-c2=-2+5i;
2.2 重載為有元函數
執行的結果同例1,兩種運算符比較,我們知道單目運算符最好被重載為成員函數,雙目運算符最好被重載為有元函數。
3 結論
以上我們總結了函數重載和運算符重載的區別和特點。眾所周知,重載是為了以不同的方式來實現函數,我們如果熟練的應用這門技術,可以提高程序的運行效率和可讀性,通過學習,使我們更透徹地理解了C++的多態性問題。
參考文獻
[1]譚浩強.C語言程序設計[M].3版.北京:清華大學出版社,2005,8.
[關鍵詞]Java JNT C DLL
在現今的軟件開發領域中,Java以其跨平臺的優勢得到大量的應用,其代碼可以一次編譯多處執行。但這種特性給Java帶來了一定的局限性,幸好Java提供了完備的C/C++語言接口,這樣我們可以利用C語言的強大功能實現Java難以實現的功能,在一定程序上消除Java的局限性和低效率。
一、創建DLL文件
使用某一種C/C++開發工具創建Dll文件,實現某一功能,供JAVA調用,例如本文在此使用Visual studio 2005創建一個名為testdll的動態庫文件。
二、使用JNI
JNI是Java Native Interface的縮寫,中文為JAVA本地調用。它允許Java代碼和其他語言寫的代碼進行交互。
1.JAVA類
在JAVA程序中,首先需要在類中聲明所調用的庫名稱,如下:
static {
System.loadLibrary(“testdll”); //加載動態庫,testdll為DLL文件名稱
}
還需要對將要調用的方法做本地聲明,關鍵字為native。并且只需要聲明,而不需要具體實現。如下:
public native static void set(int i);
public native static int get();
然后編譯該JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就會生成C/C++的頭文件。
例如程序testdll.java,內容為:
public class testdll { static { System.loadLibrary(“testdll”); } public native static int get(); public native static void set(int i); public static void main(String[] args) { testdll test = new testdll(); test.set(10); System.out.println(test.get()); } }
用javac testdll.java編譯它,會生成testdll.class。
再用javah testdll,則會在當前目錄下生成testdll.h文件,這個文件需要被C/C++程序調用來生成所需的庫文件。
2.C/C++
創建C/C++項目需要增加的頭文件有jni.h、jni_md.h這兩個文件是JNI中必須的;還有就是增加testdll.h。
對于已生成的.h頭文件,C/C++所需要做的,就是把它的各個方法具體的實現。然后編譯連接成庫文件即可。再把庫文件拷貝到JAVA程序的路徑下面,就可以用JAVA調用C/C++所實現的功能了。
接上例子。我們先看一下testdll.h文件的內容:
#include #ifndef _Included_testdll #define _Included_testdll #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint); #ifdef __cplusplus } #endif #endif
在具體實現的時候,我們只關心兩個函數原型 JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);和 JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);這里JNIEXPORT和JNICALL都是JNI的關鍵字,表示此函數是要被JNI調用的。而jint是以JNI為中介使JAVA的int類型與本地的int溝通的一種類型,我們可以視而不見,就當做int使用。函數的名稱是JAVA_再加上java程序的package路徑再加函數名組成的。參數中,我們也只需要關心在JAVA程序中存在的參數,至于JNIEnv*和jclass我們一般沒有必要去碰它。
下面我們用testdll.cpp文件具體實現這兩個函數:#include "testdll.h" int i = 0; JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass) { return i; } JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) { i = j+5; }
編譯連接成庫文件,這里就是testdll.dll。把testdll.dll拷貝到testdll.class的目錄下,java testdll運行它,就可以觀察到結果了。
三、總結
使用JNI可以在JAVA中調用其它語言編寫的代碼,在一定程度上消除JAVA的局限性和低效率。
參考文獻:
【關鍵詞】C語言 函數 類比教學法
【基金項目】防災科技學院重點教研項目2012A04;防災科技學院第一批精品建設課程。
【中圖分類號】G42 【文獻標識碼】A 【文章編號】2095-3089(2013)06-0165-02
形象類比法屬于講授教學方法的一種,即借助于兩類不同本質事物之間的相似性,通過比較,形象地將一種已經熟悉或掌握的特殊對象推移到另一種新的特殊對象上去的推理手段,也是教學中創設真實生動情景的有效工具之一。
C語言對于初學者而言,有一定的難度,學生在學習計算機方面存在比較大的弱點,思維邏輯能力不夠強,空間視覺不夠敏感。書中涉及到的一些抽象的理論知識,學生理解起來很難。為了幫助學生更好的理解抽象理論知識,在教學過程中,恰當的采用一些類比實例來幫助學生理解并提高學習的興趣。
在C語言學習過程中,從前面簡單的結構化思想轉化到函數的模塊化設計思想,因為知識的抽象性,學到函數這一章,很多同學反映學起來很困難,有一部分同學從這一章開始“知難而退”,放棄繼續學習C語言。結合自己的多年實踐教學經驗,試從幾個形象的例子類比來闡述如果理解復雜抽象的函數理論概念。
一、函數的概念
模塊化編程是指將一個龐大的程序劃分為若干個功能獨立的模塊,對各個模塊進行獨立開發,每一個模塊用來實現一個特定的功能,然后再將這些模塊統一合并為一個完整的程序。模塊化編程使程序易于維護和提高程序段的利用率,這是C語言面向過程的編程方法,可以縮短開發周期,提高程序的可讀性和可維護性。模塊的功能,在C語言中,由函數完成。函數的工作原理:分而治之!一個C程序可由一個主函數main和若干個函數構成。
一個C程序的執行:從主函數開始,在main函數中調用其他函數,其他函數也可以互相調用。主函數一般都很簡單,起到“驅動”的作用,把功能的實現都放在子函數里,一個子函數能做一件或者更多的事,可以說“主函數就是驅動程序,是用來驅動其它子程序(函數),更是整個完整程序的入口。”如果你要進入一個房子,你就必須先找到門,從門里才能進到屋子里去。C語言的主函數,就是你要運行的程序的“門”,不經過它,你就進不了房子。
music( )//音樂播放
{……}
movie( )//影視播放
{……}
online( )/*等等一序列子程序,這些子程序都需要main( )函數來驅動*/
{……}
void main( )
{
music( );
movie( );
online( );
}
程序模塊化,使程序開發更容易管理,函數把較大的任務分解成較小的任務。比如:以前作坊式的制衣流程:先紡紗織布,然后剪裁制衣,之后制作扣子縫制完成制衣。這些工作由一個家庭作坊獨立完成。類似于在C語言中由主函數完成所有的工作。現在的制衣流程:專業的織布公司、專業的制衣公司、生產加工扣子、拉鏈等輔料的公司。每一個公司類似于一個獨立的“子函數”。
二、向函數傳遞值
如果函數的參數是基本類型變量和構造類型變量,則傳遞值的拷貝。
例如制衣公司現在需要1萬條白色長30cm的銅拉鏈,他將把這些數值告訴加工輔料公司,加工輔料公司進行加工生產,即制衣公司“調用”加工輔料公司。這里的1萬條、白色、30cm及銅質這四個信息屬于傳遞的“參數”。這些參數對于制衣公司來說屬于是“實參”,對于加工輔料公司來說屬于“形參”。參數相當于公司之間的一份協議,它們的數據類型必須是一致的。制衣公司因為需求可以改變“實參”,例如改成加工2萬條白色長30cm的銅拉鏈,這時“實參”改變的時候,“形參”也跟著改變;但是,加工輔料的公司沒有自行改變制衣公司實參的權利,這就是函數的“形參”改變,“實參”不變的原則。
void Clothing_com( )//制衣公司
{
……
Accessories_com (1000,white,30,copper);//實參
……
}
void Accessories_com (int num,char color[10],float lenth,char quality[10])
//輔料公司,形參num:拉鏈數量;color:拉鏈顏色;lenth:拉鏈長度;quality:拉鏈質地
{ …… }
void main( )
{
Clothing_com( );
}
同一個函數可以被一個或多個函數調用任意多次,如加工輔料的公司可以和很多不同制衣公司合作。
三、向函數傳遞地址
如果參數是數組和指針變量,即地址,則傳遞地址值。
例如學校要鋪草坪,即學校“調用”草坪公司。一種方法是讓草坪公司在自己公司內種植草坪,草坪成熟后送到學校來,學校自己完成草坪鋪種。一種方法是由草坪公司直接把草坪種植到校園里。
第一種方法,學校需要明確告訴草坪公司需要多大面積的草坪數,函數傳遞值的拷貝。
char *Lawn_Com(float area)//草坪公司
{
char col_lawn[100];
for(int i=0;i
col_lawn[i]='*';//用*代表種植的草坪
return col_lawn;
}
void college( )//學校
{
char *college_lawn;
college_lawn=Lawn_Com(30);//30是形參,草坪公司把成熟的草坪送到學校的college_lawn。
}
void main( )
{
college( );
}
第二種方法里,學校需要明確告訴草坪公司在學校的哪個位置種植草坪,草坪公司直接派遣工作人員去“實參”所指示的“地址”種植草坪就可以了,函數參數傳遞的是地址。當函數參數傳遞的是地址值時,通過地址找到實參,然后直接對實參進行操作。
void Lawn_Com(char col_lawn[30])//草坪公司
{
for(int i=0;i
col_lawn[i]='*';//用*代表種植的草坪
}
void college( )//學校
{
char college_lawn[30];
Lawn_Com(college_lawn);//草坪公司到學校的college_lawn
}
void main( )
{
college( );
}
四、函數的返回值
函數的返回值就是把函數執行完之后的結果帶回給主調函數。函數可以有返回值,也可以沒有返回值。
如學校“調用”草坪公司鋪設草坪,在第一種方法中,學校要求草坪公司在其公司內部鋪種草坪,把鋪種成熟后草坪作為“返回值”送到學校,學校自己把草坪種到校園里,這是有返回值的函數。而在第二種方法中,學校要求草坪公司直接把草坪種到校園里,草坪種完就完成任務,草坪公司就不要再提交學校返回值了。
再如制衣公司“調用”輔料加工公司,輔料加工公司按照“實參”的要求把加工完的拉鏈成品作為“返回值”提交給制衣公司。
五、結束語
除了函數這一章外,筆者在C語言程學設計其他章節內容的教學中均嘗試采用了形象的類比教學法,效果顯著。類比教學法要求教師具有高度的概括能力,將知識進行歸納總結,在教學過程中,讓學生將實際應用和生活所熟悉的事物與枯燥、抽象的概念理論進行類比,培養學生分析和解決問題的能力,提高學生的學習興趣,讓學生喜歡C語言,學好C語言。
參考文獻:
[1]譚浩強.C程序多設計.第3版.清華大學出版社,2005
[2]韓瑩,豐繼林,單維鋒.C語言實訓教程.第1版.清華大學出版社,2013.1
關鍵詞: 股票市場收益;原油價格;Copula函數;相關性
中圖分類號:F830.91 文獻標識碼: A文章編號:1003-7217(2016)02-0032-06
一、引 言
原油是當今世界最主要的戰略能源之一,對國民經濟和金融市場的發展具有重大意義。歷史表明國際原油價格的每一次大幅波動,都會給世界經濟帶來巨大影響。從油價波動引起股市波動的機理來分析,對原油進口國而言,油價上漲會提高國內的物價水平,降低居民的實際收入水平,從而抑制居民消費,不利于經濟增長,股市也會受到影響。油價上漲還會導致中下游企業成本的增加,企業利潤的減少會減弱生產積極性,不利于經濟增長和股市的發展。同時,油價上漲必然導致生產企業減少石油的投入,降低企業的資本利用率,減少投資和資本存量,從而影響經濟的增長,進而造成股市波動。油價的波動對發展中國家的影響比對發達國家的影響要大得多,主要是因為這些經濟體依附于能源密集型產業,經歷了快速經濟增長,但能源使用效率低下[1]。鑒于新興經濟體的石油消耗不斷增加,研究國際原油價格與股票市場收益的相關性具有顯著意義。最近幾年,“金磚五國”成為新興市場的典型代表:金磚五國以快速的經濟增長速度和巨大的市場潛力著稱,逐漸成為世界經濟增長的重要推動力量。因此,本文重點研究國際原油價格與金磚五國股市收益之間的相依結構。
金洪飛,金犖[2]用VAR模型和二元GARCH模型研究了中美股市價格和國際石油價格的收益率及波動的溢出效應,實證結果表明中國股市價格與國際油價之間不存在任何方向的收益率溢出效應和波動溢出效應,而國際油價對美國股市有負向先導作用,并且存在雙向的波動溢出。Kunlapath S[3]等用Copula函數研究了股票收益和油價回報之間的相互關系,排除了石油天然氣股票公司的股票指數以去除油價和石油天然氣公司的直接關系。研究結果表明,在大多數情況下,油價和股票指數之間存在弱依賴性,這與先前的研究結果一致,然而石油消耗國和生產國的油價與股市具有強相關性。戚倩F,朱洪亮[4]應用VAR模型和誤差修正模型,研究了中美股市價格和國際石油價格間的關系及油價對中國股市板塊指數的影響,研究表明國際石油價格同中美股市指數都存在協整關系,在油價與美國股市指數的關系中,油價處于主導地位。Cuong C[5]使用非參Chiand Kplots和Copula函數分別刻畫了油價對中國和越南的相關性,國際油價與越南股市之間具有左尾相依性,與中國的結果相反。Xiaoqian Wen[6]利用Copula函數探討了在金融危機期間油價與股市之間是否具有傳染效應。雖然目前存在較多對油價和股市之間的相關性研究,但是卻嚴重缺乏對金磚五國這樣的新興經濟體的研究。因此,本文結合GARCH和Copula方法研究國際油價和金磚五國股市收益的相關性影響。
二、Copula理論與方法
(一)邊緣分布的估計
根據Copula理論,度量油價與股市收益之間的相關性,首先需要對油價和股市收益率分別建立一個邊緣分布。用正態分布擬合金融時間序列的均值方程的殘差,其結果不是很符合實際情況。GARCHGED模型能較好的描述金融時間序列的時變波動、高峰、偏斜、厚尾等分布特性。為了提高模型的擬合效果,采用基于廣義誤差分布(GED)的AR(p)GARCH(1,1)模型描述邊緣分布。模型的均值方程和方差方程如下:
由表1可知,除了油價的均值為負數之外,金磚五國股市收益率均值均為正數,但數值都較小,均在零附近。俄羅斯的標準差比較小,其他幾個市場的標準差較大。偏度顯示正向沖擊對于巴西和印度市場更為常見,而負向沖擊對于其他市場更為常見。
得出油價和股市的收益率峰度都大于6,遠遠大于正態分布的3,峰度最高的是俄羅斯股票市場,其值達到了22.9。從統計結果可知收益率服從尖峰、厚尾分布。JB統計量明顯拒絕收益正態性假設,LM檢驗表明變量存在ARCH效應。
表2給出了國際油價與金磚五國股市收益的相關系數結果。總體來看,油價和金磚五國股市的相關關系比較強。其中,Pearson線性相關、Spearman相關和Kendall相關的最大值分別是0.6870、0.5835和0.4585,除了油價與中國的相關系數較小之外,其他四國相關系數較大,說明油價與其他四國股市具有中等相關關系。這是因為巴西是石油開采大國,而石油更是作為俄羅斯的經濟命脈存在,南非的礦產資源非常豐富,卻唯獨缺少石油這種戰略資源。亞太地區近10年經濟快速增長,可以抵消油價對股市的負向沖擊。
為了提高模型的擬合效果,采用基于廣義誤差分布(GED)的AR(p)-GARCH(1,1)模型對油價和股市收益率進行建模,滯后階數選取0至10階,由AIC準則確定滯后階數。表3給出了收益序列邊緣分布的估計結果,GED分布的參數均小于2,說明尾部比正態分布的尾部更厚,反映收益率序列所得殘差項的尖峰厚尾特征,也表明GED分布能夠很好地描述收益率一般具有的非正態分布特征[8]。從結果可知,大部分估計系數和t統計量在1%的顯著性水平下是顯著的。表4是收益序列邊緣分布模型檢驗結果。LB檢驗主要是檢驗序列是否為白噪聲過程,由殘差序列的自相關系數計算而得,檢驗結果接受原假設,在滯后1,5,10階沒有自相關;LM檢驗表明殘差的平方項在滯后1,5,10階沒有自相關;KS統計量是根據估計得到的邊緣分布,對原序列做概率積分變換后再運用KS檢驗方法得到的,其目的是檢驗變換后的序列是否服從(0,1)均勻分布。KS檢驗結果表明每個邊緣分布服從(0,1)的均勻分布。
當邊緣分布確定后,利用靜態正態、Clayton、Gumbel、t Copula以及SJC Copula和時變SJC Copula函數描述油價和金磚五國股市收益的相關結構。Copula參數估計結果如表5所示。從正態Copula的估計系數來看,所有相關關系為正,油價與中國的相關程度最低,只有0.1042,油價與巴西的相關程度最高,顯然與表2描述的相關程度相似。考慮尾部的不對稱性,Clayton Copula的下尾相關系比較小,其中中國最小只有0.1274,但是對于Gumbel Copula的上尾相關系數而言,最大值有1.2477。SJC Copula的下尾和上尾系數都較小,但是下尾相關系數總體上大于上尾相關系數。因此當下尾相關時,市場管理者更應注重風險的回避。根據表5可知,時變SJC Copula的AIC最小,用來刻畫油價與金磚五國股票市場相依結構最為合適。
表6給出了國際油價WTI與金磚五國股市的尾部相關系數。正態Copula函數用于描述線性關系,沒有尾部相關性,尾部相關系數為0。從Clayton Copula和Gumbel Copula的尾部相關系數看出,油價與中國的尾部相關系數是最小的,而油價與巴西的尾部相關系數最大的。對于t Copula而言,因為它描述的是對稱分布,故下尾和上尾系數值是一樣的,油價與中國的尾部系數最小,這與表2的相關系數結果是一致的。從SJC Copula得出的結果可以看出,五個國家的下尾系數均大于上尾系數,說明油價的下跌對股市的影響大于油價的上漲對股市的影響。
參數估計結果顯示油價與巴西的相關程度最高,因此對它們之間的相依結構進行分析。
圖1、2分別給出了基于SJC Copula的油價與巴西股市的非對稱結構。2009年以前,時變SJC Copula的下尾系數和上尾系數分別維持在0.2054、0.1289附近,相關關系相對較弱;此后的幾年時間里,尾部相關程度明顯提高,時變SJC Copula的尾部相關系數總體上比靜態的尾部系數要大得多。同時還可以看出,油價與巴西股市收益的下尾系數要大于上尾系數,說明下尾的相關性比上尾的相關性要高。
石油價格收益率與金磚五國股市的相關程度取決于這些國家是否為石油進出口國家。2006年以前巴西一直是石油凈進口國,此后開始抓緊陸地石油勘探和興建煉油設施,石油產量不斷增加,成為石油出口國。石油出口帶來的收益增加會給石油出口的收入帶來正向的影響。因此,股票市場的收益會受到來自國際原油價格的變動影響。俄羅斯是全球第二大石油出口國,財政收入大部分依賴于石油的收益。石油與股市之間的相關關系也比較明顯。從負的偏度可知,油價與俄羅斯股市之間存在負向的關系,油價的下跌比上漲更能引起股市的波動。俄羅斯在911事件之后的石油產量不斷上升,其他產油國卻顯著的減少產量。因此可以說石油是俄羅斯的經濟命脈,俄羅斯經濟收入與石油息息相關。印度和中國以及南非一直都是石油凈進口國。從實證結果來看,石油與中國的相關程度最弱,印度次之。印度和中國都是非常大的經濟體,從某種程度而言,印度和中國的股市取決于多種宏觀因素的影響, 而不會單一的受到油價波動的沖擊。伴隨著中國金融經濟體制的不斷完善,中國證券市場更加規范和成熟,吸收和消化外來沖擊的能力得到進一步增強[9]。這意味著中國經濟具有強大的支撐和龐大的外匯儲備,在糟糕的環境下保護市場。隨著中國對外國投資者越來越開放,未來放開市場控制和匯率控制,這種弱相關程度可能會改變。
四、結 論
國際原油價格和股市之間的相關關系得到廣泛的關注。但是通常金融變量的分布是非正態的,線性相關顯然不太合適。本文采用Copula方法對油價與金磚五國股市收益之間的相關性進行描述。研究結果表明國際原油價格與中國股市收益呈現微弱的相關關系,而與其他四國股市收益的相關關系較為明顯。對于Copula參數估計而言,由最優AIC可知,使用時變SJC Copula描述模型更為合適。在金融全球化的趨勢下,不同國家或地區之間的金融市場的價格風險相依性逐漸加強。研究油價與金磚五國股市之間的相依關系對國際資產定價,風險管理和全球經濟體的交互作用具有深刻的意義。首先,油價波動造成的非對稱相依關系幫助投資者和政策制定者應對油價的變化,有助于謹慎投資,規避全球市場的風險傳染。其次,投資者和決策者在國際金融市場上實現投資組合和資產配置多樣化,維護發展中國家的利益。最后,動態尾部相關性的研究結果對風險管理也具有一定的指導作用,幫助政策制定者認清方向,當下尾相關性高于上尾相關性時,更應該及時規避油價波動帶來的風險沖擊,增強成員國進一步加強合作的意愿。
參考文獻:
[1] Bhar R, Nikolova B. Oil prices and equity returns in the BRIC countries[J]. World Economy, 2009, 32(7): 1036-1054.
[2]金洪飛, 金犖. 石油價格與股票市場的溢出效應――基于中美數據的比較分析[J]. 金融研究, 2008,(2):83-97.
[3]Kunlapath S, Tatevik Z, David L,Wu X. Interdependence of oil prices and stock market indices:a copula approach[J]. Energy Economics, 2014, 44(4):331-339.
[4]戚倩F, 朱洪亮. 國際石油價格與中美股票市場影響關系的計量分析[J]. 金融理論與實踐, 2011,(7):82-87.
[5]Nguyen C C, Bhatti M I. Copula model dependency between oil prices and stock markets:evidence from China and vietnam[J]. Journal of International Financial Markets Institutions & Money, 2012, 22(4): 758-773.
[6]Wen X, Wei Y, Huang D. Measuring contagion between energy market and stock market during financial crisis: A copula approach[J]. Energy Economics, 2012, 34(5): 1435-1446.
[7]Andrew J, Patton. Modelling asymmetric exchange rate dependence[J]. Social Science Electronic Publishing, 2006, 47(2):527-556.
關鍵詞:冠脈內支架植入術;再狹窄; C反應蛋白;纖溶酶原激活物抑制劑-1
中圖分類號:R815 R256.2 文獻標識碼:B 文章編號:1672-1349(2011)08-0925-02
預防冠脈支架內再狹窄是PCI必須面對的問題。再狹窄的基本病變包括炎癥反應、平滑肌增生及細胞外基質的積聚[1]。研究表明糖尿病是再狹窄的危險因素[2],并且糖尿病患者的纖溶活性受損,機體的炎性反應激活,而纖溶與炎癥機制是滲透再狹窄病理過程中的兩個主要機制[3],其中血C反應蛋白(CRP)、纖溶酶原激活物抑制劑-1(PAI-1)是反映纖溶機制與炎癥機制的常用指標,并已成為支架術后再狹窄強有力的預測指標[4],噻唑烷二酮類(TZDs)吡格列酮是否可以通過抑制血CRP與PAI-1而抑制支架內再狹窄?本研究旨通過觀察吡格列酮對這兩個因子的作用進而在理論上推測對支架內再狹窄方面的意義。
1 資料與方法
1.1 病例選擇 連續入選山西醫科大學第一醫院2007年5月―2008年1月心內科行PCI術的2型糖尿病(T2DM)并使用胰島素治療的急性冠脈綜合征患者20例。排除標準:既往有PCI史、接受過冠脈搭橋手術、心功能不全、肝腎功能異常、惡性腫瘤、感染、心肌炎、動脈夾層、血液病、伴有其他內分泌疾病的患者。
1.2 方法
1.2.1 給藥方法 將入選20例患者隨機分為觀察組與對照組,各10例。觀察組在PCI后24 h內加用鹽酸吡格列酮(艾可拓)15 mg/d,維持3個月,兩組均給予常規治療。
1.2.2 觀察指標 PCI術后24 h內、1個月及3個月測定血清高敏C反應蛋白(hs-CRP),血漿PAI-1含量。PAI-1測定:取清晨空腹肘靜脈血1.8 mL注入0.25%枸櫞酸鈉抗凝液0.2 mL試管中,離心。hs-CRP測定:取清晨空腹肘靜脈血2 mL,靜置,離心,收集上清液。二者均于-80 ℃保存直至檢測,由太陽生物技術有限公司提供的ELISA試劑盒測定。糖化血紅蛋白(HbA1c)與血脂采用全自動生化分析儀測定。
1.3 統計學處理 計量資料以均數±標準差(x±s)表示,采用t檢驗,樣本構成比的比較采用χ2檢驗。多次測量數據的分析采用重復測量數據的兩因素多水平的方差分析。采用SPSS 13.0統計軟件進行處理。
2 結 果
2.1 兩組一般臨床資料比較(見表1) 兩組一般資料比較差異無統計學意義(P>0.05)。
表1 兩組臨床資料比較
2.2 兩組hs-CRP、PAI-1及HbA1c變化(見表2~表5) 血清hs-CRP、HbA1c及血漿PAI-1濃度在不同時間點差別有統計學意義。詳見表2。血清hs-CRP濃度處理因素和時間之間無交互作用,而血清HbA1c及血漿PAI-1濃度處理因素和時間之間有交互作用;但處理因素僅對HbA1c有統計學意義。詳見表3~表5。即觀察組與對照組支架后三個指標均有隨時間逐漸降低的趨勢,且血清HbA1c及血漿PAI-1濃度觀察組較對照組降低趨勢更明顯,但使用艾可拓僅會使血清HbA1c降低有干預作用。
2.3 不良反應 在3個月的觀察期內所有患者均未出現心絞痛、再發心肌梗死、急性或亞急性血栓形成、心源性死亡的不良心血管事件;也均未出現明顯低血糖及體重的增加、未有肝功能異常(谷丙轉氨酶水平≥正常上限的3倍)、腎功能及心功能的異常。吡格列酮組有3例出現輕微下肢水腫,未經治療均于1個月內消失。
3 討 論
冠心病患者血液中CRP及PAI-1水平是增高的[5]。而這二者可促進冠脈支架術后再狹窄[3]。CRP可上調細胞間黏附分子-1、血管內皮細胞黏附分子-1、E-選擇素,介導巨噬細胞吞噬未修飾的LDL。CRP可誘導內皮細胞產生單核細胞趨化蛋白-1,增加單核細胞組織因子產生,而此因子是外源性凝血途徑的重要啟動因子,誘發血栓形成。CRP水平較高者炎癥局部釋放的某些血管收縮因子較多或血栓形成過程中血小板釋放的血栓素A2較多,誘發血栓形成;PAI-1可在局部減少纖溶酶原的激活,促進病變血管內纖維蛋白和細胞外基質的堆積。
鹽酸吡格列酮屬于新型的TZDs,TZDs是PPARγ的人工合成配體,是一類新型的胰島素增敏劑,TZDs可以改善高胰島素和高血糖血癥,使胰島素抵抗緩解[6],改善脂質代謝紊亂。對血管的作用包括改善血管內皮功能,降低血壓,減少動脈粥樣硬化炎癥替代標志[4],也可通過抑制前炎癥細胞因子,黏附分子和細胞外基質蛋白的誘導生成,達到抗炎作用。C反應蛋白是公認的最常用的急性期蛋白。PAI-1除反應纖溶活性外也作為一種急性反應性蛋白,炎癥的消除對纖溶活性的改善也起重要作用[7]。理論上TZDs有降低血CRP、PAI-1水平,但從本研究觀察到合并T2DM并行PCI術的患者在術后3個月內應用鹽酸吡格列酮除會使HbA1c的下降更顯著,對于hs-CRP、PAI-1、血壓及血脂則沒有明顯干預,可能的原因是:患者在觀察期內堅持服用氯吡格雷及阿司匹林,皮下注射胰島素,服用他汀類藥物、血管緊張素轉換酶抑制劑或血管緊張素Ⅱ受體拮抗劑,嚴格控制血壓、血糖,并盡量使血脂達標,而血壓、血糖、血脂達標及上述藥物本身均有利于降低患者血中的hs-CRP、PAI-1[8-10]。在這些因素的影響下加用鹽酸吡格列酮對于血糖的調節似乎作用較直接和有效,但對血壓、血脂、血hs-CRP及PAI-1的直接影響則較小;TZDs啟動的是一個基因調控的過程,3個月的觀察時間較短;再狹窄部位藥物濃度不足;PCI術后血hs-CRP、PAI-1還有一個自行回落過程對實驗結果有影響。
參考文獻:
[1] 潘長江.血管支架內再狹窄的機理研究進展[J].中國介入影像與治療學,2005,2(4):314-317.
[2] 王旭開,何作云.胰島素及IGF系統在冠狀動脈再狹窄形成中的作用[J].心血管病學進展,2001,22(3):140-142.
[3] 劉海波,高潤霖.血清C反應蛋白水平對冠心病介入治療術中及術后并發癥發生的預測價值[J].中國循環雜志,2000,15:264-265.
[4] 楊彬.氯沙坦在損傷血管重構中的作用及其機制的探討[J].心臟雜志,2004,16(1):23-24;28.
[5] 朱西娥.糖尿病與冠心病(上) [J].中國鄉村醫藥雜志,2002,9(11):57.
[6] 劉尊敬.PPARγ配體和相關血管病變的防治[J].國外醫學:神經病學神經外科學分冊,2004,31(2):117-120.
[7] 周明術.2型糖尿病患者急性時相反應蛋白檢測的臨床意義[J].陜西醫學雜志,2005,34(11):1347-1349.
[8] 郭書紅.氯沙坦對原發性高血壓患者PAI-1、vWF、D-D的影響[J].中國廠礦醫學,2006,19(3):199-202.
[9] 俞勻,朱大龍.PAI-1與代謝綜合征[J].國際內分泌與代謝雜志,2006,26:49-51.
[10] 祁素霞.PAI-1、CRP與胰島素抵抗及2型糖尿病的關系[J].醫學綜述,2007,13(3):212-214.
作者簡介:趙宇卉(1976―),女,主治醫師,醫學碩士,現工作于山西省忻州市人民醫院(郵編:034000);陳還珍,工作于山西醫科大學第一醫院。
關鍵詞:面向對象;代碼轉換;C/C++
中圖分類號:TP311文獻標識碼:A文章編號:1009-3044(2008)35-2181-03
An Automated Solution to Develop Object-Oriented C Program
RAO Jun-wen, ZHU Hong-ming
(Software School, Tongji University, Shanghai 201804, China)
Abstract: There are already solutions to make C language support Object-Oriented feature, but in those solutions the code framework supporting that feature needs to be provided by developers. In this solution codes will be written in C++-like grammar, while inside codes will be converted into Object-Oriented C language code, so no gap between Object-Oriented feature and C language exists. This paper analyzed the mechanisms of supporting Object-Oriented feature by using C language and codes converting, and then compared performance of this solution to that of using C++, so its advantage would be proved.
Key words: Object Oriented; codes converting; C/C++
1 方案概述
1.1 當前情況
嵌入式系統是當前最熱門最有發展前景的IT應用領域之一,然而不得不承認的是,由于嵌入式領域硬件資源的限制,絕大多數的嵌入式軟件還是用C語言或匯編來實現的,這一現狀極大影響了開發人員的工作效率和質量。眾所周之,C語言是一種不直接支持面向對象特性的語言,相對于C++等語言來說,其代碼編寫效率低,組織層次紛亂,封裝性差,不利于代碼重用。這樣的代碼,可讀性差,維護難度也很大。如果為避免這種情況而采用C++等支持面向對象特性的編程語言又會顧此失彼。C++雖然支持面向對象特性,但它所具有的其他特性,如虛函數、多重繼承、模板、異常、RTTI等,增加了代碼的復雜性,使其占用更多硬件資源,降低代碼運行的效率,這些都會極大的影響嵌入式系統的性能和成本。因此,在實際應用中使用C++開發嵌入式軟件的情況也較少。
下面本文將介紹一種不依賴編譯器的編程方案,它既具有C語言的執行效率,又支持面向對象特性。
1.2 特點
享受基本的面向對象特性,同時享受C語言的效率。
1) 本方案支持“類”的概念,包括私有成員變量和成員函數,并支持成員函數繼承和多態。
2) 類的定義是通過特殊的hpp頭文件來實現的,這個頭文件的編寫格式和C++基本相同。
3) 方案的重要部分是一個自動代碼轉換工具,它負責將hpp頭文件轉換成純C代碼。最終參加編譯的代碼都是純C代碼,因此,這個方案具有C語言所具有的代碼容量小和執行效率高等特點。
4) 方案內部使用C代碼框架實現類封裝,繼承和多態。
1.3 開發主要流程
(注:本文使用“demoClass”代表用戶定義的某一個“類”。“parentClass”代表這個類的父類。)
1) 編寫頭文件demoClass.hpp和源文件demoClass.c;
2) 轉換hpp頭文件代碼,生成中間C框架文件;
3) 編譯C文件,生成二進制文件。
2 方案設計
2.1框架
demoClass.hpp:頭文件,用于存放類的定義信息。
demoClass.c:源文件,用于存放類成員函數的實現。
demoClass.h:公共頭文件,向外提供函數接口和數據定義。
demoClass_priv.h:私有頭文件,僅供類內部的源文件使用,存放私有數據成員的定義及私有成員函數的聲明。
demoClass_info.c:源文件,用于存放類的信息結構體,以及類的構造函數定義。
testMain.c:測試文件,使用類的對象實例完成特定功能。
2.2源代碼編寫結構設計
2.2.1頭文件 .hpp VS C++頭文件.h
1) 所有public函數須都是虛函數,除了構造和析構函數。
2) 只支持private數據成員。
3) 與本類虛函數對應的實體函數在private下聲明。
4) 用以重載父類函數的實體函數在private下聲明。
2.2.2源文件 .c VS .cpp
1) 添加#include "demoClass_priv.h"私有成員內容。
2) 對象初始化函數和析構函數:
demoClassInit():對象初始化函數,各函數指針初始化。
demoClassDelete():析構函數,完成“析構”動作。
3) this: 成員函數指針;thisd: 數據成員指針
2.2.3 代碼范例
2.3 中間c代碼設計及其機制
代碼轉換工具將通過給予的hpp文件,自動生成C語言代碼框架,由他們實現各項面向對象的特性。
2.3.1 類結構
經過轉換后的C代碼分別使用兩個結構體存儲類的數據如圖2、圖3。
1) 使用demoClass 結構體存儲函數指針集以及私有數據成員結構體對象的地址。
Typedef struct {
void * pData;
errCode ( *Delete )(CMPHANDLE);
errCode ( *virtualFunc_parent1 )(CMPHANDLE);
errCode ( *virtualFunc_demo1 )(CMPHANDLE);} demoClass;
在成員函數內部,“this”指針指向demoClass對象。而thisd 的內容就是 this->pData。
2) 使用demoClass_data結構體存儲私有數據成員,由于其定義只在demoClass.c中,它并不暴露給外部類。
Typedef struct {
int privParentData1;
int privDemoData1;} demoClass_data;
雖然在對象demoClass中保存了對象demoClass_data的地址,但由于后者的定義并未公開,外部并不知道這個地址空間存儲了哪些數據,而成員函數是在demoClass.c中定義的,他們是“看”的見這張定義表的,所以只有本類的成員函數知道如何“按圖索驥”,這從一定程度上實現了隱藏類的私有成員。
3) 使用結構體ClassInfo的對象來存儲每一個類的信息,包括類名,父類ClassInfo對象指針,demoClass和demoClass_data結構體大小。每個類對應的ClassInfo對象是這個類唯一的全局變量,任何時候用戶可以調用類對應的“構造函數”制造出一個對象實例。
4) “this”和thisd指針
為了能使類的成員函數訪問本類的其他成員函數以及本類的私有數據,成員函數必須知道本對象的地址和數據成員地址,在C++中,這些是由C++編譯器內部提供this指針來實現的;在本方案中,每個成員函數都以第一個參數作為一個固定的輸入參數,來獲得本對象的地址,進而獲得數據成員的地址。this是demoClass型指針,thisd是demoClass_data型指針,它們指向各自的結構體對象。
5) 類的創建和消亡
① “構造函數”demoClassNew()
demoClassNew()是這個對象唯一暴露在外的全局函數。用戶可以通過調用它來創建對象。
demoClass* demoClassNew()
{demoClass* h= (demoClass*)ObjCreateAlloc(&demoClassInfo);
demoClassInit(h);
return h;}
a. 所有的類都通過調用ObjCreateAlloc (ClassInfo *)來實際創建對象,它依據給定的ClassInfo數據,獲得demoClass和demoClass?_data的結構體大小,分別給它們分配內存空間,并返回demoClass地址,而demoClass_data的地址則保存在demoClass之中。
ObjCreateAlloc()函數將在后文中介紹。
b. 類被創建之后,由demoClassInit()來進行初始化,基本的動作包括函數指針和成員變量的初始化,還可以有用戶自定義的動作。
② “析構函數”負責清理用完的數據或內存,并最終釋放對象自己的內存空間。
2.3.2 繼承
1) 派生類的數據繼承:成員函數指針和成員變量
派生類通過照搬基類數據的方式來實現函數和數據繼承。這種照搬的工作是由代碼轉換工具依據繼承關系完成的。在生成的C代碼中,用于存儲派生類數據的結構體demoClass,其前端數據和基類結構體parentClass的數據完全一 致 ,新 增 加 的 函數指針緊接其后。demoClass_data新增加的成員變量也同理。這樣,派生類就完全包含了一份與基類一致的公有函數指針和數據拷貝。當然,這些函數指針可能指向與基類不同的函數實體,其數據成員也可能存儲不同的內容,這取決于構造函數的實現。
2) 構造和析構函數的繼承
派生類的構造函數在自己的初始化函數開頭,先調用基類的初始化函數,它負責初始化繼承自基類的成員,在這個階段,派生類被裝扮成基類的樣子。然后派生類執行自己的初始化動作,在這個階段,派生類給新增加的函數成員和數據成員賦值,也可以修改來自基類的成員。
派生類的析構函數也分成兩部分,先清理自己新增加的成員,然后在末尾調用基類的析構函數,來清理來自基類的成員,最終釋放自己占用的內存。
3) 成員函數的繼承
與上節類似,被重載的成員函數,其新的函數實體可以包含對基類成員函數的調用,也可以不調用,完全重寫。
2.3.3 封裝
1) 通過以上的結構設計,C語言中間代碼實現了封裝性:
任何一個對象創建之后,只能通過這個對象的句柄訪問其公開的函數接口,外界看不見內部的數據,也無法通過合法的手段直接操作它們。而在對象創建之前,與這個類相關的全局元素只有兩個:全局變量demoClassInfo和全局函數demoClassNew( )。
2) 公共根類
在這套方案中,任何一個類的對象,其創建和消亡都會涉及到這個類基礎數據的處理,包括內存的分配和內部數據結構的初始化,這些是中間代碼的內容,用戶應無需關心它們,因此我們建立一個公共的虛基類rootObj,用它來封裝這些內部的操作。用戶如果要建立新的基類customClass,只需繼承這個虛基類,填寫好它對應的初始化函數customInit( )和析構函數customDelete()。根據代碼的繼承機制,新的類會遞歸調用對應的構造、析構函數,最終調用到虛基類rootObj的構造、析構函數,從而最終完成類的創建和消亡。
① 前面已經提到,類的構造函數demoClassNew()分成ObjCreateAlloc()和demoClassInit()兩個部分。
ObjCreateAlloc()函數把所有的類都當作虛基類來創建,包括給兩個結構體分配內存,并初始化pData指針。
CMPHANDLE ObjCreateAlloc(const ClassInfo* ci)
{rootObj* this;
rootObj_data* thisd;
this=malloc(ci->isize); //給demoClass分配內存
//給demoClass_data分配內存并把地址保存在pData中
this->pData = malloc(ci->dsize) ;
return this;}
② 虛基類的析構函數,負責釋放類結構所占用的內存
errCode rootObjDelete(CMPHANDLE h)
{ THIS_PTR_DEF;
free(h);
return SUCCESS;}
2.3.4 多態
本方案把所有成員函數都設置成虛函數,在內部通過函數指針的方式來實現。當派生對象要重載基類對象的某個成員函數的時候,就把對應的函數指針指向新的函數實現實體,這樣,一個同名的成員函數,根據類的不同完成著不同的操作,從而實現了多態。
2.4 代碼轉換工具的工作
總結如下:根據給予的demoClass.hpp文件,
1) 生成demoClass.h文件:
① include 父類的頭文件parentClass.h。
② 生成demoClass結構體,其中,把所有的成員函數,轉換成同名的函數指針,如果有父類,則把父類的成員函數指針放在開頭。
③ 聲明demoClassInfo變量和demoClassNew()函數。
2) 生成demoClass_priv.h文件:
① include 父類的頭文件parentClass.h。
② 生成demoClass_data結構體,其成員就是類的所有私有成員,如果有父類,則把父類的成員變量放在開頭。
③ 聲明父類的初始化和析構函數,及成員實體函數。
④ 聲明本類的初始化函數和成員實體函數。
3) 生成demoClass_info.c文件
① include本類的兩個頭文件 demoClass.h和demoClass_priv.h。
② 定義demoClassInfo變量,并賦值。
③ 定義本類的構造函數demoClassNew()。
這個代碼轉換工具由perl語言編程實現,可以集成在makefile中成為代碼預處理的一部分。
3 此方案和C++方案的對比
在linux環境下,功能完全相同的兩個程序:
4 結束語
通過此方案的轉換手段,可以在基本保持C語言性能的基礎上,開發出支持面向對象的C程序,而且不增加開發人員的額外負擔。它大大提高了程序的可復用性和可維護性,為開發結構更加復雜、代碼更加清晰易讀的嵌入式軟件系統提供了可能。在實際應用中,采用此方案的軟件代碼明顯比用原C語言實現的同樣功能的代碼更加受開發人員的歡迎。
參考文獻:
[1] 章遠陽,楊芙清,邵維中.C++語言的面向對象特性分析[J].計算機工程與應用,1992(9).
[2] 張泰樂,肖孫圣,倪宏.面向對象基本特性的c語言實現[J].微計算機應用,23(6).
關鍵詞:C語言程序設計;計算思維;抽象;自動化
美國卡內基?梅隆大學的周以真教授在2006年系統地提出了計算思維的概念[1]:計算思維指的是運用計算機科學的基礎概念進行問題求解、系統設計以及人類行為理解等一系列思維活動。其后,陳國良院士和李廉教授歸納出三種典型的科學思維,即以觀察和歸納為特征的實證思維,以推理和演繹為特征的邏輯思維,以抽象和自動化為特征的計算思維[2-3]。計算思維是計算機類課程的主要思維方式。
有關計算思維在程序設計類課程中的研究,已經引起很多學者的興趣[4-6]。這些研究雖然從案例設計和項目過程等角度做了有益探索,但卻忽略了對計算思維本質的討論。C語言程序設計課程中,我們采用李廉教授的觀點,即計算思維的本質是抽象和自動化。抽象指的是使用符號系統對問題進行精確而嚴格的描述;自動化指的是對這些符號系統施加一定操作并按照某種結構自動地執行。
一、C語言程序中的計算思維本質之一:抽象
有些C語言程序設計課程教學的一開始就提倡使用案例教學。這雖然能夠使得學生可以迅速進入實際編程環節并建立直觀感性認識,但案例教學由于往往出現“程序就是編程工具”的工具論現象,導致出現“只知其然,而不知其所以然”的學習后果,不利于學生的后續發展。
對于C語言程序來說,抽象指的是使用符號系統對求解問題進行精確而嚴格的描述,抽象的過程就是對實際系統建模的過程。實際上,程序是用來描述現實生活中某個實際存在的或不存在的系統。程序就是對系統的抽象。系統之所以存在,是因為系統具有一些關鍵特征和核心功能。程序中對系統特征進行抽象的就是操作對象,對系統功能進行抽象的就是函數。系統功能往往有多個且存在著復雜的調用關系。例如,求一個函數定積分的功能必然涉及求函數在某一個點的取值功能,如果該函數比較復雜且含有正弦、余弦和正切等三角函數,還需要繼續調用求這些三角函數值的功能,形成多級調用;有時函數執行過程中還需要調用本身,形成遞歸調用。
C語言程序中的操作對象分為變量和常量。常量是對系統中的取值不變的特征進行抽象,如圓的圓周率;而變量是對系統中取值可以改變的特征進行抽象,如圓的半徑。不管是哪類特征,都會有一個取值范圍以及所允許的操作。例如,對于課程成績,其取值范圍一般是從0~100,而允許對該特征進行的操作可以是加法和減法等算術操作以及大于和小于等比較運算;而對于課程名字這一特征,就不能進行加法和減法這樣的算術操作。C語言程序中用來對特征的取值范圍及允許的操作進行抽象的概念是數據類型。C語言程序中的抽象模塊如表1所示。
現實生活中,經常需要描述多個相同數據類型的一個系統特征,如所有同學的高等數學課程的成績,可以使用一維數組來進行描述;而描述多個不同數據類型的多個系統特征,如學生的姓名、學生的身高和學生的年齡等,可以使用結構體來進行描述;如果要描述多個相同數據類型的多個系統特征,如全班所有同學的高等數學和大學英語課程的成績,則可以使用二維數組來進行描述。
表1 C語言程序中的抽象模塊
C語言程序中的元素 現實生活中的元素
程序 系統
函數 系統功能
函數調用 功能調用
數據類型 常量 系統特征
變量
一維數組 多個相同類型的一個系統特征
多維數組 多個相同類型的多個系統特征
結構體 多個不同類型的多個系統特征
鏈表或結構體數組 多個不同類型的多個系統特征的集合
二、C語言程序中的計算思維本質之二:自動化
計算思維的另一個本質是自動化。自動化指的是對符號系統建模的各種元素施加一些操作,并按照某種順序的或非順序的結構自動地執行。對于C語言程序來說,自動化體現為函數內部的語句在EIP寄存器加法操作支持下順序自動地執行以及函數之間的調用在內存堆棧區支持下自動地進行跳轉。EIP是32位機的指令指針寄存器,用來存放下一條要執行的指令的地址。EIP寄存器中增加值的大小需要根據實際存儲指令的大小來確定。
對于C語言程序來說,自動化過程中執行的對象是語句。不同類型的語句,執行的結果和效用是不一樣的。例如,一個變量定義語句“int a”的執行結果是在內存中分配4個字節的空間,一個返回語句“return t”的執行結果是將程序的執行流程返回到主調函數中。這些語句的組合構成一個個函數,程序的執行就是在某個函數之中順序自動地執行以及在多個函數之間來回自動地跳轉。
既然程序的執行過程是在某個函數之中順序自動地執行以及在多個函數之間來回自動地跳轉,這種自動執行需要有相應的計算機軟件和硬件基礎。支持程序自動執行的軟件基礎是操作系統,支持程序自動執行的硬件基礎是計算機硬件結構,即馮?諾依曼原理的程序存儲思想。當用戶點擊執行按鈕后,程序被提交給操作系統來執行,可以不需要人為干預。此后,程序在操作系統中以進程的方式出現。操作系統協調內存、中央處理器和外存等硬件資源執行該進程。
函數中的語句之所以能夠一個接著一個順序地執行,主要依賴于EIP寄存器的加法操作。當一條指令執行完成之后,EIP寄存器在原有內容的基礎上再加上當前指令所占存儲空間大小,其內容便是下一條指令的地址。如此進行下去,就可以一個一個順序地執行函數中的語句。
程序控制之所以能夠在函數之間進行跳轉,主要依賴于操作系統管理的內存堆棧區。內存堆棧區是滿足“后進先出”操作約束的存儲區。當操作系統開始執行用戶提交的C語言程序時,首先開始從main函數執行,main函數的相關局部變量被壓入棧中;當執行到被調函數時,被調函數的相關局部變量再次被壓入棧中,程序控制轉移到被調函數,且操作只能對當前棧頂進行,而此時棧頂存儲的就是被調函數的相關局部變量;而當被調函數執行結束時,被調函數的相關局部變量從棧中退出,程序控制轉移到main函數繼續執行,此時棧頂存儲的是main函數的相關局部變量;當main函數執行結束時,main函數的局部變量從棧中退出,整個程序執行結束。下列程序執行時的堆棧變化過程示意如圖1所示。
#include "stdio.h"
double s(double r)
{ return r*r; }
int main()
{ double r;
double area;
r=2.0;
area= s(r);
printf("area=%f",area);
return 0;
}
圖1 函數調用過程的堆棧變化
自動化過程實際反映了C語言程序解決實際問題的算法流程。算法是解決某一問題的執行步驟。一般而言,使用C語言進行編程之前,需要進行相應的算法設計,即構思解決實際問題的思路和步驟。一旦這些步驟變成C語言程序語句并形成一個完整的程序,就可以提交給操作系統自動地執行這些步驟,這正是計算機解決問題的高效率的體現。
三、以計算思維為導向的C語言程序設計課程教學
1.教學內容
針對計算思維的抽象和自動化兩大本質特征,C語言程序設計課程的教學內容需要在原有的基礎上特別強調一些針對性的觀點。例如,C語言中的各種數據類型和數據結構可以完成實際系統中各種不同元素的抽象,一個函數之中的順序語句自動執行的基礎是EIP寄存器的加法操作,多個函數之間的來回自動跳轉的基礎是內存堆棧區的支持等。具體強調的觀點如表2所示。
表2 教學內容中需要強調的觀點
C語言程序設計
課程的內容 強調的觀點
C語言概述 程序是對系統的抽象
抽象過程就是C語言的建模過程
自動化過程反映C語言的算法流程
數據類型、表達式和語句 操作對象是對系統特征的抽象
語句是系統自動化執行的基本對象
控制結構 控制結構是問題求解步驟的抽象
函數中順序語句自動執行的基礎是EIP寄存器的加法操作
數組 一維數組是對多個相同類型的一個系統特征的抽象,多維數組是對多個相同類型的多個系統特征的抽象
函數 函數是對系統功能的抽象
函數調用是功能調用的抽象
函數之間的來回自動跳轉的基礎是內存堆棧區的支持
結構體 結構體是對多個不同類型的多個系統特征的抽象
指針 鏈表是多個不同類型的多個系統特征集合的抽象
2.教學方式
計算思維的本質是抽象和自動化。C語言程
序設計課程一般都是面向大一新生,理解抽象和自動化進而培養計算思維,對于還處在計算機學習起點的學生來說是比較困難的。
對于C語言程序來說,抽象過程實際就是運用C語言中各種符號對所描述系統的建模過程,培養抽象的計算思維方式就是培養使用C語言描述實際系統的思維過程。因此,可以通過啟發式教學方式引導學生思考如何使用C語言中的符號來描述系統。可以提出這樣的一系列問題:C語言中如何描述一個人的身高?如何綜合描述一個人的姓名、年齡和籍貫等?如何描述一個班中所有學生的高等數學成績?如何描述各路公共汽車站的網狀信息?通過啟發學生對這些問題的思考,讓學生所學的C語言中的各種符號不再“虛幻”,讓學生真正理解這些符號實際是一種建模元素,每種符號有著其特別的抽象描述能力。
對于C語言程序來說,理解自動化過程必須借助一些形象化的手段。例如,借助于Visual C++ 6.0平臺的單步調試功能,可以形象地演示上述C語言程序的自動化過程,如表3所示。
表3 C語言程序執行過程中EIP和ESP寄存器內容的變化
斷點 EIP寄存器內容 ESP寄存器內容 當前棧頂函數
r=2.0;語句 00401068 0013FF24 main函數
area=s(r);語句 00401076 0013FF24 main函數
return r*r;語句 00401020 0013FF18 s函數
printf("area=%f",area);語句 00401089 0013FF24 main函數
從表3可以看出,隨著EIP寄存器內容的增加,main函數中的語句順序自動執行,即從語句“r=2.0”到語句“area=s(r)”再到語句“printf("area=%f",area)”。ESP寄存器是另一個重要的寄存器,它始終存放棧頂的地址。隨著main函數對s函數的調用開始,棧頂工作函數由main函數變化為s函數;當s函數調用結束后,棧頂工作函數又由s函數回到main函數。
3.考核內容
針對C語言程序設計課程的計算思維培養要求,考核方式上必須從以考查語言的語法知識為主轉變為以考查學生的系統建模能力和算法設計能力為主。
系統建模能力的考查主要針對計算思維的抽象特征。例如,可以給出各種系統特征,考查學生使用數據類型進行描述的能力。
算法設計能力的考查主要針對計算思維的自動化特征。當然,C語言程序設計課程中涉及的都是一些如迭代、枚舉和排序等簡單算法。可將這些算法封裝成各種函數來進行調用,以考查函數中順序語句的執行以及函數間的伴隨參數傳遞的跳轉來理解自動化過程。因此,必須以簡單算
法設計和函數調用為重點考核內容,突出對函數接口設計和算法流程設計的考核。
參考文獻:
[1] Jeannette M. Wing. Computational Thinking[J]. Communications of the ACM, 2006, 49(3):33-35.
[2] 陳國良. 計算思維[J]. 中國計算機學會通訊,2012,8(1):31-34.
[3] 李廉. 計算思維――概念與挑戰[J]. 中國大學教學,2012(1):7-12.
[4] 張耀文. 基于計算思維的程序設計課程案例教學法研究[J]. 重慶電子工程職業學院學報,2012,21(3):149-150.
[5] 吳紹兵. 計算思維和程序設計能力的培養[J]. 計算機教育,2011(16):11-14.
摘要:現在單片機的程序設計,C51已經得到廣泛的推廣和應用,算是單片機的主流設計程序,甚至可以說作為單片機開發人員必須要掌握的一門語言了。本文簡要介紹了Franklin C51交叉編譯器的特點,較詳細地討論了C51語言程序設計的基本技巧及其與匯編語言程序的混合編程、中斷處理過程等實際問題。
關鍵詞:C51;C語言;編程
在研制單片機應用系統時,匯編語言是一種常用的軟件工具。它能直接操作硬件,指令的執行速度快。但其指令系統的固有格式受硬件結構的限制很大,且難于編寫與調試,可移植性也差。隨著單片機硬件性能的提高,其工作速度越來越快,因此在編寫單片機應用系統程序時,更著重于程序本身的編寫效率。而Franklin C51交叉編譯器是專為80C51系列單片機設計的一種高效的C語言編譯器,使用它可以縮短開發周期,降低開發成本,因此目前它已成為開發80C51系列單片機的流行工具。
一、C51的編程規范
(一)注釋
1.開始的注釋:
文件(模塊)注釋內容:
公司名稱、版權、作者名稱、修改時間、模塊功能、背景介紹等,復雜的算法需要加上流程說明;
函數開頭的注釋內容:
函數名稱、功能、說明 輸入、返回、函數描述、流程處理、全局變量、調用樣例等,復雜的函數需要加上變量用途說明 ;
2.程序中的注釋內容:
修改時間和作者、方便理解的注釋等。注釋內容應簡煉、清楚、明了,一目了然的語句不加注釋。
(二)命名:
命名必須具有一定的實際意義。
1.常量的命名:全部用大寫。
2.變量的命名:
3.結構體命名:
4.函數的命名:
函數名首字大寫,若包含有兩個單詞的每個單詞首字母大寫。
函數原型說明包括:引用外來函數及內部函數,外部引用必須在右側注明函數來源: 模塊名及文件名, 內部函數,只要注釋其定義文件名 ;
1.縮進:縮進以Tab為單位,一個Tab為四個空格大小。預處理語句、全局數據、函數原型、標題、附加說明、函數說明、標號等均頂格書寫。語句塊的“{”“}”配對對齊,并與其前一行對齊;
2.空格:數據和函數在其類型,修飾名稱之間適當空格并據情況對齊。關鍵字原則上空一格,如:
if ( ... ) 等,運算符的空格規定如下:“->”、“[”、“]”、“++”、“--”、“~”、“!”、“+”、“-”(指正負號),“&”(取址或引用)、“*”(指使用指針時)等幾個運算符兩邊不空格(其中單目運算符系指與操作數相連的一邊),其它運算符(包括大多數二目運算符和三目運算符“?:”兩邊均空一格,“(”、“)”運算符在其內側空一格,在作函數定義時還可據情況多空或不空格來對齊,但在函數實現時可以不用。
3.空行:程序文件結構各部分之間空兩行,若不必要也可只空一行,各函數實現之間一般空兩行
4.修改:版本封存以后的修改一定要將老語句用/* */ 封閉,不能自行刪除或修改,并要在文件及函數的修改記錄中加以記錄。
二、C51語言程序設計的基本技巧
C語言是一種高級程序設計語言,它提供了十分完備的規范化流程控制結構。因此采用C51語言設計單片機應用系統程序時,首先要盡可能地采用結構化的程序設計方法,這樣可使整個應用系統程序結構清晰,易于調試和維護。對于不同的功能模塊,分別指定相應的入口參數和出口參數,而經常使用的一些程序最好編成函數,這樣既不會引起整個程序管理的混亂,還可增強可讀性,移植性也好。
在程序設計過程中,要充分利用C51語言的預處理命令。對于一些常用的常數,如TRUE,FALSE,PI以及各種特殊功能寄存器,或程序中一些重要的依據外界條件可變的常量,可采用宏定義"#define"或集中起來放在一個頭文件中進行定義,再采用文件包含命令"#include"將其加入到程序中去。這樣當需要修改某個參量時,只須修改相應的包含文件或宏定義,而不必對使用它們的每個程序文件都作修改,從而有利于文件的維護和更新。
三、C51語言與匯編語言程序的混合編程
C51編譯器能對C語言源程序進行高效率的編譯,生成高效簡潔的代碼,在絕大多數場合采用C語言編程即可完成預期的目的。但有時為了編程直觀或某些特殊地址的處理,還須采用一定的匯編語言編程。它們必須有完整的約定,否則數據的交換就可能出錯。下面就以力源公司的10位串行A/D轉換器TLC1549 為例說明C語言程序與匯編語言程序的調用。
四、C51中斷處理過程
C51編譯器支持在C源程序中直接開發中斷過程,因此減輕了使用匯編語言的繁瑣工作,提高了開發效率。中斷服務函數的完整語法如下:
void函數名(void)[模式]
[再入]interrupt n [using r]
其中n(0~31)代表中斷號。C51編譯器允許32個中斷,具體使用哪個中斷由80C51系列的芯片決定。r(0~3)代表第r組寄存器。在調用中斷函數時,要求中斷過程調用的函數所使用的寄存器組必須與其相同。"再入"用于說明中斷處理函數有無"再入"能力。C51編譯器及其對C語言的擴充允許編程者對中斷所有方面的控制和寄存器組的使用。這種支持能使編程者創建高效的中斷服務程序,用戶只須在C語言下關心中斷和必要的寄存器組切換操作。
四、結語
C51編譯器不但可以縮短單片機控制系統的開發周期,而且易于調試和維護。此外,C51語言還有許多強大的功能,如提供豐富的庫函數供用戶直接調用,完整的編譯控制指令為程序調試提供必要的符號信息等等。總之,C51語言是廣大單片機開發人員的強有力的工具。
參考文獻:
[1]周立功.單片機實驗與實踐教程(三)[M].北京:北京航天航空大學出版社.2006
[2]柴鈺.單片機原理及應用[M].北京:西安電子科技大學出版社.2009