ARM Study Day11:标准C之函数指针、高级指针、字符指针数组、动态分配内存、标准文件操作库函数

在这里插入图片描述

//函数指针用法1演示
#include <stdio.h>
int add(int a, int b)	{
	return a + b;
}

int sub(int a, int b){
	return a - b;
}

int main(void)
{
	int ret = 0;
	//声明函数指针类型并且定义初始化函数指针变量pfunc,保存add函数的首地址
	int (*pfunc)(int, int) = add; //pfunc指向add
	//通过pfunc间接调用指向的add函数并且给add函数传递函数,用ret保存指向函数返回值
	ret = pfunc(100, 200);
	printf("add函数的返回值是%d\n", ret);
	//让pfunc保存sub函数的首地址指向sub函数
	pfunc = sub;
	//让pfunc间接调用指向的sub函数并且给sub函数传递参数
	ret = pfunc(100, 200);
	printf("add函数返回值是%d\n",  ret);
	return 0; 
}	

//函数指针用法2演示
#include <stdio.h>
//声明函数指针类型并且取别名
//给int (*)(int, int)类型取别名叫pfunc_t
typedef int (*pfunc_t)(int, int);
int add(int a, int b)   {
        return a + b;
}

int sub(int a, int b){
        return a - b;
}

int main(void)
{
        int ret = 0;
        //定义初始化函数指针变量pfunc,保存add函数的首地址
        pfunc_t pfunc  = add; //pfunc指向add
        //通过pfunc间接调用指向的add函数并且给add函数传递函数,用ret保存指向函数返回值
        ret = pfunc(100, 200);
        printf("add函数的返回值是%d\n", ret);
        //让pfunc保存sub函数的首地址指向sub函数
        pfunc = sub;
        //让pfunc间接调用指向的sub函数并且给sub函数传递参数
        ret = pfunc(100, 200);
        printf("add函数返回值是%d\n",  ret);
        return 0;
} 

```c
//定义回调函数:add和sub,回调函数的意思就是这些函数可以当成参数传递给别的函数调用
typedef int (*pfunc_t)(int, int);
int add(int a, int b)   {
        return a + b;
}

int sub(int a, int b){
        return a - b;
}
//定义调用函数cal:调用函数将来他的形参中有一个函数指针变量来保存回调函数的首地址
//那么将来调用函数通过形参函数指针变量可以间接调用回调函数

int cal(int a, int b, pfunc_t pfunc)
{
        if(pfunc == NULL)  //如果没有用给调用函数cal传递回调函数,那么就用cal函数默认的相乘功能
                return a * b;
        else
                return pfunc(a, b);//如果给cal函数传递了一个回调函数,那么就不用cal的默认相乘功能
                                        //那么就用回调函数想要的功能:相加或者相减
}
int main(void)
{
        printf("%d\n",cal(50, 100, NULL));   //就想用默认功能
        printf("%d\n",cal(50, 100, add));       //不想用默认功能,用加
        printf("%d\n",cal(50, 100, sub));       //不想用默认功能,用减
        return 0;
}


123
在这里插入图片描述

123


```c
//函数指针玩法
#include <stdio.h>
#include <stdlib.h>  //声明qsort函数
int intcmp(const void *p1, const void *p2)
{
        return *(const int *)p1 - *(const int *)p2;
}

