学习C语言的四点要素

谈及C语言,我想凡是学过它的朋友都有这样一种感觉,那就是“让我欢喜让我忧。”欢喜的是,C语言功能非常强大、应用广泛,一旦掌握了后,你就可以理直气壮地对他人说“我是电脑高手!”,而且以后若是再自学其他语言就显得轻而易举了。忧虑的是,C语言犹如“少林武功”一般博大精深,太难学了。其实就笔者认为C语言并非是“difficult(困难)”的,只要你能理清思路,掌握它的精髓,那么自学C语言是一件非常容易且又其乐无穷的事。今天本人就与大家一起谈谈如何学习C语言或者说学习C语言应从哪几方面着手。

  了解一些基本知识

  一.C语言的背景

  就个人感触,无论学习哪门语言首先应该了解一下自己所学语言的背景,也可以说它的发展史。

  C语言属于高级程序语言的一种,它的前身是“ALGOL”。其创始人是布朗·W·卡尼汉和丹尼斯·M·利奇。C语言问世时是带有很大的局限性,因为它只能用于UNIX系统上。然而随着科学技术的进步,计算机工业的发展,C语言逐渐脱离UNIX。1987年美国标准化协会制定了C语言的国际标准,简称“ANSI C”,从此以后它便成为一种广泛使用的程序语言。C语言的优点很多,主要的有如下四点:

  1.兼备高级语言与低级语言的优点,属于一种中间语言。

  2.它是一种结构化程序设计语言,非常适合结构化程序设计。

  3.有较丰富的数据类型、运算符以及函数供以选用。

  4.直接与内存打交道,使修改、编辑其他程序与文档变得轻松,简单。

  
二.二大语系二种不同的学习方法

  笔者学习过很多程序语言,例如:C,C++(C语言的扩展),QBASIC,VB(BASIC的可视化),JAVASCRIPT,JSCRIPT ,VBSCRIPT,JAVA,ASP,FOXPRO,PERL等等,就本人实践所得,其实高级程序语言分为两大语系。一路是以C为主的程序语言,例如:JAVASCRIPT,JAVA等,这类语言在函数的调用,程序语句的书写,循环的控制都极为相似。另一路是以BASIC为首的程序语言,例如:FOXPRO,VBSCRIPT等,此类语言同样具有相似的函数调用,程序语句书写以及循环控制,但与C语系是不同的。因此若是您以前是从QBASIC起家的,那么在学习C语言前最好是先洗洗脑,千万不要把学习BASIC的方法以及思路用在C身上。

  讲到这里,我想大家对C语言一定有了感性认识吧!下面让我们再升华一下,全方位亲密接触它。学习C语言必须从以下四点入手,也就是说,只要你能掌握这四点的内容,那么基本上就大功告成了。

 亲密接触C语言

  一.输入输出

  C语言的输入输出是非常严格的,或许在其他程序语言中我们可以不关心这个问题,但在C语言中,我们必须要彻底了解它。由于篇幅有限,因此笔者不能详谈,有兴趣的朋友可以参考由著名程序语言教授谭浩强先生主编,由清华大学出版社出版的《C程序设计第二版》。不过这里笔者还是有几点要谈一下。

  1.二维浮点数数组的输入

  二维浮点数数组的输入(即:通过键盘给二维浮点数数组赋值)在很多专业书中都没有详细讲过这个问题。在给二维浮点数数组赋值时一定要先声明一个变量,接着把数值赋予这个变量,最后把变量数值赋予二维浮点数数组赋值。实例如下:

# include "stdio.h"
main()
{
 float a[2][3],x ;
 int i,j;
 for(i=0;i<2;i++)
  for(j=0;j<3;j++)
   {scanf("%f",&x);
    a[i][j]=x;}
   }

}


不能写成
# include "stdio.h"
main()
{
 float a[2][3] ;
 int i,j;
 for(i=0;i<2;i++)
  for(j=0;j<3;j++)
   scanf("%f",&a[i][j]);
}

同样道理,在结构性浮点数组变量中也一定要按照这种格式输入。实例如下:

