您的位置:首页 > 其它

关于大学生如何进行编码规范的火拼

2012-08-21 11:40 183 查看

关于大学生如何进行编码规范的火拼

分类:
程序人生 2009-04-24 13:28
4677人阅读
评论(21)
收藏
举报

发起人:肖舸

参与人:CSDN学生大本营的C/C++的朋友

转载人:老紫竹

原地址:http://student.csdn.net/space.php?uid=39028&do=thread&id=287

加入讨论的方式: http://student.csdn.net/invite.php?u=2324&c=47889c9260258df7
肇事者:吉首大学 邓嘉(C/C++学生)

男主角:肖舸,韩卫平

配 角:赵洪亮 陈建树 周海鑫

事情起因:老肖经常被同学问代码的事情,可这些代码在他看来简直是“太难看懂”了,老紫竹的家所以有此感慨。

经过: 可不可以拜托各位一件事情?

很多同学喜欢把代码拿上来,询问。

不过,肖老师是程序白痴,看不懂同学们的代码。

举个例子

这是某位同学的代码,我仅仅是举例子,不是针对这位同学,希望不要见怪哈。

[cpp]
view plaincopyprint?

#include<iostream> 这个看得懂

using namespace std; 这个也知道
int main() 这个简直太懂了
{
int num=1997; num请问是准备做什么的?
long fn[10000]={0}; fn请问是做什么的?10000是什么意思?
fn[0]=fn[1]=1; 为啥0和1这两个单元要赋初值?为啥是1?
int i,j; 这个能猜出来,这是循环变量。
for(i=2;i<=num;i++) 为啥是2开始,而不是0?
{
for(j=1;j<=fn[0];j++) 第二重循环式做啥的?fnp[0]不是1吗?为啥不写成1?
fn[j]*=i; 这个*是什么意思?
for(j=1;j<=fn[0];j++) 同样的问题
if(fn[j]>=10000) 10000是什么意思?
{
fn[j+1]+=fn[j]/10000; 这两行是什么意思?
fn[j]%=10000; 这里求出的余数是什么意思?
}
if(fn[j]>0) 为啥是大于0?可不可能小于0?
fn[0]++;
}
for(i=fn[0];i>0;i--) 为啥从后向前打印?
cout<<fn[i];
return 0;
}

[cpp]
view plaincopyprint?

int SafePrintf(char* szBuf,int nMaxLength,char *szFormat, ...)
{
int nListCount=0;
va_list pArgList;
if (!szBuf) goto SafePrintf_END_PROCESS;
va_start (pArgList,szFormat);
nListCount+=Linux_Win_vsnprintf(szBuf+nListCount,
nMaxLength-nListCount,szFormat,pArgList);
va_end(pArgList);
if(nListCount>(nMaxLength-1)) nListCount=nMaxLength-1;
*(szBuf+nListCount)='/0';
SafePrintf_END_PROCESS:
return nListCount;
}

int SafePrintf(char* szBuf,int nMaxLength,char *szFormat, ...)
{
int nListCount=0;
va_list pArgList;
if (!szBuf) goto SafePrintf_END_PROCESS;
va_start (pArgList,szFormat);
nListCount+=Linux_Win_vsnprintf(szBuf+nListCount,
nMaxLength-nListCount,szFormat,pArgList);
va_end(pArgList);
if(nListCount>(nMaxLength-1)) nListCount=nMaxLength-1;
*(szBuf+nListCount)='/0';
SafePrintf_END_PROCESS:
return nListCount;
}


这是一段变参的字符串打印函数,我也没有加任何注释,如果有看不懂的同学,请直接向我询问。

里面使用的是匈牙利命名法。

我们的规定,程序中永远不准使用直接的常数。任何常数必须用宏表明其含义。

只准有两个地方出现常数

for(i=0;i<n;i++)

while(1)

0,1是唯一被允许使用的常数。

大家看到的,也是唯一被允许写出的循环,其他任何循环形式,递减,老紫竹的家do while,不允许使用。

关键算法不允许直接写出,只准使用宏表示,宏名表示其真实含义。

每个计算宏内只允许出现1个四则运算符号,且不管是何种运算,均必须使用()包围。

每个变量和函数名必须直接表意。

main函数是组织者,不允许直接实现功能,永远只能调用别的函数。