int main(void)
{
        int a[] = {13, 34, 9, 44, 54, 22, 15, 9 };
        int len = sizeof(a)/sizeof(a[0]);
        //qsort已经把快速排序算法流程算好了,只需要编写一个回调函数intcmp
        //比较两个数的大小,然后将比较的结果给qsort,将来qsort自动调用intcmp,
        //根据返回值结果自动进行排序
        //大大减轻开发的工作量
        qsort(a, len, sizeof(a[0]), intcmp);
        for(int i = 0;i < len; i++)
                printf("%d\n", a[i]);
        printf("\n");
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1111

//数组指针演示
#include <stdio.h>
int main(void){
	int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
	for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++)	
	{
		for(int j = 0; j< sizeof(a[0])/sizeof(a[0][1]); j++)
			printf("%d ", a[i][j]);  //*(a[i]+j) = *(*(a+i)+j)
		printf("\n");
	}
	//通过数组指针来访问二维数组
	int (*p)[4] = a;//定义初始化数组指针变量p来保存二维数组的首地址
	for(int i = 0; i< 3; i++){
		for(int j = 0; j < 4; j++)
			printf("%d ", p[i][j]);
		printf("\n");
	}
       //二维转一维	
	int *p1 =(int *)a;
	for(int i = 0; i < 12; i++)
		printf("%d ", p1[i]);
	printf("\n");

	//一维转二维
	int b[] = {0,1,2,3,4,5,6,7,8,9,10,11};
	int (*p2)[4] =(int (*)[4])b; //强制将int类型转换为数组指针
	for(int i = 0; i < 3; i++)
		for(int j = 0; j < 4; j++)
			printf("%d ", a[i][j]);
		printf("\n");
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//二级指针演示
#include <stdio.h>
int main(void) {
        int n = 10;
        int *p = &n;
        int **pp = &p;
        printf("n = %d, &n = %p\n, n, &n");
        printf("p = %p, &p = %p, *p = %d\n", p, &p, *p);
        printf("pp = %p, &pp = %p, *pp = %p, **pp = %d\n", pp, &pp, *pp, **pp);
        //通过p访问n
        *p = 300;
        printf("n = %d\n", *p);
        //通过pp访问n
        **pp = 400;
        printf("n = %d\n", **pp);
        return 0;
}

1111

//二级指针的应用
//笔试题:编写一个函数实现两个字符串的交换
//char *pa = "hello", char *pb = "world"  目标:pa->"world" pb->"hello"
//切记切记切记:如果将来一个函数 要修改一级指针的指向,这个函数的形参要定义为二级指针
#include <stdio.h>
void swap(char *p1, char *p2){ //p1 = pa, p2=pb
        char *p3 = p1;
        p1 = p2;
        p2 = p3;
}

void swap1(char **p1, char **p2){//p1 = &pa p2 =&pb
        char *p3 = *p1; //将pa保存的地址给p3
        *p1 = *p2;  //直接将实参pb保存的地址给实参pa
        *p2 = p3;  //将p3保存的地址直接给实参pb
}
int main(void)
{
        char *pa = "hello", *pb = "world";
        swap(pa, pb);
        printf("pa = %s, pb = %s\n",pa, pb);
        swap1(&pa, &pb);
        printf("pa = %s, pb = %s\n",pa, pb);
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


//malloc /free 标准C库函数演示:从堆区分配内存,C语言的第四种分配内存方法,可以大量分配并且类型无关
//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>  //库函数的声明
int main(void){
        int *p = NULL;
        //调用malloc分配内存
        p = (int *)malloc(8); //连续分配8字节内存,返回内存的首地址保存到p中
        if(p == NULL)
        {
                printf("内存分配失败了。\n");
                return -1;
        }
        printf("分配成功,首地址是%p\n", p);
        *(p+0) = 520;  //向前4字节写入520
        *(p+1) = 521;  //向后4字节写入520
        printf("%d, %d\n", p[0], p[1]);
        //调用free释放内存否则内存泄漏
        free(p);
        p= NULL;        //好习惯,否则p是一个野指针,因为p此时指向的内存已经被释放了,不再是合法有效的内存了
        return 0;
}

//calloc/free标准C库函数演示:从堆区分配额你村,C语言的第四种分配内存方法:可以大量分配并且类型无关
//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
	int *p = NULL;
	//调用calloc分配内存
	p = (int *)calloc(4, sizeof(int));//连续分配16字节内存,返回内存的首地址保存到P中
	if(p == NULL){
	printf("内存分配失败了.\n");
	return -1;
}
	printf("分配成功,首地址是%p\n", p);
	//初始化分配的内存
	for(int i = 0; i < 4; i++)
		p[i] = i + 1;
	//打印
	for(int i = 0; i < 4; i++)
		printf("%d", *(p+i));
	printf("\n");
	//调用free释放内存 否则内存泄漏
	free(p);
	p = NULL;
	return 0}

//分配内存的效率低下
#include <stdio.h>
#include <stdlib.h>
#define NUMB 4
int main(void)
{
        int *p = NULL;
        //调用malloc分配内存        p = (int *)malloc(8);//连续分配8字节内存,返回内存的首地址保存到P中
        if(p == NULL){
        printf("内存分配失败了.\n");
        return -1;
}
        printf("分配成功,首地址是%p\n", p);
        *(p + 0) = 520;
        *(p + 1) = 521;
        printf("%d, %d\n", p[0], p[1]);
        //调用realloc调整内存大小
        p = realloc(p, 16);
        //在原先malloc分配的内存基础上继续额外多分配8字节内存,并且返回新的内存
首地址给p
        //初始化分配的内存
        for(int i = 0; i < NUMB; i++)
                p[i] = i + 1;
        //打印
        for(int i = 0; i < NUMB; i++)
                printf("%d ", *(p+i));
        printf("\n");
        //调用free释放内存 否则内存泄漏
        free(p);
        p = NULL;
        //好习惯,否则p是一个野指针
        return 0}

在这里插入图片描述

**

IO流与标准库

**
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//文件操作标准C库函数
#include <stdio.h>
int main(void)
{
        FILE *fp = NULL;

        fp = fopen("a.txt", "r");
        if(fp == NULL){
                printf("打开失败.\n");
                return -1;
        }

        printf("打开成功.\n");

        fclose(fp);
        return 0;
}

//文件操作标准C库函数
#include <stdio.h>
int main(void)
{
        FILE *fp = NULL; //FILE结构体就是描述文件打开后的各种属性,程序员无需关注内部成员
        fp = fopen("a.txt", "r");//以只读方式打开当前目录下的a.txt文件
        if(fp == NULL){
                printf("打开失败.\n");
                return -1;
        }
        printf("打开成功.\n");
        int i = 0;
        char a[20] = {0};
        double d = 0;
        //按照指定的格式从fp对应的文件中读取数据存到变量i,a,d中
        fscanf(fp, "%d%s%lf", &i, a, &d);
        fclose(fp); //关闭文件
        fp = NULL; //好习惯
        printf("i = %d, a = %s, d = %lg\n", i, a, d);
        FILE *fpw = fopen("b.txt", "w");
        if(fpw == NULL)
        {
                printf("打开失败。\n");
                return -1;
        }
        fprintf(fpw, "copy:%d %s %lf", i, a, d);
        fclose(fpw); //关闭b.txt
        fpw = NULL;
        //stdin,stdout,stderr三个默认的文件指针
        fscanf(stdin, "%d%s%lf", &i, a, &d);//从键盘标准输入设备上输入数据保存到变量中
        printf("i = %d, a = %s, d = %lg\n", i, a, d);
        fprintf(stdout, "i = %d, a = %s, d = %lg\n", i, a, d);
        fprintf(stderr, "i = %d, a = %s, d = %lg\n", i, a, d);
        return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//fputc和fget函数展示
#include <stdio.h>
int main(void)
{
        FILE *fpr = fopen("a.txt", "r");
        FILE *fpw = fopen("b.txt", "w+");
        char str[4] = {0};  //用于保存从文件中读取的字符串
        while(fgets(str, 4, fpr) != NULL)  //循环从文件中读取3个字符
        {
                fputs(str, fpw); //然后将读取的数据写入到文件中
        }
        while(1)
        {
                ch = fgetc(fpr); //从a.txt读取一个字符
                if(ch == EOF)   //判断是否读取到文件的尾部
                        break;
                fputc(ch, fpw);  //向b.txt写入一个字符
        }
        fclose(fpr);
        fclose(fpw);
        fpr = NULL;
        fpw = NULL;
        return 0;
}

在这里插入图片描述
在这里插入图片描述

//fread,fwrite
#include <stdio.h>
int main(void){
        FILE *fp = fopen("a.txt", "w+");
        int a[] = {1,2,3,4,5,6,7,8};
        int len = sizeof(a)/sizeof(a[0]);
        int size = 0;

        size = fwrite(a, sizeof(int), len, fp);//向文件写入len个int>类型的数据,期望写入4*len=32个字节
        printf("实际写入了%d个数据\n", size);

        rewind(fp);  //将文件的操作位置重新定位到文件的开头

        int b[8] = {0}; //暂存将来从文件中读取到的数据
        size = fread(b, sizeof(int), 10, fp);//从文件中希望读取10个>数据
        printf("实际读取了%d个数据\n", size);

        for(int i = 0;i < size; i++)
                printf("%d", b[i]);
        printf("\n");

        fclose(fp);
        fp = NULL;
        return 0;
}

在这里插入图片描述

//fread,fwrite
#include <stdio.h>
int main(void){
	FILE *fp = fopen("a.txt", "w+");
	int a[] = {1,2,3,4,5,6,7,8};
	int len = sizeof(a)/sizeof(a[0]);
	int size = 0;

	size = fwrite(a, sizeof(int), len, fp);//向文件写入len个int类型的数据,期望写入4*len=32个字节
	printf("实际写入了%d个数据\n", size);

	rewind(fp);  //将文件的操作位置重新定位到文件的开头

	int b[8] = {0}; //暂存将来从文件中读取到的数据
	size = fread(b, sizeof(int), 10, fp);//从文件中希望读取10个数据
	printf("实际读取了%d个数据\n", size);

	for(int i = 0;i < size; i++)
		printf("%d", b[i]);
	printf("\n");

	//fseek函数演示
	int c[2] = {0};
	fseek(fp, 8, SEEK_SET);
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);

	fseek(fp, 8, SEEK_CUR);//从当前位置(5)个位置往后8个字节开始操作文件
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);

	fseek(fp, -12, SEEK_END); //从文件微博往前12个字节开始操作文件
	//1 2 3 4 5 6 7 8
	//
	fread(c, sizeof(int), 2, fp);//读取完毕,文件位置跑到5
	printf("%d %d\n",c[0], c[1]);
	fclose(fp);
	fp = NULL;
	return 0;
}

在这里插入图片描述
在这里插入图片描述

//feof,ferror
#include <stdio.h>
int main(void)
{
	FILE *src = fopen("a.txt", "r");
	FILE *dst = fopen("b.txt", "w");
	int bytes;
	unsigned char buf[1024];

	while(bytes = fread(buf, 1, sizeof(buf), src)){
		if(fwrite(buf, 1, bytes, dst) != bytes)
		{
			printf("写入失败。\n");
			return -1;
		}
	}

	//判断读取失败的原因
	//读失败
	if(ferror(src)){
		printf("读取失败。\n");
	}

	//读到尾部
	if(feof(src))
	{
		printf("到头啦\n");
		return 0;
	}

	fclose(src);
	fclose(dst);
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值