全球前十强,年薪15万的面试题

kary 2007-08-08 08:09:17
程序风格的作用主要是使代码容易阅读。代码应该时清楚的和简单的-------具有直截了当的逻辑、自然的表达式、通行的语言使用方式、有意义的名字和有帮助作用的注释等,应该避免耍小聪明,绝不使用非正规的结构。
下面的代码具有很多缺陷,请从风格的角度评论并改正下面各个代码片断:
/* return SUCCESS */
return SUCCESS;

----------------------------------------------------------------------------------------
if (!(block_id < actblks) ¦ ¦ !(block_id >= unblocks))

-----------------------------------------------------------------------------------------
int count = 0;
while (count < total) {
count++;
if (this.getName(count) == nametable.userName()) {
return (true);
}
}

-------------------------------------------------------------------------------------------
i= 0;
while(i <= n-1)
array[i++] = 1.0;

----------------------计算n的阶乘---------------------------------------------------------------------
int factorial(int n)
{
int fac;
fac = 1;
while (n--)
fac *= n;
return fac;
}

-----------C函数,但是Java开发人员也可以做-----------------------------------------
if (i > j)
printf(“%d is greater than %d.\n”, i, j)
else
printf(“%d is smaller than %d.\n”, i, j)

-------------------------------------- C语言--------------------------------------------
#define MAX(a, b) a >b? a:b
...全文
2327 46 打赏 收藏 举报
写回复
46 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
dingzyi 2011-08-12
新手。看看。。
  • 打赏
  • 举报
回复
kary 2007-08-18
结贴了。
如果把前面每个人的答案综合一下,这题目就答圆满了。
所以答案不再给了,呵呵。
  • 打赏
  • 举报
回复
snake1234 2007-08-17
```真的生病了,住院...哎,被人不幸言中.

风格嘛...是什么样的不重要,重要的是有个人的风格,当然这要是良好的,始终如一的.

划分子函数有个好办法,就是子函数的命名,一定要能用1句话描述出子函数的功能.
  • 打赏
  • 举报
回复
yi86853443 2007-08-17
呵呵,学习的!
  • 打赏
  • 举报
回复
勉励前行 2007-08-17
當寫代碼多了以後,代碼書寫格式一般都會定形,使用哪種風格已經不大重要。會自然地依據所需要表達的意思編排自己的代碼,使閱讀者看起來更舒服。這時C/C++自由自在的風格能更好地得到體現,也正是這樣,規范化的書寫模式在C/C++世界比在其他語言更難推廣。

  一直以來C/C++有用小函數構建大功能的編程習慣。這要求一個C/C++函數不要太長,因為那不利於閱讀與理解,無論如何不規范,閱讀一個100行的代碼函數要比閱讀一個1000行代碼的函數容易很多。C/C++這種用小函數構建大功能的習慣,也令得代碼規范化得不到足夠重視。用小函數構建大功能的方式方便了閱讀,降低了代碼規范化的要求;這比代碼規范化更需要編程功力,需要編程者劃分更細致的編程接口,同時,更細小的函數其重用度也更高,而且inline函數及編譯器優化也保障了程序性能不會下降,那才是用C/C++編程更要注重的地方:函數功能內聚,類功能內聚,用函數與類構建復雜的模塊或更復雜的類。

  對於命名習慣,如果不是全局變量或接口,對於變量名的要求無必要過份,如果什麼東西都規范化,就叫迂腐了。象禁用goto或函數單一出口等所謂的規范,只適用於在大函數(200行以上)中,但C/C++本來就不提倡函數行數過多,如果使用goto,使程序更易閱讀,為什麼不給用呢?(不少地方用goto,比不用goto其代碼閱讀的難易程序相差很大,執行效率也更高)。提倡函數行數過多,但也不提倡為了行數而將一個功能內聚的函數強行分解為多個小函數。

 代碼不僅僅是要正確運行,還是寫給別人看的。接口則是要給別人用的,不是僅僅給自己用起來爽。心中記得這個原則,其他規范可以先放一邊去,做到心中有一把尺,出入規范而又超脫於規范之上。

  • 打赏
  • 举报
回复
kary 2007-08-16
snake1234(川流不息) 失眠真的很严重呢,凌晨6点还没睡。身体可是本钱,赶紧看一下医生,搞点药吃吃,很快就好的。推荐思诺思,效果不错。
你大部分答得很不错的。我现在说一下第一题的答案:这个注释是没有意义的。

实际项目中,一个很重要的活动是制定项目规约,但是却不那么好制定。我就看到过这样的项目,每个return语句都加上了如题目中类似的注释。只是没有题目中这么傻,有可能是:
/* Succeed */
return SUCCESS;
从表面上看,项目做的很规范,因为所有的代码都是这么注释的,但却是白费力气的。

比上面的情况更糟糕的,是有一个项目规定一个机能只能有一个类。原因是制定规约的人觉得让每个人自由命名会做出很差的代码来。但是这么做的结果是,有的机能很复杂,有好几千行代码,当这么多代码龟缩在一个类里面的时候,简直就是维护的灾难。

书上写的规定是死的,都有自己的适用语境。如果遇到很难断定的情况,只要记住一个目的:要让代码简洁易懂。

再如,有人说一个函数最好只有一个出口。但是要注意他说的其实要根据实际情况甄别的。我就见到过有人写出了这么一段代码:
boolean nullFlag = false;
for(....) {
if (...) {
nullFlag = true;
break;
}
}
if (!nullFlag) {
while(....).{
if (...) {
nullFlag=true;
break;
}
}
}

..................
return nullFlag;
象这样的check函数,还不如每遇到一个为null的条件,就直接返回。代码清楚,容易检查错误。

最后说一下为返回语句注释的比较好的例子:
if (...) {
return NULL; /* out of memory */
}

这个注释是有意义的。因为该段函数失败的时候就返回NULL。而注释正好说明了为什么返回NULL。
  • 打赏
  • 举报
回复
snake1234 2007-08-15
失眠```还真把那么多写完了,热都要热死.
说说自己的感受吧,平时工作的时候,看到有些组内成员的代码,真有点想冲上去把他掐死的冲动.累教不改.已经养成了恶劣的坏习惯,一段不到100行的代码,可以找十几处隐型BUG,和缺陷.实在让人无法和这些人共同开发下去.
说到水平,越工作越觉得自己差,越读书越觉得自己太粗浅.
特别是最近1年来,常常失眠,闭上眼睛就是自己代码的BUG,别人的代码如何优秀.
  • 打赏
  • 举报
回复
snake1234 2007-08-15
/* return SUCCESS */
return SUCCESS;

//有等于无的注释,使用/**/注释最好分层
/*
return SUCCESS
SUCCESS为常量XX
*/
return (SUCCESS);

----------------------------------------------------------------------------------------
if (!(block_id < actblks) || !(block_id >= unblocks))

//多余的!操作,要让看代码的人多想一下
if (((block_id >= actblks) || (block_id < unblocks))

------------------Java语言-----------------------------------------------------------------------
int count = 0;
while (count < total) {
count++;
if (this.getName(count) == nametable.userName()) {
return (true);
}
}

//1.对JAVA不熟,但是单从风格上来说,使用while普遍不如使用for效率高(当然有些编译器做过优化的话,while,for的汇编代码是一样的)
//2. total是什么?如果是常量,而且与上下文不相关,这里应该加入注释
//3. this.getName(count) , nametable.userName()原型以及作用应该描述一下
//4. 纯粹个人喜好:if条件下执行的单语句return,如果不复杂,最好不用{},这样看起来清爽一些,排版也清晰,如果处于风格统一考虑,也可以全部使用if(){}的方式
//修改如下:
int count;
for (count = 0; count < total; count++){ //const int total = xxxx
if (this.getName(count) == nametable.userName()) //this.getName(count)xxxx, nametable.userName()xxxx
return (true);
}

----------------------初始化一个数组,数组大小为n---------------------------------------------------------------------
i= 0;
while(i <= n-1)
array[i++] = 1.0;

//1.i的类型?n的类型?array的类型?
//2.i <= n-1和第一个问题一样,多余的减操作,还要让看代码的人多想一下
//3.使用while同上的问题一样,效率不如for
//4.在while语句下使用i++还不如把i++单独拿出来。让代码更清晰。
//5.array的长度?!在未知长度的情况下,随便使用下标附值,非常危险,很容易越界。特别是当arrar为指针类型的时候,在注释里最好标明!
//6.array声明的位置?如果是全局量,可以不初始化。如果为局部变量,就必须初始化。

int i; //i:int型
for (i = 0;i < n;i++) //n为array数组的长度。
{
array[i] = 1.0; //array[]为float型数组
}

----------------------计算n的阶乘---------------------------------------------------------------------
int factorial(int n)
{
int fac;
fac = 1;
while (n-- > 0)
fac *= n;
return fac;
}

//1.代码有错误,无法正确计算出0,1的阶乘
//2.这里使用while,不但代码比较复杂,让人无法一眼看明白,也存在效率问题
//3.fac为0的情况是特殊的,所以要提前判断!!!
//4.fac为局部量,同时!局部量要养成加前缀的习惯!
//5.传入参数命名问题!不要随便使用 n,m这些没有实际意义的参数。
//6.形成自己的风格,传入参数要和局部变量命名区分
int factorial(int _Radix)
{
if (0 == _Radix)
return 1;

int nFac ;
int i;
for (i = _Radix);i > 0;i--)
nFac *= _Radix;
return nFac;
}

----------------------------------------------------
if (i > j)
printf(“%d is greater than %d.\n”, i, j);
else
printf(“%d is smaller than %d.\n”, i, j);

//1.打印语句逻辑上有问题吧,不大于就是小与或等于
printf(“%d is not greater than %d.\n”, i, j);

-------------------------------------- C语言--------------------------------------------
#define MAX(a, b) a >b? a:b

//使用define,不要忘记把传入参数全部用()括起来
#define MAX(a,b) (a) > b ? (a) : (b)




  • 打赏
  • 举报
回复
snake1234 2007-08-15
...仔细看了下,真要深究,问题多的都不想写了...很多属于个人编程上的习惯问题,还是坏习惯,最容易引入隐型bug那种```
  • 打赏
  • 举报
回复
orc1984 2007-08-15
mark
  • 打赏
  • 举报
回复
kary 2007-08-14
这样写也是可以的(把int i = 0去掉),不过最合适的写法应该是
int factorial(int n)
{
assert(n >= 0);
int fac = 1;

for (int i = 2; i <= n; i++)
{
fac *= n;
}
return fac;
}
用while循环也是可以的。
int factorial(int n)
{
assert(n >= 0);
int fac = 1;

while(n > 1)
{
fac *= n;
n--;
}

return fac;
}
原题之所以出错,其实是因为n-->0是个复合语句。编写的时候要尽量避免复合语句,特别是要避免放在while或者for的循环结束条件中。对循环变量进行明确变更很重要。
for循环在编程中更多的被采用,可能是因为for语句将循环变量的初始化,循环结束条件,循环变量的变更放在同一条语句中,从而更容易检查。但是while循环也是经常用的,如Java的迭代器,Linux下的while(1).
但是用递归的话在这儿不太合适。

至于这题,我觉得只要答出是因为采用了复合语句作为循环结束条件导致的BUG就可以了。
  • 打赏
  • 举报
回复
jinfushi0417 2007-08-14
请大虾指点以下
这么写符合编程风格吗 ?
  • 打赏
  • 举报
回复
jinfushi0417 2007-08-14

----------------------计算n的阶乘---------------------------------------------------------------------

int factorial(int n)
{
int i=0;
int fac;
fac = 1;
while (n!=0)
{
fac*=n;
n--;
}
return fac;
}
  • 打赏
  • 举报
回复
liuqingwu228 2007-08-13
题目很有趣,很多常见问题
  • 打赏
  • 举报
回复
Spiritring 2007-08-13
这是入门题吧?
  • 打赏
  • 举报
回复
higter 2007-08-12
各位看清题意,要求从风格出发解决问题,
什么用for比while更好呀,
什么1.0与1等同..耍小聪明的作风
………………

你们也太耍自己的聪明了吧
  • 打赏
  • 举报
回复
sunraiing9 2007-08-12
我笨拙 不明白望指点
  • 打赏
  • 举报
回复
sunraiing9 2007-08-12
int factorial(int n)
{
int fac;
fac = 1;
while (n--)
fac *= n;
return fac;
}

这样也行?
参数也可以做自加自减操作吗
  • 打赏
  • 举报
回复
m_sean 2007-08-11
关于宏的问题,好像有一个问题是这样
------------------------------------------
int a = 1;
int b = 0;
MAX(a++, b);
------------------------------------------
int a = 1;
int b = 10;
MAX(a++, b);
------------------------------------------
以上两种写法会导致a的自增次数不同,也就是a的自增次数受到a和b大小关系的影响,
这应该不是一般情况下希望发生的,只少如果max是一个函数,就不是这样的效果
  • 打赏
  • 举报
回复
ERR0RC0DE 2007-08-11
/* return SUCCESS */
return SUCCESS;

应该是风格问题,单行注解最好是用//

-------------------------------------------------------------------------------------
if (!(block_id < actblks) || !(block_id >= unblocks))
a: actblks, unblocks是啥东西,会看半天
b: 跟楼上差不多,写法看起来很累。

------------------Java语言----------------------------------------------------------
int count = 0;
while (count < total) {
count++;
if (this.getName(count) == nametable.userName()) {
return (true);
}
}

a:
int count = 0
改成:
int index = 0
这样更直观点,this.getName(count)让人看起来别扭,写成this.getName(index),变量命名直观,一目了然的好。

b:
如果上面代码是函数,少处理了return false的情况。
----------------------初始化一个数组,数组大小为n-------------------------------------i= 0;
while(i <= n-1)
array[i++] = 1.0;

初始化都用memset,即使自己写一般是用for循环

----------------------计算n的阶乘---------------------------------------------------------------------
int factorial(int n)
{
int fac;
fac = 1;
while (n-- > 0)
fac *= n;
return fac;
}
阶乘很容易溢出,最好result=>unsigned/__int64,并使用for循环

----------------------------------------------------
if (i > j)
printf(“%d is greater than %d.\n”, i, j);
else
printf(“%d is smaller than %d.\n”, i, j);
用三目操作简化
-------------------------------------- C语言-----------------------------------------
#define MAX(a, b) a >b? a:b
括号据说很重要。
  • 打赏
  • 举报
回复
加载更多回复
相关推荐
发帖
C++ 语言
加入

6.2w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
申请成为版主
帖子事件
创建了帖子
2007-08-08 08:09
社区公告
暂无公告