* 武汉大学珞珈学院 卢阳(C/C++学生)

老师的这篇帖子让我想起了软考下午试题的一些不科学的地方。比如说一个很简单的数据结构的题目,如果整个程序都让我们自己编码,那可以说事一件相对幸福的事了,但它恰恰不这样做,一段代码5个空,让我们自己填。老紫竹的家这下子题目难度就陡增了。为什么?代码里一系列乱七八糟的变量,m,n,i,j,也不写注释。虽然考试的时候大家都是如此,从某种意义上来说是平等的。但还是忍不住抱怨下。

* 韩卫平(C/C++老师)

对于新手而言,能作出来就可以了,那么多条条框框只会打击积极性。

* 吉首大学 邓嘉(C/C++学生)

呜呜~~

上面的就是我的代码。

本来想写注释的,但是要写的话,太多了,而且还描述不清楚,故就省略了。呜呜,看来要改了........

顺便去了解匈牙利命名法。

* 北邮(软件工程) 陈建树(C/C++学生)

匈利利命名法有大小写,又很长,输入速度巨慢,肖老师有什么好的解决方法?平时写代码我跟邓兄差不多。。。。汗

* 韩卫平(C/C++老师)

用不用匈牙利命名法无所谓,关键是易读。

我倒是不提倡用 匈牙利命名法。

* 北邮(软件工程) 陈建树(C/C++学生)

韩卫平(C/C++老师): 用不用匈牙利命名法无所谓,关键是易读。

我倒是不提倡用 匈牙利命名法。

我试过一段时间的按意义命名,缩写的厉害了自已也看不懂,写长了输入量太大,老紫竹的家肖老师平时是怎么命名的?

* 韩卫平(C/C++老师)

length count size之类的,要是英文不好可以用中文,反正VS2008支持中文变量,函数名啥的。都可以用中文

在公司做的话就按照公司的标准来、

* 吉首大学 邓嘉(C/C++学生)

我原来用来c++入门的书,是Y.Daniel Liang的

《Introduction to Programming with C++》。由于里面的命名都是按意义的,于是有很长一段时间,都是按照那样来的。但是,基本上每次都要开个金山词霸去查询单词,都要拿个笔记本记单词。后来就没有坚持了~~

* 南京大学 王明强(Java学生)

对程序目的和关键的变量和语句简要注释一下不是很好吗,易读易写

* 武汉大学 周海鑫(Java学生)

想成为一个合格的程序员,平时必须要注意养成代码的规范性。

* 武汉大学 周海鑫(Java学生)

代码规范是一个程序员最低最基本的要求。

* 上海海天信息系统工程有限公司 常健(Java爱好者)

我觉得越是新手,越是要养成一个良好的编码习惯。第一篇受影响的文章是林锐博士的高质量 C/C++

至今有段时间了,不过我希望大家都能要成一个好的编码习惯,LZ老师说的不错

* 同济大学 挽弓挽强(C/C++学生)

可以用visual assist啊,不知道你用过没,第一次输入一个变量之后,比如int iLength,第二次只要输入il,编译器会自动让你选择是否你所要打的是iLength

* 肖舸

一开始习惯不养好,永远写不出工程型代码。

就是喜欢它规矩多。

比如,一个变量,是内部变量,m_打头,如果想让它变成全局的,需要显式修改g_打头,老紫竹的家这实际上是逼着程序员重新过一遍自己的代码,想想,这么改有没有必要?能不能不改?改了会有什么不好的恶果?

另外,匈牙利命名法从命名上能看出属性。

比如m_pQueue->AddLast,大家能知道什么意思吗?

如果写成m_Queue->AddLast,直接看就知道程序出问题了,因为不是指针变量,不允许使用->,只能用.

程序员不怕多敲字的,怕的是自己看不到bug。

那这个程序在很多Linux的编辑器中将不可编辑,因为都是乱码。

其实我考软考不及格的。呵呵。

我比较喜欢写赚钱的代码,不太喜欢写考试的代码。

[cpp]
view plaincopyprint?

typedef struct _CListen_ListenAcceptTask_Param_
{
Linux_Win_SOCKET m_nSocket;
CListen* m_pThis;
}SCListenAcceptTaskParam;
const ULONG SCListenAcceptTaskParamSize=sizeof(SCListenAcceptTaskParam);

