計算機達人成長之路之別告訴我你懂數組(1)

引言

程序員最希望什麼,當然是用最少的代碼,實現最多的功能,用簡單的代碼,實現最複雜的功能。換句話說就是又要馬兒跑,又不給馬兒吃草。只是,這可能嗎?在這個世界中,總是一分耕耘,一分收穫,一份代碼,一份功能,有哪種簡單迅速而又全面的東西嗎。

有!這個東西就是數組,只要條件滿足,使用數組可以優化代碼,簡化編程,減少錯誤,真不愧是編程偷懶,敏捷開發的必備良藥!

第一章        數組初體驗

計算機語言如雨後春筍般層出不窮,相互之間暗戰不止!老牌語言牢牢佔據排名榜前三,新的語言也在排名榜上突飛猛進。

不同的語言之間,總是或多或少存在着差異,所以開發者們眼花繚亂,不知道選擇何種語言爲好。

但是,如果能夠突破語言的迷霧,大家會發現,雖然不同的語言存在着區別,但是也有着一些共同的東西,數組恰恰就是其中之一。

1、整體與個體

數組是一個掩藏個性的地方。本來作爲一個變量,能夠擁有自己的名字是一件比較風光的事情,無論這個名字是一個字母還是若干單詞,總之給了開發者記住自己的機會。

不過可惜,有的變量沒有獨立的名字,若干變量合在一起,共同使用一個名字,這就是數組。

單個變量描述方式:int amt, accno, accdate, reqdate;

數組描述方式:int a[4]

對於數組中的變量而言,獨立擁有姓名是一個奢望,稱職他們的方式就是“在共同的變量名稱後面加上編號”,正如 “9527是他永久的編號”一樣,唐伯虎入華府後的稱呼就是“華府家丁[9527]”。

爲什麼要引入數組?這種撲滅個性的作法難道值得推廣嗎?使用具備個性的變量名稱的代碼應該更加容易閱讀理解纔對。比較如下兩段代碼:

  1. strcmp(szAmt, “100.00”);  
  2. strcmp(szAccno, “955990109000000”);  
  3. strcmp(accdate, “20110630”);  
  4. strcmp(reqdate, “20110629”);  
  5.  

代碼1-1

 

  1. strcmp(szBuf[0], “100.00”);  
  2. strcmp(szBuf[1], “955990109000000”);  
  3. strcmp(szBuf[2], “20110630”);  
  4. strcmp(szBuf[3], “20110629”);  
  5.  

 

代碼1-2

顯然,代碼1-1更加容易理解,大家可以猜測出,變量szAmt是金額,szAccno是賬戶,accdatereqdate都是日期。但若使用代碼1-2,歷時久遠之後,szBuf的含義可能也會隨着時間的推移而逐漸被淡忘,意圖再次看懂代碼,或者看懂別人的代碼,就必須經過一番寒徹骨才行。

既然如此,爲什麼還要產生“數組”這個東東,而且是很多語言中都使用了數組這個東東呢?那是因爲,數組不適合這種張揚個性的環境,它使用共性來掩蓋個性,體現的是“團結就是力量”,“兄弟齊心,其力斷金”。

作業1

1)已知某銀行某項目中使用了字符串szBuf記載交易報文信息,報文使用定長格式,分別記載了各個交易數據域,如下所示:

字符串第1位~19位代表了“賬戶”;長度19。

字符串第20位~27位代表了“姓名”;長度8。

字符串第28位~39位代表了“交易金額”;長度12。

字符串第40位~47位代表了“交易日期”;長度8。

字符串第48位~55位代表了“交易流水號”;長度8。

字符串第56位~59位代表了“交易狀態”;長度4。

字符串第60位~69位代表了“交易說明”;長度10。

程序要求將szBuf中的各個數據域拆分並分別存入其對應的變量中,對應關係如下所示:

char szAccno[20];              //代表“賬戶”

char szName[9];          //代表“姓名”

char szAmt[13];           //代表“交易金額”

char szDate[9];            //代表“交易日期”

char szLine[9];            //代表“交易流水號”

char szStatus[5];         //代表“交易狀態

char szBz[11];             //代表“交易說明”

請設計程序實現之,並在屏幕上每一行分別一各數據域以及該域的序號,爲了並於觀察,可用“【】”包含域數據。

比如字符串:

szBuf[]="9559901010008888888木鴻飛  600.00      20110630063001230000測試一次  ";

則拆分後存入結果如下表所示:

變量

含義

內容(爲表明效果,特增加“【】”,另外符號“_”代表空格)

szAccno

賬戶

9559901010008888888

szName

姓名

【木鴻飛__

szAmt

交易金額

600.00______

szDate

交易日期

20110630

szLine

交易流水號

06300123

szStatus

交易狀態

0000

szBz

交易說明

【測試一次__

程序運行結果應該如下:

1號域, 【9559901010008888888

2號域, 【木鴻飛 

3號域, 【600.00     

4號域, 【20110630

5號域, 【06300123

6號域, 【0000

7號域, 【測試一次 

2)在程序設計好之後需求發生變更,報文格式變更如下:

