C语言常见问题

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

第第第第1章章章章C语言语言语言语言本章主要描述C语言一些基本要素。当你开始编写C程序时,你可能对C语言的一些基本问题感到困惑,如C语言所使用的约定、关键字和术语等。本章将回答这方面你经常会遇到的一些问题。例如,switch语句是最常用的一种C语言构件,本章将回答与它有关的三个常见问题。本章还涉及其它几个问题,如循环、分支、运算符的优先级和程序块技术。在阅读本章时,请注意有关switch语句和运算符优先级的一些问题,这些问题常常会使C语言的初学者感到迷惑。1.1什么是局部程序块(localblock)?局部程序块是指一对大括号({})之间的一段C语言程序。一个C函数包含一对大括号,这对大括号之间的所有内容都包含在一个局部程序块中。if语句和swich语句也可以包含一对大括号,每对大括号之间的代码也属于一个局部程序块。此外,你完全可以创建你自己的局部程序块,而不使用C函数或基本的C语句。你可以在局部程序块中说明一些变量,这种变量被称为局部变量,它们只能在局部程序块的开始部分说明,并且只在说明它的局部程序块中有效。如果局部变量与局部程序块以外的变量重名,则前者优先于后者。下面是一个使用局部程序块的例子:#includestdio.hvoidmain(void);voidmain(){/*Beginlocalblockforfunctionmain()*/inttest_var=10;printf(Testvariablebeforetheifstatement:%d\n,test_var);if(test_var5){/*Beginlocalblockforifstatement*/inttest_var=5;printf(Testvariablewithintheifstatement:%d\n,test_var);{/*Beginindependentlocalblock(nottiedtoanyfunctionorkeyword)*/inttest_var=0;printf(Testvariablewithintheindependentlocalblock:%d\n,test_var)}/*Endindependentlocalblock*/printf(Testvariableaftertheifstatement:%d\n,test_var);}/*Endlocalblockforfunctionmain()*/上例产生如下输出结果:Testvariablebeforetheifstatement:10Testvariablewithintheifstatement:5Testvariablewithintheindependentlocalblock:0Testvariableaftertheifstatement:10注意,在这个例子中,每次test_var被定义时,它都要优先于前面所定义的test_var变量。此外还要注意,当if语句的局部程序块结束时,程序重新进入最初定义的test_var变量的作用范围,此时test_var的值为10。请参见:1.2可以把变量保存在局部程序块中吗?1.2可以把变量保存在局部程序块中吗?用局部程序块来保存变量是不常见的,你应该尽量避免这样做,但也有极少数的例外。例如,为了调试程序,你可能要说明一个全局变量的局部实例,以便在相应的函数体内部进行测试。为了使程序的某一部分变得更易读,你也可能要使用局部程序块,例如,在接近变量被使用的地方说明一个变量有时就会使程序变得更易读。然而,编写得较好的程序通常不采用这种方式来说明变量,你应该尽量避免使用局部程序块来保存变量。请参见:1.1什么是局部程序块?1.3什么时候用一条switch语句比用多条if语句更好?如果你有两个以上基于同一个数字(numeric)型变量的条件表达式,那么最好使用一条switch语句。例如,与其使用下述代码:if(x==l)printf(xisequaltoone.\n);elseif(x==2)printf(xisequaltotwo.\n);elseif(x==3)printf(xisequaltothree.\n);elseprintf(xisnotequaltoone,two,orthree.\n);不如使用下述代码,它更易于阅读和维护:switch(x){case1:printf(xisequaltoone.\n);break;case2:printf(xisequaltotwo.\n);breakcase3:printf('xisequaltothree.\n);break;default:printf(xisnotequaltoone,two,orthree.\n);break;}注意,使用switch语句的前提是条件表达式必须基于同一个数字型变量。例如,尽管下述if语句包含两个以上的条件,但该例不能使用switch语句,因为该例基于字符串比较,而不是数字比较:char*name=Lupto;if(!stricmp(name,Isaac))printf(Yournamemeans'Laughter'.\n);elseif(!stricmp(name,Amy))printf(Yournamemeans'Beloved'.\n);elseif(!stricmp(name,Lloyd))printf(Yournamemeans'Mysterious'.\n);elseprintf(Ihaven'taclueastowhatyournamemeans.\n);请参见:1.4switch语句必须包含default分支吗71.5switch语句的最后一个分支可以不要break语句吗?1.4switch语句必须包含default分支吗?不,但是为了进行错误检查或逻辑检查,还是应该在switch语句中加入default分支。例如,下述switch语句完全合法:switch(char_code){casetyt:case'y':printf(YouansweredYES!\n)breakcase'N':case'n':printf(YouansweredNO!\n);break}但是,如果一个未知字符被传递给这条switch语句,会出现什么情况呢?这时,程序将没有任何输出。因此,最好还是加入一个default分支,以处理这种情况:......default:printf(Unknownresponse:%d\n,char_code);break......此外,default分支能给逻辑检查带来很多方便。例如,如果用switch语句来处理数目固定的条件,而且认为这些条件之外的值都属于逻辑错误,那么可以加入一个default分支来辨识逻辑错误。请看下列:voidmove_cursor(intdirection){switch(direction){caseUP:cursor_up()breakcaseDOWN:cursor_down()breakcaseLEFT:cursor_left()breakcaseRIGHT:cursor_right()breakdefault:printf(Logicerroronlinenumber%ld!!!\n,__LINE__)break}}请参见:1.3什么时候用一条switch语句比用多条if语句更好?1.5Switch语句的最后一个分支可以不要break语句吗?1.5switch语句的最后一个分支可以不要break语句吗?尽管switch语句的最后一个分支不一定需要break语句,但最好还是在switch语句的每个分支后面加上break语句,包括最后一个分支。这样做的主要原因是:你的程序很可能要让另一个人来维护,他可能要增加一些新的分支,但没有注意到最后一个分支没有break语句,结果使原来的最后一个分支受到其后新增分支的干扰而失效。在每个分支后面加上break语句将防止发生这种错误并增强程序的安全性。此外,目前大多数优化编译程序都会忽略最后一条break语句,所以加入这条语句不会影响程序的性能。请参见:1.3什么时候用一条switch语句比用多条if语句更好?1.4switch语句必须包含default分支吗?1.6除了在for语句中之外,在哪些情况下还要使用逗号运算符?逗号运算符通常用来分隔变量说明、函数参数、表达式以及for语句中的元素。下例给出了使用逗号的多种方式:#includestdio.h#includestdlib.hvoidmain(void);voidmain(){/*Here,thecommaoperatorisusedtoseparatethreevariabledeclarations.*/inti,j,k;/*Noticehowyoucanusethecommaoperatortoperformmultipleinitializationsonthesameline.*/i=0,j=1,k=2;printf(i=%d,j=%d,k=%d\n,i,j,k);/*Here,thecommaoperatorisusedtoexecutethreeexpressionsinoneline:assignktoi,incrementj,andincrementk.Thevaluethatireceivesisalwaystherigbtmostexpression.*/i=(j++,k++);printf(i=%d,j=%d,k=%d\n,i,j,k);/*Here,thewhilestatementusesthecommaoperatortoassignthevalueofiaswellastestit.*/while(i=(rand()%100),i!=50)printf(iis%d,tryingagain...\n,i)printf(\nGuesswhat?iis50!\n)}请注意下述语句:i:(j++,k++)这条语句一次完成了三个动作,依次为:(1)把k值赋给i。这是因为左值(lvaule)总是等于最右边的参数,本例的左值等于k。注意,本例的左值不等于k++,因为k++是一个后缀自增表达式,在把k值赋给j之后k才会自增。如果所用的表达式是++k,则++k的值会被赋给i,因为++k是一个前缀自增表达式,k的自增发生在赋值操作之前。(2)j自增。(3)k自增。此外,还要注意看上去有点奇怪的while语句:while(i=(rand()%100),i!=50)printf(iis%d,tryingagain...\n);这里,逗号运算符将两个表达式隔开,while语句的每次循环都将计算这两个表达式的值。逗号左边是第一个表达式,它把0至99之间的一个随机数赋给i;第二个表达式在while语句中更常见,它是一个条件表达式,用来判断i是否不等于50。while语句每一次循环都要赋予i一个新的随机数,并且检查其值是否不等于50。最后,i将被随机地赋值为50,而while语句也将结束循环。请参见:1.12运算符的优先级总能保证是“自左至右”或“自右至左”的顺序吗?1.13++var和var++有什么区别?1.7怎样才能知道循环是否提前结束了?循环通常依赖于一个或多个变量,你可以在循环外检查这些变量,以确保循环被正确执行。请看下例:intxchar*cp[REQUESTED_BLOCKS]/*Attempt(invain,Imustadd...)toallocate51210KBblocksinmemory.*/for(x=0;xREQUESTED_BLOCKS;x++){cpi[x]=(char*)malloc(10000,1)if(cp[x]==(char*)NULL)break}/*IfxislessthanREQUESTED-BLOCKS,theloophasendedprematurely.*/if(xREQUESTED_BL

1 / 146
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功