| |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| -> C++知识库 -> C语言程序设计基础 -> 正文阅读 |
|
|
[C++知识库]C语言程序设计基础 |
C语言程序设计基础文章目录
前言今天终于把这个笔记弄完了。再整理笔记期间经历了几次危机——文档丢失,数据出错等等,甚至一度不想写这个了,还是感谢d2hoDQo=,这个笔记是整理了大一所学习的一些知识,以及结合了老师上课所讲制作的,希望能帮助大家。不足的地方希望指出。 后续还会进行一些补充。。。 第1章 c语言编程1.1 课程地位
1.1.1 C语言能用来做什么?
1.2 如何学好C语言
1.2.1 课程目标
1.3 什么是程序
1.3.1 日常生活中的程序
1.3.2 计算机中的程序
程序:为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合 1.4 C 语言简介
1.4.1 特点结构化的程序设计语言:层次清晰,便于按模块化方式组织程序,易于调试和维护 语句简洁:学习时入门相对容易,C 语言很好地总结了其他语言提出的程序库概念 功能强大:既可用于系统软件的开发,也适合于应用软件的开发。 移植性好:只要对这种语言稍加修改,便可以适应不同型号机器或各类操作系统。 1.4.2 C语言发展历史
机器语言:CPU指令系统,由0、1序列构成的指令码组成
汇编语言:用助记符号描述的指令系统,可进行地址、位操作
高级语言:可读性,移植性好,编写应用程序一般较难实现汇编语言的某些功能
C语言兼有高级和低级语言的功能适合写系统软件和应用软件又称中级语言 1.4.3 C 程序的基本结构
1.4.4 C 程序中的注释
1.4.5 高级语言的编译和执行
高级语言程序
编译程序解释程序编译器解释器
机器代码
计算机硬件
高级语言的编译和执行
1.4.6 编译和执行C程序
C源程序
编译
目标文件
连接
可执行程序
C语言函数库
编译和执行C程序
源程序:是用户创建的文件,以==“.c”或者“.cpp”==为文件扩展名保存 目标文件:是编译器的输出结果。这类文件的常见扩展名为==“.o”或“.obj”== 可执行文件:是连接器的输出结果。可执行文件的扩展名为==“.exe”== 头文件:含有函数的声明和预处理语句,用于帮助访问外部定义的函数。头文件的扩展名为==“.h”==。 1.4.7 C程序的开发过程
分析问题
编制程序
编译
连接
调试运行
完成
C程序的开发过程
1.5 Visual Studio IDE工具
Microsoft Visio Studio 2008下载地址
安装过程CSDN搜Visual Studio安装就会有 另外一个比较好的编辑工具: Source Insight 学习用:Dev-C++ 1.6 小结
第2章 变量和数据类型2.1 回顾
2.2 本章目标
2.3 C语言中的基本元素
2.3.1 常量常量用于定义具有如下特点的数据:
2.3.2 变量
存储 Rate
10
将值存储为DiscAmt
0.5
将值存储为Result
9.5
Rate-DiscAmt
Rate * 5%
2.3.3 声明和使用变量
给变量赋值,除了给一个直接的值以外,还可以通过计算获得。 2.3.4 变量命名变量的命名规则:
2.4 基本数据类型
数据类型
数值
非数值
整型
非整型
int
short int
long int
float
double
char
2.4.1 整型
2.4.1.1 使用整型变量声明:
可按如下方式初始化:
在同一语句中可以声明多个类型相同的变量 2.4.2 浮点型
2.4.2.1 单精度浮点型声明:
初始化:
2.4.2.2 双精度浮点型声明:
初始化:
2.4.3 字符型char
2.5 输入/输出函数2.5.1 printf函数实例
2.5.2 转换字符串
2.5.3 转义序列
2.5.4 scanf 函数
实例
2.5.5 算术运算符
2.5.5.1 算术运算符示例
2.5.6 类型转换2.5.6.1 自动类型转换原则:把表示范围小的类型的值转换到表示范围大的类型的值
short
int
long
float
double
2.5.6.2 强制类型转换
2.5.7 接受并显示字符2.5.7.1 getchar() 函数语法:
2.5.7.2 getchar()和putchar()示例
2.6 小结
第3章 条件判断3.1 回顾
3.2 本节目标
3.3 多重条件判断
有
没有
有
没有
开始
是否有黄瓜
做黄瓜沙拉
可以上菜
结束
是否有胡萝卜
做胡萝卜沙拉
不能上菜
3.4 多重条件结构
多重条件结构
多重if
嵌套if
switch结构
3.5 多重 if 结构
3.6 嵌套 if 结构
C语言规定,每个 else 部分总属于前面最近的那个缺少对应的 else 部分的 if 语句。 提倡使用大括号括起来以避免看起来有二义性。 示例:
3.7 switch 结构
在使用switch结构时应注意以下几点:
3.8 比较多重 if 和 switch 结构
示例
3.9 条件运算符
示例
3.10 小结
第4章 循环结构while4.1 回顾
4.2 目标
4.3 循环的必要性
4.3.1 为什么需要循环控制例如:全班有50个学生,统计各学生三门课的平均成绩。
用while循环结构实现
4.4 while 循环4.4.1 while 循环的一般语法
规则1:
规则2:
4.4.2 工作原理
4.4.3 while循环的特点是先判断条件表达式,后执行循环体语句 4.4.4 例题4.4.4.1 示例1求1+2+3+…+100,即
4.4.4.2 示例2
4.4.4.3 示例3
4.5 do—while4.5.1 Do-while 循环的一般语法:
4.5.2 工作原理它先执行循环体中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。 4.5.3 do–while语句的特点先无条件地执行循环体,然后判断循环条件是否成立 4.5.4 例题4.5.4.1 示例1
解题思路
4.5.4.2 示例2
4.6 嵌套循环4.6.1 嵌套 while 循环4.6.1.1 语法
4.6.1.2 示例用“*”打印一个直角三角形图案。
4.6.2 嵌套 do-while 循环4.6.2.1 语法
4.6.2.2 示例
4.7 小结
第4章 循环结构for4.1 回顾
4.2 目标熟练使用for循环 理解break 和 continue 语句的用法 熟练使用嵌套循环 4.3 用for 语句实现循环
4.4 语法
4.5 工作原理
4.6 示例
4.7 逗号运算符
|
| datatype | arrayName | size |
|---|---|---|
| 类型说明符 int、char、float … | 数组名 | 常量表达式:数组大小 |
示例
int num[50];
char list_of_initials[20];
double pressure_level[6];
#define LIMIT 20
. . .
int emp_codes[LIMIT];
定义一维数组的一般形式为:类型符 数组名[常量表达式];
int a[4+6]; //合法
int n=10; //不合法
int a[n];
- 在定义数组并对其中各元素赋值后,就可以引用数组中的元素
- 注意:只能引用数组元素而不能一次整体调用整个数组全部元素的值
引用数组元素的表示形式为: 数组名[下标]
a[0]=a[5]+a[7]-a[2*3] //合法
int n=5,a[10]; //合法
a[n]=20;
int arr[10] = {10,9,8,7,6,5,4,3,2,1,0}; //错误!越界了
int arr[10] = {9,8,7,5}; //正确,后面的6个元素未初始化
int arr[] = {9,8,7}; //正确:元素个数为 3
int arr[]={}; //错误,到底是几个元素?
在定义数组的同时,给各数组元素赋值
int a[10]={0,1,2,3,4,5,6,7,8,9};
int a[10]={0,1,2,3,4};//相当于
int a[10]={0,1,2,3,4,0,0,0,0,0};
int a[10]={0,0,0,0,0,0,0,0,0,0};//相当于
int a[10]={0};
int a[5]={1,2,3,4,5};//可写为
int a[ ]={1,2,3,4,5};
为一维数组动态赋值
float price[4];
printf(“Enter prices of 4 books\n”);
for (i = 0;i <= 3; i++)
{
scanf(“%f”,&price[i]);
}

