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. 关于TP3.2框架读取Sql server中文字段数据以及处理乱码的一些小心得

    最近要做一个项目,需要使用TP3.2框架,之前什么也不会,就硬着头皮上了,结果真的闹了挺多emmmmmm挺低级的错误,就像SQL Server中文字段的读取,一开始我是照着读取英文字段的格式来写的,在 ...

  2. PAT (Basic Level) Practice 1006 换个格式输出整数

    个人练习 让我们用字母B来表示“百”.字母S表示“十”,用“12...n”来表示个位数字n(&lt10),换个格式来输出任一个不超过3位的正整数.例如234应该被输出为BBSSS1234,因为 ...

  3. Codeforces Round #458C DP

    C. Travelling Salesman and Special Numbers time limit per test 1 second memory limit per test 256 me ...

  4. Android面试收集录11 Window+Activity+DecorView+ViewRoot之间的关系

    一.职能简介 Activity Activity并不负责视图控制,它只是控制生命周期和处理事件.真正控制视图的是Window.一个Activity包含了一个Window,Window才是真正代表一个窗 ...

  5. 8,Linux系统基础优化及常用命令

    Linux基础系统优化 引言没有,只有一张图. Linux的网络功能相当强悍,一时之间我们无法了解所有的网络命令,在配置服务器基础环境时,先了解下网络参数设定命令. ifconfig 查询.设置网卡和 ...

  6. PJSIP-PJMEDIA【使用pjmedia 播放wav格式的音乐】

    应宝哥建议以及更好的交流学习,这篇开始使用中文,英语就先放一放吧! 要使用PJSIP中的PJMEDIA首先我们需要搭建好它所需要的环境. [环境搭建与调试] 1 在 工具 加入pjmedia所需要的包 ...

  7. shell脚本递归删除空文件夹

    有时我们需要递归删除空文件夹,网上找了一下,没有发现比较好的脚本,于是自己动手写了一个 脚本 #!/bin/bash # author: 十年后的卢哥哥(http://www.cnblogs.com/ ...

  8. Linux/Unix中系统级IO

    Linux/unix I/O:将设备映射为文件的方式,允许Unix内核引出一个简单.低级的应用接口. Linux/unix IO的系统调用函数很简单,它只有5个函数:open(打开).close(关闭 ...

  9. 开源api文档

    蒲公英——API文档 https://www.pgyer.com/doc/api

  10. 使用cloudbase-init初始化windows虚拟机

    CloudBase-init简介 cloudbase-init 是 Windows 和其他系统的云初始化程序,可以设置主机名.创建用户.设置静态ip.设置密码等.对应的linux初始化程序是cloud ...