[cpp]
view plaincopyprint?

#include<iostream> 这个看得懂

using namespace std;  这个也知道
int main() 这个简直太懂了
{
int num=1997;              num请问是准备做什么的?
long fn[10000]={0};          fn请问是做什么的?10000是什么意思?
fn[0]=fn[1]=1;             为啥0和1这两个单元要赋初值?为啥是1?
int i,j;  这个能猜出来,这是循环变量。
for(i=2;i<=num;i++)  为啥是2开始,而不是0?
{
for(j=1;j<=fn[0];j++)  第二重循环式做啥的?fnp[0]不是1吗?为啥不写成1?
*** 此处没有大括号,因此,for语句的循环范围仅限于下面一句话,
但是看缩进关系,好像不对。
fn[j]*=i;  这个*是什么意思?
for(j=1;j<=fn[0];j++)  同样的问题
***此处的问题同上,也是循环体没有大括号,结果仅包含下面一句话
if(fn[j]>=10000)  10000是什么意思?
{
fn[j+1]+=fn[j]/10000;  这两行是什么意思?
fn[j]%=10000;  这里求出的余数是什么意思?
}
if(fn[j]>0)  为啥是大于0?可不可能小于0?
fn[0]++;
}
for(i=fn[0];i>0;i--)  为啥从后向前打印?
cout<<fn;
return 0;
}

#include<iostream> 这个看得懂
using namespace std;  这个也知道
int main() 这个简直太懂了
{
int num=1997;              num请问是准备做什么的?
long fn[10000]={0};          fn请问是做什么的?10000是什么意思?
fn[0]=fn[1]=1;             为啥0和1这两个单元要赋初值?为啥是1?
int i,j;  这个能猜出来,这是循环变量。
for(i=2;i<=num;i++)  为啥是2开始,而不是0?
{
for(j=1;j<=fn[0];j++)  第二重循环式做啥的?fnp[0]不是1吗?为啥不写成1?
*** 此处没有大括号,因此,for语句的循环范围仅限于下面一句话,
但是看缩进关系,好像不对。
fn[j]*=i;  这个*是什么意思?
for(j=1;j<=fn[0];j++)  同样的问题
***此处的问题同上,也是循环体没有大括号,结果仅包含下面一句话
if(fn[j]>=10000)  10000是什么意思?
{
fn[j+1]+=fn[j]/10000;  这两行是什么意思?
fn[j]%=10000;  这里求出的余数是什么意思?
}
if(fn[j]>0)  为啥是大于0?可不可能小于0?
fn[0]++;
}
for(i=fn[0];i>0;i--)  为啥从后向前打印?
cout<<fn;
return 0;
}


顺便去了解匈牙利命名法。

如果你要说的话,用人的话都说不清楚,或者说出来,人都听不懂,请问计算机还能听懂不?

写程序,我的感觉就是做文章。

写一段话,就是让人看了,知道先做什么,再做什么,最后得到什么,得到的结果有什么意义。

写一段程序,就是让计算机看了,知道先做什么,老紫竹的家再做什么,最后得到什么,得到的结果有什么意义。

有差别吗?

* 南京工业大学Mars工作室 夏金龙(Java学生)

嗯,受教了....以后写代码尽量标准!

* 徐浩然(C/C++老师)

这些都是最基础的东西哦。如果你写的代码别人看不懂的话,你将来也会看不懂的。

* 北邮(软件工程) 陈建树(C/C++学生)

恩,看来以后我一定要强迫自己编码规范

* 北邮(软件工程) 陈建树(C/C++学生)

以前一直用vc2008速成版,用不了,前几天换成VC6了,装了visual assist,但还没用过,谢谢你啊

* 吉首大学 杜飞(游戏开发学生)

对 应该有一个好习惯

* 赵洪亮(C/C++菜鸟)

其实我还是觉得匈牙利命名法比较诡异

没有长时间的经验是很难看懂的

Java和C#里的命名是最接近自然语言的 缺点是名字太长

* 肖舸

Java和C#里的命名是最接近自然语言的 缺点是名字太长

你不喜欢你的老板,但是你得从老板手里赚钱,这就是道理。