字符串第1位~8位代表了“交易日期”;        //位置提前

字符串第9位~20位代表了“交易流水號”;     //位置提前,長度加長

字符串第21位~39位代表了“賬戶”;

字符串第40位~47位代表了“姓名”;

字符串第48位~63位代表了“交易金額”;      //長度加長

字符串第64位~71位代表了“傳票號       //新增域

字符串第72位~75位代表了“交易狀態”;

//取消了“備註”域。

字符串實例和變量情況如下:

char szBuf[]="201106300630123456789559901010008888888木鴻飛  600.00          999912340000";

char szAccno[20];              //代表“賬戶”

char szName[9];          //代表“姓名”

char szAmt[17];           //代表“交易金額”

char szDate[9];            //代表“交易日期”

char szLine[13];          //代表“交易流水號”

char szStatus[5];         //代表“交易狀態

char szBill[9];                     //代表“傳票”

程序1-1

【特別提示】在查閱程序前,請各位讀者務必獨立思考並且完成上述試題,然後再來閱讀程序。

首先使用函數strncpy分別複製數據,然後分別在每個字符串後面增加結束符0,最後再分別顯示出來即可,程序代碼如下所示:

 

  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3.    
  4. int main(int argc, char *argv[])  
  5. {  
  6.     char szBuf[]="9559901010008888888木鴻飛  600.00      20110630063001230000測試一次  ";  
  7.     char szAccno[20];             //代表"賬戶"  
  8.     char szName[9];                //代表"姓名"  
  9.     char szAmt[13];                 //代表"交易金額"  
  10.     char szDate[9];                  //代表"交易日期"  
  11.     char szLine[9];          //代表"交易流水號"  
  12.     char szStatus[5];      //代表"交易狀態"  
  13.     char szBz[11];           //代表"交易說明"     
  14.     /* 以下爲處理代碼 */   
  15.     strncpy(szAccno, szBuf, 19);  
  16.     szAccno[19]=0;  
  17.     strncpy(szName, szBuf+19, 8);  
  18.     szName[8]=0;  
  19.     strncpy(szAmt, szBuf+27, 12);  
  20.     szAmt[12]=0;  
  21.     strncpy(szDate, szBuf+39, 8);  
  22.     szDate[8]=0;  
  23.     strncpy(szLine, szBuf+47, 8);  
  24.     szLine[8]=0;  
  25.     strncpy(szStatus, szBuf+55, 4);  
  26.     szStatus[4]=0;  
  27.     strncpy(szBz, szBuf+59, 10);  
  28.     szBz[10]=0;  
  29.          /* 以下爲打印代碼 */ 
  30.     printf("第1號域, 【%s】\n",  szAccno);  
  31.     printf("第2號域, 【%s】\n",  szName);  
  32.     printf("第3號域, 【%s】\n",  szAmt);  
  33.     printf("第4號域, 【%s】\n",  szDate);  
  34.     printf("第5號域, 【%s】\n",  szLine);  
  35.     printf("第6號域, 【%s】\n",  szStatus);  
  36.     printf("第7號域, 【%s】\n",  szBz);  
  37.     system("PAUSE");      
  38.     return 0;  
  39.  
  40. }  
  41.  

 

代碼1-1

 

【程序說明】以下代碼在Windows XP Dev C++下編譯通過,如果在DOSUnix/Linux下設計,可以取消“system("PAUSE");”一行。

【特別提示】如果你在之前沒有獨立設計程序,而是直接看到這裏,請將上述代碼輸入電腦,調試通過後再接着閱讀。

【程序分析】

上述程序中存在三宗罪。

第一宗罪:代碼冗長。

其實很無奈,上述程序代碼太不整潔,疑式重複代碼太多。以“處理代碼”部分爲例,其實大部分代碼遵循如下規則:

    strncpy(字符串變量, szBuf+起始位置, 長度);

    szBz[長度]=0;

乍一看很可以使用循環方式來解決,但其實不然,因爲每一個“字符串變量”、“起始位置”和“長度”就是不一樣,就是不能整合到循環之中。

同理“打印代碼”部分也是一樣,想整合而不能。

第二宗罪:容易出錯。

在上述代碼中,每個數據域的起始位置都是在計算之後顯示的寫入代碼中,如果某一個地方出現失誤,則將導致後續一連串的錯誤。

比如下述代碼:

    strncpy(szName, szBuf+19, 8);

    szName[8]=0;

    strncpy(szAmt, szBuf+27, 12);

其中szAmt的“起始位置”爲szName的“起始位置+長度”,以後的都是前一個“起始位置+長度”,這個過程需要手工完成,倘若計算錯誤或者輸入錯誤,則可能引起後續一系列的錯誤。

第三宗罪:代碼重用效果差。

按照題設的需求,報文格式會發生變化,此時需要更改全部的“處理代碼”部分,程序的重用性能太差了。

作業2

更改代碼1-1,使之捷徑、可重用,不易出錯。

                                   

                                        前一篇     目錄   後一篇

                             

PS:歡迎跟帖,寫下自己的作業心得。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章