写在前面:本文主要是结合郝斌老师的教程所写。如有不恰当的地方,欢迎大家指点批评。
帅帅又来了
数组、函数
数组
一位数组
- 为n个变量连续分配存储空间;
- 数据类型必须一致;
- 所有变量所占字节必须相等;
例一:第一个数组程序
/*
2021年1月10日
第一个数组程序
*/
# include <stdio.h>
int main(void)
{
int i;
int a[5] = {1, 2, 3, 4, 5};
for (i=0; i<5; i++)
printf("%d\n", a[i]);
return 0;
}
/*
--------------------------------
在VC++6.0中运行结果为:
1
2
3
4
5
--------------------------------
*/
数组初始化
- 完全初始化:
int a[5] = {1, 2, 3, 4, 5}; - 不完全初始化,未被初始化的自动为零
int a[5] = {1, 2, 3}; - 不初始化,所有元素都是垃圾值:
int a[5] - 清零:
int a[5] = {0};
错误写法
1.定义数组的同时对整体赋值,其他情况错误
int a[5];
a[5] = {1,2,3,4,5}; // 错误
int a[5] = {1, 2, 3, 4, 5}; // 正确
2.超出数组范围
int a[5] = {1, 2, 3, 4, 5};
a[5] = 100; // 没有a[5]
3.数组A、B值复制
int a[5] = {1, 2, 3, 4, 5};
int b[5];
// b = a; 错误
-------------------------------------------
int a[5] = {1, 2, 3, 4, 5};
int b[5];
for (i=0; i<5; i++)
b[i] = a[i]; // 正确
例二:数组数据的倒置
/*
2021年1月11日
数组数据的倒置
*/
# include <stdio.h>
int main(void)
{
int a[5] = {1,2,3,4,5};
int i;
int b[5];
for (i=0; i<5; i++)
{
b[i] = a[4-i];
printf("%d\n", b[i]);
}
return 0;
}
/*
---------------------------------
在VC++6.0中运行结果为:
5
4
3
2
1
---------------------------------
*/
数组作为参数传递
/*
2021年1月20日13:47:34
求数组最大值
目的:数组与函数相结合使用
*/
# include <stdio.h>
# define Max 5
void findmax(int values[Max])
{
int i;
int max = values[0];
for (i=1; i<Max; i++)
{
if (max < values[i])
max = values[i];
}
printf("该数组最大值为:%d\n", max);
}
int main(void)
{
int nums[Max] = {2, 5, 85, 6, 91};
findmax(nums);
return 0;
}
/*
-------------------------------------------
在VC++6.0中运行的结果为:
该数组最大值为:91
-------------------------------------------
*/
二维数组
int a[4][5]; // 数组顺序:a[0][0],a[0][1]……
初始化
1.标准初始化
int a[3][4] = {
{1, 2, 3, 4}, // ,
{4, 5, 6, 7},
{8, 9, 10, 11}
}; // ;
2.二维数组的一个输出
/*
2021年1月11日
二维数组的一个输出
*/
# include <stdio.h>
int main(void)
{
int a[3][4] = {
{1, 2, 3, 4},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
printf("%d\n", a[2][3]); // 最大位置的元素
return 0;
}
/*
----------------------------------------
在VC++6.0中运行结果为:
11
----------------------------------------
*/
3.二维数组全部输出
/*
2021年1月11日
二维数组内容全部输出:借助for循环
*/
# include <stdio.h>
int main(void)
{
int i,j;
int a[3][4] = {
{1, 2, 3, 4},
{5, 6, 8, 9},
{7, 10,11,12}
};
for (i=0; i<3; i++)
{
for (j=0; j<4; j++)
printf("%d ", a[i][j]); // printf("%-3d", a[i][j]); 左对齐
printf("\n");
}
return 0;
}
/*
-------------------------------
在VC++6.0中运行结果为:
1 2 3 4
5 6 8 9
7 10 11 12
--------------------------------
*/
函数(面向过程的理解)
1.why
- 避免程序化操作;
- 有利于程序模块化;
2.what
- 能够完成特定功能的独立的代码单元
3.how
- 函数的返回值 函数的名字(函数的形参列表)
{
函数的执行体
} - return
- 函数的返回值的类型
/*
2021年1月11日
函数返回值类型
*/
# include <stdio.h>
int f() // ---->int 决定返回值类型
{
return 10.2; // 因为函数的返回值类型是int,所以最终返回值是10 不是10.2
}
int main(void)
{
int i = 99;
float x = 6.0;
x = f();
printf("%lf\n", x);
return 0;
}
/*
--------------------------------------------------------------------------------
在VC++6.0中运行结果为:
10.000000
--------------------------------------------------------------------------------
*/
函数调用
/*
2021年1月22日10:56:05
函数的简单调用
《C语言从入门到精通》
*/
# include <stdio.h>
void printstar()
{
printf("************************\n");
}
int sum(int a, int b)
{
return a+b;
}
int main(void)
{
int x, y, z;
x = 3;
y = 2;
printstar(); // 调用printstar()函数
z = sum(3, 2); // 调用sum() 函数
printf("%d + %d = %d\n", x, y, z);
printstar();
return 0;
}
/*
------------------------------------------
在VC++6.0中运行结果为:
************************
3 + 2 = 5
************************
------------------------------------------
*/
break 和 return 的用法
例一:break 的用法:终止循环和switch
/*
2021年1月11日
break 的用法
*/
# include <stdio.h>
void f(void) // 无返回值时需要写成void(空类型)
{
int i;
for (i=0; i<5; i++)
{
printf("大家好!\n");
break; // 仅仅终止循环
}
printf("同志们好!\n");
}
int main(void)
{
f();
return 0;
}
/*
-----------------------------
在VC++6.0中运行结果为:
大家好!
同志们好!
-----------------------------
*/
例二:return 的用法:终止被调函数,向主调函数返回表达式的值
/*
2021年1月11日
return 的用法
*/
# include <stdio.h>
void f(void) // 无返回值时需要写成void(空类型)
{
int i;
for (i=0; i<5; i++)
{
printf("大家好!\n");
return; // return 终止整个函数
}
printf("同志们好!\n");
}
int main(void)
{
f();
return 0;
}
/*
-----------------------------
在VC++6.0中运行结果为:
大家好!
-----------------------------
*/
例三:void int 的return
(表达式为空,则只终止函数,不向被调函数返回任何值)
void f()
{
return; // void 时 return 后不用跟数字
}
int max()
{
return 10; // int 时 return 返回数字 否则报错
}
函数的分类
- 有参函数 和 无参函数
- 有返回值 和 无返回值
- 库函数 和 自定义函数
- 普通函数 和 主函数(一个程序有且只能有一个主函数,主函数调用普通函数,普通函数之间可以相互调用,主函数时程序的入口)
- 值传递函数 和 地址传递函数
判断素数
/*
2021年1月11日
判断数字是否为素数 ---仅用主函数实现(1)
*/
# include <stdio.h>
int main(void)
{
int val;
int i;
scanf("%d", &val);
for (i=2; i<val; i++)
{
if (val%i == 0)
break;
}
if (i == val)
printf("Yes!\n");
else
printf("No!\n");
return 0;
}
/*
---------------------------------
在VC++6.0中运行结果为:
5
Yes!
62
No!
---------------------------------
*/
/*
2021年1月11日
判断数字是否为素数-----用函数操作(2)
*/
# include <stdio.h>
bool IsPrime(int val) // 形参个数由功能确定
{
int i;
for (i=2; i<val; i++)
{
if (val%i == 0)
break;
}
if (i == val)
return true;
else
return false;
}
int main(void)
{
int m;
scanf("%d", &m);
if (IsPrime(m))
printf("Yes!\n");
else
printf("No!\n");
return 0;
}
/*
---------------------------------
在VC++6.0中运行结果为:
5
Yes!
62
No!
---------------------------------
*/
函数声明
- 定义函数必须放在被调函数的前面,否则在开始位置必须有函数声明
# include <stdio.h>
void f(void); // 函数声明 ";必须有"
int main(void)
{
f();
return 0;
}
void f(void) // 定义函数
{
printf("hh!\n");
}
形参和实参
形参和实参的关系
- 形参只是一个形式,在调用前并不分配内存空间。函数调用时,系统为形参分配内存单元,然后将主调函数中的实参传递给被调函数的形参。被调函数执行完毕后,通过return 语句返回结果,系统将形参的内存单元释放。
- 实参形参只能单向传递即(实参---->形参)
- 实参形参可以重名,因为形参实参分居在不同的内存单元,两者没有影响。
/*
2021年1月12日
形参实参关系:一一对应
*/
# include <stdio.h>
void f(int i, float x) // int i, float x 形参
{
printf("i = %d x = %f\n", i, x);
}
int main(void)
{
f(5, 6.0); // 5, 6.0 实参
return 0;
}
/*
-----------------------------------------
在VC++6.0中运行结果为:
i = 5 x = 6.000000
-----------------------------------------
*/
/*
2021年1月22日12:10:27
使用函数交换两个数的值
《C语言从入门到精通》
目的:形参实参两者的相互影响、参数传递
*/
# include <stdio.h>
void swap(int a, int b) // a , b 形参是局部变量只能在被调函数内部执行
{
int temp;
temp = a;
a = b;
b = temp;
printf("a = %d, b = %d\n", a, b);
}
int main(void)
{
int x, y;
printf("请输入两个数x,y(中间用空格分隔):\n");
scanf("%d %d", &x, &y);
printf("交换前x = %d, y = %d\n", x, y);
printf("调用函数中:\n");
swap(x, y); // 形参是实参的copy 形参不会影响实参的变化
printf("交换后x = %d, y = %d\n", x, y); // 形参的值并不能反过来传递给实参 所以实参仍然不变
return 0;
}
/*
-----------------------------------------------------
在VC++6.0中运行结果为:
请输入两个数x,y(中间用空格分隔):
24 6
交换前x = 24, y = 6
调用函数中:
a = 6, b = 24
交换后x = 24, y = 6
-----------------------------------------------------
*/
函数的嵌套
/*
2021年1月22日14:24:43
函数的嵌套
《C语言从入门到精通》
*/
# include <stdio.h>
fun2(int x, int y) // 省略不写 默认int 类型
{
int z_1;
z_1 = 2 * x - y;
return z_1;
}
fun1(int x, int y)
{
int z_2;
z_2 = fun2(x, x+y);
return z_2;
}
main()
{
int a, b, c;
printf("请输入两个整数:\n");
scanf("%d %d", &a, &b);
printf("a = %d b = %d\n", a, b);
c = fun1(a, b);
printf("c = %d\n", c);
return 0;
}
/*
--------------------------------------
在VC++6.0中运行结果为:
请输入两个整数:
6 9
a = 6 b = 9
c = -3
试数:
main函数
a = 6 b = 9 // 实参
调用fun1后
x = 6 y = 9
fun2(6, 15)
调用fun2后
x = 6 y = 15
z_1 = 2 * 6 - 15 = -3
return z_1;
返回fun1
z_2 = z_1 = -3;
return z_2;
main函数
c = -3
--------------------------------------
*/
实际中的函数
- 简化代码
- 一个函数的功能应该尽量单一
/*
判断是否为素数(2)
*/
# include <stdio.h>
bool IsPrime(int j)
{
int i;
for (i=2; i<j; i++)
{
if(0 == j % i)
break;
}
if (j == i)
return true;
else
return false;
}
int main(void)
{
int val;
printf("请输入一个数字:");
scanf("%d", &val);
if (IsPrime(val))
printf("Yes!\n");
else
printf("No!\n");
return 0;
}
常用的系统函数
- 机械工业出版的《turboc2.0实用大全》
- double sqrt (double x);(求平方根)
- int abs (int x); (求绝对值)
- double fabs (double x); (求绝对值)
递归
- 程序一:递归求阶乘 (n! = ?)
/*
2021年1月22日14:45:34
递归求阶乘 (n! = ?)
《C语言从入门到精通》
*/
# include <stdio.h>
long fac(int n)
{
long m;
if (n == 1)
m = 1;
else
m = fac(n - 1) * n; // 函数自我调用
return m;
}
main()
{
int n;
printf("input a value n:");
scanf("%d", &n);
printf("%d! = %d\n", n, fac(n));
return 0;
}
/*
-------------------------------------
在VC++6.0中运行的结果为:
input a value n:5
5! = 120
-------------------------------------
*/
- 程序二:递归求斐波那契数列
/*
2021年1月22日15:28:18
递归求斐波那契数列
《C语言从入门到精通》
*/
# include <stdio.h>
long fibonacci(int n)
{
if (n == 1 || n == 2)
return 1;
else
return (fibonacci(n -1) + fibonacci(n - 2));
}
main()
{
int n, i;
long y;
printf("input n:");
scanf("%d", &n);
for(i=1; i<=n; i++)
{
y = fibonacci(i);
printf("%d\t", y);
if (i % 10 == 0) // 换行
{
printf("\n");
}
}
printf("\n");
}
/*
---------------------------------------------------------------------------
在VC++6.0中运行结果为:
input n:19
1 1 2 3 5 8 13 21 34 55
89 144 233 377 610 987 1597 2584 4181
---------------------------------------------------------------------------
*/
- 程序三:带参数的main函数
/*
2021年1月22日16:00:41
带参数的main函数
目的:调试
《C语言从入门到精通》
*/
# include <stdio.h>
int main(int argc, char *argv[])
{
int count;
printf("The command line has %d arguments:\n", argc-1);
for (count=1; count<argc; count++)
printf("%d:%s\n",count,argv[count]);
}
/*
--------------------------------------------------------------------------------
在VC++6.0中运行结果为:
The command line has 3 arguments:
1:I
2:am
3:happy!
The command line has 2 arguments:
1:100
2:255
--------------------------------------------------------------------------------
注意:
1.主函数中带有参数需要调试步骤
project --> Settings --> Debug --> program arguments(输入参数)--> OK
2.在命令行中输入的都将作为字符串形式存储于内存中 任何形式都必须以%s格式输出
--------------------------------------------------------------------------------
*/
变量的作用域和存储方式
- 按作用域分:
- 全局变量:函数外部定义的变量
- 局部变量:函数内部的变量或者形参
int k = 0; // 全局变量
void f(int i) // int i 局部变量
{
int j = 30; // 局部变量
}
- 局部变量和全局变量同名时,全局变量会被局部变量屏蔽
- 按存储方式分:
- 静态变量
- 自动变量
- 寄存器变量
你知道我缺点什么