喜欢是一回事,赚钱是另外一回事,找既喜欢,又赚钱的事情做,太难了。

呵呵,我从内心讲,最开始也不喜欢匈牙利命名法的,不过它能帮我赚钱,养活老婆和孩子,这就够了。

命名其实是越长越好的,因为表意性很好,大家看了像看文章一样,一目了然。

我有些代码,10年了,还在用,就是因为当初写的时候,变量名,老紫竹的家函数名,写得很清晰。我到现在一看就明白,又没什么bug,为啥不用呢?

上文中举出的例子代码,就是2002年写的,到现在都还在用。7年了。

很多人忌讳写长名字,主要原因,可能还是怕敲起来麻烦。

但现代的IDE编辑器,包括VC,其实有很方便的拷贝功能,事实上,我的变量名,函数名,都只敲一遍,以后全部是拷贝+粘贴。

这样还有一个好处,就是我写的代码,永远不会有笔误,不会因为我敲错一个字符而导致bug。用一个好的习惯,解决整整一个方面的bug,你说划算不划算?

当然也有一个坏处啦,如果一个名字中的英文拼错了,完了,这个拼写错误将会从头贯穿到尾,让人看起来很难受。呵呵。

不过要解决也很简单,就是一个全局替换就好了。

名字长了,不容易重名,全局替换也就方便了,免得一个替换,n多的bug。这也是好处。

我写的最长的名字,237字符吧,VC和gcc好像都支持超过255字符的名字。

名字还是长点好。

嗯,当然还有一个坏处,就是我键盘左边的ctrl键,总是被磨得光溜溜的,也第一个坏,很容易坏。

那有啥办法,一个键盘20块钱,批发17,买5个放家里搁着好了。

* 学生大本营辅导员 张媛(Java爱好者)

肖老师讲课真幽默

* 肖舸

严肃点,我们这打劫呢!

* 太原理工大学 刘川平(C/C++学生)

编码规范很重要,深有体会。呵呵

* 韩卫平(C/C++老师)

写程序为啥非要在乎条条框框?

写程序第一点是易于维护,不用匈牙利命名就不易于维护了?老紫竹的家我见过7000行的一个函数,命名规则,代码非常规范。你说这个代码是好代码么?

一个类一个函数多到用匈牙利命名法来区分成员的地步的时候,只能说名设计上有问题。造成所谓的万能类,万能函数。这时候就得依靠合理的命名法,来管理不同类型不同功能的变量。

* 肖舸

如果一个函数写7000行,这个函数基本上就不可维护了。

我们一般规定,每个程序员的最大函数行数,和自己身高的厘米数相同。

呵呵。

哇,7000行,这就是传说中的,一个函数写两米多高啦。

* 韩卫平(C/C++老师)

对于学习的时候来说,我是非常不建议使用visual assist。我见过不少程序员用这个,然后不小心删了一个;号,就在那里找BUG,找了半个小时都没找出来。我直接看到在那里少了一个;号。老紫竹的家都写代码几年了,语法都错误都不能快速的解决。

学习的时候别偷懒,记住写的代码,很有帮助。

不知道肖老师在没有visual assist的情况下能写多少代码不出编译错误?

* 肖舸

我有点点好奇哈,随便问问。

请问您现在在哪家公司高就?

bug,能看见,就不叫bug。

* 韩卫平(C/C++老师)

怎么了,要来检查工作?

* 肖舸

不敢,随便问问,可以不回答的。

呵呵。

不打不相识哈。

交个朋友。

* 韩卫平(C/C++老师)

问题是,看不出来。类声明最后少了一个;然后错误报到cpp文件中。

以前我们有个老大,用VIM写程序,没有任何智能提示,完全自己敲代码,敲多少行都不会出啥问题,没编译错误,没逻辑错误。最常见的场景是帮新手改代码,改好直接就说“行了可以用了”。老紫竹的家不用编译调试。那人编译测试,果然没问题。

* 肖舸

你老大很牛啊。

不过,这是艺术,不是科学,艺术是不具备可复制性的。

在公司里面的商用工程实践中,我们强调科学,即能迅速在团队内部复制一种能力,最快速度把团队的开发水平拉平,避免出现短板现象,即由于某个程序员的失误,导致整个项目进度延期,最后大家受损。

