数组指针、函数指针、二级指针、字符串函数

数组指针

#include <stdio.h>

int getTheData(int (*p)[4],int hang,int lie)//(*p)[4]是数组指针
{
	int data;
	data = *(*(p+hang)+lie);//将对应数组中的值找出来
	return data;
	//return p[hang][lie];//同理 将对应数组中的值找出来
}
void tipsInputHangLie(int *pm, int *pn)//形参中的变量类型要与实参中相同,都是int
{
	printf("输入行列值:\n");
	scanf("%d%d",pm,pn);//指针就是地址,对相应的地址进行操作
	puts("done!");
}
//arr,arr[0]
int main()
{
	int arr[3][4] = {{11,22,33,44},{12,13,15,16},{22,66,77,88}};//arr+
	int ihang,ilie;
	int data;
	
	//1. 提示用户输入行列值
	tipsInputHangLie(&ihang,&ilie);//对地址进行操作,所以函数中的操作能改变ihang和ilie的值
	//2. 找出对应行列值的那个数
	data = getTheData(arr,ihang,ilie);//arr是数组的地址,也就是指针
	//3. 打印出来
	printf("%d行%d列的值是%d\n",ihang,ilie,data);
}

输出内容
在这里插入图片描述

函数指针

回掉函数的底层逻辑就是函数指针

#include <stdio.h>
#include <stdlib.h>

int getMax(int data1, int data2)
{
	return data1>data2 ? data1:data2;
}

int getMin(int data1, int data2)
{
	return data1<data2 ? data1:data2;
}

int getSum(int data1, int data2)
{
	return data1+data2;
}

int dataHandler(int data1, int data2, int (*pfunc)(int, int ))//第三个形参是函数指针,函数指针中对类型有要求,形参名可省略
{
	int ret;
	ret = (*pfunc)(data1,data2);//调取函数,求得返回值
	return ret;
}
int main()
{	
	int a = 10;
	int b = 20;
	int cmd;
	int ret;
	
	int (*pfunc)(int , int );
	
	printf("请输入1(取大值),2(取小值),或者3(求和)\n");
	scanf("%d",&cmd);
	switch(cmd){
		case 1:
			pfunc = getMax;//对地址进行了更改,也就变化了对应的值
		break;
		case 2:
			pfunc = getMin;
		break;
		case 3:
			pfunc = getSum;
		break;
		default:
			printf("输入错误!@输入1(取大值),2(取小值),或者3(求和)\n");
			exit(-1);//异常退出
		break;
	}
	ret = dataHandler(a,b,pfunc);//pfunc获取了对应的函数名,第三个实参pfunc是函数指针的地址
	printf("ret = %d\n",ret);
	return 0;
}

输出内容
在这里插入图片描述

函数指针数组

#include <stdio.h>
#include <stdlib.h>

int getMax(int data1, int data2)
{
	return data1>data2 ? data1:data2;
}

int getMin(int data1, int data2)
{
	return data1<data2 ? data1:data2;
}

int getSum(int data1, int data2)
{
	return data1+data2;
}
int main()
{	
	int a = 10;
	int b = 20;
	int ret;
	
	int (*pfunc[3])(int , int )={
		getMin,
		getMax,
		getSum};//函数指针数组!初始化,将数组中的值(这个值是个地址,也就是指针,这个指针是个函数指针,将三个函数地址放在数组里)
	
	for(int i=0;i<3;i++){
		ret = (*pfunc[i])(a,b);//遍历数组中的三个函数指针,获取返回值
		printf("ret = %d\n",ret);
	}
	
	return 0;
}

输出内容
在这里插入图片描述

函数指针

#include <stdio.h>

int* getPosPerson(int pos, int (*pstu)[4])//函数指针,返回指针的函数
{
	int *p;
	p = (int *)(pstu+pos);//二维数组地址+输入的数就是对应的数组值,然后赋值给P
	return p;
}

int main()
{
	int scores[3][4]={
		{55,66,77,88},//学生1
		{66,55,99,100},//学生2
		{11,22,33,59},//学生3
	};
	int *ppos;
	int pos;
	printf("请输入你需要看的学生号数:0,1,2\n");
	scanf("%d",&pos);
	
	ppos = getPosPerson(pos, scores);//获取对应数组的地址
	for(int i=0;i<4;i++){//将小数组里面的值进行遍历出来输出
		printf("%d ",*ppos++);//++代表偏移一个int整形的字节数
	}
	return 0;
}

输出内容
在这里插入图片描述

二级指针

#include <stdio.h>

void getPosPerson(int pos, int (*pstu)[4],int **ppos)//函数指针,返回指针的函数
{
	*ppos = (int *)(pstu+pos);//用二级指针的目的是直接修改了MAIN函数中的ppos的值
}

int main()
{
	int scores[3][4]={
		{55,66,77,88},
		{66,55,99,100},
		{11,22,33,59},
	};
	int *ppos;
	int pos;
	printf("请输入你需要看的学生号数:0,1,2\n");
	scanf("%d",&pos);
	
	getPosPerson(pos, scores,&ppos);
	for(int i=0;i<4;i++){
		printf("%d ",*ppos++);
	}
	return 0;
}

输出内容
在这里插入图片描述

在新版的C语言中出现了断言函数assert

assert() 的用法很简单,我们只要传入一个表达式,它会计算这个表达式的结果:
如果表达式的结果为“假”,assert() 会打印出断言失败的信息,并调用 abort() 函数终止程序的执行;
如果表达式的结果为“真”,assert() 就什么也不做,程序继续往后执行。

#include <stdio.h>
#include <assert.h>
char* myStrcpy(char *des, char *src)
{
	//assert 的作用是现计算表达式 expression ,如果其值为假(即为0),
	//那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行
	assert(des != NULL && src != NULL);//断言
	
	char *bak = des;
	
	while( *src != '\0'){
		*des = *src;
		des++;
		src++;
	}
	*des = '\0';
	
	return bak;
}

char* myStrcpy2(char *des, char *src)
{
	if(des == NULL || src == NULL){
		return NULL;
	}
	char *bak = des;
	
	while( *src != '\0'){
		*des++ = *src++;
	}
	*des = '\0';
	
	return bak;
}
char* myStrcpy3(char *des, char *src)
{
	if(des == NULL || src == NULL){
		return NULL;
	}
	char *bak = des;
	
	while( (*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}
char* myStrncpy(char *des, char *src, int count)
{
	if(des == NULL || src == NULL){
		return NULL;
	}
	char *bak = des;
	
	while( *src != '\0' && count>0){
		*des++ = *src++;
		count--;
	}
	if(count > 0){
		while(count > 0){
			count--;
			*des++ = '\0';
		}
		return des;
	}
	*des = '\0';
	
	return bak;
}

int main()
{
	char str[128] = {'\0'};
	char *pstr = NULL;
	char a = 'm';
	char b;
	if((b=a) == 'm'){
		printf("ok\n");
	}
	char *p = "chenlichen handsome";
	myStrcpy(pstr, p);//这么一拷贝显然是假,P不为NULL,所以打印错误LOG信息,结束程序
	puts(str);
	return 0;
}

输出结果:

ok
Assertion failed: des != NULL && src != NULL, file 1.c, line 7

字符串拼接函数strcat

#include <stdio.h>
#include <string.h>

int main()
{
	char str[128] = "liuzhihao";
	char *p = "xiaohao";
	char *p2;
    p2 = strcat(str,p);
	puts(str);
	puts(p2);
	return 0;
}

输出结果

liuzhihaoxiaohao
liuzhihaoxiaohao

多种写法实现strcat

#include <stdio.h>
#include <string.h>
#include <assert.h>

char* myStrcat(char *des, char *src)
{
	assert( des!=NULL && src!=NULL);
	char *bak = des;
	
	while(*des){
		des++;
	}
	while((*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}
char* myStrcat2(char *des, char *src)
{
	char *bak = des;
	strcpy(des+strlen(des),src);
	return bak;
}

char* myStrcat3(char *des, char *src)
{
	assert( des!=NULL && src!=NULL);
	char *bak = des;
	
	for(;*des!='\0';des++);
	while((*des++ = *src++) != '\0');
	*des = '\0';
	
	return bak;
}
int main()
{
	char str[128] = "liuzhihao";
	char *p2;
	char *p = " xiaohao";
	p2 = myStrcat(str,p);
	//p2 = strcat(str,p);
	puts(str);
	//puts(p2);
	return 0;
}

strcmp函数

#include <stdio.h>
#include <string.h>
#include <assert.h>

int myStrcmp(char *str1, char *str2)
{
	int ret = 0;
	int n_str1 = 0;
	int n_str2 = 0;
	char *bakStr1 = str1;
	char *bakStr2 = str2;

	while( *str1 && *str2 && (*str1 == *str2)){
		str1++;
		str2++;
	}
	if(*str1 || *str2){
		str1 = bakStr1;
		str2 = bakStr2;
		while(*str1){
			n_str1 += *str1;
			str1++;
		}
		while(*str2){
			n_str2 += *str2;
			str2++;
		}
	}
	ret = n_str1 - n_str2;
	if(ret < 0){
		ret = -1;
	}
	if(ret > 0){
		ret = 1;
	}
	return ret;
}
int main()
{
	char *p1 = "chmnlichend";
	char *p2 = "chenlzchend";

	int ret = myStrcmp(p1,p2);//-1 1 0
	int ret = strcmp(p1,p2);//-1 1 0
	if(ret == 0){
		puts("相同");
	}
	printf("RET = %d\n",ret);
	return 0;
}

结构体指针

#include <stdio.h>

struct Test
{
	int idata;
	char cdata;
};

int main()
{
	int  var = 20;  
    int  *ip;     
    ip = &var; 

	printf("ip%d\n", *ip);//这里是用*号是因为,变量就是指针,也就是地址
	
    struct Test t1 = {10, 'c'}; //1. 类型 2.名 3.值 4.地址
    
    struct Test *ps;
	ps = &t1;
    printf("t1的idata=%d\n",t1.idata);//变量名访问,用点运算符
	printf("t1的idata=%d\n",ps->idata);//这里ps->idata的前面没用*,因为结构体成员是int型的,所以不用*,取决于结构体成员的类型,用.还是用->取决于结构体是指针还是普通变量
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值