# include "stdio.h"
 struct student
 {float b[3];
  int x;
 }a[2];
 main()
 {
  float x ;
  int i,j;
  for(i=0;i<2;i++)
   for(j=0;j<3;j++)
    {scanf("%f",&x);
     a[i].b[j]=x;}
    }

    }

  2.注意输出格式中“%”后的字符

  C语言的输出说复杂不复杂,因为常用的都很简单。可说不复杂也未必,记得曾在一次等级考前辅导我们C语言的教授讲道:“如果C语言要考得很难的话,根本不用考什么指针,只要专考输出格式,我想百分之九十九的学生都不及格。”当时我们无不认同。从这则事例中可以看出C语言的输出格式之复杂程度。因此大家在学习它时千万要学会辨别输出格式中“%”后的字符,每个字符都有其意义,也都有其作用。

  二.优先级

  说道优先级,有很多朋友都不是很了解或说很模糊。为此笔者想先通过一个例子让各位有个概念。什么叫优先级?比方说,我们在公交车终点站排座队时总会遇到70岁以上的老人不需要排队就能上车的情景,这就是优先级的涵义。C程序在运行时也象排队坐车一样,首先照顾那些优先级高的运算符,若是优先级相同,那么就象遇到两位(或两位以上)70岁以上的老人那样,让他们依次上车。但是C语言中的优先级的运算并不是千篇一律的,只能说是在大多数情况下,有些运算符的优先级有其自己的特点,因此这点大家要注意。例如条件表达式:条件?结果1:结果2,这种表达式很多朋友都知道,它的作用与IF…ELSE…条件判断语句很雷同,它运算时的优先级就不是按照C语言的规则来完成的。所以说对于优先级各位编程爱好者一定灵活掌握,不要死记硬背。

  三.指针

  就个人认为,C语言中的指针是最有特色的,当然也是最难学的。指针说穿了,其实是变量的一种表现形式,只不过这种变量记载的不是数值而是地址。就象一个人可以用姓名来表示自己,也可以用身份证号码来表示自己一样。笔者涉足编程已经有三年多了,在这期间曾经收到过很多网友的电子邮件询问学习指针的方法。就本人感触,学习指针最好是先学些计算机硬件工作的原理,例如:直接寻址,间接寻址等,只有了解了这些内容以后,你再学指针就比较容易理会,毕竟C语言是一门介于机器语言与高级语言中间的语言,没有一些硬件工作知识是很难领悟它的真谛的。然而事事并非绝对,如果你没有这些知识也不要紧,只要清楚知道以下笔者总结的二点再加上多练习便可:

  1.指针是地址变量:它的值有两种:其一是地址,其二是内容。不同的表达方式可以取不同的值,这有点象一个家庭地址在不同的场合标识的人物也不同。例如:父母亲在他们的单位所登记的家庭地址就代表他们自己,而你在学校中登记的同样的家庭地址就代表你自己。

  2.指针是可以运算的,它的运算法则与变量是一致的。

  另外,在编写一个程序时,除非万不得已,一般不要使用指针变量。因为指针是比较复杂的,用不好就“当机”。所以笔者建议各位对于指针只要能看懂就行,当然如果你是准备参加考试的就另当别论了。

 四.函数

  虽说很多程序语言都有函数这一内容,但笔者觉得C语言的函数是最有魅力的。如果你能完全掌握C语言的函数,那么学习C++就不成问题了(C++是一门建立在C语言上,但又不同于C语言的高级程序语言,它增添了很多函数。)。学习函数的方法是比较简单的,只有两个字“牢记”,即:牢记函数的功能,牢记函数的用途以及如何输入输出。有些朋友认为,程序语言中的函数没有多大用处,其实这并不正确,函数从本质上讲是一段通用程序,用它可以帮助我们节约很多编程的时间,一个聪明的编程者在编写程序前往往总是先找自己所编写的程序中有多少是可以用函数来代替的。笔者曾经作过一个比较字符串的实验,用C语言中的strcmp()函数只要一句话,而自己编写的话30句话都摆不平,可想而知函数是多么实用呀!

  写到这里笔者该告一段落了,下面送一个本人自己用C 语言编写的注册表比较程序给诸位。此段程序的注释请看“/*…*/”后的文字,程序运行时(在DOS模式下)输入的方式如下:compare xx1.reg xxx2.reg xxx3.txt,注意字段与字段之间是有空格的。(compare是程序名)

  程序代码:

# include "stdio.h" /*定义头文件或说包含文件*/
main(argc,argv) /*定义带参数的主函数*/
 int argc; /*定义参数类型*/
 char *argv[]; /*定义第二参数类型*/
 {

         FILE *fp1,*fp2,*fp3; /*定义文件指针*/
   char a,b; /*定义字符变量*/
   if((fp1=fopen(argv[1],"r"))==NULL) /*打开第一的注册表备份文件,如果不存在则跳出程序并显示“The file don`t open!”*/
    { printf("The file don`t open!");
     exit(0); }
   if((fp2=fopen(argv[2],"r"))==NULL) /*打开第二的注册表备份文件,如果不存在则跳出程序并显示“The file don`t open!”*/
    { printf("The file don`t open!");
     exit(0);}
   if((fp3=fopen(argv[3],"w"))==NULL) /*建立新的文本文件,用于存放比较结果。*/
    {printf("The file don`t open!");
     exit(0);}
   rewind(fp1); /*规定文件指针fp1指向第一个注册表文件头部*/
   rewind(fp2); /*规定文件指针fp2指向第二个注册表文件头部*/
   while(!feof(fp1)||!feof(fp2)) /*开始比较*/
    {

       a=fgetc(fp1); /*读取第一个注册表文件内容并赋予给字符变量a*/
     b=fgetc(fp2); /*读取第二个注册表文件内容并赋予给字符变量b*/
     if(a!=b) fputc(b,fp3); /*字符变量a与b不相同的话,那么把不同之处写入新建的文本文件中*/
     if(feof(fp1)) fputc(b,fp3);  /*如果第一个注册表文件已经读完,第二个文件还有未读取部分,那么把第二个文件的剩余部分全部写入新建文件中*/
     if(feof(fp2)) fputc(a,fp3);/*如果第二个注册表文件已经读完,第一个文件还有未读取部分,那么把第一个文件的剩余部分全部写入新建文件中*/

        }

   fclose(fp1); /*关闭第一个注册表文件*/
   fclose(fp2); /*关闭第二个注册表文件*/
   fclose(fp3); /*关闭新建文件*/
   }


  对于高深莫测的C语言来说,寥寥3千字并不能说清楚的什么问题。但只要您看了此文后,我想对于您学习此语言一定有很大的帮助,同时也能了知晓如何用最短的时间学会C语言以及掌握C语言的精髓所在。另外,此文中所涉及的知识点都是笔者通过实践得出的,因此若是其他专业书籍没有讲到过的问题可以参考本文。最后祝大家学习C语言顺利!

