笔记
函数(继续)
四.数组作为函数参数传递
1)数组的要素:起始地址(数组名),数组的容量
2)数组作为函数参数传递,属于地址传递,形参内容的改变,实参内容也会跟着改变
3)定义形参接受数组时,接受数组名时,只需要定义一个变量标识数组即可
4.1值传递
值传递过程中,型参与实参操作的是不同的内存空间
当普通变量作为函数参数传递时,是单向的值传递,仅仅只是将实参的值,复制一份给形参使用,新参的改变不会影响到实参的值
4.2地址传递
当实参传递的是数组名、指针或变量的地址时,可以理解成是地址传递,地址传递过程中,型参与实参操作的是同一块内存空间,形参对内存空间进行改变时,实参也跟着一起改变
五.递归函数
递归的概念 | 所谓递归就是一个函数直接或间接的形式调用自身,这样的函数调用,我们称为递归调用 |
递归条件 | 1.递归出口:用于终止递归进行的条件 2.递归表达式:能够让递归继续进行的函数调用 |
递归思想 | 当直接解决规模较大的问题不能进行时,需要先解决规模较小的原理一致的问题后,大的问题得以解决时,可以考虑使用递归 |
示例:(求斐波那契数列)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int fbnqsl(int n)
{
if(n==2||n==1)
return 1;
else
{
return fbnqsl(n-1)+fbnqsl(n-2);
}
}
int main(int argc, const char *argv[])
{
int n=0,sum=0;
printf("请输入斐波那契数列的项数:\n");
scanf("%d",&n);
sum=fbnqsl(n);
printf("第%d项为:%d\n",n,sum);
return 0;
}
指针
一.指针的相关概念
1)引入目的:能够从地址的角度,找到内存中的数据;而不是以变量的角度去找,效率较高
2)指针变量:由于指针这个地址编号很难记忆,我们引入指针变量存储指针
存储地址的变量称为指针变量
3)指针变量中,指针存储地址,作为一个特殊的数据类型,其大小固定为8字节
二.指针变量的定义
定义格式 | 数据类型*指针名 列:int *ptr; |
指针变量的初始化 | 1.使用一个相同数据类型的变量的地址为其进行初始化 2.使用一个已经初始化了的指针变量给一个新的指针变量进行初始化 3.使用地址的0就是NULL为其初始化 4.注意:没有初始化的指针变量不能直接使用,因为该指针变量中存储一个随即地址,如果对其进行更改,可能会导致系统崩坏 5.野指针:指向非法内存的指针称为野指针 产生情况: 1.定义指针时,没有为其进行初始化 2.指向一个内存空间,但是随着程序的进行,该内存空间被回收了,那么该指针也是野指针(选空指针) 3.数组下标越界时,访问的地址也是野指针 |
指针变量的使用 | 1.指针变量在定义时,*号只是身份的象征,表示该语句定义的是指针变量 2.指针变量使用时,*号表示一个运算,取值运算,就是取得该指针变量指向的内存空间中的值 3.总结*在C语言中的用途: 1)表示乘号,是一个双目运算符 2)定义指针时,是身份的象征,表示定义的是指针变量 3)使用指针时,是取值运算符,表示取得指针变量指向的内存空间中的值 4.总结&在C语言中的用途 1)一个&表示双目运算符 按位 与运算 2)两个&&表示双目运算符 逻辑 与运算 3)一个&表示单目运算符 取址运算 5.&于*在指针的方面,互为逆运算 |
指针的大小与指针的类之间的关系 | 不同的数据类型的指针所占内存空间都是一样的,都是指针的大小,32位系统下为4字节,64位系统下为8字节 指针的数据类型存在的意义,不是为了给指针分配内存空间的,而是为了指针偏移使用的 不同类型的指针,在进行指针偏移时,偏移的大小跟数据类型有关 指针每偏移一个单位,内存空间就会偏移一个数据类型大小的字节数 指针指向普通变量时,指针的偏移是没有意义的,但是,指针指向数组时,指针的偏移就有了现实的意义,表示指向上一个元素或者下一个元素的地址 |
作业
1.使用递归实现求n的k次方
#include<stdio.h>
int ci_fang(int n,int k)
{
if(k==1)
{
return n;
}
else
{
return n*ci_fang(n,k-1);
}
}
int main(int argc, char const *argv[])
{
int n=0,k=0;
printf("请输入你要求的的数:\n");
scanf("%d",&n);
getchar();
printf("请输入你要求它的次方数:\n");
scanf("%d",&k);
getchar();
printf("%d的%d次方为:%d\n",n,k,ci_fang(n,k));
return 0;
}
2.使用递归实现strlen的功能
#include<stdio.h>
int di_gui_strlen(char a[])
{
char *p=a;
if(*p=='\0')
{
return 0;
}
else
{
return 1+di_gui_strlen(p+1);
}
}
int main(int argc, char const *argv[])
{
char arr[100]={0};
printf("请输入一个字符串:\n");
scanf("%s",arr);
printf("该字符串的长度为:%d\n",di_gui_strlen(arr));
return 0;
}
3.使用递归实现汉诺塔问题
#include<stdio.h>
int hang_nuo_ta(int n)
{
if(n==1)
{
return 1;
}
else if(n==2)
{
return 3;
}
else
{
return hang_nuo_ta(n-1)+hang_nuo_ta(n-1)+1;
}
}
int main(int argc, char const *argv[])
{
int n=0;
printf("请输入汉诺塔的数量:\n");
scanf("%d",&n);
printf("运行次数为%d\n",hang_nuo_ta(n));
return 0;
}
4.定义一个函数将一个字符串从大到小排序
#include<stdio.h>
#include<string.h>
void zhi_fu_pai_xu(char a[20][100],int flag)
{
for ( int i = 1; i < flag; i++)
{
for (int j = 0; j < flag-i; j++)
{
if(strcmp(a[j],a[j+1])<0)
{
char tempa[100]="";
strcpy(tempa,a[j]);
strcpy(a[j],a[j+1]);
strcpy(a[j+1],tempa);
}
}
}
printf("字符串由大到小为:\n");
for (int i = 0; i < flag; i++)
{
printf("%s\n",a[i]);
}
}
int main(int argc, char const *argv[])
{
int flag=0;
char a[20][100];
printf("请输入你要输入的字符串个数:\n");
scanf("%d",&flag);
getchar();
for (int i = 0; i < flag ; i++)
{
printf("输入第%d个字符串:\n",i+1);
scanf("%s",a[i]);
getchar();
}
zhi_fu_pai_xu(a,flag);
return 0;
}
5.实现一个函数,用于检查一个字符串是否为回文字符串(正序反序都相同)
#include<stdio.h>
void hui_weng(char a[100])
{
int len=0;
int flag=0;
for (int i = 0; a[i] != '\0'; i++)
{
len++;
}
for (int i = 0; i < len/2; i++)
{
if(a[i]!=a[len-i-1])
flag=1;
}
if(flag==1)
printf("该字符串不是回文字符串\n");
else
printf("该字符串是回文字符串\n");
}
int main(int argc, char const *argv[])
{
char a[100]={0};
printf("请输入一个字符串:\n");
scanf("%s",a);
hui_weng(a);
return 0;
}
6.判断自己的主机是大端存储还是小端存储
#include <stdio.h>
int main(int argc, char const *argv[])
{
int num1=1;
char *p1=(char*)&num1;
if(*p1==1)
{
printf("小端存储\n");
}
else
{
printf("大段存储\n");
}
}
7.有一段文本,写一段程序统计其中的单词数(单词间隔不一定为空格)
#include<stdio.h>
void dang_ci_shu(char a[100])
{
int sum=0;
int flag_tou=0;
int flag_wei=0;
int len=0;
for (int i = 0; a[i] != '\0'; i++)
{
len++;
}
for (int i = 0; i<len; i++)
{
if(i==len-1)
flag_wei=1;//如果为字符串最后一位,尾标置一,防止漏判
if(flag_tou==0)//如果头标为零进入判断,遇到字母,头标为一
{
if((a[i]>='a'&&a[i]<='z')||(a[i]>='a'&&a[i]<='z'))
flag_tou=1;
}
if(flag_wei==0&&flag_tou==1)//如果头标为一,尾标为零进入判断,遇到非字母,尾标为一
{
if(!((a[i]>='a'&&a[i]<='z')||(a[i]>='a'&&a[i]<='z')))
flag_wei=1;
}
if(flag_tou==1&&flag_wei==1)//头标尾标都为一则证明扫过一个单词,总数加一,并置零头尾标
{
sum++;
flag_tou=0;
flag_wei=0;
}
}
printf("该文本中有%d个单词\n",sum);
}
int main(int argc, char const *argv[])
{
char a[100];
printf("请输入一段文本:\n");
gets(a);
dang_ci_shu(a);
return 0;
}