1.数组的练习题
(1)删除指定数
先输入10个数字,存在数组中,输入一个整数n,删除等于n的数字,剩余在最前面;
后面的依次覆盖前面,删除一个,只看前九个(数组的有效元素个数-1);
外循环,如果进行了删除操作,i不变;
int main()
{
int arr[10] = { 1,1,2,2,3,1,2,2,4,2};
int size = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int n = 0;
scanf("%d", &n);
while (i < size)
{
if (arr[i] == n)
{
int j = i + 1;
while (j < size)
{
arr[j - 1] = arr[j];
j++;
}
size--;
}
else
{
i++;
}
}
for (int i = 0; i <= size - 1; i++)
{
printf("%d", arr[i]);
}
}
(2)合并两个升序排列的数组;
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,3,4,5,6 };
int arr3[10] = { 0 };
int i = 0;
int j = 0;
int k = 0;
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
int sz2 = sizeof(arr2) / sizeof(arr2[0]);
while (i < sz1 && i < sz2)
{
if (arr1[i] < arr2[j])
{
arr3[k] = arr1[i];
i++;
}
else {
arr3[k] = arr2[j];
j++;
}
k++;
}
while (i < sz1)
{
arr3[k] = arr1[i];
i++;
k++;
}
while (j < sz2)
{
arr3[k] = arr2[j];
j++;
k++;
}
for (i = 0; i < k; i++)
{
printf("%d ", arr3[i]);
}
return 0;
}
(3)杨辉三角
每个数都是他左上方和右上方之和;
int main()
{
int i = 0; int j = 0;
int arr[10][10];
for (i = 0; i < 10; i++)
{
arr[i][0] = arr[i][i] = 1;
for (j = 1; j < i; j++)
{
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
}
for (i = 0; i < 10; i++)
{
for (j = 0; j <= i; j++)
{
printf("%-6d", arr[i][j]);
}
printf("\n");
}
return 0;
}
2.函数
(1)库函数,自定义函数
函数要放在主函数外面,全局;
int ret=add(5,10);函数调用;
(2)自定义函数
根据功能,设置好返回值,
设置函数名
接受传过来的数据
实现对应函数体
(3)形参,实参
void表示返回值为空 ;
调用函数时,形参开辟空间,拷贝;
形参是实参的一份临时拷贝;
(4)return的使用;
如果有if,确保每一种情况都有返回值;
(5)自定义函数中求数组元素个数;如果数组经历了函数传参;不能通过sizeof求元素个数;
原因:数组传参穿的是数组首元素地址,数组传参会退化为指针;
(6)数组传参不是把所有的数组都传递,而是首元素地址;操作的还是原来的数组;
(7)函数的形式参数是和函数的实参个数匹配;
函数的实参是数组,形参也是可以写成数组形式的
形参如果是一维数组,数组大小可以省略不写
形参如果是二维数组,行可以省略,但是列不能省略
数组传参,形参是不会创建新的数组的
形参操作的数组和实参的数组是同一个数组
3.函数的嵌套调用和链式访问;
嵌套调用:在一个函数中调用另一个函数
嵌套定义:
链式访问:把一个函数当做另一个函数的参数
(1)输入某年某月某日计算从1.1开始,经过了多少天;
4.函数的声明(必须在使用之前)和定义
返回值类型,名字,形参
函数的实现:具体的操作
函数的定义是特殊的声明;
5.多文件编译:
6.<>在库中找
“”,在当前路径找,然后在库中找;
7.两个关键字;
static静态:1.延长局部变量的生命周期,跟随进程;2.程序起来之后就创建好了,只初始化一次;3.改变局部变量在内存中的存储位置,由栈区到静态区;4.未初始化,默认为0;
内存:
****栈区:局部变量存在栈区,函数调用所开辟的空间,函数栈帧,,函数调用地址,函数形参,
****堆区:动态内存;
****静态区(全局区):
栈空间分配原则:由高到低;
static修饰全局变量;破坏了外部链接属性;
static修饰函数;破坏了外部链接属性;只能在当前文件中使用;
extern声明:全局变量;
8.函数的递归:函数自己调用自己;
两个必要条件:
(1)存在限制条件;
(2)无限接近限制条件;
9.递归练习:
(1)计算n的阶乘:
(2)顺序打印整数的每一位;
(3)逆序打印:
(4)求第n个斐波那契数列:
(5)汉诺塔
作业:
1.删除数组元素:
int main()
{
int arr[10] = { 1,1,2,2,3,1,2,2,4,2};
int size = sizeof(arr) / sizeof(arr[0]);
int i = 0;
int n = 0;
scanf("%d", &n);
while (i < size)
{
if (arr[i] == n)
{
int j = i + 1;
while (j < size)
{
arr[j - 1] = arr[j];
j++;
}
size--;
}
else
{
i++;
}
}
for (int i = 0; i <= size - 1; i++)
{
printf("%d", arr[i]);
}
}
2.合并两个整型数组:
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,3,4,5,6 };
int arr3[10] = { 0 };
int i = 0;
int j = 0;
int k = 0;
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
int sz2 = sizeof(arr2) / sizeof(arr2[0]);
while (i < sz1 && i < sz2)
{
if (arr1[i] < arr2[j])
{
arr3[k] = arr1[i];
i++;
}
else {
arr3[k] = arr2[j];
j++;
}
k++;
}
while (i < sz1)
{
arr3[k] = arr1[i];
i++;
k++;
}
while (j < sz2)
{
arr3[k] = arr2[j];
j++;
k++;
}
for (i = 0; i < k; i++)
{
printf("%d ", arr3[i]);
}
return 0;
}
3.杨辉三角
int main()
{
int arr[10][10];
int i = 0; int j = 0;
for (i = 0; i < 10; i++)
{
arr[i][0] = arr[i][i] = 1;
for (j = 1; j < i; j++)
{
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
}
for (i = 0; i < 10; i++)
{
for (j = 0; j <= i; j++)
{
printf("%-6d", arr[i][j]);
}
printf("\n");
}
}
4.整理自定义函数的格式:
核心组成(3部分)
1. 返回值类型:函数执行后返回的数据类型,无返回值写 void
2. 函数名与参数列表:参数需写明类型+名称,无参数写 () 或 (void)
3. 函数体:花括号内的执行代码, return 后的值类型需与返回值类型一致
5. 形参实参的区别
实际参数就是真实传递给函数的参数
形式参数是函数用来接收实参的参数
6.返回值类型
1.return后边可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式
的结果。
2.return后边也可以什么都没有,直接写return;这种写法适合函数返回类型是yoid的情况.
3.return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型
4.return语句执行后,函数就彻底返回,后边的代码不再执行。
5.如果函数中存在if等分支的语句,则要保证每种情况下都有retun返回,否则会出现编译错误
7.数组传参
void set_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
arr[i] = -1;
}
}
void printf_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
set_arr(arr, sz);
printf_arr(arr, sz);
return 0;
}
作业:
1.函数的嵌套调用和链式访问
嵌套调用就是函数之间互相调用,相互配合完成一个更加复杂的程序
链式访问就是将一个函数的返回值作为另一个函数的参数
万年历:
int isleapyear(int y)
{
if ((y % 4 == 0 && y % 400 != 0) || (y % 400 == 0))
return 1;
else
return 0;
}
int getdays(int y, int m, int d)
{
int days[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
int day = 0;
for (int i = 1; i < m; i++)
{
day += days[i];
}
day = day + d;
if (isleapyear(y)&&m>2)
{
day += 1;
}
return day;
}
int main()
{
int year = 0; int month = 0; int day = 0;
scanf("%d %d %d", &year, &month, &day);
int d = getdays(year, month, day);
printf("%d", d);
}
2.理解函数的声明和定义
函数声明仅说明函数的名称、返回值类型和参数列表,不包含实现,用于告知编译器函数接口;函数定义则包含完整的函数体,是函数的具体实现。当函数定义在调用之后时,必须先声明,否则会编译报错。
3.理解多文件编译
企业中写代码的时候,一般不会将所有的代码都放在一个文件中,而是会根据程序的功能将代码拆分放在多个文件中。一般情况下,函数的声明,类型的声明放在头文件(.h)中,函数的实现是放在原文件(.c)中;
4.理解关键字static作用;
Static的意思是静态的,可以修饰局部变量,全局变量以及函数,Static修饰局部变量,改变了变量的生命周期,生命周期改变的本质,是改变了变量的存储类型。本来一个局部变量是存储在内存的占区的,但是被static修饰后存储到了静态区,存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收,但是作用域不变的;
5.递归
(1)计算n的阶乘:
int Fact(int n)
{
if (n == 0)
return 1;
else
return n * Fact(n - 1);
}
int main()
{
int n;
scanf("%d", &n);
printf("%d", Fact(n));
}
(2)顺序打印整数的每一位;
void Print(int n)
{
if(n>9)
{
Print(n/10);
}
printf("%d ", n%10);
}
int main()
{
int m = 0;
scanf("%d", &m);
Print(m);
return 0;
}
(3)逆序打印:
void ReversePrint(int n)
{
printf("%d ", n % 10);
if (n / 10 > 0)
{
ReversePrint(n / 10);
}
}
int main()
{
int m = 0;
scanf("%d", &m);
ReversePrint(m);
return 0;
}
(4)求第n个斐波那契数列:
int fib(int n) {
if (n == 1 || n == 2) return 1;
return fib(n - 1) + fib(n - 2);
}
int main() {
int n;
scanf("%d", &n);
printf("%d", fib(n));
return 0;
}
(5)汉诺塔
//汉诺塔
void hanoi(int n,char c1,char c2,char c3)
{
if (n == 1)
{
printf("从%c移动到%c\n", c1, c3);
return;
}
hanoi(n - 1, c1, c3, c2);
printf("从%c移动到%c\n", c1, c3);
hanoi(n - 1, c2, c1, c3);
}
int main()
{
hanoi(3, 'A', 'B', 'C');
return 0;
}