//函数指针用法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);
}