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)
{
   printf("%d\t%d",b,sizeof(a));
}

原因1:高效

原因2:
C语言处理a[n]的时候,它没有办法知道n是几,它只知道&n[0]是多少,它的值作为参数传递进去了
虽然c语言可以做到直接int fun(char a[20]),然后函数能得到20这个数字,但是,C没有这么做。

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++封装随笔的更多相关文章

  1. 原生Ajax封装随笔

    XMLHttpRequest 对象用于和服务器交换数据.我们使用 XMLHttpRequest 对象的 open() 和 send() 方法: open(method,url,async) metho ...

  2. 学习java随笔第八篇:封装、继承、多态

    java和c#一样都是面向对象的语言. 面向对象的语言有三大特征:封装.继承.多态 封装 封装:隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别. class Perso ...

  3. Java 基础入门随笔(7) JavaSE版——面向对象定义、特征:封装、构造函数

    面向对象 面向过程:对于面向过程思想,强调的是过程(动作). 面向对象:对于面向对象思想,强调的是对象(实体). 特点: 1,面向对象就是一种常见的思想.符合人们的思考习惯.2,面向对象的出现,将复杂 ...

  4. 《高性能javascript》 领悟随笔之-------DOM编程篇(二)

    <高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...

  5. .NET 同步与异步之封装成Task(五)

    本随笔续接:.NET 实现并行的几种方式(四) 前篇随笔已经介绍了几种可以实现并发的方式,其中异步方法.是最简便的方式.而 异步方式是基于 Task 和 async修饰符和await运算符实现的. 换 ...

  6. C#开发微信门户及应用(36)--微信卡劵管理的封装操作

    前面几篇介绍了微信支付方面的内容,本篇继续微信接口的一些其他方面的内容:卡劵管理.卡劵管理是微信接口里面非常复杂的一个部分,里面的接口非常多,我花了不少时间对它进行了封装处理,重构优化等等工作,卡劵在 ...

  7. C#开发微信门户及应用(35)--微信支付之企业付款封装操作

    在前面几篇随笔,都是介绍微信支付及红包相关的内容,其实支付部分的内容还有很多,例如企业付款.公众号支付或刷卡支付.摇一摇红包.代金券等方面的内容,这些都是微信接口支持的内容,本篇继续微信支付这一主题, ...

  8. C#开发微信门户及应用(33)--微信现金红包的封装及使用

    我在上篇随笔<C#开发微信门户及应用(32)--微信支付接入和API封装使用>介绍为微信支付的API封装及使用,其中介绍了如何配置好支付环境,并对扫码支付的两种方式如何在C#开发中使用进行 ...

  9. C#开发微信门户及应用(32)--微信支付接入和API封装使用

    在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...

随机推荐

  1. 申请qq第三方登录 http://www.php20.com/forum.php?mod=viewthread&tid=29 (出处: 码农之家)

    百度  qq互联  进入网站 按图中的步骤申请第三方登录即可 先申请成为开发者 审核通过后再继续操作 提交 后列表中会出现提交的申请. 状态为审核中,审核通过会得到下图. 点查看 红线后面就是appi ...

  2. POJ:2100-Graveyard Design(尺取)

    Graveyard Design Time Limit: 10000MS Memory Limit: 64000K Total Submissions: 8504 Accepted: 2126 Cas ...

  3. python Re库的介绍

    re库的贪婪匹配和最小匹配 后面跟着?变为最小匹配

  4. Android面试收集录14 Android进程间通信方式

    一.使用 Intent Activity,Service,Receiver 都支持在 Intent 中传递 Bundle 数据,而 Bundle 实现了 Parcelable 接口,可以在不同的进程间 ...

  5. https refused 解决方法

    今天调试Android程序,所有的手机都ok,后来,我一个手机一直说,refused. 其实这就说明代码是没有问题的,你应该可以根据这个把代码的原因排除.然后剩下的,网络请求还能有什么,网路白. 果然 ...

  6. CF6C Alice, Bob and Chocolate

    CF6C Alice, Bob and Chocolate 题目链接 写了一天搜索写的有点累了,就顺手水了一道CF的模拟题 这道题就是简单的模拟整个题的过程,注意最后输出的形式就好了QWQ AC代码如 ...

  7. Oracle exp,imp,expdp,impdp数据导入导出

    一.导出模式(三种模式)及命令格式 1. 全库模式 exp 用户名/密码@网络服务名 full=y file=路径\文件名.dmp log=路径\文件名.log 2. 用户模式(一般情况下采用此模式) ...

  8. Windows环境下svn服务器的安装步骤

    做为一个程序开发人员,就算自己一个人写程序,也应该有一个SVN版本控制系统,以便对开发代码进行有效的管理. 下载SVN服务器 下载地址是:http://subversion.apache.org/pa ...

  9. JavaSE总结--异常

    throwable Error: Exception: 编译型异常: 运行时异常:

  10. Android学习记录(6)—将java中的多线程下载移植到Android中(即多线程下载在Android中的使用)③

    在这一节中,我们就来讲多线程下载以及断点续传在android中怎么使用,前两节是为本节做准备的,没有看前两节的同学,最好看完前面的两篇文章再来看这篇.其实在android端的应用和java基本上是差不 ...