C语言中的“c应输入声明端的预期声明或语句” 是什么意思

- Database Error
The server is currently busy. Please try again later.
已经将此出错信息详细记录, 由此给您带来的访问不便我们深感歉意.今天看啥 热点:
C语言变量声明问题——变量定义一定要放在所有执行语句/语句块的最前面吗?,变量最前面&
报错信息:error C2065: 'salary' : undeclared identifier
#include &stdio.h&
void main(){
printf("我的成绩是100分!");//不使用变量
//使用变量
salary = 100;
printf("我的成绩是%d分!",salary);
问题根源:编译器问题&&C89和C99
C89规定,在任何执行语句之前,在块的开头声明所有局部变量。
在C99以及C++中则没有这个限制,即在首次使用之前,可在块的任何位置都可以声明变量。
变量声明放在前面就不报错了&&&&&&
#include &stdio.h&
void main(){
//使用变量
salary = 100;
printf("我的成绩是100分!");//不使用变量
printf("我的成绩是%d分!",salary);
不同风格利弊
变量在函数开头定义:便于修改
变量就近定义:便于阅读
变量在块语句的开头定义:有的临时变量放在语句块开头,可以不用在函数开头定义,并且在使用完毕后释放空间,可以这么做,但不要无故添加花括号来提高代码的结构。
要达到最大的兼容跨平台性,还是放在函数开头定义吧
使用哪种方式,看实际情况+个人喜好!
我个人是比较喜欢就近定义的,觉得比较方便一点。
可是,现在使用的VC6.0,编译器可能是C89的,所以不得不用开头定义。
顺便提一提:该文件的后缀名为.c
在网上查了一下,有许多说法,列举一二(意思大同小异)
1.源文件保存为.c格式的话变量只能定义在最前,若保存为.cpp格式的话,变量定义较为灵活,不用在最前。
2.在C语言里,变量只能在函数的开头处声明和定义。在函数里要用到的变量必须要在开头处声明定义。声明定义的前面不能有任何其他非声明定义的语句。全局变量在函数体的外部声明定义。而C++里(.CPP文件是按C++标准编译的),只要在用到变量前对该变量进行声明定义就行了,位置不做特别要求。而C语言的就定了在一个模块里(函数、循环体等)先声明一切所需变量后才能进行相关操作的规定。
然而,把后缀名改为.cpp后,还是报错
void main()改为int main(void)就可以了
#include &stdio.h&
int main(void ){
//使用变量
salary = 100;
printf("我的成绩是100分!");//不使用变量
printf("我的成绩是%d分!",salary);
应该是语言的数据类型的问题吧???是不是呢?大神何处在~
(完,可待续)
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&
C语言最近更新C语言中函数的声明、定义及使用的入门教程
投稿:goldensun
字体:[ ] 类型:转载 时间:
这篇文章主要介绍了C语言中函数的声明、定义及使用的入门教程,重点讲述了main函数的相关知识,需要的朋友可以参考下
对函数的“定义”和“声明”不是一回事。函数的定义是指对函数功能的确立,包括指定函数名,函数值类型、形参及其类型以及函数体等,它是一个完整的、独立的函数单位。而函数的声明的作用则是把函数的名字,函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时进行对照检查(例如,函数名是否正确,实参与形参的类型和个数是否一致),它不包括函数体。——谭浩强 ,《C程序设计》(第四版),清华大学出版社,2010年6月,p182
这段论述包含了许多概念性错误,这些概念错误在许多C语言书中都同样普遍存在。为了说明这些错误,首先来回顾一下C语言演变和发展的一些情况。
最早,C语言的代码可以这样写:
printf("hello,world!\n");
注意,这段代码对标识符printf没有进行任何说明。这是因为printf()函数的返回值为int类型。当时的C语言规定,对于没有任何说明的函数名,编译器会默认为返回值为int类型,因此对这样的函数名可以不做任何说明。那个时期的C语言,很多情况下int可以不写。例如main()函数返回值的类型为int就可以不写。
但是需要特别说明的是,这种“省劲”的写法已经过时,从C90标准起,这种写法就步入了被逐步抛弃的过程(尽管当时还没有完全立即废止)。C99废除了隐式函数声明法则(remove implicit function declaration),另外,省略main()前面的int也已经不再容许了。
在C语言早期,尽管有时不需要对函数名进行说明,但有些情况下对函数名进行说明还是必须的,比如:
double sqrt();
int main()
printf("%f\n" , sqrt(9.) );
这是因为函数sqrt()返回值的类型不是int类型而是double类型,编译器编译时需要知道sqrt(9.)这个表达式的类型。
不难注意到这种对函数名的说明非常简单,这是最早期的一种函数类型说明的形式。这种说明只着重说明函数名是一个函数及其返回值类型,如果程序员在调用函数时存在参数类型或个数方面的错误编译器是无法察觉的,因为函数类型说明中“()”内没有任何信息。
这种办法只说明了函数名与()进行运算的结果也就是函数返回值的数据类型,无法进一步检查参数方面的错误是这种写法的不足之处。
如果不写函数类型说明,也可以把函数定义写在函数调用之前:
double square ( double x)
return x *
int main(void)
printf("%f\n" , square(3.) );
这表明函数定义也具有对函数名的类型加以说明的效果,因此从这个意义上来说,函数定义也是一种对函数类型的说明。这种办法可以检查出函数调用时在参数个数和类型方面的错误。
但是,用这种办法说明函数名并不好,因为这样做在编程时还需要考虑应该把哪个函数定义写在前面,哪个写在后面的问题。假如函数A调用函数B,函数B调用函数C,函数C又调用函数A,究竟如何安排函数定义的顺序就会让人感到无所适从。此外这种办法也不利于代码的组织,在由多个源文件组成的源程序时,这种写法就更会捉襟见肘、漏洞百出。因此,在1990年,C标准借鉴C++语言规定了一种新的说明函数名的方法,这就是函数原型(Function Propotype)式说明函数类型的方法:
double square ( double ); //或 double square ( double x)
int main(void)
printf("%f\n" , square(3.) );
double square ( double x)
return x *
使用这种办法,不但可以检查函数调用时参数类型和个数方面的错误,同时解决了源代码的组织问题,因为程序员不必再考虑该把哪个函数写在前面、哪个写在后面这种无聊的问题了。这种办法全面地说明了函数名的数据类型。此外要说明的是,把形参及其数据类型写在“()”内形式的函数定义也属于函数原型(Function Propotype)的范畴。
由此可见,古老的、不对参数进行任何说明的函数类型说明方式、函数定义以及函数原型式的函数类型说明方式都具有说明函数名意义的效用。从这个意义上讲它们都是函数声明。在C语言中,声明(Declaration)这个词的本义就是指定标识符的意义和性质(A declaration specifies the interpretation and attributes of a set of identifiers.),某个标识符的定义(Definition)同时也是这个标志符的“声明”(Declaration)。函数定义(Function definition)则意指包括函数体。(A definition of an identifier is a declaration for that identifier that: ……for a function, includ)。函数原型则特指包括说明参数类型的函数声明,它同样包含用这种方式写出的函数定义。
现在回过头来看样本中的第一句话:“对函数的“定义”和“声明”不是一回事”。由于函数定义本身就是一种函数声明,怎么可以说它们不是一回事呢?这句话的逻辑就如同说“男人”和“人”不是一回事。你可以说男人和女人不是一回事,因为他们没有交集。但没法说男人和人不是一回事,因为男人是人的子集,男人就是人的一种,怎么可以说男人和人不是一回事呢?
那么,不带函数体的函数声明应该如何称呼呢?在C语言中,它们叫被做“函数类型声明”(Function type declaration)。函数类型声明最主要的特点是声明了函数名是一个函数及其返回值的类型,如果也声明了参数的类型,则是函数原型式的函数类型声明。
样本中的“而函数的声明的作用则是把函数的名字,函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时进行对照检查(例如,函数名是否正确,实参与形参的类型和个数是否一致),它不包括函数体”这句话同样不通。其主要错误是它混淆了“函数原型式类型声明”与“函数声明”这两个概念,前一个概念只是后一个概念的子集。函数声明中不但包含“函数类型声明”,也包含“函数定义”和老式的“函数类型声明”。由于函数定义本身就是一种函数声明,所以无法断定函数的声明是否包括函数体;而且老式的函数类型声明(例如double sqrt();)也属于函数声明,这种函数声明并不检查参数类型及个数方面的错误。此外函数声明也并没有检查“函数名”正确与否的功能。
这段文字中的“函数类型”这个概念也有错误,函数类型所描述的不但包括函数返回值类型,也可能一并描述参数的个数和类型(如果是函数原型),因此不能与“形参的类型、个数”相提并论。
现代的C语言的函数定义和函数类型声明都采用函数原型式的风格,C99把旧的非原型形式视为过时,这意味着非原型形式以后可能被禁止。
main()函数
在各种C语言书上,能看到各式各样main()函数的写法,简直令人无所适从,这是这么回事?原因主要有两个:一个是随着C语言的发展和演化,main()函数的写法也在不断变化;另外,某些书籍写法不规范或误导的现象也同时存在。
最初main()函数的写法非常简洁,那个时候的C程序员哪怕一个字符似乎都不肯多写。不知道是因为当时键盘质量不好还是因为编辑器太糟糕的缘故,那个时代的C程序员似乎惊人地一致崇尚“简约”——甚至可以说是“至简”。
printf("hello,world\n");
这就是main()函数最古老的写法,K&R在他们的经典名著《The C Programming Language》中的第一个C语言源程序(1978)。这种写法是那个时代的主流。
简直和裸体差不多,连#include&stdio.h&也没有么?在《The C Programming Language》的第一版中确实没有。那个时代的C语言,返回值类型为int的函数不用声明。不过在该书的第二版(1988)中这个程序被改成了:
#include &stdio.h&
printf("hello,world\n");
返回值类型为int的函数不用声明的规则改变了吗?规则没有改变。改变了的是观念,人们已经不再倾向于代码的“至简”,而开始倾向于在代码中交代清楚每一个标识符的来龙去脉。从C89开始倡导在函数调用之前一定要有函数声明,但并没有强求,而在C99这已经是强制性的要求了。由于《The C Programming Language》第二版正值ANSI C标准颁布(1989)前夕出版,所以这种变化也应该视为ANSI C标准的倾向性以及K&R对新标准的认同。尽管这个例子没有完全反映出来这种认同。
为什么说没有完全反映出来这种认同呢?因为这个main()的定义并没有按照函数原型(Function prototype)的方式来写,C90中规定不带参数的main()函数应该这样写:
int main(void) { /*. . .*/}
但同时规定那个int可以省略。C90把()内不写任何内容视为过时的写法,尽管C90无奈地容忍了它(The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature.)。
为什么要容忍?因为有许多老式的代码还在用。
如果以C99的标准看这个main()写得如何呢?C99不容许省略int。但同样只把()内不写任何内容视为过时,而没有完全禁止,可见习惯力量的顽固。
那又为什么说K&R对新标准的认同呢?《The C Programming Language》第二版中的其他函数定义和函数类型声明基本上都改成了函数原型风格。比如,在讲解main()函数的参数时,K&R把原来的main()函数
#include &stdio.h&
main(argc,argv)
char *argv[];
#include &stdio.h&
main(int argc, char *argv[])
前一个写法今天已经差不多绝迹,后一个main()以今天的眼光来看有些奇怪,main()的参数是用函数原型风格写的,但却没有写main()返回值的类型,给人有点半新半旧的感觉。尽管不能说它违背C90(因为C90容许不写main()前面的int),但如果写上了返回值的类型int,就同时满足现代C99标准的要求了。
这里出现的“return 0;”是怎么回事?这在现代C语言中已经是司空见惯了,它返回给操作系统一个值以表明程序是在何种状态下结束的。但在另一段代码中,K&R似乎又走得太远:
#include &stdio.h&
main(int argc,char *argv[])
int found = 0 ;
/*……计算found的值 */
这个实在有些“标新立异”,居然把计算结果返回给了操作系统,颇有突破常规之嫌。
那前面几个没有“return 0;”的main()函数会怎么样?按照C90标准,会返回一个不确定的int类型的值,如果确实不关心这个返回值是多少,不写确实可以。但C99却要求编译器在编译的时候帮忙给补上这个“return 0;”,C99在必须写int这个问题上没有迁就懒人,但在这里却对偷懒的做法给予了迁就。 问:如果确实不关心main()函数的返回值,把main()的返回值定义为void类型如何?我看到许多书上都这样写的。
#include &stdio.h&
void main()
printf("This is a C program.\n");
这在C99之前是一种野路子写法,究竟从哪里冒出来的,无据可考。但前几年的主流教科书中这种写法很常见。K&R(C语言的发明者)没有这样写过,C90国际标准也不承认这种写法。Bjarne Stroustrup(C++语言的创始人)在他的关于C++的FAQ中,在回答是否可以写“void main()”时愤怒地回答说这种写法在C++和C中都不曾有过。事实上,很多C语言专家都认为“void main()”非常邪恶。
因此,在C99之前,这是不符合标准的写法。尽管这段代码的功能似乎是输出“This is a C program.”,但其实却不是一个“C program”。
但是有时这样写并没有产生错误啊?首先,C语言的错误不一定反应在编译、链接或运行过程中。你输出一个垃圾值也可能一路通过编译、链接或运行,但这不说明你的代码没有错误,更不能说明这样的代码正确、有意义。其次,这样的写法在有些编译器下程序会产生崩溃或得到警告。这说明这种写法至少不普遍性适用的。可以说,如果不是C99标准,这种写法根本没有立锥之地。
C99给了这种写法以立足之地么?从某种意义上也许可以这样理解。因为K&R没承认过这种写法,C90根本不承认这种写法,C99虽然没有正式承认这种写法,但为这种写法留了一个后门:“It shall be defined ……or in some other implementation-defined manner”。这意思就是说,如果编译器明确声称允许void main()这种写法的话,那么C99不再象C90那样简单认为这种写法违背C标准。
但是不管怎么说,这种写法最多是某些编译器的一种“方言土语”,如果没有特殊理由,比如仅仅是工作在某个特殊环境,且仅仅使用特定的编译器而根本不考虑程序的可移植性,为什么不写普遍适用的形式呢?
既然很多C语言专家都认为“void main()”非常邪恶,C99为什么包容这种写法呢?很难确定C99是否就是打算专门想把这种写法也“收容”在标准之列。因为除了void main(),还有另外一些main()函数的写法被C90排除在标准之外了。而现在,这些写法在理论上也具备了符合C99标准的可能性。
还有什么样的main()函数?很多编译器都支持下面的main()的写法:
int main(int argc, char *argv[], char *env[])
居然有3个形参,那个env是做什么用的?那个参数可以使程序获得环境变量。
什么叫环境变量?简单地讲可以理解为操作系统记录的一些数据,比如计算机的名字,操作系统放在哪里等等。应用程序在运行时可能要用到这些信息,这时可以通过env这个参数来获得。
如果编译器不支持main()的第三个参数怎么办?标准库函数也可以达到同样的目的。
#include &stdlib.h&
char *getenv(const char *name);
是否可以说void main()和int main(int argc, char *argv[], char *env[])也符合C99标准呢?恐怕还不能这么说,现在只是不能说这两种写法一定不符合C99标准。但这两种写法不符合C90标准是确定的,这两种写法的可移植性很差也是确定无疑的。C99标准在这里写的很模糊,没有进一步界定“implementation-defined manner”的含义。除非编译器声明遵守C99标准,且容许这两种写法,否则断言这两种写法符合C99标准属于空穴来风。
有人说“C99建议把main函数指定为int型”,这种说法对吗?显然不对。因为C99并非绝对不包容返回值非int类型的main()。正确的说法是,C90要求main()函数的返回值一定得是int型。但C90容许不写那个int,而C99则要求必须写上这个“int”。
下面这种风格如何?
#include &stdio.h&
int main()
printf("This is a C program.\n");
这个写法有点不伦不类。返回值的类型int写了,这个和C89的倡导或C99的要求一致,但是()里面什么都不写,又与标准的所倡导的风格不符,所以说不伦不类。这种写法目前的标准依然容许,但属于标准目前尚能容忍的但即将过时的(obsolescent)写法,被抛弃只是早晚的问题。这种写法就如同古代的函数形参的写法一样:
main(argc,argv)
char *argv[];
都属于历史的垃圾。
见过在main()的函数体的“}”之前前写一句getch();,这个是怎么回事?这个是时代的产物。在PC从DOS时代转变为Windows时代的过程中,DOS时代开发的IDE(主要是TC)无法在运行程序后显示输出结果,为了在运行后从容仔细地观察一下运行结果再返回IED界面,加上了这么一句,人为地延长程序运行时间(因为getch()会等待用户输入一个字符)。但这与main()本身的结构无关。这条语句不具备普遍意义,只是将就过时的IDE的一种权宜之计而已。所谓不具备普遍意义是指,第一,真正的程序往往不需要这条语句,就是说这条语句与程序功能无关;第二,getch()这个函数并不是标准函数,只有个别的编译器才支持它,在其他编译器上写这条语句,很可能行不通。
为什么不用getchar()这个标准库函数呢?getchar()的功能和getch()有点区别,前者会在标准输出设备上显示用户键入的字符,这显得很不利索,而后者则不会显示用户所键入的字符,更接近“Press Any Key to continue……”的效果。
有的代码在main()函数结束前写system("PAUSE");,是否也是这个意思?是的。这也是一种人工制造的“请按任意键继续. . .”,与程序功能结构无关,只是为了方便地观察输出结果。但是这种写法比调用getch()要好,因为system()函数是标准库函数,各个编译器都提供支持。
有一种说法,“在最新的C99标准中,只有以下两种定义方式是正确的:”
int main( void )
int main( int argc, char *argv[] )
这种说法对吗?
这种说法显然不对。但可以确认的是这两种定义方式一定正确。不但在C99来说是正确的,以C89来说也是正确的。
还有一种写法:
int main( void )
return EXIT_SUCCESS;
那个EXIT_SUCCESS是怎么回事?
return EXIT_SUCCESS;是与return 0;等价的一种文雅的写法。EXIT_SUCCESS是在stdlib.h中定义了的符号常量,返回这个值表示程序任务完成后程序退出。在stdlib.h定义的另一个符号常量EXIT_FAILURE,通常用于程序无法完成任务而退出。
实在太眼花缭乱了,需要记住这么多吗?显然没必要。很多东西都是历史原因遗留下的垃圾。
如果学习C语言,应该记住或使用哪种呢?显然是:
int main( void )
int main( int argc, char *argv[] )
第一,他们普遍适用,不存在可移植性的问题;
第二,就目前看,他们不存在任何过时或即将过时的成分。当然,如果喜欢文雅,不写return 0;而写EXIT_SUCCESS也可以。 顺便说一句,有的学习者记不住带参数main()函数两个形参的名字。其实这两个形参的名字也可以自己取,不一定用那两个名字,只要记住类型就可以了。第二个参数的类型也可以是char **,这和原来的是等价的。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具C语言中Printf和Scanf&的使用方法详细
Printf和Scan函数的使用方法
一&printf()函数是格式化输出函数,&一般用于向标准输出设备按规定格式输出&
信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:&
&&&&&&printf("&格式化字符串&",&&参量表&);&
&&&&其中格式化字符串包括两部分内容:&一部分是正常字符,&&这些字符将按原&
样输出;&另一部分是格式化规定字符,&以"%"开始,&后跟一个或几个规定字符,&
用来确定输出内容格式。&
&&&&参量表是需要输出的一系列参数,&其个数必须与格式化字符串所说明的输出&
参数个数一样多,&各参数之间用","分开,&且顺序一一对应,&&否则将会出现意想&
不到的错误。&
&&&&格式化字符串的格式是:
&&&&&&%[标志][输出最小宽度][.精度][长度]格式字符
1.&&&标志:标志字符为-、+、#、空格四种,其意义下表所示:
&&&&&标志&&&&&&&&&&&&&&&意义
&&&&&-&&&&&&&&&&&&&&&&&结果左对齐,右边填空格
&&&&&+&&&&&&&&&&&&&&&&&输出符号(正号或负号)
&&&&&空格&&&&&&&&&&&&&&输出值为正时冠以空格,为负时冠以负号
&&&&&#&&&&&&&&&&&&&&&&&对c,s,d,u类无影响;对o类,在输出时加前缀o;对x类,在输出时加前缀0x;对e,g,f&类当结果有小数&&&&&&&&&&&&&&&&&&&&&&&&时才给出小数点(??????)
#i&nclude
int&a=100;
float&b=123.255;
printf("a=%d&",a);
printf("a=d&",a);
printf("a=%-10d&",a);
printf("a=%+d&",a);
printf("a=%&d&",a);
printf("a=%#o&",a);
printf("a=%#x&",a);
printf("b=%#f&",b);
a=&&&&&&&100
b=123.254997&&(?????)
2.输出最小宽度:用十进制整数来表示输出的最少位数。(至少要输出这么多位!)
&&&&&&&&&&&&&&&若实际位数多于定义的宽度:则按实际位数输出。
&&&&&&&&&&&&&&&若实际位数少于定义的宽度:则右对齐,左边留空。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&有负号,左对齐,右边留空
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&表示宽度的数字以0开始,则右对齐,左边留空。
例2&#i&nclude
int&a=3456;
printf("a==&",a);&&&&//若实际位数多于定义的宽度:则按实际位数输出
printf("a=d&",a);&&&//若实际位数少于定义的宽度:则右对齐,左边留空
printf("a=%-10d&",a);&&//若实际位数少于定义的宽度:有负号,左对齐,右边留空
printf("a=0d&",a);&&//若实际位数少于定义的宽度:表示宽度的数字以0开始,则右对齐,左边留空
printf("a=%-010d&",a);&//左对齐,0无意义。
运行结果:
a=&&&&&&3456
3.精度:精度格式符以“.”开头,后跟十进制整数。意义是:
&&&&如果输出数字,则表示小数的位数;若实际位数大于所定义的精度数,则四舍五入。若不足则补0;
&&&&如果输出的是字符,则表示输出字符的个数;若实际位数大于所定义的精度数,则截去超过的部分。
#i&nclude
printf("%.3f&",12.3456);
printf("%.9f&",12.3456);
printf("%.3s&","abcdefg");
printf("%.9s&","abcdefg");
运行结果:
12.346&&&&&&&&&&//四舍五入到小数点后三位
12.&&&&//不足补0
4.长度:长度格式符为h,l两种,h表示按短整型量输出,l表示按长整型量输出?????
5.Turbo&C2.0提供的格式字符如下:&
━━━━━━━━━━━━━━━━━━━━━━━━━━&
&&&符号&&&&&&&&&&&&&&&&&&作用&
──────────────────────────&
&&&&%c&&&&&&&&&&&&&&单个字符&&
&&&&%d&&&&&&&&&&&&&&十进制有符号整数&
&&&&%e&&&&&&&&&&&&&&以“科学记数法”的形式输出十进制的浮点数&&如2.451e+02
&&&&%f&&&&&&&&&&&&&&输出十进制浮点数,不带域宽时,保留6位小数
&&&&%g&&&&&&&&&&&&&&选用e或f格式中较短的一个输出十进制浮点数,不输出无效零
&&&&%0&&&&&&&&&&&&&&无输出无符号八进制整数
&&&&%p&&&&&&&&&&&&&&指针的值
&&&&%s&&&&&&&&&&&&&&输出字符串
&&&&%u&&&&&&&&&&&&&&输出无符号十进制整数&
&&&&%x,&%X&&&&&&&&&&输出无符号十六进制整数&(不输出前缀Ox)
━━━━━━━━━━━━━━━━━━━━━━━━━━&
2.&一些特殊规定字符&
━━━━━━━━━━━━━━━━━━━━━━━━━━&
&&&&字符&&&&&&&&&&&&&&&&&&&&&&&&&&&作用&
──────────────────────────&
&&&&&&&&&&&&&&&&&&&&&&&&换行&
&&&&&f&&&&&&&&&&&&&&&&&&&清屏并换页&
&&&&&&&&&&&&&&&&&&&&&&&&回车&
&&&&&&&&&&&&&&&&&&&&&&&&Tab符&
&&&&&xhh&&&&&&&&&&&&&&&&&表示一个ASCII码用16进表示,&
&&&&&&&&&&&&&&&&&&&&&&&&&&其中hh是1到2个16进制数&
━━━━━━━━━━━━━━━━━━━━━━━━━━&
使用这些转义字符时不需要加上%,可单独使用!
&&&&由本节所学的printf()函数,&并结合上一节学习的数据类型,&编制下面的程&
序,&以加深对Turbo&C2.0数据类型的了解。&
&&&&&#i&nclude&
&&&&&#i&nclude&
&&&&&int&main()&
&&&&&&&&&&char&c,&s[20],&*p;&
&&&&&&&&&&int&a=1234,&*i;&
&&&&&&&&&&float&f=3.;&
&&&&&&&&&&double&x=0.54321;&
&&&&&&&&&&p="How&do&you&do";&
&&&&&&&&&&strcpy(s,&"Hello,&Comrade");&
&&&&&&&&&&*i=12;&
&&&&&&&&&&c='x41';&
&&&&&&&&&&printf("a=%d&",&a);&&&&&&
&&&&&&&&&&printf("a=m&",&a);&&&&&
&&&&&&&&&&printf("a=d&",&a);&&&&
&&&&&&&&&&printf("a=-&",&a);&&&&&
&&&&&&&&&&printf("*i=M&",&*i);&&&
&&&&&&&&&&printf("*i=%-4d&",&*i);&&
&&&&&&&&&&printf("i=%p&",&i);&&&&&&
&&&&&&&&&&printf("f=%f&",&f);&&&&&&
&&&&&&&&&&printf("f=6.4f&",&f);&&&&
&&&&&&&&&&printf("x=%lf&",&x);&&&&&&&&
&&&&&&&&&&printf("x=.16lf&",&x);&
&&&&&&&&&&printf("c=%c&",&c);&&&&&&
&&&&&&&&&&printf("c=%x&",&c);&&&&&&
&&&&&&&&&&printf("s[]=%s&",&s);&&&&
&&&&&&&&&&printf("s[]=%6.9s&",&s);&
&&&&&&&&&&printf("s=%p&",&s);&&&&&&
&&&&&&&&&&printf("*p=%s&",&p);&&&&&
&&&&&&&&&&printf("p=%p&",&p);&&&&&&
&&&&&&&&&&getch();&
&&&&&&&&&&retunr&0;&
其他需要注意的一些问题:
1.如果用浮点数表示字符或整型量的输出格式,&小数点后的数字代表最大宽度,&
&&&小数点前的数字代表最小宽度。&
&&&例如:&%6.9s&表示显示一个长度不小于6且不大于9的字符串。若大于9,&&则第9个字符以后的内容将被删除。&
2.使用printf函数时还要注意一个问题,那就是输出表列中的求值顺序。不同的编译系统不一定相同,可以从左到右,也可从右到左。Turbo&C是按从右到左进行的。请看下面两个例子:
&&int&i=8;
&&printf("%d&%d&%d&%d&%d&%d&",++i,--i,i++,i--,-i++,-i--);
&&int&i=8;
&&printf("%d&",++i);
&&printf("%d&",--i);
&&printf("%d&",i++);
&&printf("%d&",i--);
printf("%d&",-i++);
&&printf("%d&",-i--);
运行结果:
这两个程序的区别是用一个printf语句和多个printf&语句输出。但从结果可以看出是不同的。为什么结果会不同呢?就是因为printf函数对输出表中各量求值的顺序是自右至左进行的。在第一例中,先对最后一项“-i--”求值,结果为-8,然后i自减1后为7。&再对“-i++”项求值得-7,然后i自增1后为8。再对“i--”项求值得8,然后i再自减1后为7。再求“i++”项得7,然后i再自增1后为8。&再求“--i”项,i先自减1后输出,输出值为7。&最后才求输出表列中的第一项“++i”,此时i自增1后输出8。
但是必须注意,求值顺序虽是自右至左,但是输出顺序还是从左至右,因此得到的结果是上述输出结果。
补充:最近在调试程序时发现一段代码如下:
&printf(sFormat,"%%0�",THE_NUMBER_LEN);
输出数组后发现sFormat =
d;其中宏THE_NUMBER_LEN定义的为4,发现如果需要通过在printf转化的数组中出现%,那么就使用%%来代替,且后面的所有字符都会直接放入sFormat数组中一直遇到新的%。只有碰到“%+特定字符”,才会把右边对应的变量放入进来。
例如:&printf(sFormat,"ABC%%d%d%%s�bc",THE_NUMBER_LEN,6);输出为ABC�%s6
还有就是发现如果是修改成%0�,输出的字符串就变成&&
�,这样我猜想就是在printf函数时,碰到第一个%0后知道再遇见下一个%前,如果中间没有特定字符d,s,e,f等,通通变成空格,而我在%中间增加两个的非特殊字符后,发现�前面的空格急剧增加,原因就不清楚。故两%之间不能增加其他非特殊字符。
二&Scan函数
&&&&scanf()函数是格式化输入函数,&它从标准输入设备(键盘)&读取输入的信息。&
其调用格式为:&
&&&&&&scanf("&格式化字符串&",&&地址表&);&
&&&&格式化字符串包括以下三类不同的字符;&
&&&&1.&格式化说明符:&格式化说明符与printf()函数中的格式说明符基本相同。&
&&&&2.&空白字符:&空白字符会使scanf()函数在读操作中略去输入中的一个或多&
个空白字符。&
&&&&3.&非空白字符:&一个非空白字符会使scanf()函数在读入时剔除掉与这个非&
空白字符相同的字符。&
&&&&注意:(1)地址表是需要读入的所有变量的地址,&而不是变量本身:
&&&&&&&&&&&&&----如果是一般的变量,通常要在变量名前加上"&";但输出时是用变量名
&&&&&&&&&&&&&----如果是数组,用数组名就代表了该数组的首地址;输出时也是用数组名
&&&&&&&&&&&&&----如果是指针,直接用指针名本身,不要加上“*”;输出时也用该指针即可。
&&&&&&&&&&&&
各个变量的地址之间同","分开。&
&&&&&&&&&&int&i;&
&&&&&&&&&&char&*p,&str[20];&
&&&&&&&&&&scanf("%d",&&i);&
&&&&&&&&&&scanf("%s",&p);&&&&&&&&&&&
&&&&&&&&&&scanf("%s",&str);&
&&&&&&&&&&printf("i=%d&",i);&
&&&&&&&&&&printf("%s&",&p);&&&&&&&&
&&&&&&&&&&printf("%s&",&str);&
&&&&&(2)scanf函数中是否包含空白/非空白字符导致输入格式的不同
&&&&&&&&&&如:scanf("%d,%d",&i,&j);&&&scanf中有,所以输入的格式应该是5,6==&i=5,j=6
&&&&&&&&&&&&&&scanf("%d%d",&i,&j);&&&&可以用空格或回车来分隔两个输入&如&5&6==&i=5,j=6
&&&&&&&&&&&&&&scanf("%d&&%d",&i,&j);&&同上
&&&&&(3)&实际使用scanf()函数时存在一个问题,&下面举例进行说明:&
&&&&当使用多个scanf()函数连续给多个字符变量输入时,&例如:&
&&&&&main()&
&&&&&&&&&&char&c1,&c2;&
&&&&&&&&&&scanf("%c",&&c1);&
&&&&&&&&&&scanf("%c",&&c2);&
&&&&&&&&&&printf("c1&is&%c,&c2&is&%c",&c21,&c2);&
运行该程序,&输入一个字符A后回车&(要完成输入必须回车),&在执行scanf&
("%c",&&c1)时,&给变量c1赋值"A",&但回车符仍然留在缓冲区内,&执行输入语句&
scanf("%c",&&c2)时,&变量c2输出的是一空行,&如果输入AB后回车,&那么输出结&
果为:&c1&is&A,&c2&is&B。&
&&&&要解决以上问题,&可以在输入函数前加入清除函数fflush()(&这个函数的使&
用方法将在本节最后讲述)。修改以上程序变成:&
&&&&&#i&nclude&
&&&&&main()&
&&&&&&&&&&char&c1,&c2;&
&&&&&&&&&&scanf("%c",&&c1);&
&&&&&&&&&&fflush(stdin);&
&&&&&&&&&&scanf("%c",&&c2);&
&&&&&&&&&&printf("c1&is&%c,&c2&is&%c",&c1,&c2);&
在输入字符数据时,若格式控制串中无非格式字符,则认为所有输入的字符均为有效字符。
例如:scanf("%c%c%c",&a,&b,&c);
输入为:d&&&e&&&f
则把'd'赋予a,&'&'&赋予b,'e'赋予c。
只有当输入为:&def
时,才能把'd'赋于a,'e'赋予b,'f'赋予c。
如果在格式控制中加入空格作为间隔,
如:scanf&("%c&%c&%c",&a,&b,&c);
则输入时各数据之间可加空格。
&&char&a,b;
&&printf("input&character&a,b&");
&&scanf("%c%c",&a,&b);
&&printf("%c%c&",a,b);
由于scanf函数"%c%c"中没有空格,输入M&&N,结果输出只有M。而输入改为MN时则可输出MN两字符。
(4)格式字符串的一般形式为:
[输入数据宽度][长度]类型
其中有方括号[]的项为任选项。各项的意义如下:
1)类型:表示输入数据的类型,其格式符和意义如下表所示。
&&&格式&&&&&&&&&字符意义
&&&d&&输入十进制整数
&&&o&&输入八进制整数
&&&x&&输入十六进制整数
&&&u&&输入无符号十进制整数
&&&f或e&&&&&&&&&输入实型数(用小数形式或指数形式)
&&&c&&输入单个字符
&&&s&&输入字符串
2)“*”符:用以表示该输入项,读入后不赋予相应的变量,即跳过该输入值。
&&&&如:scanf("%d&%*d&%d",&a,&b);
当输入为:1&&&2&&&3时,把1赋予a,2被跳过,3赋予b。
3)宽度:用十进制整数指定输入的宽度(即字符数)。
&&&&scanf("]",&a);
只把12345赋予变量a,其余部分被截去。
又如:scanf("MM",&a,&b);
将把1234赋予a,而把5678赋予b。
scanf("MM",&a,&b);
printf("a=%d,b=%d",a,b);
输入&12345&67890
运行结果&a=1234,b=5
4)&长度:长度格式符为l和h,l表示输入长整型数据(如%ld)&和双精度浮点数(如%lf)。h表示输入短整型数据。
使用scanf函数还必须注意以下几点:
1)scanf函数中没有精度控制,如:scanf("%5.2f",&a);是非法的。不能企图用此语句输入小数为2位的实数。
2)在输入多个数值数据时,若格式控制串中没有非格式字符作输入数据之间的间隔则可用空格,TAB或回车作间隔。C编译在碰到空格,TAB,回车或非法数据(如对“%d”输入“12A”时,A即为非法数据)时即认为该数据结束。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 声明语句 的文章

 

随机推荐