第二天 C程序的组成
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://hyhgd.blog.51cto.com/347087/87756 |
一个简单的C程序 实例2.1展示了MULTIPLY.C的源代码。这是一个非常简单的程序。它所做的只是从键盘输入两个数字并且计算它们的乘积。在现阶段,不要担心不能理解程序工作的细节。现在只是增加你对一些C程序的相似的组件的理解,让你更容易地懂得本书中将展示的实例。
在看这个简单的程序之前,你需要知道函数的概念,因为函数是C语言编程的核心。一个函数是一个程序代码中被命名的具有某些功能的区域。通过引用函数的名字,你的程序可以执行函数之中的代码。同样程序可以调用被称为变量的信息到函数之中。并且函数可以将信息返回到程序的主体部分。C语言有两种类型的函数,一个是库函数,被装置于C编译器中作为编译器的一部份,另一个是用户自定义函数,是由你,程序员创建的。你将在本书中学到这两种函数。
注意,正如本书中的所实例一样,实例2.1中的行号并不是程序的一部分,它们只是为了便于识别而存在,所以在编辑时不要输入它们。
实例2.1. MULTIPLY.C.1: /* 程序计算两个数的乘积。 */ 2: #include <stdio.h>3:4: int a,b,c;/*变量定义*/5: 6: int product(int x, int y);/*函数原型*/ 7:8: main()9: {10: /* 输入第一个数字 */ 11: printf("Enter a number between 1 and 100: ");12: scanf("%d", &a);13:14: /* 输入第二个数字 */ 15: printf("Enter another number between 1 and 100: ");16: scanf("%d", &b);17:18: /* 计算并显示结果 */ 19: c = product(a, b);20: printf ("%d times %d = %d\n", a, b, c);21:22: return 0;23: }24:25: /* 函数返回两个变量的乘积 */ 26: int product(int x, int y)/*函数定义*/ 27: {28: return (x * y);29: }Enter a number between 1 and 100: 35Enter another number between 1 and 100: 2335 times 23 = 805
程序的组件 下面讨论了前面简单实例的不同组件。在讨论过程中包含了行号所以你可以轻松地辨别我们讨论的部分。
主函数(main()) (第8至23行) 每个C程序中必须包含一个且只能包含一个主函数。在其最简单的形式中,主函数由函数名main、一对空括号以及一对花括号构成。包含于花括号中的是主函数的函数体的代码。一般情况下,程序的执行由主函数的第一句开始,在主函数的最后一句结束。
#include指令 (第2行)#include指令指导C编译器在编译过程中从包含文件中添加内容到程序中。一个包含文件是包含你的程序或者编译器需要信息的单独的磁盘文件。你永远不需要对它们做修改,因此它们与你的源代码分开存放。所有的包含文件必须以.H为扩展名(比如,STDIO.H)。
使用#include指令来指导编辑器在编译过程中向你的程序增加一个特殊的包含文件。在这个简单的程序中#include指令意思是“增加STDIO.H这个文件夹中的内容”大多数C程序需要一个或多个包含文件。更多关于包含文件的知识将在第21天“编辑器使用”中讨论。
变量的定义 (第4行)一个变量是一个数据存储单元的名称。在程序执行过程中,你的程序使用变量来储存不同类型的数据。在C语言中,一个变量必须先定义后使用。一个变量的定义告诉编译器,变量的名称和它所储存数据的类型。在这个简单的程序中,第4段是变量的定义,int a,b,c;,定义了三个用a,b,c来命名的变量,并且每个变量储存一个整型数据。更多关于变量以及变量的定义将在第三天“储存数据:变量和常量”中学习。
函数原型 (第6行) 一个函数原型给C编译器提供了函数名和包含于程序中的函数变量。它必须在函数调用之前。一个函数原型与函数的定义有明显的不同,函数的定义包含了构成函数体的实际代码段。(函数的定义将在这章后面部份详细讲解)
程序语句 ( 11, 12, 15, 16, 19, 20, 22, 28行) C程序的实际工作是由其语句完成的。C语句在屏幕上显示信息、从键盘读放数据、进行数学运算、调用函数、从磁盘读取文件以及执行其它程序需要执行的操作。本书的大部分内容致力于教你不同的C语句。现在,记住在你的源代码中,C语句通常是一行一句,并以冒号结束。下面是对MULTIPLY.C中的语句段做详细的解释。
printf() printf()语句(11,15,20行)是一个在屏幕上显示信息的库函数。这条语句可以在屏幕上显示简单的文档信息(比如11和15行)、消息信息以及一个或多个变量的值(比如20行)。
scanf() scanf()语句(12和16行)是另一个库函数。它从键盘读取数据并且将数据传递给一个或多个程序变量。
product()
19行的语句调用名称为product()的函数。即,它执行包含于函数product()里的语句。它同样将a和b变量传递给函数。当函数product()里的语句执行完成后,product()向主函数返回一个值。这个值储存于变量c中。
return23和28行都包含有return语句。28行的return语句是product()函数里的一部分。它计算变量x和y的乘积并将其结果返回给product()语句。22行的return语句只是在程序结束之前给操作系统返回个0的值。
函数定义 ( 26行到 29行) 一个函数是一个独立的,自身包含代码,被编写来完成一项特殊功能的代码。每个函数都有一个名字,并且函数中代码是由程序语句中的使用函数名称来执行的,这被称为函数调用。
在26行至29行中被命名为product()的函数是一个用户自定义函数。正如名称所暗示的,用户自定义函数是用户在程序开发的过程中编写的。这是一个简单的函数。它的功能只是将两个变量相乘并将值返回给调用它的函数。在第5天,“函数:基础”,你将学习正确使用函数是形成良好C编程习惯的一个重要部份。
注意在一个真正的C程序中,你不可能只是为了一些简单任务,比如两数乘积而编写一个函数。我这样做仅仅为了举例。
C同样也包含了作为C编译器内容的库函数。库函数完成大部份你的程序需要的常规任务(比如屏幕显示、键盘读入以及磁盘文件读入与读出)。在这个简单程序中,printf()和scanf()都是库函数。
程序注释 ( 1, 10, 14, 18, and 25行) 凡是你程序中以“/*”作为开始,以“*/”作为结束的部分都被称为注释。编译器忽视了所有的注释,所以他们对程序怎样运行完全没有任何影响。你可以往你的注释中加入任何东西,因为它不会影响到你程序的运行。注释可以是一行的一部份,一个整行,或者多行。这里有三个例子: /* 一个整行的注释 */ int a,b,c; /* 一个部份行注释 */ /* 一个 被 分为几行的注释 */然而你不可以嵌套注释(即,你不能在一个注释中再加入另一个)。大部份编译器不接受如下注释: /*/* 嵌套注释 */ */
一些编译器允许嵌套注释,仅管这是一个诱人特点,但你应该避免这样。因为C语言的特点之一是可移稙性,使用像嵌套注释一类的功能会让你的程序的可移稙性受到影响。嵌套注释也可能导致查找错误上的困难。
许多程序员新手认为注释是没必要的,是浪费时间。这是错误的!在你编写代码的时候,算法可能会显得非常清晰。然而当你的程序变得越来越大,越来越复杂的时候,或者当你需要修改你六个月以前写的程序的时候,你将发现注释是有用的。现在是你养成为程序结构和算法自由注释习惯的时候。
注意:许多人开始在他们的程序中使用一个新的注释方式。在C++和java中,你可以使用双斜杠来标注注释。这里有两个例子:
//这一整行都是注释
int x;//注释由斜杠开始。
这两个斜杠标明了后面是注释。仅管一些C编译器支持这个注释方式,但如果你对可移稙性感兴趣的话,你最好避免使用这种方式
最好对你的程序源代码增加充足的注释,特别是给对你或对其他日后帮你修改源代码的人来说不清楚的语句或函数做充分的注释。
不要对一些你已熟知的语句增加一些不必要的注释。比如输入 /* 这将在屏幕上显示“Hello,World!”*/ printf("Hello World!");
就显得太繁琐了,除非你完全不知道printf()函数以及它的作用。
最好形成一个有用的风格。过于简单或过于详细都不好,也不要太冗长以至于你花费过多的时间和精力在注释上!
花括号 ( 9, 23, 27,和 29行)使用花括号将构成C语言函数的程序段包起来—包括main()函数也是。一组一个或多个语句包含在一个花括号中被称为一个块。在后续章节中你将看到,C语言的块有许多用法。
运行程序 按部就班地输入、编译以及运行MULTIPLY.C。它提供了使用编辑器和编译器的额外练习。回忆第一天“开始学习C语言”中学习的编程步骤:
2. 运行你的编辑器;
3. 完全输入实例2.1中MULTIPLY.C的源代码,但得省掉行号和冒号;
4.保存程序文件;
5.对你的编译器输入正确的命令对程序进行编译、链接。如果没有出现错误,你可以在命令提示中输入multiply来运行程序
6. 如果有一个或多个错误信息,返回第二步并改正错误。
关于准确性的注意事项 电脑是准确、快速的,但它是完全按照指令逐字翻译的。它并不能够改正你最简单的错误,它的每一步都完全按你输入的指令进行,而并不是按你所想的进行。
这同样适用于你的C源代码。你程序中的一个简单的输入错误可能会导致C编译器停止、中断甚至于崩溃。很幸运,仅管编译器并不足够智能来改正你的错误(每个人都会出错!),但它足够聪明来发现并指出你的错误(在前面章节中你已经看到了编译器怎样报告错误以及你怎么翻译那些错误信息)。
对程序组件的回顾 到现在我们已经讲解了一个程序的所有组件,在看到任意程序时候你应该能够找到相同之处。看实例2.2你是否能够分别出不同的组件。
实例2.2. LIST_IT.C.1: /* LIST_IT.C—这个程序展示了一个由行号构成的列表! */ 2: #include <stdio.h>3: #include <stdlib.h>4:5: void display_usage(void);6: int line;7:8: main( int argc, char *argv[] )9: {10: char buffer[256];11: FILE *fp;12:13: if( argc < 2 )14: {15: display_usage();16: exit(1);17: }18:19: if (( fp = fopen( argv[1], "r" )) == NULL )20: {21: fprintf( stderr, "Error opening file, %s!", argv[1] );22: exit(1);23: }24:25: line = 1;26:27: while( fgets( buffer, 256, fp ) != NULL )28: fprintf( stdout, "%4d:\t%s", line++, buffer );29:30: fclose(fp);31: return 0;32: }33:34: void display_usage(void)35: {36: fprintf(stderr, "\nProper Usage is: " );37: fprintf(stderr, "\n\nLIST_IT filename.ext\n" );38: }C:\>list_it list_it.c1: /* LIST_IT.C – 这个程序展示了一个带行号的列表! */ 2: #include <stdio.h>3: #include <stdlib.h>4:5: void display_usage(void);6: int line;7:8: main( int argc, char *argv[] )9: {10: char buffer[256];11: FILE *fp;12:13: if( argc < 2 )14: {15: display_usage();16: exit(1);17: }18:19: if (( fp = fopen( argv[1], "r" )) == NULL )20: {21: fprintf( stderr, "Error opening file, %s!", argv[1] );22: exit(1);23: }24:25: line = 1;26:27: while( fgets( buffer, 256, fp ) != NULL )28: fprintf( stdout, "%4d:\t%s", line++, buffer );29:30: fclose(fp);31: return 0;32: }33:34: void display_usage(void)35: {36: fprintf(stderr, "\nProper Usage is: " );37: fprintf(stderr, "\n\nLIST_IT filename.ext\n" );38: }
分析: LIST_IT.C与你在第一天的操作练习7中输入的PRINT_IT.C相似。实例2.2在屏幕上显示了经保存的C程序列单,而不是通过打印机将它们打印出来。
看这个实例,你能够找到那些不同之处。主函数(main())从8行开始直到23行结束;2和3行都包含有#include指令;第6,10以及11行都有变量定义;第5行有个函数原型,void display_usage(void)。 这个程序有很多语句(13,15,16,19,21,22,25,27,28,30,31,36以及37行都是)。Display_usage()的定义从34行38行。花括号包含了整个程序的代码段。最后,只有在第1行有注释。对多数程序来说,你不应该只包含一条注释。
LIST_IT.C调用了许多函数。它只调用了一个用户自定义函数,display_usage()。它所使用的库函数包括:16行和22行的exit(),19行的fopen(),21,28,36和37行的fprintf()27行的fgets以及30行的fclose()。这些库函数将在本书后面详细介绍。
总结 这章很短,但它很重要,因为它向你介绍了大多数C程序组件。你已知道,每个C程序中必需的部分是主函数;程序的实际工作是由程序语句指导电脑按你的想法运行。同时,这章也向你介绍了变量以及变量的定义,并且告诉你怎样在源代码中使用注释。
除了主函数外,一个C程序可以使用两个附加函数:库函数,作为编译环境的一部分被编译器提供;用户自定义函数,由程序员创建。
Q&AQ程序中的注释有什么作用?
A 注释只对程序员有效。当编译器将源代码转化为目标代码的时候,它将注释和空格都忽略掉。这就意味着,他们对可执行程序没有任何作用。的确,注释让你的源代码更庞大,但这并无影响。总之,你应该使用注释以及空格来使你的源代码尽可能的容易理解,容易掌握。
Q函数块与函数语句有什么区别?
A.函数块是包含于花括号中一组语句。一个块可以在多数函数语句使用的地方使用。
Q 怎样知道库函数是有效的?
A 许多编译器都有操作手册来说明库函数的功能,它们通常是按字母顺序进行排列。另一个获得库函数是否有效的方法是买一本罗列它们的书。在附录E“常用C函数”中列出了许多可用函数。在你了解大多数C语言后,阅读附录获取函数知识是个很好的方法,这会让你不再重写一些库函数(就像没必要再重造车轮一样)。
专题练习专题练习给你提供有测试问题来帮助你巩固对所学知识的理解,并且提供操作练习来让你获取编程的经验。在开始下一章学习前,试着理解小测试和操作练习的答案。所有答案提供于附录G中的“答案”里。小测试1. 一组由一个或多个C语句包含于一个花括号里的程序段是什么?
2.每个C程序必须包含的一个组件是什么?
3. 怎样添加注释,为什么使用注释?
4.什么是函数?
5. C语言提供两种类型的函数,它们分别是什么,它们有哪些不同?
6. #include指令有什么作用?
7. 能否嵌套使用注释?
8. 注释是否能够超过一行?
9.包含文件的另一个名称叫什么?
10.什么是包含文件?
操作练习1.写个尽量小的程序
2. 仔细观察下面的程序: 1: /* EX2-2.C */2: #include <stdio.h>3:4: void display_line(void);5:6: main()7: {8: display_line();9: printf("\n Teach Yourself C In 21 Days!\n");10: display_line();11:12: return 0;13: }14:15: /* print asterisk line */16: void display_line(void)17: {18: int counter;19:20: for( counter = 0; counter < 21; counter++ )21: printf("*" );22: }23: /* end of program */
a. 哪些行有函数语句?
b. 哪些行有变量定义?
c. 哪些行是函数原型?
d.哪些行是函数定义?
e. 哪些行有注释?
3. 写个注释的例子。
1: /* EX2-4.C */2: #include <stdio.h>3:4: main()5: {6: int ctr;7:8: for( ctr = 65; ctr < 91; ctr++ )9: printf("%c", ctr );10:11: return 0;12: }13: /* end of program */
5. 下面的程序有什么作用?(输入、编译、运行它) 1: /* EX2-5.C */2: #include <stdio.h>3: #include <string.h>4: main()5: {6: char buffer[256];7:8: printf( "Enter your name and press <Enter>:\n");9: gets( buffer );10:11: printf( "\nYour name has %d characters and spaces!",12 strlen( buffer ));13:14: return 0;15: }
|


恒逸
博客统计信息
热门文章
最新评论
友情链接