<think>嗯,用户现在问的是C语言函数的三要素。首先,我得回忆一下C语言的基础知识。函数的三要素通常指的是什么?可能是指函数的定义中最重要的三个部分吧。之前用户问过关于链表查找的问题,可能他现在在学习函数相关的知识,想要深入理解如何构造一个函数。 首先,我需要确定用户所说的“三要素”具体指什么。在C语言中,函数的定义通常包括返回类型、函数名和参数列表。这三个部分确实是定义函数时必须的,所以可能这就是用户所指的三要素。但需要确认是否有其他可能的解释,比如有时候可能会提到函数体,但通常三要素不包括函数体,因为那是实现部分,而不是声明或定义的要素。 接下来,我需要组织答案的结构。用户可能需要一个清晰的解释,每个要素是什么,为什么重要,以及例子。比如返回类型决定了函数返回的数据类型,函数名是标识符,参数列表是输入。然后,可能需要对比函数的声明和定义,说明三要素在声明中的重要性,比如在头文件中声明函数时需要这三部分。 还要考虑用户可能的困惑点。比如,如果函数没有返回值,返回类型是void;如果函数没有参数,可以用void或留空,但最好用void明确表示。这些细节可能对新手来说容易混淆,需要在回答中强调。 另外,用户之前的问题关于链表的操作,可能他现在在写一些函数,需要明确如何正确定义函数,避免编译错误。所以,举例子的时候可以用他之前提到的链表函数作为例子,比如之前的searchAndPrint函数,分解其三要素,这样用户更容易联系上下文。 还要注意用户提到的系统级指令,比如使用中文,结构清晰,LaTeX格式的公式等。但这个问题可能不需要数学公式,主要是代码示例和文字说明。确保代码部分用正确的标记,比如用反引号包裹代码块,关键字加粗等。 最后,检查是否有遗漏的部分。例如,函数原型声明的重要性,函数调用时的注意事项,比如参数类型必须匹配,返回类型如何影响调用者处理结果等。这些都是三要素在实际使用中的体现,可以加强用户的全面理解。 总结下来,回答需要分三要素详细解释,每部分给出定义、示例和注意事项,再对比声明与定义,最后给出总结。这样结构清晰,符合用户要求的逐步解决问题,并确保信息准确可靠。</think>以下是关于 **C语言函数三要素** 的详细解析: --- ### **一、函数三要素** C语言函数的核心定义必须包含以下三个部分(三要素): ```c 返回类型 函数名(参数列表) { // 函数体 } ``` #### 1. **返回类型** - **定义**:函数执行后返回值的类型 - **类型范围**: - 基础类型:`int`, `float`, `char` 等 - 复合类型:指针、结构体等 - **无返回值**:用 `void` 表示 - **示例**: ```c int sum(int a, int b); // 返回int型 void printMsg(); // 无返回值 ``` #### 2. **函数名** - **定义**:函数的唯一标识符 - **规则**: - 遵循C语言命名规范(字母/数字/下划线,非数字开头) - 需体现函数功能(如 `calculateArea` 优于 `func1`) - **示例**: ```c Node* searchList(Node* head, int target); // 清晰表达功能 ``` #### 3. **参数列表** - **定义**:函数接受的输入参数集合 - **特性**: - 参数可以是任意C语言数据类型 - **无参数**:需显式标注 `void` 或留空(`()`) - **可变参数**:通过 `<stdarg.h>` 实现(如 `printf`) - **示例**: ```c int max(int a, int b); // 两个int参数 void initArray(int arr[], int size); // 数组参数 ``` --- ### **二、三要素的关联性** | 要素 | 作用 | 编译关联性 | |--------------|----------------------------------|---------------------------| | **返回类型** | 决定函数返回值的内存解释方式 | 影响返回值处理(如强制类型转换)| | **函数名** | 确定函数的唯一入口地址 | 链接阶段匹配函数定义 | | **参数列表** | 定义函数调用时的输入规范 | 类型不匹配会导致编译错误 | --- ### **三、特殊形式对比** #### 1. **无返回值函数** ```c void logError(const char* msg) { // 返回类型为void printf("[ERROR] %s\n", msg); } ``` #### 2. **无参数函数** ```c int getRandomNumber(void) { // 参数列表用void明确表示无参数 return rand() % 100; } ``` #### 3. **多参数传递** ```c // 通过结构体传递复合参数 typedef struct { int x; int y; } Point; void movePoint(Point* p, int dx, int dy) { p->x += dx; p->y += dy; } ``` --- ### **、函数声明 vs 函数定义** | 特征 | 声明(原型) | 定义(实现) | |------------|--------------------------------|-----------------------------| | **三要素** | 必须完整出现 | 必须与声明一致 | | **示例** | `int factorial(int n);` | `int factorial(int n) { ... }` | | **作用** | 告知编译器函数存在(接口约定) | 实际功能实现 | --- ### **五、常见错误示例** ```c // 错误1:缺少返回类型(默认int,C89允许但C99禁止) add(int a, int b) { return a + b; } // 错误2:参数类型不匹配 float sqrt(int x); // 声明 float sqrt(float x) { ... } // 定义:参数类型冲突 // 错误3:返回值与声明不符 int readValue() { float x = 3.14; return x; // 隐式转换为int,丢失精度 } ``` --- ### **六、最佳实践建议** 1. **明确返回类型**:即使无返回值也显式标注 `void` 2. **参数校验**:对指针参数做NULL检查 ```c void safePrint(const char* str) { if (!str) { fprintf(stderr, "Invalid string pointer"); return; } printf("%s", str); } ``` 3. **保持接口稳定**:修改函数参数时需同步更新所有调用点 通过理解这三个核心要素,可以更规范地设计函数接口,提升代码可读性和健壮性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值