C++封装随笔
1接口的封装和设计思想入门
接口的封装和设计思想入门 |
第一套api函数 |
#ifndef _CLT_SOCKET_H__ #define _CLT_SOCKET_H__ //客户端初始化环境 int cltSocket_init(void **handle); //5day //客户端发报文 int cltSocket_senddata(void *handle, unsigned char *buf, int buflen); //客户端收报文 int cltSocket_resvdata(void *hanle , unsigned char *buf, int *buflen); //4 客户端销毁环境 int cltSocket_destory(void *handle); #endif |
第二套api函数 |
//第二套api函数 #ifndef _CLT_SOCKET_H__ #define _CLT_SOCKET_H__ //客户端初始化环境 int cltSocket_init2(void **handle); //5day //客户端发报文 int cltSocket_senddata2(void *handle, unsigned char *buf, int buflen); //客户端收报文 int cltSocket_resvdata2(void *hanle , unsigned char **buf, int *buflen); //为什么这个地方换成了一个二级指针,而且又增加了一个接口 4day int cltSocket_resvdata_Free2(unsigned char *buf); //4 客户端销毁环境 //为什么这个地方又加了一个* 4day int cltSocket_destory2(void **handle); #endif |
我们找到了一套标准,我们可以高效的学习,更重要的是,我们能务实的,集中话题学习这套api函数 |
Socket动态库业务模型思路分析 |
3学习标准热身
排序 |
选择法排序思想总结 |
核心排序代码 |
printfArray3(a); for(i=0; i<10; i++) { for (j=i+1;j<10; j++) { if (a[i] < a[j]) { tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } printf("\n排?序¨°之?后¨®:"); |
结论 //1数组做函数参数,会退化为指针 //2在形参里面出现的char buf[30] int a[10] c/c++编译器会把它当做指针,也不会主动的多分配内存,c、c++编译器会自动优化 // int i = 0; int num1 = sizeof(a); int num2 = sizeof(*a); int num = sizeof(a)/sizeof(*a); int num1 = sizeof(a); //数据类型不一样 //3 sizeof(a)大小不一样的实质是a的数据类型不一样 |
4数据类型本质剖析
数据类型问题抛出 |
压死初学者的三座大山 1、数组类型 2、数组指针 3、数组类型和数组指针的关系 |
void main() { int a[10] = {1, 3, 44, 2, 3, 44, 5, 5,6, 67}; printf(“a:%d &a:%d \n”, a, &a); //a &a大小一样 printf(“a+1:%d &a+1:%d \n”, a+1, &a +1 ); //+1 大小不一样 //a &a数据类型不一样 步长不一样 //压死出血 system(“pause”); } |
数据类型分为两种,简单、一个复杂,思考复杂数据类型的时候,不能用简单数据类型思考之。。。。。抛砖 |
//写一个函数 把内存地址给传出被调用函数,方法有2种 |
结论: 数据类型本质:固定大小内存的别名 数据类型取别名 typdedef 抛出问题: 如何表达:int array[10] int add(int a, int d);//15 |
5变量的本质
修改变量的方法 两种+引用 |
变量的本质:连续内存块的别名,变量是一个标号。再抛砖 程序的内存四区图,画变量示意图时,主要把变量放在外面,内存空间留出来 |
内存空间可以再取给别名吗? |
6内存四区概念
基本概念 |
函数1调用函数2,函数1称为主调函数 函数2称为被调用函数 |
规则1:Main(主调函数)分配的内存(在堆区,栈区、全局区)都可以在被调用函数里使用吧。 |
规则2:在被调用函数里面分配的内存 1、如果在被调用函数里面的临时区(栈)分配内存,主调用函数是不能使用的。 |
char * getstring3() { char buf[30]; strcpy(buf, "abcde"); return buf; } |
铁律1
铁律1:指针是一种数据类型 1) 指针也是一种变量,占有内存空间,用来保存内存地址 测试指针变量占有内存空间大小 2)*p操作内存 在指针声明时,*号表示所声明的变量为指针 在指针使用时,*号表示 操作 指针所指向的内存空间中的值 *p相当于通过地址(p变量的值)找到一块内存;然后操作内存 *p放在等号的左边赋值(给内存赋值) *p放在等号的右边取值(从内存获取值) 3)指针变量和它指向的内存块是两个不同的概念 //含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++ //含义2 给*p赋值*p='a'; 不会改变指针变量的值,只会改变所指的内存块的值 //含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结! //含义4 =左边char *p //含义5 保证所指的内存块能修改 4)指针是一种数据类型,是指它指向的内存空间的数据类型 含义1:指针步长(p++),根据所致内存空间的数据类型来确定 p++=è(unsigned char )p+sizeof(a); 结论:指针的步长,根据所指内存空间类型来定。 |
不断地修改指针变量的值含义场景建立
//不断地修改指针变量的值含义 //需要建立场景,解决指针乱指问题 void main() { int i = 10; char buf[20]; char *p = NULL; strcpy(buf, "a234567899987654"); p = &buf[0]; p = &buf[1]; p = &buf[2]; p = &buf[3]; p = &buf[4]; for (i=0; i<10; i++) { p = &buf[i]; } } |
2经验话语
#ifndef _CLT_SOCKET2_H__ #define _CLT_SOCKET2_H__ #endif // 避免在.c里面 重复包含多次头文件 #include "cltsocket.h" #include "cltsocket.h" #include "cltsocket.h" |
Shift+del建组合删除一行 |
Ctlr+u 让单词从小写变大写 Shift+ctrl+u 从大小变小写 |
//避免多次重复包含 整个思路分析 |
C语言中的灰色地带这种问题,往后放 |
|
有关字面量
有关字面量的理解 |
{ //10 字面量 放在不能取地址 没有放在堆栈、全局区,可以按照放在代码区之类的区域内理解它。 int *a = &10; } |
怎么样理解(多级)指针做函数参数,
//对参数的指针类型应该怎么理解 |
//理解角度需要从两个角度出发 //第一个角度:站在c/c++编译器的角度 对形参,如果是指针类型,c编译器只会把它当作一个指针变量来看。(配四个自己的内存)。 ////char *p7 形参 是变量 //第二个角度:我们只有在使用指针所指向的内存空间的时候,我们才去关心内存是一维的,还是二维的。 |
/* void senddata01(char *p1); void senddata01(char* p1); void senddata02(char ** p1); void senddata02(char * *p1); void senddata02(char **p1); void senddata03(char ***p1); void senddata04(char *p[]); void senddata04(char * p[]); void senddata04(char *p []); void senddata05(char (*p)[10]); void senddata05(char (*p) [10]); void senddata05(char *****p4); */ |
内存块数据打包
//(unsigned char *buf +len)内存块的数据打包
有关[] *
//buf[i]-->buf[0+i];--->*(p+i) ---> p[i] //站在c++编译器的角度, *p 相当于我们程序员手工(显示)利用间接赋值,去操作内存 //[]怎么理解,只不过是c++编译器帮我们程序员做了一个*p的操作 |
char buf[100] = "abcdefg"; char *p = NULL; for (i=0; i<strlen(buf); i++) { printf(" %c", p[i]); } printf("\n"); for (i=0; i<strlen(buf); i++) { printf(" %c", *(p+i)); } |
间接赋值成立的是三个条件
间接赋值成立的是三个条件 |
/* 间接赋值成立的三个条件 条件1:定义了一个变量(实参)定义了一个变量(形参) 条件2:建立关联,//实参取地址传给形参 条件3://*p形参,去间接的修改实参的值 main --->func */ |
//间接赋值成立的三个条件,应用起来。。。。 |
//123 写在一个函数里面,那么成了第一个应用场景 //12 3 //间接赋值是指针存在的最大意义 //1 23 //抛砖,,,,到时候,要认识啊。 |
//间接赋值的应用场景有2个 |
//场景1:在函数指针 *p1++ = *p2++ //场景2:指针做函数参数,通过*p形参求间接的修改实参的值,这才是指针存在的最大意义、。 //这才是C语言特有的现象,才是指针的精华 |
//*p间接赋值是指针存在的最大意义(现实意义) |
接口的封装和设计 //函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p, //来改变实参,把运算结果传出来。 //指针作为函数参数的精髓。 |
推论 |
//指针做函数参数 //函数调用过程中, //用1级指针(通常是形参,)去修改0级指针(通常是实参)的值 //用2级指针(通常是形参,)去修改1级指针(通常是实参)的值 //用3级指针(通常是形参,)去修改2级指针(通常是实参)的值 //用8级指针(通常是形参,)去修改7级指针(通常是实参)的值 //用n级指针(通常是形参,)去修改n-1级指针(通常是实参)的值 |
/* 整个C/C++领域值得我们做技术推演的领域 0--1 1->2 2->3 c++多态(函数指针做函数参数) Aop切面编程(2-3) */ |
03字符串专题讲座
内存模型
//1在c中没有字符串这种类型,是通过字符串数组(char buf[100])去模拟 //2 字符串和字符串数组的区别 是不是 带有\0 |
//print函数是c库函数,它就是按照C风格字符串进行输出数据 //通过字符串常量初始化字符串数组 //通过这种方法它会自动给你\0 char buf4[] = "abcdefg"; printf("%s\n", buf4); |
// //strlen() 是一个函数 求字符串的长度(不是求字符数组的长度),它的长度不包括\0 //sizeof() 是一个操作符,求数据类型(实体)的大小 |
int main13() { char buf[20]="aaaa"; int a = 10; //字面量 char buf2[] = "bbbb"; //char ***********************************************p1 = "111111"; char *p1 = "111111"; char *p2 = malloc(100); strcpy(p2, "3333"); //&a; //&a表达式 表达式的运算结果放在寄存器里 } |
//buf[i]-->buf[0+i];--->*(p+i) ---> p[i] //站在c++编译器的角度, *p 相当于我们程序员手工(显示)利用间接赋值,去操作内存 //[]怎么理解,只不过是c++编译器帮我们程序员做了一个*p的操作 |
//因为后缀++的优先级,高于,*p; void copy_str4(char *from , char *to) { while((*to ++ = *from++) != '\0') { ; } } |
重要概念概念
在C语言中使用字符数组来模拟字符串 C语言中的字符串是以’\0’结束的字符数组 C语言中的字符串可以分配于栈空间,堆空间或者只读存储区 |
03 字符串操作 数组法,下标法 字符数组名,是个指针,是个常量指针; 字符数组名,代表字符数组首元素的地址,不代表整个数组的。 如果代表这个数组,那需要数组数据类型的知识! |
字符串做函数参数
void copy_str01(char *from, char *to) { for (; *from!='\0'; from++, to++) { *to = *from; } *to = '\0'; } void copy_str02(char *from, char *to) { while(*from!='\0') { *to++ = *from++; } *to = '\0'; } void copy_str03(char *from, char *to) { while( (*to=*from) !='\0') { to++; from++; } } void copy_str04(char *from, char *to) { while( (*to++=*from++) !='\0') { ; } } int copy_str05_good(const char *from, char *to) { if (from==NULL || to==NULL) { printf("func copy_str05_good() err. (from==NULL || to==NULL)\n"); return -1; } while( (*to++=*from++) !='\0') { ; } return 0; } |
字符串操作典型错误
建立一个思想:是主调函数分配内存,还是被调用函数分配内存; |
越界 语法级别的越界 |
char buf[3] = "abc"; |
越界
越界 语法级别的越界 |
char buf[3] = "abc"; |
不断修改内存指针变量
越界 |
void copy_str_err(char *from, char *to) { char *fromtmp = from; for (; *from!='\0'; from++, to++) { *to = *from; } *to = '\0'; printf("to:%s", to); printf("from:%s", from); } |
4、你向外面传递什么
1、临时str3内存空间 |
// char *str_cnct(x,y) /*简化算法*/ // char *x,*y; char *str_cnct(char *x, char* y) /*简化算法*/ { char str3[80]; char *z=str3; /*指针z指向数组str3*/ while(*z++=*x++); z--; /*去掉串尾结束标志*/ while(*z++=*y++); z=str3; /*将str3地址赋给指针变量z*/ return(z); } 2、经验要学习 while(*z++=*x++); z--; /*去掉串尾结束标志*/ |
char *str_cnct(char *x, char* y) /*简化算法*/ { char * str3= (char *)malloc(80) char *z=str3; /*指针z指向数组str3*/ while(*z++=*x++); z--; /*去掉串尾结束标志*/ while(*z++=*y++); z=str3; /*将str3地址赋给指针变量z*/ return(z); } |
char *str_cnct(char *x, char* y) /*简化算法*/ { If (x == NULL) { Return NULL; } char * str3= (char *)malloc(80) char *z=str3; /*指针z指向数组str3*/ while(*z++=*x++); z--; /*去掉串尾结束标志*/ while(*z++=*y++); z=str3; /*将str3地址赋给指针变量z*/ note: return(z); } Main () { Char *p = str_cnct(“abcd”, “ddeee”); If (p != NULL) {Free(p) ;p = NULL}//yezhizhen } |
int getKeyByValude(char *keyvaluebuf, char *keybuf, char *valuebuf, int * valuebuflen) { int result = 0; char *getbuf = new char[100]; memset(getbuf, 0, sizeof(getbuf)); char *trimbuf = new char[100]; memset(trimbuf, 0, sizeof(trimbuf)); int destlen = strlen(keyvaluebuf); if (keybuf == NULL || keyvaluebuf == NULL || valuebuf == NULL/* || valuebuflen == NULL*/) { result = -1; return result; } if (strstr(keyvaluebuf, keybuf) == NULL) { result = -1; return result; } else { for (int i = 0; i < destlen; i++) { if (*keyvaluebuf == '=') { *keyvaluebuf++; break; } keyvaluebuf++; } while(*keyvaluebuf != '\0') { *valuebuf = *keyvaluebuf; valuebuf++; keyvaluebuf++; } *valuebuf = '\0'; } int len = strlen(valuebuf); return result; } |
字符串项目开发模型
strstr+while语句进行符合条件字符串查找
demo04_两头堵
demo05_字符串反转
const专题讲座
1、 const基础知识(用法、含义、好处、扩展)
int main() { const int a; // int const b; const int *c; int * const d; const int const *e ; return 0; } Int func1(const ) 初级理解:const是定义常量==》const意味着只读 |
含义: //第一个第二个意思一样 代表一个常整形数 //第三个 c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改) //第四个 d 常指针(指针变量不能被修改,但是它所指向内存空间可以被修改) //第五个 e一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改) |
Const好处 //合理的利用const, //1指针做函数参数,可以有效的提高代码可读性,减少bug; //2清楚的分清参数的输入和输出特性 |
结论: //指针变量和它所指向的内存空间变量,是两个不同的概念。。。。。。 //看const 是放在*的左边还是右边 看const是修饰指针变量,还是修饰所指向的内存空变量 |
04二级指针输入模型
二级指针内存模型图
数组名
1数组名
//二维数组也是线性排列的 |
void printArray(int *a, int size) { int i = 0; printf("printArray: %d\n", sizeof(a)); for(i=0; i<size; i++) { printf("%d\n", a[i]); } } int main() { int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; char cc[10][30]; int* p = &a[0][0]; printf("sizeof(&a):%d \n", sizeof(&a)); printf("sizeof(a):%d \n", sizeof(a)); printf("sizeof(*a):%d \n", sizeof(*a)); printf("sizeof(&cc):%d \n", sizeof(&cc)); printf("sizeof(cc):%d \n", sizeof(cc)); printf("sizeof(*cc):%d \n", sizeof(*cc)); //printArray(p, 6); getchar(); return 0; } |
2、本质分析 //int a[5] 一维数组名代表数组首元素的地址 //int a[5] ===> a的类型为int* //二维数组名同样代表数组首元素的地址 //int b[2][5]===>b的类型为int(*)[5] //测试如何测试:指针也是一种数据类型,它的数据类型是指它所执行的内存空间的数据类型 //如何测试b的步长? //推导。。。。。。。 |
//结论:二维数组名 char cc[10][30] 是一个数组指针,char (*)[30] |
2多维数组做函数参数退化
1、 C语言中只会以机械式的值拷贝的方式传递参数(实参把值传给形参) |
int fun(char a[20], size_t b) |
原因1:高效 |
原因2: |
2、二维数组参数同样存在退化的问题 |
二维数组可以看做是一维数组 二维数组中的每个元素是一维数组 二维数组参数中第一维的参数可以省略 void f(int a[5]) ====》void f(int a[]); ===》 void f(int* a); void g(int a[3][3])====》 void g(int a[][3]); ====》 void g(int (*a)[3]); |
3、等价关系 |
数组参数 等效的指针参数 一维数组 char a[30] 指针 char* 指针数组 char *a[30] 指针的指针 char **a 二维数组 char a[10][30] 数组的指针 char(*a)[30] |
char * a[30] char(*a)[30] char(*a)(30) 怎么区分:指针数组、数组指针 |
3数组指
C++封装随笔的更多相关文章
- 原生Ajax封装随笔
XMLHttpRequest 对象用于和服务器交换数据.我们使用 XMLHttpRequest 对象的 open() 和 send() 方法: open(method,url,async) metho ...
- 学习java随笔第八篇:封装、继承、多态
java和c#一样都是面向对象的语言. 面向对象的语言有三大特征:封装.继承.多态 封装 封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别. class Perso ...
- Java 基础入门随笔(7) JavaSE版——面向对象定义、特征:封装、构造函数
面向对象 面向过程:对于面向过程思想,强调的是过程(动作). 面向对象:对于面向对象思想,强调的是对象(实体). 特点: 1,面向对象就是一种常见的思想.符合人们的思考习惯.2,面向对象的出现,将复杂 ...
- 《高性能javascript》 领悟随笔之-------DOM编程篇(二)
<高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...
- .NET 同步与异步之封装成Task(五)
本随笔续接:.NET 实现并行的几种方式(四) 前篇随笔已经介绍了几种可以实现并发的方式,其中异步方法.是最简便的方式.而 异步方式是基于 Task 和 async修饰符和await运算符实现的. 换 ...
- C#开发微信门户及应用(36)--微信卡劵管理的封装操作
前面几篇介绍了微信支付方面的内容,本篇继续微信接口的一些其他方面的内容:卡劵管理.卡劵管理是微信接口里面非常复杂的一个部分,里面的接口非常多,我花了不少时间对它进行了封装处理,重构优化等等工作,卡劵在 ...
- C#开发微信门户及应用(35)--微信支付之企业付款封装操作
在前面几篇随笔,都是介绍微信支付及红包相关的内容,其实支付部分的内容还有很多,例如企业付款.公众号支付或刷卡支付.摇一摇红包.代金券等方面的内容,这些都是微信接口支持的内容,本篇继续微信支付这一主题, ...
- C#开发微信门户及应用(33)--微信现金红包的封装及使用
我在上篇随笔<C#开发微信门户及应用(32)--微信支付接入和API封装使用>介绍为微信支付的API封装及使用,其中介绍了如何配置好支付环境,并对扫码支付的两种方式如何在C#开发中使用进行 ...
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...
随机推荐
- 关于TP3.2框架读取Sql server中文字段数据以及处理乱码的一些小心得
最近要做一个项目,需要使用TP3.2框架,之前什么也不会,就硬着头皮上了,结果真的闹了挺多emmmmmm挺低级的错误,就像SQL Server中文字段的读取,一开始我是照着读取英文字段的格式来写的,在 ...
- PAT (Basic Level) Practice 1006 换个格式输出整数
个人练习 让我们用字母B来表示“百”.字母S表示“十”,用“12...n”来表示个位数字n(<10),换个格式来输出任一个不超过3位的正整数.例如234应该被输出为BBSSS1234,因为 ...
- Codeforces Round #458C DP
C. Travelling Salesman and Special Numbers time limit per test 1 second memory limit per test 256 me ...
- Android面试收集录11 Window+Activity+DecorView+ViewRoot之间的关系
一.职能简介 Activity Activity并不负责视图控制,它只是控制生命周期和处理事件.真正控制视图的是Window.一个Activity包含了一个Window,Window才是真正代表一个窗 ...
- 8,Linux系统基础优化及常用命令
Linux基础系统优化 引言没有,只有一张图. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. ifconfig 查询.设置网卡和 ...
- PJSIP-PJMEDIA【使用pjmedia 播放wav格式的音乐】
应宝哥建议以及更好的交流学习,这篇开始使用中文,英语就先放一放吧! 要使用PJSIP中的PJMEDIA首先我们需要搭建好它所需要的环境. [环境搭建与调试] 1 在 工具 加入pjmedia所需要的包 ...
- shell脚本递归删除空文件夹
有时我们需要递归删除空文件夹,网上找了一下,没有发现比较好的脚本,于是自己动手写了一个 脚本 #!/bin/bash # author: 十年后的卢哥哥(http://www.cnblogs.com/ ...
- Linux/Unix中系统级IO
Linux/unix I/O:将设备映射为文件的方式,允许Unix内核引出一个简单.低级的应用接口. Linux/unix IO的系统调用函数很简单,它只有5个函数:open(打开).close(关闭 ...
- 开源api文档
蒲公英——API文档 https://www.pgyer.com/doc/api
- 使用cloudbase-init初始化windows虚拟机
CloudBase-init简介 cloudbase-init 是 Windows 和其他系统的云初始化程序,可以设置主机名.创建用户.设置静态ip.设置密码等.对应的linux初始化程序是cloud ...