数组指针
#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;
}