计算机达人成长之路之别告诉我你懂数组(1)

  1. 云栖社区>
  2. 博客>
  3. 正文

计算机达人成长之路之别告诉我你懂数组(1)

技术小胖子 2017-11-08 01:43:00 浏览612
展开阅读全文

引言

程序员最希望什么,当然是用最少的代码,实现最多的功能,用简单的代码,实现最复杂的功能。换句话说就是又要马儿跑,又不给马儿吃草。只是,这可能吗?在这个世界中,总是一分耕耘,一分收获,一份代码,一份功能,有哪种简单迅速而又全面的东西吗。

有!这个东西就是数组,只要条件满足,使用数组可以优化代码,简化编程,减少错误,真不愧是编程偷懒,敏捷开发的必备良药!

第一章        数组初体验

计算机语言如雨后春笋般层出不穷,相互之间暗战不止!老牌语言牢牢占据排名榜前三,新的语言也在排名榜上突飞猛进。

不同的语言之间,总是或多或少存在着差异,所以开发者们眼花缭乱,不知道选择何种语言为好。

但是,如果能够突破语言的迷雾,大家会发现,虽然不同的语言存在着区别,但是也有着一些共同的东西,数组恰恰就是其中之一。

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,使之捷径、可重用,不易出错。




 本文转自 zhuyunxiang 51CTO博客,原文链接:http://blog.51cto.com/zhuyunxiang/600261,如需转载请自行联系原作者





网友评论

登录后评论
0/500
评论