因此,我们团队中,一般不太强调个性化,强调标准化,一个算法,如果库里面有提供,就强迫使用,不允许自己开发,如果库代码性能不行,自然有负责库维护的人完成。

同理,一个算法,如果两个模块都用到,ok,先写完的入库,第二个不准写,用第一个的。

大家的代码,要求千篇一律,使用统一的格式,使用统一的命名法,使用统一的结构原则。

这也许会抹杀程序员的创造性,但是,在项目压得紧的时候,团队合作开发,不这么做,会死人的。

我就是用这种方法,去年做的一个服务器集群,几十万行代码写下来,9轮测试,只有51个bug,属于C和C++这边的,只有7个bug。

我想,就算是你老大,也喜欢这么低的bug率。

* 赵洪亮(C/C++菜鸟)

呵呵,我从内心讲,最开始也不喜欢匈牙利命名法

Visual Assist X还是很好用的,现在的IDE都有代码提醒功能

所以打错变量名的问题很少出现的

只是觉得太长的变量名会使代码行变得老长

反而影响可读性

匈牙利命名现在我也习惯了,但是有时候忘了去遵守

比如strFileName我经常性的忘写str 写成fileName

szBuffer写成bufferSize,虽然不符合规范

但是易读性还是有的

* 韩卫平(C/C++老师)

在公司里面的商用工程实践中,我们强调科学,老紫竹的家即能迅速在团队内部复制一种能力,最快速度把团队的开发

扯远了

我的意思就一点,对于新手而言,没必要遵守公司的那一套。

只要写出来的代码易读,别人一看就明白的那种即可。

* 肖舸

匈牙利命名

代码横向变长,请多回行。

fileName可以,只要表意性够了就好了。

szBuffer写成bufferSize,就太过分了,还不如不表意,你完全在误导嘛。

* 四川大学锦江学院 黄启银(C/C++学生)

良好的编程风格,易于检查错误,应该养成的良好的风格。

* 肖舸

对于新手而言,还是有必要考虑学出来以后,是要找工作的。

嗯,家里面很有钱,把程序纯粹当爱好的,这辈子不需要工作的,确实可以不按照公司里面的规矩来。

* 武汉大学珞珈学院 卢阳(C/C++学生)

没办法啊,学校太烂。

如今都在寝室看书,自己动手写代码。虽然是计科系,但在系里真正由交流的就一个同学。

我们系里的风气是这样的,玩的人玩的太彻底,陷在游戏里。学的人都为奖学金。现在大三,在我看来考研能成功的人顶多5%,但是居然有80%人参加考研。

我是拒绝考研的那类人,因为学校招牌不硬,时间也不多,老紫竹的家如果还把那么多时间投资在数学,政治,和专业理论上,就基本没时间动手了。万一考不上,那形式就相当被动了。想出去实习,但没本本不行吧?你再怎么说你做过多少事,连一个像样的证书都拿不出来,人家不甩呀。

所以被逼去考那个考试,总感觉这个考试不太具备说服力。但在中国就是这样,呵呵。考考也无妨吧,不过挂了后浪费的120块钱够自己心疼一会了。

* 肖舸

如今都在寝室看书,自己动手写代码。虽然是计科系,但在系里真正由交流的就一个同学。

我们系里的风气是这样的,玩的人玩的太彻底,陷在游戏里。学的

这倒是中肯之言。

必要时,贴贴金是对的。

进公司做事,需要一些证书做敲门砖。

不过,既然学了,努力学到真本事,证书这么考,也有道理,其实给的条件越少,越能锻炼人,当锻炼好了。

考挂了怕什么?再来就好了。

人生一世,三起三落不到头。

* 武汉大学珞珈学院 卢阳(C/C++学生)

普罗通信西安有限公司 肖舸(C/C++老师): 这倒是中肯之言。

必要时,贴贴金是对的。

进公司做事,需要一些证书做敲门砖。

不过,既然学了,努力学到真本事,证书这么考,也有道理,老紫竹的家其实给的条件越少,越能锻炼人,当锻炼好

恩,我是这么想的。

很多人怕输,觉得输了后没面子。感觉那些人不太像是为自己而活着,更想是活的给别人看的。这样活着太累。其次,当你静下心来会发现,就算自己失败后,敢取笑你的人又真正有多少,可能都没人会关注你。