例 对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,要求按逆序输出。
- 解题思路:
- 定义一个长度为10的数组,数组定义为整型
- 要赋的值是从0到9,可以用循环来赋值
- 用循环按下标从大到小输出这10个元素
#include <stdio.h>
int main()
{ int i,a[10];
for (i=0; i<=9;i++) //使a[0]~a[9]的值为0~9
a[i]=i;
for(i=9;i>=0; i--)//先输出a[9],最后输出a[0]
printf("%d ",a[i]);
printf("\n");
return 0;
}
| a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | a[8] | a[9] |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
示例

# include <stdio.h>
void main()
{
int i;
float item_rate[5],total=0;
printf("\n 请输入商品价格:");
for(i=0;i<5;i++)
{
scanf("%f",&item_rate[i]);
total=total+item_rate[i];
}
printf(“\n 所有商品的合计费用:%f\n ",total);
}
datatype arrayName[rowsize] [colsize];
int num[4] [2];
4 X 2 = 8 8*sizeof(int)字节

int books[4][2] = {{11, 1294},{22,450}, {33,4000}, {44,79}}; //对
int arr[ ][3] = { {1,2,3}, {4,5,6} }; //对
int arr[2][ ] = { {1,2,3}, {4,5,6} }; //错误
例

int i, j, num[4][2];
for (i = 0; i <= 3; i++)
{
for (j = 0; j <=1 ; j++)
{
scanf("%d",&num[i][j]);
}
}
示例
int i,j,student[3][2];
for(i = 0;i < 3;i++)
{
printf("\n 输入学号 %d 两个学期的成绩:",i+1);
for(j = 0;j < 2;j++)
scanf("%d",&student[i][j]);
}
printf("\n 学员的学号及其两个学期的成绩为:\n ");
printf("\n \t学号\t第一学期\t第二学期");
for(i = 0;i < 3;i++)
{
printf("\n\t");
printf("%d\t",i+1);
for(j = 0;j < 2;j++)
printf("%d\t\t",student[i][j]);
printf("\n ");
}

求一组数中的最大值和最小值 。
void main()
{
int num[5],max,min,i;
printf("请输入5个数:\n");
for(i=0;i<5;i++)
scanf("%d",&num[i]);
max=num[0];
min=num[0];
for(i=1;i<5;i++)
{
if (max<num[i])
max=num[i];
if (min>num[i])
min=num[i];
}
printf("\n最大值为:%d",max);
printf("\n最小值为:%d\n",min);
}
//读入5个值保存在数组中,求最大值和最小值
输入10个数,保存在一个数组中,在数组中查找某个数,给出是否找到的信息。如果找到了,要求输出该数在数组中所处的位置;如果找不到,输出“没有找到!”。
#define N 10
……
for(i=0;i<N;i++)
scanf("%d",&num[i]);//读入10个值保存在数组中
printf("\n 请输入要查找的数:");
scanf("%d",&search);
for (i=0;i<N;i++)
{
if (num[i]==search)
break;
} //在数组中查找,一旦找到,通过break语句跳出循环
if(i<N)
printf("\n 在数组的第 %d 个位置找到了数字 %d !\n",i+1,search);
else
printf("\n 没有找到!\n");
……
有10个地区的面积,要求对它们按由小到大的顺序排列。
解题思路:
- 排序的规律有两种:一种是“升序”,从小到大;另一种是“降序”,从大到小
- 把题目抽象为:“对n个数按升序排序”
- 采用起泡法排序
for(i=0;i<5;i++)
if (a[i]>a[i+1])
{ t=a[i];a[i]=a[i+1];a[i+1]=t; }

for(i=0;i<4;i++)
if (a[i]>a[i+1])
{ t=a[i];a[i]=a[i+1];a[i+1]=t; }

for(i=0;i<3;i++)
if (a[i]>a[i+1])
{ t=a[i];a[i]=a[i+1];a[i+1]=t; }

for(i=0;i<2;i++)
if (a[i]>a[i+1])
{ t=a[i];a[i]=a[i+1];a[i+1]=t; }

for(i=0;i<1;i++)
if (a[i]>a[i+1])
{ t=a[i];a[i]=a[i+1];a[i+1]=t; }


int a[10]; int i,j,t;
printf("input 10 numbers :\n");
for (i=0;i<10;i++) scanf("%d",&a[i]);
printf("\n");
for(j=0;j<9;j++)
for(i=0;i<9-j;i++)
if (a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
printf("the sorted numbers :\n");
for(i=0;i<10;i++) printf("%d ",a[i]);
printf("\n");

编写C程序实现冒泡排序算法,按照降序排列一组数。
#define N 5
……
int grade[N],temp;
for(i=0;i<N;i++)
scanf("%d",&grade[i]);
for(i=0;i<N;i++)
{
for(j=0;j<N-i-1; j++)
{
if(grade[j] < grade[j+1])
{
temp = grade[j+1];
grade[j+1] = grade[j];
grade[j] = temp;
}
}
}
……
如果一个数组中保存的元素是有序的(由大到小),向这个数组中插入一个数,使得插入后的数组元素依然保持有序。
#define N 5
……
int num[N+1]={23,45,60,67,88},in;
printf("\n 请输入一个要插入的数:");
scanf("%d",&in);
for(i=0;i<N;i++)
{
if(num[i]>in)
break;
}//查找第一个大于要插入数的位置
for(j=N;j>i;j--)
num[j]=num[j-1];//为要插入的数留出位置
num[i]=in;//将要插入的数保存到该位置
printf("\n 插入后的数组元素:\n");
for(i=0;i<N+1;i++)
printf("%d ",num[i]);
printf("\n");
……
用来存放字符数据的数组是字符数组
字符数组中的一个元素存放一个字符
定义字符数组的方法与定义数值型数组的方法类似
char c[10];
c[0]=’I’; c[1]=’ ’;
c[2]=’a’; c[3]=’m’;
c[4]=’ ’; c[5]=’h’;
c[6]=’a’; c[7]=’p’;
c[8]=’p’; c[9]=’y’;
| c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | c[8] | c[9] |
|---|---|---|---|---|---|---|---|---|---|
| I | a | m | h | a | p | p | y |
char c[10]={’I’,’ ’,’a’,’m’,’ ’,’h’,’a’,’p’,’p’,’y’};
| c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | c[8] | c[9] |
|---|---|---|---|---|---|---|---|---|---|
| I | a | m | h | a | p | p | y |
char c[10]={’c’,’ ’,’p’,’r’,’o’,’g’,’r’,’a’,’m’};
| c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | c[8] | c[9] |
|---|---|---|---|---|---|---|---|---|---|
| c | p | r | o | g | r | a | m | \0 |
char diamond[5][5]={{’ ’,’ ’,’*’},
{’ ’,’*’,’ ’,’*’},
{’*’,’ ’,’ ’,’ ’,’*’},
{’ ’,’*’,’ ’,’*’},
{’ ’,’ ’,’*’} };
解题思路:
- 定义一个字符数组,并用“初始化列表”对其赋以初值
- 用循环逐个输出此字符数组中的字符
#include <stdio.h>
int main()
{ char c[15]={'I',' ','a','m',' ','a',' ','s','t','u','d','e','n','t','.'};
int i;
for(i=0;i<15;i++)
printf("%c",c[i]);
printf("\n");
return 0;
}
解题思路:
定义一个字符型的二维数组,用“初始化列表”进行初始化
用嵌套的for循环输出字符数组中的所有元素。
#include <stdio.h>
int main()
{ char diamond[][5]={{' ',' ','*'},
{' ','*',' ','*'},{'*',' ',' ',' ','*'},
{' ','*',' ','*'},{' ',' ','*'}};
int i,j;
for (i=0;i<5;i++)
{for (j=0;j<5;j++)
printf("%c",diamond[i][j]);
printf("\n");
}
return 0;
}
- 在C语言中,是将字符串作为字符数组来处理的
- 关心的是字符串的有效长度而不是字符数组的长度
- 为了测定字符串的实际长度,C语言规定了字符串结束标志==’\0’==
- \0’代表ASCII码为0的字符
- 从ASCII码表可以查到,ASCII码为0的字符不是一个可以显示的字符,而是一个“空操作符”,即它什么也不做
- 用它作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志
char c[]={”I am happy”};
可写成
char c[]=”I am happy”;
相当于
char c[11]={”I am happy”};
char c[10]={”China”};
可写成
char c[10]=”China”;
从c[5]开始,元素值均为\0
只显示
printf(”%s”,c);

? 逐个字符输入输出(%c)
? 整个字符串一次输入输出(%s)
输出的字符中不包括结束符’\0’
用%s输出字符串时,printf函数中的输出项是字符数组名,不是数组元素名
如果一个字符数组中包含多个’\0’,则遇第一个’\0’时输出就结束
可以用scanf函数输入一个字符串
scanf函数中的输入项c是已定义的字符数组名,输入的字符串应短于已定义的字符数组的长度
char c[6];
scanf(”%s”,c); // China↙
//系统自动在China后面加一个’\0’
char str1[5],str2[5],str3[5];
scanf(”%s%s%s”,str1,str2,str3);
//How are you? ↙
| str1 | H | o | w | \0 | \0 |
|---|---|---|---|---|---|
| str2 | a | r | e | \0 | \0 |
| str3 | y | o | u | ? | \0 |
在C函数库中提供了一些用来专门处理字符串的函数,使用方便
? puts (字符数组)
? char str[20]=”China”;
? puts(str);
? 输出China
? gets(字符数组)
? char str[20];
? gets(str);
? Computer↙
? strcat(字符数组1,字符数组2)
char str1[30]=”People”; //要足够大
char str2[]=”China”;
printf(”%s”, strcat(str1,str2));
输出:PeopleChina
使用字符串函数时,在程序开头用#include <string.h>
#include <string.h> 包括哪些函数
strcpy一般形式为:
strcpy(字符数组1,字符串2)
作用是将字符串2复制到字符数组1中去
char str1[10],str2[]=”China”;
strcpy(str1,str2);
- 可以用strncpy函数将字符串2中前面n个字符复制到字符数组1中去
strncpy(str1,str2,2);
- 作用是将str2中最前面2个字符复制到str1中,取代str1中原有的最前面2个字符
- 复制的字符个数n不应多于str1中原有的字符
其一般形式为
strcmp(字符串1,字符串2)
作用是比较字符串1和字符串2
strcmp(str1,str2);
strcmp(”China”,”Korea”);
strcmp(str1,”Beijing”);
- 字符串比较的规则是:将两个字符串自左至右逐个字符相比,直到出现不同的字符或遇到’\0’为止
- 如全部字符相同,认为两个字符串相等
- 若出现不相同的字符,则以第一对不相同的字符的比较结果为准
两个字符串自左向右逐个字符相比
(按ASCII值大小相比较)
”A”<”B” ”a”>”A”
”computer”>”compare”
”these”>”that” ”1A”>”$20”
”CHINA”>”CANADA”
”DOG”<”cat”
”Tsinghua”>”TSINGHUA”
比较的结果由函数值带回
- 如果字符串1=字符串2,则函数值为0
- 如果字符串1>字符串2,则函数值为一个正整数
- 如果字符串1<字符串2,则函数值为一个负整数
if(str1>str2) printf(”yes”); //错误
if(strcmp(str1,str2)>0)
printf(”yes”); //正确
其一般形式为:
? strlen (字符数组)
它是测试字符串长度的函数
函数的值为字符串中的实际长度
用变量word作为判别当前是否开始了一个新单词的标志,若word=0表示未出现新单词,如出现了新单词,就把word置成1
前面一个字符是否空格可以从word的值看出来,若word等于0,则表示前一个字符是空格;如果word等于1,意味着前一个字符为非空格
if(c==' ')
word=0;
else if(word==0)
{ word=1;
num++;
}
| 当前字符 | I | a | m | a | b | o | y | . | |||
|---|---|---|---|---|---|---|---|---|---|---|---|
| 是否空格 | 否 | 是 | 否 | 否 | 是 | 否 | 是 | 否 | 否 | 否 | 否 |
| word原值 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 |
| 新单词开始否 | 是 | 否 | 是 | 否 | 否 | 是 | 否 | 是 | 否 | 否 | 否 |
| word新值 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 |
| num值 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 4 | 4 | 4 | 4 |
……
char string[81],c;
int i,num=0,word=0;//一定要设初始值
gets(string);
for (i=0;(c=string[i])!=‘\0’;i++) //相当于 c=string[i]; c!=‘\0’
if(c==‘ ’) word=0;
else if(word==0)
{ word=1;
num++;
}
printf(“%d words\n”,num);
……
例 有3个字符串,要求找出其中最大者
解题思路:设一个二维的字符数组str,大小为3×10。每一行存放一个字符串
char str[3][10];
经过三次两两比较,就可得到值最大者,把它放在一维字符数组string中
if (strcmp(str[0],str[1])>0)
strcpy(string,str[0]);
else
strcpy(string,str[1]);
if (strcmp(str[2],string)>0)
strcpy(string,str[2]);
可以把**str[0],str[1],str[2]**看作3个一维字符数组,可以把它们如同一维数组那样进行处理
for (i=0;i<3;i++)
gets (str[i]);

#include<stdio.h>
#include<string.h>
int main ( )
{
char str[3][10];
char string[10];
int i;
for (i=0;i<3;i++)
gets (str[i]);
if (strcmp(str[0],str[1])>0)
strcpy(string,str[0]);
else
strcpy(string,str[1]);
if (strcmp(str[2],string)>0)
strcpy(string,str[2]);
printf("\nthe largest:\n%s\n",string);
return 0;
}
.
- 如果程序的功能比较多,规模比较大,把所有代码都写在main函数中,就会使主函数变得庞杂、头绪不清,阅读和维护变得困难
- 有时程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码,这使程序冗长,不精炼
采用“组装”的办法简化程序设计的过程
事先编好一批实现各种不同功能的函数
把它们保存在函数库中,需要时直接用
函数就是功能
每一个函数用来实现一个特定的功能
函数的名字应反映其代表的功能
在设计一个较大的程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能
C程序可由一个主函数和若干个其他函数构成
主函数调用其他函数,其他函数也可以互相调用
同一个函数可以被一个或多个函数调用任意多次
? ************
? How do you do!
? ************
解题思路:
在输出的文字上下分别有一行“*”号,显然不必重复写这段代码,用一个函数print_star来实现输出一行“*”号的功能。
再写一个print_message函数来输出中间一行文字信息
用主函数分别调用这两个函数
#include <stdio.h>
int main()
{ void print_star(); //声明函数
void print_message();
print_star(); print_message();
print_star();
return 0;
}
//定义函数
void print_star()//输出16个*
{ printf(“******************\n”); }
void print_message() //输出一行文字
{ printf(“ How do you do!\n”); }
(1) 一个C程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。对较大的程序,一般不希望把所有内容全放在一个文件中,而是将它们分别放在若干个源文件中,由若干个源程序文件组成一个C程序。这样便于分别编写、分别编译,提高调试效率。一个源程序文件可以为多个C程序共用。
(2) 一个源程序文件由一个或多个函数以及其他有关内容(如预处理指令、数据声明与定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译的,而不是以函数为单位进行编译的。
(3) C程序的执行是从main函数开始的,如果在main函数中调用其他函数,在调用后流程返回到main函数,在main函数中结束整个程序的运行。
(4) 所有函数都是平行的,即在定义函数时是分别进行的,是互相独立的。一个函数并不从属于另一个函数,即函数不能嵌套定义。函数间可以互相调用,但不能调用main函数。main函数是被操作系统调用的。
(5) 从用户使用的角度看,函数有两种。
①库函数,它是由系统提供的,用户不必自己定义而直接使用它们。应该说明,不同的C语言编译系统提供的库函数的数量和功能会有一些不同,当然许多基本的函数是共同的。
②用户自己定义的函数。它是用以解决用户专门需要的函数。
(6) 从函数的形式看,函数分两类。
① 无参函数。无参函数一般用来执行指定的一组操作。无参函数可以带回或不带回函数值,但一般以不带回函数值的居多。
② 有参函数。在调用函数时,主调函数在调用被调用函数时,通过参数向被调用函数传递数据,一般情况下,执行被调用函数时会得到一个函数值,供主调函数使用。
C语言要求,在程序中用到的所有函数,必须==“先定义,后使用”==
指定函数名字、函数返回值类型、函数实现的功能以及参数的个数与类型,将这些信息通知编译系统。
1.定义无参函数
定义无参函数的一般形式为:
类型名 函数名(void)
{
函数体
} //包括声明部分和语句部分
2.定义有参函数
定义有参函数的一般形式为:
类型名 函数名(形式参数表列)
{
函数体
}
3. 定义空函数
定义空函数的一般形式为:
类型名 函数名( )
{ }
- 先用空函数占一个位置,以后逐步扩充
- 好处:程序结构清楚,可读性好,以后扩充新功能方便,对程序结构影响不大
该函数名为max,它有两个float类型的参数,返回值为float类型。在函数体内实现了求两个数中较大的数,并将它返回。折扣后的价格。
void displayDiscount()
{
float price, discount_amt;
printf("请输入价格");
scanf("%f, &price);
discount_amt = 0.75 * price;
printf("折扣额为 %f", discount_amt);
}
float max(float x, float y)
{
float m;
if (x > y)
m=x;
else
m=y;
return m;
}
函数调用的一般形式为:
函数名(实参表列)
如果是调用无参函数,则“实参表列”可以没有,但括号不能省略
如果实参表列包含多个实参,则各参数间用逗号隔开
按函数调用在程序中出现的形式和位置来分,可以有以下3种函数调用方式:
1. 函数调用语句
把函数调用单独作为一个语句
如printf_star();
这时不要求函数带回值,只要求函数完成一定的操作
2. 函数表达式
函数调用出现在另一个表达式中
如c=max(a,b);
这时要求函数带回一个确定的值以参加表达式的运算
3. 函数参数
函数调用作为另一函数调用时的实参
如m=max(a,max(b,c));
其中max(b,c)是一次函数调用,它的值作为max另一次调用的实参
例7.3.2 输入两个整数,要求输出其中值较大者。要求用函数来找到大数。
解题思路:
(1)函数名应是见名知意,今定名为max
(2) 由于给定的两个数是整数,返回主调函数的值(即较大数)应该是整型
(3)max函数应当有两个参数,以便从主函数接收两个整数,因此参数的类型应当是整型
先编写max函数:
int max(int x,int y)
{
int z;
z=x>y?x:y;
return(z);
}
在max函数上面,再编写主函数
#include <stdio.h>
int main()
{ int max(int x,int y); int a,b,c;
printf(“two integer numbers: ");
scanf(“%d,%d”,&a,&b);
c=max(a,b);
printf(“max is %d\n”,c);
}
在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参被临时分配内存单元。

通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数值(函数的返回值)
(1)函数的返回值是通过函数中的return语句获得的。
(2) 函数值的类型。应当在定义函数时指定函数值的类型
(3)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致
例7.3.4将例7.3.2稍作改动,将在max函数中定义的变量z改为float型。函数返回值的类型与指定的函数类型不同,分析其处理方法。
解题思路:如果函数返回值的类型与指定的函数类型不同,按照赋值规则处理。
#include <stdio.h>
int main()
{ int max(float x,float y);
float a,b; int c;
scanf("%f,%f,",&a,&b);
c=max(a,b);
printf("max is %d\n",c);
return 0;
}
int max(float x,float y)
{ float z;
z=x>y?x:y;
return( z ) ;
}
在一个函数中调用另一个函数需要具备如下条件:
(1) 被调用函数必须是已经定义的函数(是库函数或用户自己定义的函数)
(2) 如果使用库函数,应该在本文件开头加相应的#include指令
(3) 如果使用自己定义的函数,而该函数的位置在调用它的函数后面,应该声明
例7.4 输入两个实数,用一个函数求出它们之和。
- 解题思路:用add函数实现。首先要定义add函数,它为float型,它应有两个参数,也应为float型。特别要注意的是:要对add函数进行声明。
- 分别编写add函数和main函数,它们组成一个源程序文件
- main函数的位置在add函数之前
- 在main函数中对add函数进行声明
#include <stdio.h>
int main()
{ float add(float x, float y); //对add函数声明
float a,b,c;
printf("Please enter a and b:");
scanf("%f,%f",&a,&b);
c=add(a,b); //调用add函数
printf("sum is %f\n",c);
return 0;
}
//求两个实数之和,函数值也是实型
float add(float x,float y)//定义add函数
{ float z;
z=x+y;
return(z);
}
如 float add(float x, float y);
float add(float, float);
原型说明可以放在文件的开头,这时所有函数都可以使用此函数

例7.5 输入4个整数,找出其中最大的数。用函数的嵌套调用来处理。
解题思路:
main中调用max4函数,找4个数中最大者
max4中再调用max2,找两个数中的大者
max4中多次调用max2,可找4个数中的大者,然后把它作为函数值返回main函数
main函数中输出结果
#include <stdio.h>
//主函数
int main()
{ int max4(int a,int b,int c,int d); //对max4 函数声明
int a,b,c,d,max;
printf(“4 interger numbers:");
scanf("%d%d%d%d",&a,&b,&c,&d); //输入4个整数
max=max4(a,b,c,d); //调用后肯定是4个数中最大者
printf("max=%d \n",max); //输出最大者
return 0;
}
//max4函数
int max4(int a,int b,int c,int d)
{ int max2(int a,int b); //对max2 函数声明
int m;
m=max2(a,b); //a,b中较大者
m=max2(m,c); //a,b,c中较大者
m=max2(m,d); //a,b,c,d中最大者
return(m);
}
//max2函数
int max2(int a,int b) //找a,b中较大者
{ if(a>=b)
return a;
else
return b;
//if else可写成下面这
//return(a>b?a:b);
}
int f(int x)
{
int y,z;
z=f(y);
return (2*z);
}
//应使用if语句控制结束调用

例7.6 有5个学生坐在一起**
- 问第5个学生多少岁?他说比第4个学生大2岁
- 问第4个学生岁数,他说比第3个学生大2岁
- 问第3个学生,又说比第2个学生大2岁
- 问第2个学生,说比第1个学生大2岁
- 最后问第1个学生,他说是10岁
- 请问第5个学生多大
解题思路:
要求第5个年龄,就必须先知道第4个年龄
要求第4个年龄必须先知道第3个年龄
第3个年龄又取决于第2个年龄
第2个年龄取决于第1个年龄
每个学生年龄都比其前1个学生的年龄大2
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=10
#include <stdio.h>
int main()
{ int age(int n);
printf("NO.5,age:%d\n",age(5));
return 0;
}
int age(int n)
{ int c;
if(n==1) c=10;
else c=age(n-1)+2;
return(c);
}

例 用递归方法求n!。
解题思路:
- 求n!也可以用递归方法,即5!等于4!×5,而4!=3!×4…,1!=1
- 可用下面的递归公式表示:
![]()
#include <stdio.h>
int main()
{int fac(int n);
int n; int y;
printf("input an integer number:");
scanf("%d",&n);
y=fac(n);
printf("%d!=%d\n",n,y);
return 0;
}
int fac(int n)
{
int f;
if(n<0)
printf("n<0,data error!");
else if(n==0 | | n==1)
f=1;
else f=fac(n-1)*n;
return(f);
}
//注意溢出

例 输入10个数,要求输出其中值最大的元素和该数是第几个数。
解题思路:
- 定义数组a,用来存放10个数**
- 设计函数max,用来求两个数中的大者
- 在主函数中定义变量m,初值为a[0],每次调用max函数后的返回值存放在m中
- 用“打擂台”算法,依次将数组元素a[1]到a[9]与m比较,最后得到的m值就是10个数中的最大者
#include <stdio.h>
int main()
{ int max(int x,int y);
int a[10],m,n,i;
printf(“10 integer numbers:\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
printf("\n");
for(i=1,m=a[0],n=0;i<10;i++)
{ if (max(m,a[i])>m)
{ m=max(m,a[i]);
n=i;
}
}
printf(“largest number is %d\n",m);
printf(“%dth number.\n“,n+1);
}
int max(int x,int y)
{ return(x>y?x:y); }
- 除了可以用数组元素作为函数参数外,还可以用数组名作函数参数(包括实参和形参)
- 用数组元素作实参时,向形参变量传递的是数组元素的值
- 用数组名作函数实参时,向形参 传递的是数组首元素的地址
例 有一个一维数组score,内放10个学生成绩,求平均成绩。
解题思路:
- 用函数average求平均成绩,用数组名作为函数实参,形参也用数组名
- 在average函数中引用各数组元素,求平均成绩并返回main函数
#include <stdio.h>
int main()
{ float average(float array[10]);
float score[10],aver; int i;//定义实参数组
printf("input 10 scores:\n");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
printf("\n");
aver=average(score);
printf("%5.2f\n",aver);
return 0;
}
float average(float array[10])//定义形参数组
{ int i;
float aver,sum=array[0];//相当于score[0]
for(i=1;i<10;i++)
sum=sum+array[i]; //相当于score[i]
aver=sum/10;
return(aver);
}
例7.11 有两个班级,分别有35名和30名学生,调用一个average函数,分别求这两个班的学生的平均成绩。
解题思路:
- 需要解决怎样用同一个函数求两个不同长度的数组的平均值的问题
- 定义average函数时不指定数组的长度,在形参表中增加一个整型变量i
- 从主函数把数组实际长度从实参传递给形参i
- 这个i用来在average函数中控制循环的次数
- 为简化,设两个班的学生数分别为5和10
#include <stdio.h>
int main()
{ float average(float array[ ],int n);
float score1[5]={98.5,97,91.5,60,55};
float score2[10]={67.5,89.5,99,69.5,
77,89.5,76.5,54,60,99.5};
printf(“%6.2f\n”,average(score1,5));
printf(“%6.2f\n”,average(score2,10));
return 0;
}
//调用形式为average(score1,5)时
//调用形式为average(score2,10)时
float average(float array[ ],int n)
{ int i;
float aver,sum=array[0];//相当于score1[0]// 相当于score2[0]
for(i=1;i<n;i++)//n相当于5//n相当于10
sum=sum+array[i];//相当于score1[i] //相当于score2[i]
aver=sum/n;
return(aver);
}
…
定义变量可能有三种情况:
在一个函数内部定义的变量只在本函数范围内有效
在复合语句内定义的变量只在本复合语句范围内有效
在函数内部或复合语句内部定义的变量称为==“局部变量”==
float f1( int a) //a、b、c仅在此函数内有效
{ int b,c;
……
}
char f2(int x,int y) //x、y、i、j仅在此函数内有效
{ int i,j;
……
}
int main( ) //m、n仅在此函数内有效
{ int m,n;
……
return 0;
}
int main ( )
{ int a,b;
…… //a、b仅在此复合语句内有效
{ int c;
c=a+b;
…… //c仅在此复合语句内有效
}
……
}
在函数内定义的变量是局部变量,而在函数之外定义的变量称为外部变量**
外部变量是全局变量(也称全程变量)
全局变量可以为本文件中其他函数所共用
有效范围为从定义变量的位置开始到本源文件结束
int p=1,q=5
float f1(int a)
{ int b,c; …… }
char c1,c2; //p、q、c1、c2为全局变量
char f2 (int x, int y)
{ int i,j; …… } //p、q的有效范围
int main ( )
{ int m,n; //c1、c2的有效范围
……
return 0;
}
例1
有一个一维数组,内放10个学生成绩,写一个函数,当主函数调用此函数后,能求出平均分、最高分和最低分。
解题思路:调用一个函数可以得到一个函数返回值,现在希望通过函数调用能得到3个结果。可以利用全局变量来达到此目的。
#include <stdio.h>
float Max=0,Min=0;
int main()
{ float average(float array[ ],int n);
float ave,score[10]; int i;
printf("Please enter 10 scores:\n");
for(i=0;i<10;i++)
scanf("%f",&score[i]);
ave=average(score,10);
printf("max=%6.2f\nmin=%6.2f\n
average=%6.2f\n",Max,Min,ave);
return 0;
}
float average(float array[ ],int n)
{ int i; float aver,sum=array[0];
Max=Min=array[0];
for(i=1;i<n;i++)
{ if(array[i]>Max) Max=array[i];
else if(array[i]<Min) Min=array[i];
sum=sum+array[i];
}
aver=sum/n;
return(aver);
}

建议不在必要时不要使用全局变量
例2
若外部变量与局部变量同名,分析结果。
#include <stdio.h>
int a=3,b=5;
int main()
{ int max(int a,int b);
int a=8;
printf(“max=%d\n”,max(a,b)); //a为局部变量,仅在此函数内有效,b为全部变量
return 0;
}
int max(int a,int b) //a、b为局部变量,仅在此函数内有效
{ int c;
c=a>b?a:b;
return(c);
}
指针是一个变量,它存储另一个对象的内存地址
指针的声明由基本类型、星号 (*) 和变量名组成
为指针赋值,赋值运算符右侧必须是一个地址如果是普通变量需要在前面加一个取地址运算符 &;如果是另一个指针变量或者是一个数组,不需要加 &运算符
运算符 * 用于返回指针指向的内存地址中存储的值

指针也是一个变量,只不过该变量中存储的是另一个对象的内存地址
如果一个变量存储另一个对象的地址,则称该变量指向这个对象
由于指针值是数据,指针变量可以赋值,所以一个指针的指向在程序执行中可以改变。指针p 在执行中某时刻指向变量x,在另一时刻也可以指向变量y

值为NULL的指针称为空指针,这意味着,指针并不指向任何地址。
在头文件 stdio.h 中,NULL 定义为常量。
?
//取地址符
int num, *ptrnum;
ptrnum = #
//间接运算符
int num, *ptrnum;
ptrnum = #
*ptrnum=15;
指针变量的命名规则和其他变量的命名规则一样
指针不能与现有变量同名
指针可存放 C 语言中的任何基本数据类型、数组和其他所有高级数据结构的地址
若指针已声明为指向某种类型数据的地址,则它不能用于存储其他类型数据的地址
应为指针指定一个地址后,才能在语句中使用指针
#include <stdio.h>
void main()
{
int var = 10;
int *ptr_var;
ptr_var = &var;
printf(" var 的值是: %d", var);
printf("\n var 的内存地址是: %x", &var);
printf("\n 指针 ptr_var 的地址是: %x\n", &ptr_var);
printf("\n var 的值是: %d", *ptr_var);
printf("\n var 的地址是: %x\n", ptr_var);
}
//var的值是:10
//var 的内存地址是:12ff7c
//指针ptr_var的地址是:12ff78
//var的值是:10
//var的地址是:12ff7c
void main()
{
int num1 = 50, num2 = 100;
int *ptr1, *ptr2;
ptr1 = &num1;
printf(" num1 的值是: %d", *ptr1);
printf("\n num1 的地址是: %x \n", ptr1);
ptr2 = &num2;
printf("\n num2 的值是: %d", *ptr2);
printf("\n num2 的地址是: %x \n", ptr2);
*ptr2 = *ptr1;
printf("\n 重新赋值后 num2 的值是: %d", *ptr2);
printf("\n 重新赋值后 num2 的地址是: %x\n", ptr2);
}


使用递增/递减运算符(++ 和 --)将指针递增或递减

将指针加上或者减去某个整数值

比较两个指针
#include<stdio.h>
void main ()
{
int *ptrnum1, *ptrnum2;
int value = 1;
ptrnum1 = &value;
value += 10;
ptrnum2 = &value;
if (ptrnum1 == ptrnum2)
printf("\n 两个指针指向同一个地址\n");
else
printf("\n 两个指针指向不同的地址\n");
}
? int a[10];
? pa=&a[0]; // 或者 pa=a;
? int *ptr,data[10];
? ptr=data+3;//或者ptr=&data[3]

#include <stdio.h>
void main()
{
int data[] = {5, 10, 15, 20, 25};
int i = 0;
int *ptr;
ptr = data;
while(i < 5)
{
printf(“\n 第 %d 个元素的存储地址为:%x,
值为: %d\n“,i+1, ptr, *ptr);
i++;
ptr++;
}
}
//第1个元素的存储地址为:12ff6c,值为:5
//第2个元素的存储地址为:12ff70,值为:10
//第3个元素的存储地址为:12ff74,值为:15
//第4个元素的存储地址为:12ff78,值为:20
//第5个元素的存储地址为:12ff7c,值为:25

void main()
{
char name[5] = {'M', 'A', 'D', 'A', 'M'};
int flag = 1;
char *start=name, *end=name+4;
for(;start <= end; start++, end--){
if(*start != *end)
{
flag = 0;break;
}
}
if(flag)
printf("\n 该字符串是回文串\n");
else
printf("\n 该字符串不是回文串\n");
}
指针是一个变量,它存储另一个对象的内存地址
指针的声明由基本类型、星号 (*) 和变量名组成
为指针赋值,赋值运算符右侧必须是一个地址。如果是普通变量需要在前面加一个取地址运算符 &;如果是另一个指针变量或者是一个数组,不需要加 &运算符
运算符 ***** 用于返回指针指向的内存地址中存储的值
指针的算术运算的含义是指针的移动,将指针执行加上或者减去一个整数值n的运算相当于指针向前或向后移动n个数据单元
指针可以执行比较相等的运算,用来判断两个指针是否指向同一个变量
指向数组的指针,存储的是数组中元素的地址。数组data的第 (i + 1) 个元素的地址可表示为 &data[i] 或 (data+i)
想了解更多请私信,后续还会补充一些,不足的地方请指出。
|
|
| C++知识库 最新文章 |
| 【C++】友元、嵌套类、异常、RTTI、类型转换 |
| 通讯录的思路与实现(C语言) |
| C++PrimerPlus 第七章 函数-C++的编程模块( |
| Problem C: 算法9-9~9-12:平衡二叉树的基本 |
| MSVC C++ UTF-8编程 |
| C++进阶 多态原理 |
| 简单string类c++实现 |
| 我的年度总结 |
| 【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
| c语言常见错误合集 |
|
|
| 上一篇文章 下一篇文章 查看所有文章 |
|
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
| 360图书馆 购物 三丰科技 阅读网 日历 万年历 2026年2日历 | -2026/2/2 23:42:46- |
|
| 网站联系: qq:121756557 email:121756557@qq.com IT数码 |