第13天小整理
1.有关字符串的问题分析
#include <stdio.h>
#include <string.h>
int main(){int b=0;char a[5]={0};gets(a);b=strlen(a);printf("%d\n",b);return 0;
}
在此处输入10个字符,输出结果将为10,而非5。
这是因为:
gets
函数存在严重的安全隐患,因为它不会检查输入的字符串长度是否会超出目标数组的大小,很容易导致缓冲区溢出错误。strlen
函数会从字符串的起始位置开始,一直计数直到遇到空终止符'\0'
。
当gets()产生溢出错误时,可能会得到这样的提示
*** stack smashing detected ***: terminated
2.使用字符串进行格式化输出
int main(){int a=5;char *str="%d\n";printf(str,a);return 0;
}
这里首先定义了一个字符指针 str
,并将其初始化为字符串 "%d\n"
。
调用 printf
函数,将字符指针 str
所指向的格式控制字符串作为第一个参数传入,将整型变量 a
作为第二个参数传入。这样做的效果等同于直接写 printf("%d\n", a);
,也就是会将变量 a
的值以十进制整数的形式输出,然后换行。
当程序运行时,会输出:5
3.函数指针调用
(1)直接调用
#include <stdio.h>int fun(void) {// 先定义函数fun,这里函数fun只是简单返回一个值42return 42;
}int main() {int (*p)(void) = fun; // 定义并初始化函数指针p,让它指向fun函数int result = p(); // 使用函数指针p调用函数funprintf("函数调用结果: %d\n", result);return 0;
}//42
我们通过函数指针 p
调用了函数 fun
。这里 p()
的作用就和之前直接写 fun()
是一样的,都是去执行函数 fun
里面的代码逻辑,然后函数 fun
会返回一个值(在这里它返回 42),这个返回值就被存储在了变量 result
里,后面我们就可以用这个 result
做其他的事情啦
(2)作为函数参数传递调用方式
#include <stdio.h>int fun(void) {// 同样先定义函数fun,返回值为42return 42;
}void newFun(int (*func)(void)) {// 定义一个新的函数newFun,它接受一个函数指针作为参数int result = func();printf("在新函数中调用结果: %d\n", result);
}int main() {int (*p)(void) = fun;// 定义并初始化函数指针p指向fun函数newFun(p);// 把函数指针p传递给新函数return 0;
}
首先我们还是有函数 fun
和让函数指针 p
指向它的操作。
然后我们定义了一个新的函数newFun,这个函数的参数是一个函数指针 func
,它要求这个函数指针指向的函数是不接受任何参数且返回值类型为 int
的函数(和我们前面定义的函数指针 p
以及函数 fun
的特性是匹配的)。
在主函数里,我们通过 newFun(p)
把函数指针 p
传递给了 newFun函数。
到了 newFun 函数里面,通过 int result = func();
这一行,就用接收到的函数指针 func
(其实这里的 func
就是我们传进去的 p
)去调用了函数 fun
,然后把调用得到的结果输出显示出来了。
🤫最后,是一个关于对数组进行增删改查操作的函数封装小练习
//数组的增删改查功能集合
#include <stdio.h>
#include <string.h>
int flag=0;
void add(int a[]);
void search(int a[]);
void change(int a[]);
void dele(int a[]);
void list(int a[]);
int main(){int a[50]={0},i;char val=0,temp=0;while(1){printf("------------------------------------------------\n");printf("0.退出\n1.增加数据\n"); printf("2.查找数据\n3.更改数据\n"); printf("4.删除数据\n5.查看当前数据\n"); printf("------------------------------------------------\n");scanf("%c",&val);printf("\n");while(getchar()!='\n');//清空缓冲区 switch(val){case '0':return 0;break;case '1':add(a);break;case '2':search(a);break;case '3':change( a);break;case '4':dele(a);break;case '5':list(a);break;default:printf("there is not this\n");break;}}return 0;
}
void list(int a[50]){int i;printf("现在我们有:");for(i=0;i<50;i++){if(a[i]!=0){printf("%d、",a[i]);}}printf("\n");
}
void add(int a[50]){int n=0,i;char y=0;for(i=0;i<50 && a[i]!=0;i++){n++;}printf("请输入想添加的数据\n");for(i=n;i<50;i++){scanf("%d",&a[i]);while(getchar()!='\n');//清空缓冲区 printf("添加成功\n");printf("是否输入完毕?y or n \n");scanf("%c",&y);while(getchar()!='\n');//清空缓冲区 if(y=='y'){break;} else{printf("请输入想添加的数据\n"); }} printf("现在我们有:");for (i = 0; i < 50; i++) {if (a[i]!= 0) {printf("%d、", a[i]);}}printf("\n");
}void search(int a[50]){int sear=0,i,found=0; printf("请输入想查询的数据\n");scanf("%d",&sear);while(getchar()!='\n');//清空缓冲区 for(i=0;i<50;i++){if(a[i]==sear){printf("是第%d个\n",i+1);found++;}}if(found==0){printf("这儿没有这数\n");}
}
void change(int a[50]){int chan=0,chang=0,i;printf("现在我们有:");for(i=0;(a[i]!=0)&&(a[i+1]!=0);i++){printf("%d、",a[i]);}printf("\n");printf("请输入想修改的数据\n");scanf("%d",&chan);while(getchar()!='\n');//清空缓冲区 for(i=0;i<50;i++){if(a[i]==chan){printf("要改成什么:");scanf("%d",&chang);while(getchar()!='\n');a[i]=chang; }}printf("修改完成!\n");}void dele(int a[50]){int delet=0,i,j;printf("现在我们有:");for(i=0;i<50;i++){if(a[i]!=0){printf("%d、",a[i]);}}printf("\n");printf("请输入想删除的数据\n");scanf("%d",&delet);while(getchar()!='\n');//清空缓冲区 for(i=0;i<50;i++){if(a[i]==delet){flag++;for (j = i; j < 49; j++) {a[j] = a[j + 1];}a[49] = 0;i--; // 因为数组元素向前移动了,所以要重新检查当前位置}}if(flag==0){printf("这儿没有这个数\n");}else {printf("删除成功\n"); }}
以及2.0版本
//新增:插入功能和排序功能
#include <stdio.h>
int s[50]={0};//定义数据数组
int n=0;
int VAL[50]={0};//定义下标数组 char menu(void);//菜单函数声明
void ADD(void);//添加函数声明
void PRINT(void);//输出函数声明
int FIND(void);//查询函数声明
void CHANGE(void);//修改函数声明
void DELETE(void);//删除函数声明
void INSERT(void);//插入函数声明
void SEQUENCE(void);//排序函数声明
int main()
{char ret=0;//定义获取返回值结果变量 while(1){ret = menu();//选项为菜单函数返回值 switch(ret){case '0':return 0;break;case '1':ADD();break;case '2':PRINT();break;case '3':FIND();break;case '4':CHANGE();break;case '5':DELETE();break;case '6':INSERT();break;case '7':SEQUENCE();break;default :printf("error!\n");}}return 0;
}char menu(void)
{char val=0;//定义选择项 printf("0.退出 1.新增 2.打印 3.查询 4.修改 5.删除 6.插入 7.排序\n");scanf("%c",&val);while(getchar()!='\n');return val;
}void ADD(void)
{if(n>=50)//判断数据数组是否存满 {printf("存储已满!\n");return ;}printf("新增数据:");scanf("%d",&s[n]);//输入新数据 while(getchar()!='\n');n++;//数据个数自增
}void PRINT(void)
{for(int i=0;i<n;i++){//遍历输出数据 printf("%d ",s[i]);}printf("\n");
}int FIND(void)
{int tmp=0; int VALN=0;//定义下标数组个数位 printf("查询的数据:");scanf("%d",&tmp);//输入查询数据 while(getchar()!='\n');for(int i=0;i<n;i++){if(tmp==s[i])//遍历判断是否与查询数据相同 {printf("下标:%d\n",i); //输出相等的数据的下标 VAL[VALN]=100+i;//将其下标计入下标数组VAL的VALN位 VALN++;//个数位自增 }}if(VALN==0)//如果个数位未变,则数据不存在 {printf("数据不存在!\n");}return VALN;//返回相同数据的个数
}void CHANGE(void)
{int ret = FIND();//获取相同数据的个数 if(ret == 0){return ;}若无相同个数,直接返回 for(int i=0;i<ret;i++){//遍历下标数组,输出数据数组中对应的值 printf("新值:");scanf("%d",&s[VAL[i]-100]);while(getchar()!='\n');} printf("修改完成!\n");
}void DELETE(void)
{int ret = FIND();//获取相同数据的个数 if(ret == 0){//若无相同个数,直接返回 return ;}for(int i=ret-1;i>=0;i--){//依次向前遍历下标数组的每个下标值 for(int j=VAL[i]-100;j<n-1;j++){//j获取到下标值后,将对应下标值后数据前移,覆盖应删除数据。 s[j]=s[j+1];}n--;//每经过依次删除循环,数据个数自减1 }printf("删除完成!\n");
}
void INSERT(void){printf("想插入到哪个数据之前\n");int ret = FIND();//获取相同数据的个数 if(ret == 0){//若无相同个数,直接返回 return ;}for(int i=0;i<ret;i++){for(int j=n-1;j>=(VAL[i]-100);j--){s[j+1]=s[j];}printf("请输入插入值:"); scanf("%d",&s[VAL[i]-100]);while(getchar()!='\n');n++;}printf("插入成功!\n");
}
void SEQUENCE(void){int tmp=0;char op;printf("请选择如何排序?A.从小到大 B.从大到小\n");scanf("%c",&op);while(getchar()!='\n');if(op=='A'){printf("将数据从小到大排序:");for(int i=1;i<n;i++){for(int j=0;j<n-i;j++){if(s[j]>s[j+1]){tmp=s[j];s[j]=s[j+1];s[j+1]=tmp;}} }return PRINT(); }else{printf("将数据从大到小排序:");for(int i=1;i<n;i++){for(int j=0;j<n-i;j++){if(s[j]<s[j+1]){tmp=s[j];s[j]=s[j+1];s[j+1]=tmp;}} }return PRINT(); }
}