不以自我为中心就不会怕输。

* 吉首大学 邓嘉(C/C++学生)

[cpp]
view plaincopyprint?

#include<iostream>

using namespace std;
int main()
{
int num=1997; //num——要求的阶乘的原始数数

int fn[1000]={0}; //fn存储一个1000位数的整数数组

fn[0]=1; //fn[0]用来存放“位数”,初始值为1。

fn[1]=1; //fn[1]用来表示第一个数。

int i,j; //循环变量。

for(i=2;i<=num;i++) //i从2开始,是因为fn[1]已经定义了为1。就是1!,故从2开始算阶乘。

{
for(j=1;j<=fn[0];j++) //数组中内容运算,即:把每一个内容不为0的数组元素*i;

//fn[0]不是1吗?为啥不写成1?因为fn[0]用来存放位数,会随着后面的

//运算而增加变量值

fn[j]*=i;
for(j=1;j<=fn[0];j++) //这个循环,用来遍历整个数组

if(fn[j]>=10000) //我以“10000”为一“位”,即:满10000,往前面进一位。

{
fn[j+1]+=fn[j]/10000; //如果fn[j]的值大于了10000,则进位到fn[j+1]

fn[j]%=10000;
/*这里求出的余数指: 嗯,打个比方 “ 5*9 ” 得到fn[j]=45; 把45/10得到的值加到fn[j+1]上,45%10得到的值赋给fn[j]。即:得到 fn[j+1]=4,fn[j]=5 (前提是fn [j+1]原本的值为0,在这里是以十进制,我的程序里面采用10000进制,满10000了,进一位)*/
}
if(fn[j]>0) //为啥是大于0?可不可能小于0?此处的作用:如果有进位,则fn[0]自增。

// 因为fn[0]是用来表示位数的。

fn[0]++;
}
for(i=fn[0];i>0;i--) //为啥从后向前打印?因为最高位在最前面的非0值数组元素中。

cout<<fn;
return 0;
}

#include<iostream>
using namespace std;
int main()
{
int num=1997; //num——要求的阶乘的原始数数
int fn[1000]={0}; //fn存储一个1000位数的整数数组
fn[0]=1; //fn[0]用来存放“位数”,初始值为1。
fn[1]=1; //fn[1]用来表示第一个数。
int i,j; //循环变量。
for(i=2;i<=num;i++) //i从2开始,是因为fn[1]已经定义了为1。就是1!,故从2开始算阶乘。
{
for(j=1;j<=fn[0];j++) //数组中内容运算,即:把每一个内容不为0的数组元素*i;
//fn[0]不是1吗?为啥不写成1?因为fn[0]用来存放位数,会随着后面的
//运算而增加变量值
fn[j]*=i;
for(j=1;j<=fn[0];j++) //这个循环,用来遍历整个数组
if(fn[j]>=10000) //我以“10000”为一“位”,即:满10000,往前面进一位。
{
fn[j+1]+=fn[j]/10000; //如果fn[j]的值大于了10000,则进位到fn[j+1]
fn[j]%=10000;
/*这里求出的余数指: 嗯,打个比方 “ 5*9 ” 得到fn[j]=45; 把45/10得到的值加到fn[j+1]上,45%10得到的值赋给fn[j]。即:得到 fn[j+1]=4,fn[j]=5 (前提是fn [j+1]原本的值为0,在这里是以十进制,我的程序里面采用10000进制,满10000了,进一位)*/
}
if(fn[j]>0) //为啥是大于0?可不可能小于0?此处的作用:如果有进位,则fn[0]自增。
// 因为fn[0]是用来表示位数的。
fn[0]++;
}
for(i=fn[0];i>0;i--) //为啥从后向前打印?因为最高位在最前面的非0值数组元素中。
cout<<fn;
return 0;
}

上课回来看到回复,于是补充了。感觉好多的地方都没有写明白。

(嗯,上传的时候,排版不知道会不会被打乱)

* 华东交通大学 无为(C/C++学生)

写大家看地懂的代码

* 武汉科技大学 赵孜泷(Java学生)

也对.以后必须说明

分享到:

上一篇:大学该如何渡过这几年的个人观点?

下一篇:大话IT技术人员的几个层次
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: