C语言学习9: malloc动态内存存储,动态内存分配去空格字符增长版,动态内存分配去符号incr增长版,型参和返回值都是int型的函数的指针,main函数的地址也可以用指针指向,typedef定义函数指针,函数定义与嵌套的作用,返回函数指针类型,const作用
1,malloc动态内存存储
#include <stdio.h> #include <stdlib.h> #include <string.h> //动态存储 int main(void) { int *p=NULL; int *tmp=NULL; int n; int ret; int count=0; while(1) { retry: printf("input num:"); ret=scanf("%d",&n); while(getchar()!='\n');//清空输入输出缓存区里面的东西 if(ret==0) goto retry; if(n==-1) break; tmp=malloc(sizeof(int) * (count+1)); //多一个是因为有一个结束符 if(NULL==tmp) goto err0; memcpy(tmp,p,sizeof(int) * count); //从p所指的内存地址的起始位置开始拷贝sizeof(int)*count //个字节到tmp所指向的内存地址的起始位置中 tmp[count]=n; //tmp得到每个输入的值, free(p);//释放旧空间 p=tmp;//将p指向新的空间 count++;//输入一个数字,count加1 } int i; for(i=0;i<count;i++) { printf("%d ",p[i]); } putchar('\n'); free(p); return 0; err0: free(p); return 1;//释放空间 } //只能接收数字,空格默认结束
结果:
will@will-laptop:~/ex/8$ ./a.out input num:5 input num:6 input num:7 input num:8 input num:8 input num:2 input num:-1 5 6 7 8 8 2
2,动态内存分配版的去空格,其中内存增长的方式是一个一个的加起来
#include <stdio.h> #include <stdlib.h> #include <string.h> //对一段语句进行单词的动态存储 char *my_gets(void) { char *p=NULL,*tmp=NULL; int ch,count=0; while((ch=getchar())!='\n')//输入字符并清空输入区 { tmp=malloc(count+1); //因为是字符,所以char是1,所以输入的count长字符,用count //长的空间存放 if(NULL==tmp) goto err0; memcpy(tmp,p,count); tmp[count]=ch; //这个就是来作用的玩意temp[1],temp[2],temp[3]都是相当于一个 //个数组赋值,count的每次增加都是给分配空间加大的 free(p);//释放老空间 p=tmp;//将tmp开辟的空间起始内存地址给p,使p的空间容纳存储的 //字符 count++;//每输入一次加一次 } /* if(NULL==p)//最开始 { p=malloc(1); if(NULL==p) goto err0; }*/ p[count]='\0';//给这个加一个结束符,占用一个字节即char长度 return p; err0: free(p); //释放空间 return NULL; } char **cut_word(char *s,int *cnt) { //这个就是去掉空格和逗号 char **p=NULL; char **tmp=NULL; int word_start,word_len; int i=0,count=0; while(1) { if(s[i]!=' '&&s[i]!=',') { word_start=i; while(s[i]!=' '&&s[i]!=','&&s[i]!='\0') i++; word_len=i-word_start; printf("count=%d\n",count); printf("start:%c,end:%c\n",*(s+word_start),*(s+i-1)); tmp=malloc(sizeof(char*)*(count+1)); if(NULL==tmp) goto err0; memcpy(tmp,p,sizeof(char*)*count); free(p); p=tmp; //开辟一个空间个数组p p[count]=malloc(word_len+1); //这个就是p[1]里面拥有一个单词的的字符串 if(NULL==p[count]) goto err0; memcpy(p[count],s+word_start,word_len); p[count][word_len]='\0'; count++; } if(s[i]=='\0')//整个字符串处理完成后跳出 break; i++; } *cnt=count;//记录单词个数 return p; err0: for(i=0;i<count;i++) free(p[i]); free(p);//原则谁开辟谁回收,这个开辟了p和p[]所以两者要释放 return NULL; } void free_word(char **p,int row) { int i; for(i=0;i<row;i++) free(p[i]); free(p); }//同理释放 int main(void) { char **pwords=NULL;//为了得到像二维数组的地址,必须二级指针 char *s=NULL;//为了得到输入一连串字符的地址 int cnt; printf("input str:"); s=my_gets(); puts(s); printf("_______________________________\n"); pwords=cut_word(s,&cnt); //为了改变cnt的值,只能使指针进去,所以变成&cnt int i; for(i=0;i<cnt;i++) puts(pwords[i]);//给人的感觉就是一个指针的效果 free_word(pwords,cnt);//释放在cut_word函数中的malloc free(s);//释放在get_word函数中的malloc return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out input str:what your naem xxxx what your naem xxxx _______________________________ count=0 start:w,end:t count=1 start:y,end:r count=2 start:n,end:m count=3 start:x,end:x what your naem xxxx
3,动态内存分配版的去空格,去符号。不过这个不是来一个字符增加一个,而是只增加一次incr大小的空间。避免多次操作浪费时间。
#include <stdio.h> #include <stdlib.h> #include <string.h> char *my_gets(int max,int incr) { char *p=NULL; char *tmp=NULL; p=malloc(max+1); if(NULL==p) goto err0; int ch,count=0; while((ch=getchar())!='\n') { if(count>=max) { tmp=malloc(max+incr+1);//比较大小重新分配指定大小 if(NULL==tmp) goto err1; memcpy(tmp,p,max); free(p); p=tmp; max+=incr; } p[count]=ch; count++; } p[count]='\0'; printf("111111111111111]\n"); return p; err1: free(p); err0: return NULL; } char **cut_word(char *s,char *delim,int *cnt) { char **p=NULL; char **tmp=NULL; int word_start,word_len; int i=0,count=0; while(1) { if(!strchr(delim,s[i])) { word_start=i; while(!strchr(delim,s[i])&&s[i]!='\0') i++; word_len=i-word_start; printf("count=%d\n",count); printf("start:%c,end:%c\n",*(s+word_start),*(s+i-1)); tmp=malloc(sizeof(char *)*(count+1)); if(NULL==tmp) goto err0; memcpy(tmp,p,sizeof(char *)*count); free(p); p=tmp; p[count]=malloc(word_len+1); if(NULL==p[count]) goto err0; memcpy(p[count],s+word_start,word_len); p[count][word_len]='\0'; count++; } if(s[i]=='\0') break; i++; } *cnt=count; return p; err0: for(i=0;i<count;i++) free(p[i]); free(p); return NULL; } void free_word(char **p,int row) { int i; for(i=0;i<row;i++) free(p[i]); free(p); } int main(void) { char *s=NULL; char **pwords=NULL; int cnt; printf("input s:"); s=my_gets(5,10); puts(s); pwords=cut_word(s," ,?!:\"\'",&cnt); int i; for(i=0;i<cnt;i++) puts(pwords[i]); free_word(pwords,cnt); free(s); return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out input s:what your naem : 111111111111111] what your naem : count=0 start:w,end:t count=1 start:y,end:r count=2 start:n,end:m what your naem
4,型参和返回值都是int型的函数的指针。函数指针的用法
#include <stdio.h> int add(int l,int r) { return l+r; } int sub(int l,int r) { return l-r; } int main(void) { //pfunc是int(*)(int,int)类型 //pfunc指向int()(int,int)函数类型 int (*pfunc)(int,int)=NULL; //pfunc1是double(*)(double,double)类型 double(*pfunc1)(double,double)=NULL; int a=9,b=6; int ret; pfunc=add; ret=pfunc(a,b); printf("ret=%d\n",ret); pfunc=⊂ ret=(*pfunc)(a,b); printf("ret=%d\n",ret); printf("----------------------\n"); //强制类型转换 //程序员要自己保证,所指向的函数,其返回值和参数类型 //都相同(类型兼容,占用空间一致,形式不会变化) pfunc1=(double(*)(double,double))add; //强制转化为双精度 ret=pfunc1(a,b); printf("ret=%d\n",ret); return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out ret=15 ret=3 ---------------------- ret=9
5,main函数地址可以用指针指向
#include <stdio.h> int main(void) { void *p=main; printf("addr of main=%p\n",main); printf("addr of main=%p\n",p); return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out addr of main=0x83fd addr of main=0x83fd
7,typedef定义
#include <stdio.h> typedef int int32; #define INIT32 int //fun_t代表 int()(int,int)函数类型 typedef int (func_t)(int,int); //pfun_t代表int(*)(int,int)函数指针类型 typedef int (*pfunc_t)(int,int); int add(int l,int r) { return l+r; } int sub(int l, int r) { return l-r; } int main(void) { INIT32 a=12; int32 b=8; int ret; func_t *pf1 = add; ret= pf1(a,b); printf("ret=%d\n",ret); pfunc_t pf2 = sub; ret=pf2(a,b); printf("ret = %d\n",ret); return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out ret=20 ret = 4
8,函数定义后与嵌套的作用
#include <stdio.h> typedef int int32; #define INT32 int //fun_t代表 int()(int,int)函数类型 typedef int (fun_t)(int , int); //pfunc_t代表 int(*)(int,int)函数指针类型 typedef int (*pfunc_t)(int, int); int add(int l, int r) { return l+r; } int sub(int l, int r) { return l-r; } //int operation(pfunc_t pf,int a ,int b) //两者定义完全相同 int operation(int (*pf)(int,int),int a,int b) { return pf(a,b); } int main(void) { INT32 a=12; int32 b=8; int ret; ret=operation(add,a,b); printf("ret=%d\n",ret); printf("----------------------------\n"); ret=operation(sub,a,b); printf("ret=%d\n",ret); return 0; }
结果:
will@will-laptop:~/ex/8$ gcc 8.8.c will@will-laptop:~/ex/8$ ./a.out ret=20 ---------------------------- ret=4
9,返回函数指针类型
#include <stdio.h> typedef int (func_t)(int,int); //同样这两个也是代表不同的函数类型,不过意思都是一样 typedef int (*pfunc_t)(int,int); int add(int l,int r) { return l+r; } int sub(int l,int r) { return l-r; } //pfunc_t choice_func(int choice) //这个就是使用上面定义的两个不同的方式进行函数的使用 int (*choice_func(int choice))(int,int) { if(choice == 0) return add; else return sub; } int main(void) { int a=2,b=8; int ret; ret=choice_func(0)(a,b); printf("ret=%d\n",ret); printf("------------------------\n"); ret=choice_func(1)(a,b); printf("ret=%d\n",ret); return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out ret=10 ------------------------ ret=-6
10,singnal函数见杂项吧
11,const作用
#include <stdio.h> int main(void) { int a=8; //不能通过p修改 *p const int *p=NULL; // int const *p=NULL; p=&a; printf("a=%d,*p=%d\n",a,*p); //不能通过p修改 *p // *p=32;这个是直接赋值 a=16; printf("a=%d,*p=%d\n",a,*p); printf("---------------------------\n"); //变量p1是const,p1本身不能被修改 //意味着该指针变量只能在初始化时“赋值” int *const p1=&a; //这个被初始化赋值不能修改了 *p1=32; printf("a=%d,*p=%d\n",a,*p); //p本身是const的 //并且不能通过p2修改 *p2 const int *const p2 = &a; printf("a=%d,*p2=%d\n",a,*p2); //不能通过p3修改 *p3,也不能通过 *p3 修改 **p3 const int * const *p3; return 0; }
结果:
will@will-laptop:~/ex/8$ ./a.out a=8,*p=8 a=16,*p=16 --------------------------- a=32,*p=32 a=32,*p2=32