今天终于把这个笔记弄完了。再整理笔记期间经历了几次危机——文档丢失,数据出错等等,甚至一度不想写这个了,还是感谢d2hoDQo=,这个笔记是整理了大一所学习的一些知识,以及结合了老师上课所讲制作的,希望能帮助大家。不足的地方希望指出。
后续还会进行一些补充。。。
了解C语言的运行环境。
熟悉关键字的使用语法。
掌握各种解决问题的手段或方法。
反复练习动手,从中反馈。
学会做梦。
- 程序一词来自生活,通常指完成某些事务的一种既定方式和过程
- 在日常生活中,可以将程序看成对一系列动作的执行过程的描述
程序:为了让计算机执行某些操作或解决某个问题而编写的一系列有序指令的集合
- C 语言是贝尔实验室的 Dennis Ritchie 在1973年设计的。
- C 最初用于开发系统级程序。
- 在微机上,有许多性能良好的商品C 语言系统可用。包括Turbo C、Borland C/C++;Microsoft Visual C/C++ 等。
结构化的程序设计语言:层次清晰,便于按模块化方式组织程序,易于调试和维护
语句简洁:学习时入门相对容易,C 语言很好地总结了其他语言提出的程序库概念
功能强大:既可用于系统软件的开发,也适合于应用软件的开发。
移植性好:只要对这种语言稍加修改,便可以适应不同型号机器或各类操作系统。
机器语言:CPU指令系统,由0、1序列构成的指令码组成
如:10000000 加
10010000 减
汇编语言:用助记符号描述的指令系统,可进行地址、位操作
如 ADD A, B
编写系统软件,直接对硬件操作,可读性,移植性差
高级语言:可读性,移植性好,编写应用程序一般较难实现汇编语言的某些功能
如:地址和位的操作
C语言兼有高级和低级语言的功能适合写系统软件和应用软件又称中级语言
#include
void main()
{
printf("Hello World\n");
}
以**#**开始的语句称为预处理器指令
#include语句不是必需的,但是,如果程序有该语句,就必须将它放在程序的开始处
以==.h为后缀的文件被称为头文件==,可以是 C 程序中现成的标准库文件,也可以是自定义的库文件。
**stdio.h**文件中包含了有关输入输出语句的函数
main() 函数是 C 程序处理的**起点**
main() 函数可以返回一个值,也可以不返回值。如果某个函数没有返回值,那么在它的前面有一个关键字 **void**
它表示函数的开始,后面是函数的主体
在函数定义的后面有一个左大括号,即**{**
大括号也可以用于将语句块括起来
在函数定义的结尾处有一个右大括号,即 }
在屏幕上产生一行输出**“Hello world”**,并换行(\n)
函数主体中的每个语句都**以分号结束**。
C 程序中的一个语句可以跨越多行,并且用分号通知编译器该语句已结束。
/* *************************
作者:此程序由××× 编写
创建日期:
描述:用来打印输出“Hello World”
…
…
************************** */
#include
void main()
{
printf("Hello World\n");
}
C 程序可以包含注释,以便向读者作一般说明
编译器并不处理这些注释
在程序中添加注释是一个好的编程习惯,可以增强程序的可读性。
源程序:是用户创建的文件,以==“.c”或者“.cpp”==为文件扩展名保存
目标文件:是编译器的输出结果。这类文件的常见扩展名为==“.o”或“.obj”==
可执行文件:是连接器的输出结果。可执行文件的扩展名为==“.exe”==
头文件:含有函数的声明和预处理语句,用于帮助访问外部定义的函数。头文件的扩展名为==“.h”==。
- 编译中发现错误,转回修改源程序
- 连接中发现错误,转回修改源程序
- 调试运行中发现问题,表明分析本身有错误,重新分析问题
https://msdn.itellyou.cn/
CSDN搜Visual Studio安装就会有
另外一个比较好的编辑工具:
Source Insight
学习用:Dev-C++
常量用于定义具有如下特点的数据:
- 在程序中保持不变
- 在程序内部频繁使用.
- 需要用比较简单的方式替代某些值
- 编写程序时,常常需要将数据存储在内存中,方便后面使用这个数据或者修改这个数据的值。
- 通常使用变量来存储数据。使用变量可以引用存储在内存中的数据,并随时根据需要显示数据或执行数据操纵。
声明变量:Datatype variablename;
定义时初始化变量:Datatype variablename = value;
定义后初始化变量:variablename = value;
给变量赋值,除了给一个直接的值以外,还可以通过计算获得。
变量的命名规则:
名称 | 全称类型说明符 | 缩写类型说明符 | 位数 | 范围 |
---|---|---|---|---|
整型 | int | int | 16 | -32768 至 +32767 |
无符号整型 | unsigned int | unsigned | 16 | 0 至 65,535 |
短整型 | short int | short | 16 | -32768 至 +32767 |
无符号短整型 | unsigned short int | unsigned short | 16 | 0 至 65,535 |
长整型 | long int | long | 32 | -2,147,483,648 至 2,147,483,647 |
无符号长整型 | unsigned long int | unsigned long | 32 | 0 至 4,294,967,295 |
声明:
int page_number;
long int population;
unsigned int age;
可按如下方式初始化:
page_number=0;
int max_marks = 100;
在同一语句中可以声明多个类型相同的变量
名称 | 类型说明符 | 位数 | 范围 | 有效数字 |
---|---|---|---|---|
单精度浮点型 | float | 32 | -3.4E38~3.4E38 | 7 |
双精度浮点型 | double | 64 | -1.79E+308 ~ +1.79E+308 | 16 |
声明:
float selling_price;
初始化:
float selling_pric = 11.3;
selling_price = 65.90;
声明:
double pressure_level;
初始化:
pressure_level = 213.5671435568967;
udouble dvalue = 35.4;
char
值 | 符号 | 值 | 符号 | 值 | 符号 |
---|---|---|---|---|---|
0 | 空字符 | 44 | , | 91 | [ |
32 | 空格 | 45 | - | 92 | ** |
33 | ! | 46 | . | 93 | ] |
34 | " | 47 | / | 94 | ^ |
35 | # | 48 ~ 57 | 0 ~ 9 | 95 | - |
36 | $ | 58 | : | 96 | ` |
37 | % | 59 | ; | 97 ~ 122 | a ~ z |
38 | & | 60 | < | 123 | { |
39 | ’ | 61 | = | 124 | | |
40 | ( | 62 | > | 125 | } |
41 | ) | 63 | ? | 126 | ~ |
42 | ***** | 64 | @ | 127 | DEL (Delete键**)** |
43 | + | 65 ~ 90 | A ~ Z |
实例
#include
void main()
{
int num;
printf("请输入一个数:"); //输出
scanf("%d",&num); //输入
printf("\n%d 的平方为 %d \n",num,num*num);
}
int visitor_count = 150;
printf ("%d" , visitor_count); //输出和结果为150
int salary = 5500;
printf ("%10d" , salary);
/*输出结果_ _ _ _ _ _5500
*输出结果的左边显示了 6 个空格
*/
float circumference = 9.4786789;
printf (" %f" , circumference);
// 输出结果:9.478679
//默认情况下精确到六位小数
double mercury_level = 168.2251074;
printf ("%7.2f" , mercury_level);
/*输出结果: _168.23
*宽度,表示所有的数字和小数点所占的位数。不够7位右对齐。
*精度(精确到小数点后多少位)
*/
#include
void main()
{
float radius=1.5, high=2.0;
float pi=3.14159, vol;
/*计算体积*/
vol=pi*radius*radius*high;
/*输出体积的值*/
printf("vol=%7.2f\n",vol);
}
//输出:vol=14.14
转换字符串 | 说 明 |
---|---|
%d | 将参数按整数形式转换输出,对应参数应是int 类型 |
%ld | 将参数按长整数形式转换输出,对应参数应是long 类型 |
%c | 输出一个字符,对应参数应该是一个字符 |
%s | 输出一个字符串,对应参数应该是一个字符串 |
%f | 将参数按带小数点数形式输出,对应参数应是double 类型,默认情况下精确到 6 位小数 |
转义序列 | 名称 | 描述 |
---|---|---|
\a | 警告 | 产生一则警告。 |
\b | 退格 | 将光标回退一格。 |
\f | 换页 | 将光标移到下一页的第一格。 |
\n | 换行 | 将光标移到下一行的第一格。 |
\r | 回车 | 将光标移到当前行的第一格。 |
\t | 水平制表 | 将光标移到下一个水平制表位置。 |
\v | 垂直制表 | 将光标移到下一个垂直制表位置。 |
\’ | 单引号 | 产生一个单引号。 |
\" | 双引号 | 产生一个双引号。 |
? | 问号 | 产生一个问号。 |
\\ | 反斜线 | 产生一条反斜线。 |
\0 | 空 | 产生一个空字符。 |
scanf 函数从标准输入(键盘)读取信息,按照格式描述把读入的信息转换为指定数据类型的数据,并把这些数据赋给指定的程序变量。
scanf("%d",&num);
// %d转换字符串
// &符号(附在读取的每个变量上)用于指明变量在内存中的位置
// num变量的名称
转换字符串 | 参数变量的类型 | 要求的实际输入 |
---|---|---|
%d | int | 十进制数字序列 |
%ld | long | 十进制数字序列 |
%f | float | 十进制数,可以有小数点及指数部分 |
%lf | double | 十进制数,可以有小数点及指数部分 |
实例
#include
void main()
{
double radius,high,vol;
printf("请输入圆柱体底面积的半径和圆柱体的高: ");
scanf("%lf%lf",&radius,&high);
vol=3.14*radius*radius*high;
printf("radius=%7.2f,high=%7.2f,vol=%7.2f\n",
radius,high,vol);
}
/*请输入圆柱体底面积的半径和圆柱体的高: 5 10
*radius=5.00, high=10.00, vol=785.00
*/
#include
void main()
{
int a = 5, b = 3, c = 25, d = 12;
float qu;
int re,in,de;
/* 使用算术运算符 */
qu = a / b; // 除法
re = a % b; // 求模
in = ++c;
de = --d;
printf ("商为 %f\n",qu);
printf ("余数为 %d\n",re);
printf ("加 1 后为 %d\n",in);
printf ("减 1 后为 %d\n",de);
}
/*输出:
*商为 1.000000
*余数为 2
*加 1 后为 26
*减 1 后为 11
*/
原则:把表示范围小的类型的值转换到表示范围大的类型的值
int a = 5, b = 3;
float qu = float(a) / b;
语法:
char variablename;
variablename = functionname;
/*例如:
* char c;
* c=getchar();
*/
#include
void main()
{
char a,b;
printf(" 请输入两个字符:\n");
a=getchar();
fflush(stdin);
b=getchar();
fflush(stdin);
putchar(a);
putchar(b);
putchar('\n');
}
/*输出:
*请输入两个字符:
*O
*K
*OK
*Press any key to continue_
*/
要处理多重条件判断的情况,需要使用多重条件结构
多重 if 结构是if-else 的另一种形式 ,这种形式也称为阶梯式 if-else-if
#include
void main()
{
float grade;
printf("\n 请输入期末考试成绩: ");
scanf("%f", &grade);
if(grade>=90)
printf("\n 优");
else if ((grade>=80) && (grade<90))
printf("\n 良");
else if ((grade>=60) && (grade<80))
printf("\n 中");
else
printf("\n 差");
printf("\n");
}
/*请输入期末考试成绩:59
*grade =90
*结果 差
*/
嵌套 if 结构就是将整个 if 块插入另一个 if 块中
if (表达式1)
if (表达式2)
if (表达式3)
语句;
else
语句;
if (x > 0)
if (y > 1)
z = 1;
else /*这个 else 部分属于哪个 if?*/
z = 2;
C语言规定,每个 else 部分总属于前面最近的那个缺少对应的 else 部分的 if 语句。
提倡使用大括号括起来以避免看起来有二义性。
示例:
#include
void main()
{
int a,b;
printf("\n 请输入 A 和 B 的值: ");
scanf("%d%d",&a,&b);
if(a!=b)
if(a>b)
printf("\n A>B\n");
else
printf("\n A);
else
printf("\n A=B\n");
}
//a 68 b 93
//输出A
- switch-case 语句是多路判断语句
- switch 语句计算条件表达式并对照多个常数值进行检查
switch (表达式) //计算表达式的值
{
case 常量 1: //如果等于常量1
语句;
break;
case 常量 2: //如果等于常量2
语句;
break;
default: //如果没有找到匹配的值
语句;
}
在使用switch结构时应注意以下几点:
- 在case后的各常量表达式的值不能相同,否则会出现错误;
- 在case后,允许有多个语句,可以不用{}括起来;
- 每个case语句后都必须有一个break语句,否则会出现错误;
- 各case和default子句的先后顺序可以变动,而不会影响程序执行结果;
- default子句可以省略;
char in_char;
printf("\n 请输入一个小写字母: ");
scanf("%c", &in_char);
switch(in_char)
{
case 'a': printf("\n 您输入的是元音字母 a\n");
break;
case 'e': printf("\n 您输入的是元音字母 e\n");
break;
case 'i': printf("\n 您输入的是元音字母 i\n");
break;
case 'o': printf("\n 您输入的是元音字母 o\n");
break;
case 'u': printf("\n 您输入的是元音字母 u\n");
break;
default: printf("\n 您输入的不是元音字母 \n");
}
//请输入一个小写字母:e
//您输入的是元音字母 e
- 多重if结构和switch结构都可以用来实现多路分支
- 多重if结构用来实现两路、三路分支比较方便,而switch结构实现三路以上分支比较方便
- 在使用switch结构时,应注意分支条件要求是整型表达式,而且case语句后面必须是常量表达式
- 有些问题只能使用多重if结构来实现,例如要判断一个值是否处在某个区间的情况
void main()
{
char c;
printf("\n 请输入一个字符: ");
c=getchar();
if(c<32)
printf("\n 该字符是一个控制字符。\n");
else if(c>='0'&&c<='9')
printf("\n 该字符是一个数字。\n");
else if(c>='A'&&c<='Z')
printf("\n 该字符是一个大写字母。\n");
else if(c>='a'&&c<='z')
printf("\n 该字符是一个小写字母。\n");
else
printf("\n 该字符是其他字符。\n");
}
//请输入一个字符:E
//该字符是一个大写字母
示例
int a,b; char op;
printf("\n 输入操作数1,运算符,操作数2: ");
scanf("%d,%c,%d",&a,&op,&b);
switch(op)
{
case '+': printf("\n %d+%d=%d\n",a,b,a+b);
break;
case '-': printf("\n %d-%d=%d\n",a,b,a-b);
break;
case '*': printf("\n %d×%d=%d\n",a,b,a*b);
break;
case '/': printf("\n %d/%d=%d\n",a,b,a/b);
break;
default: printf("\n 运算符错误!");
}
//输入操作数1,运算符,操作数2:45,*,2
//45×2 = 90
//使用“if-else”的等同代码
if (num>100)
{
value=‘y’;
}
else
{
value=‘n’;
}
示例
#include
void main()
{
double sal;
double rate;
printf("\n 请输入基本工资:");
scanf("%lf",&sal);
rate= (sal<=1000) ? 0 : 0.05;
sal=sal-(sal-1000)*rate;
printf("\n 税后工资为:%7.2f \n",sal);
}
//假设输入基本工资:1500
//税后工资为:1475.00
int result1,result2,result3;
int result4,result5;
result1 = 1 * 10;
printf("1 × 10 = %d \n",result1);
result2 = 2 * 10;
printf("2 × 10 = %d \n",result2);
result3 = 3 * 10;
printf("3 × 10 = %d \n",result3);
result4 = 4 * 10;
printf("4 × 10 = %d \n",result4);
result5 = 5 * 10;
printf("5 × 10 = %d \n",result5);
/*很多重复语句
1 × 10 = 10
2 × 10 = 20
3 × 10 = 30
4 × 10 = 40
5 × 10 = 50
(上个数字 +1) × 10
*/
例如:全班有50个学生,统计各学生三门课的平均成绩。
//输入学生1的三门课成绩,并计算平均值后输出
scanf(“%f,%f,%f”,&s1,&s2,&s3);
aver=(s1+s2+s3)/3;
printf(“aver=%7.2f”,aver);
//输入学生2的三门课成绩,并计算平均值后输出
scanf(“%f,%f,%f”,&s1,&s2,&s3);
aver=(s1+s2+s3)/3;
printf(“aver=%7.2f”,aver);
//要对50个学生进行相同操作重复50次
用while循环结构实现
while(i<=50)
{ scanf…… ;
aver=…… ;
printf…… ;
i++;
}
while (表达式)
{
语句;
}
规则1:
[<初始化>]
while(循环条件)
{
<循环体>
}
//循环条件中使用的变量需要经过初始化
规则2:
while (index < 100)
{
. . .
. . .
index++;
}
//while 循环主体中的语句必须修改循环条件的值,否则会形成死循环
计算表达式的值,当值为真(非0)时,执行循环体语句,一旦条件为假,就停止执行循环体。
如果条件在开始时就为假,那么不执行循环体语句直接退出循环。
先判断条件表达式,后执行循环体语句
求1+2+3+…+100,即
∑ n = 1 100 n \sum_{n=1}^{100} n n=1∑100n
解题思路:
- 这是累加问题,需要先后将100个数相加
- 要重复100次加法运算,可用循环实现
- 后一个数是前一个数加1而得
- 加完上一个数i后,使i加1可得到下一个数
#include
int main()
{
int i=1,sum=0; //不能少
while (i<=100)
{ sum=sum+i; //复合语句
i++; //不能丢,否则循环永不结束
}
printf("sum=%d\n",sum);
return 0;
}
#include
void main ()
{
int num=1,result;
while (num<=10)
{
result=num*10;
printf("%d × 10 = %d \n",num,result);
num++;
}
}
#include
void main ()
{
int c=0,count=0;
double f;
while (c <= 250 && count<10)
{
count++;
printf("%d: ",count);
f=c * 9 / 5.0 + 32.0;
printf("C = %d, F = %7.2f\n", c, f);
c = c + 20;
}
}
do
{
语句;
} while (表达式);
它先执行循环体中的语句,然后再判断条件是否为真,如果为真则继续循环;如果为假,则终止循环。
先无条件地执行循环体,然后判断循环条件是否成立
用do–while语句求: 1+2+3+…+100,即
∑ n = 1 100 n \sum_{n=1}^{100} n n=1∑100n
解题思路
#include
int main()
{ int i=1,sum=0;
do
{
sum=sum+i;
i++;
}while(i<=100);
printf("sum=%d\n",sum);
return 0;
}
输入数字 5 后,do…while 循环中的条件为假, 输出结果消息后,程序终止。
int number=5,guess;
printf ("猜一个介于 1 与 10 之间的数\n");
do
{
printf("请输入您猜测的数:");
scanf("%d",&guess);
if (guess > number)
printf("太大\n");
else if (guess < number)
printf("太小\n");
} while (guess != number);
printf("您猜中了! 答案为 %d\n",number);
while(i <= 10) //外循环
{
. . .
while (i <= j)//内循环
{
. . .
. . .
}
. . .
}
只有在内循环完全结束后,外循环才会进行下一趟。
用“*”打印一个直角三角形图案。
void main()
{
int nstars=1,stars;
while(nstars <= 10)//外层循环控制打印的行数
{
stars=1;
while (stars <= nstars)//内层循环控制每行打印*号的个数
{
printf("*");
stars++;
}
printf("\n");
nstars++;
}
}
do
{
. . .
do
{
. . .
}while( . . .)
. . .
}while( . . . )
//只有在内循环完全结束后,外循环才会进行下一趟。
int x;
char i, ans;
ans='y';
do
{
x=0;
printf("\n请输入字符序列:");
fflush(stdin);
do{
i=getchar();
x++;
}while( i !='\n' ); //检查条件判断是否按下回车键。如果否, 循环继续执行后续语句;如果是,循环回到开始处。
printf("\n输入的字符数为:%d", --x);
printf("\n是否需要输入更多序列 (Y/N) ? ");
ans = getchar();
}while(ans =='Y' || ans == 'y');//如按下 Y/y, 则循环从开始处执行,否则循环停止
熟练使用for循环
理解break 和 continue 语句的用法
熟练使用嵌套循环
- for语句不仅可以用于循环次数已经确定的情况,还可以用于循环次数不确定而只给出循环结束条件的情况
- for语句完全可以代替while语句
for (i=1;i<=100;i++)
{
printf("%d ", i );
}
for(<初始化循环变量> ;<循环条件> ; <修改循环变量的值>)
{
<循环体语句>;//不能省略
}
#include
void main()
{
int number,count,factorial=1;
printf("\n 请输入任意一个正整数:");
scanf("%d",&number);
for(count = 1; count <=number; count++)
factorial=factorial*count;
printf("\n %d的阶乘 = %d\n",number,factorial);
}
//请输入任意一个正整数:5;5的阶乘 = 120
//循环执行五次
- for语句中的三个表达式都可以是逗号表达式
- 逗号表达式就是通过“,”运算符隔开的多个表达式组成的表达式
- 逗号表达式从左往右计算。逗号运算符在 C 语言运算符中的优先级最低
#include
void main()
{
int i,j,max;
printf("请输入一个值 \n");
printf("根据这个值可以输出以下加法表:");
scanf("%d",&max);
for(i = 0,j = max ; i <=max ; i++,j--)
printf("\n %d + %d = %d",i,j,i + j);
printf("\n");
}
//i = 0初始化语句只执行一次
//i <=max 循环执行max次
改变循环执行的状态
跳出 for 循环
for( ; ; )
{
printf("这将一直进行下去");
i = getchar();
if(i == 'X' || i == 'x')
break;
}
跳出 while 循环
while(1)
{
if(x == 10)
break;
}
跳出 do-while 循环
do
{
if (x == 10)
break;
}while (x< 15);
#include
void main()
{
int count=0,ch;
printf("\n 请输入一行字符:");
while((ch=getchar())!='\n')
{
if(ch==' ')
break;
count++;
}
printf("\n 共有 %d 个有效字符。\n",count);
}
在全系1000学生中,征集慈善募捐,当总数达到10万元时就结束,统计此时捐款的人数,以及平均每人捐款的数目。
编程思路:
循环次数不确定,但最多循环1000次
在循环体中累计捐款总数
用if语句检查是否达到10万元
如果达到就不再继续执行循环,终止累加
计算人均捐款数
变量amount,用来存放捐款数
变量total,用来存放累加后的总捐款数
变量aver,用来存放人均捐款数
定义符号常量SUM代表100000
#include
#define SUM 100000//指定符号常量SUM代表100000
int main()
{ float amount,aver,total; int i;
for (i=1,total=0;i<=1000;i++) //应该执行1000次
{ printf("please enter amount:");
scanf("%f",&amount);
total= total+amount; //达到10万,提前结束循环
if (total>=SUM) break;
}
aver=total / i ; printf("num=%d\naver=%10.2f\n",i,aver);
return 0;
}
#include
void main()
{
int i,sum = 0;
for(i=1; i<=100;i++)
{
if( i % 10 == 3)
continue;
sum += i;
}
printf("sum = %d \n",sum);
}
//循环执行到 i = 13
//循环执行到 i = 101
//输出:sum = 4570
要求输出100~200之间的不能被3整除的数
编程思路:
- 对100到200之间的每一个整数进行检查
- 如果不能被3整除,输出,否则不输出
- 无论是否输出此数,都要接着检查下一个数(直到200为止)。
for(n=100;n<=200;n++)
{ if (n%3==0)
continue;
printf("%d ",n);
}
continue语句只结束本次循环,而不是终止整个循环的执行
break语句结束整个循环过程,不再判断执行循环的条件是否成立
问题描述:
用“*”输出一个菱形图案,图案如下:
void main()
{
int i,j,k;
for(i=1;i<=4;i++)//控制打印的行数
{
for(j=1;j<=4-i;j++)//控制每行打印的空格数
printf(" ");
for(k=1;k<=2*i-1;k++) //控制每行打印的*号数
printf("*");
printf("\n");
}
for(i=1;i<=3;i++)//控制打印的行数
{
for(j=1;j<=i;j++)//控制每行打印的空格数
printf(" ");
for(k=1;k<=7-2*i;k++) //控制每行打印的*号数
printf("*");
printf("\n");
}
}
void main()
{
int i,j,n;
n=0;
for(i=100;i<=200;i++)
{
j=2;
while(i%j!=0)//从2到i之间寻找第一个能被整除的数
j++;
if(i==j)//如果第一个能被整除的数等于该数本身,则说明该数为素数
{
printf("%4d",i);
n++;
if(n%8==0)//控制每行输出8个素数
printf("\n");
}
}
printf("\n");
}
void main()
{
int i,num;
char answer;
do
{
printf("请输入一个数:");
scanf("%d",&num);
printf("\n");
for (i = 1; i <= 10; i++)
{
printf("=");
}
printf("\n 该数是 %d",num);
printf("\n\n 您是否还要输入其他的数(y/n)?");
fflush(stdin);
answer = getchar();
} while (answer != 'n');
}
- 前几章使用的变量都属于基本类型,例如整型、字符型、浮点型数据,这些都是简单的数据类型。
- 对于有些数据,只用简单的数据类型是不够的,难以反映出数据的特点,也难以有效地进行处理。
如果有1000名学生,每个学生有一个成绩,需要求这1000名学生的平均成绩。
用s1,s2,s3,……,s1000表示每个学生的成绩,能体现内在联系。
C语言用方括号中的数字表示下标,如用s[15]表示
- 数组是一组有序数据的集合。数组中各数据的排列是有一定规律的,下标代表数据在数组中的序号
- 用一个数组名和下标惟一确定数组中的元素
- 数组中的每一个元素都属于同一个数据类型
- 数组是可以在内存中连续存储多个元素的结构
- 数组中的所有元素必须属于相同的数据类型
示例:学员单门课程的成绩
示例:学员两门课程的成绩
datatype arrayName[size];
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
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
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
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
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
#include
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
#include
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
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
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
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
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
//主函数
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个学生多大
解题思路:
#include
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
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
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
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
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
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
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
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
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
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)
想了解更多请私信,后续还会补充一些,不足的地方请指出。