剑法篇

C语言-列表

◀ 返回

线性表

  • 顺序表
  • 链式表

线性表的本质

定义:
	由0个或多个数据元素的集合
	数据元素之间是有顺序的
	数据元素的个数是有限个
	数据元素的类型必须相同
	
专业的定义:
	线性表是具有相同类型的n(n>=0)个数据元素的有限序列
	(a0,a1,a2,..an)
	ai是表项,n是长度
	
性质:
	a0为线性表的第一个元素,只有一个后继
	an为线性表的最后一个元素,只有一个前驱
	除a0和an以外的其他元素ai,既有前驱也有后继.	

线性表的操作

	创建
	销毁
	插入
	删除
	获得表中某个位置的元素
	获得线性表的长度
	清空

线性表的操作对应于我们程序中的一组函数

List *List_Create(void);
void List_Destroy(List *list);
void List_Clear(List *list);
int List_Insert(List *list, ListNode *node, int pos)
ListNode * List_Delete(List *list, int pos)
ListNode * List_Get(List *list, int pos)
int List_Length(List *list)

线性表的顺序存储结构

线性表的顺序存储结构是指用一段地址连续的存储单元依次存储线性表的数据元素 看成C语言的数组,用C语言的一维数组实现顺序存储结构

	#define MAXSIZE 20 //线性表的最大容量
	typedef struct _list {
		char node[MAXSIE]; //存储空间的起始地址是node
		int length; //表示线性表的当前长度
	}List;

获得元素的操作

	char Get(List *list, int pos) {
		char ret = -1;
		
		// 1. 判断list的合法性
		// 2. 判断位置的合法性
		if ( (list!=NULL) &&(0<=pos) && (pos<list->length) )
			// 3. 获得元素	
			ret = list->node[pos];
		return ret;
	}

插入元素的操作

算法:
	1.判断线性表的合法性	
	2.判断插入位置的合法性
	3.把最后一个元素到插入位置的元素依次后移一个位置
	4.将新元素插入
	5.将长度加1
int Insert(List *list, char c, int pos) {
		int ret = (list!=NULL);
		int i = 0;
		
		ret = ret && (list->length <= MAXSIZE);
		ret = ret && (0<=pos);	

		if ( ret ) {
			if ( pos > list->length)
				pos = list->length;
			
			for (i=list->length; i>pos; i--)
				list->node[i] = list->node[i-1]; 
			
			list->node[i] = c;
			list->length++;
		}

		return ret;
	}

删除元素操作

算法:
	1.判断线性表的合法性	
	2.判断删除位置的合法性
	3.将元素取出
	4.将删除位置之后的所有元素都向前移动一个位置
	5.顺序表的长度-1
har Delete(List *list, int pos) {
			char ret = -1;
			int i = 0;
			
			if ( (list!=NULL)&&(0<=pos)&&(pos<list->length) ){
				ret = list->node[pos];
				for (i=pos+1; i<list->length; i++)
					list->node[i-1] = list->node[i];
				list->length--;
			}
		
			return ret;
		}

优点可以快速的获取表中合法位置的元素 缺点插入和删除的时候需要移动大量的元素

剑法篇

C源码加壳解析

◀ 返回

问题描述

字符串被显示为acssi码, 数值被hex加减

源码

转换思路

字符: acssi 转 string 数值: 计算出值

贴代码

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define setnull(x) memset(&(x), 0, sizeof(x))
#define CAL(x, y, z) x + y - z
#define ERR_EXIT(m) \
    do { \
        fprintf(stderr, "[%s][%d]:%s %s \n" ,__FILE__, __LINE__, m, strerror(errno));\
        exit(EXIT_FAILURE); \
        }while(0)


int main( int argc, char **argv){
    int i,j,len,varLen,ilen ;
    char buf[1024];
    char temp[2];
    char var[64],var1[64];
    char ascii[2];
    char hexBuf[1024];
    char fbuf[1024];
    char tobuf[1024];
    int begin = 0, end = 0; 
    char *data;
    char *pstr;
    char *pstr1;
    int retlen;
    char varBuf[20];
    char varRet;
    char srcfile[256],destfile[256];

    setnull(srcfile);
    setnull(destfile);
    sprintf(srcfile,"%s", argv[1]);
    sprintf(destfile,"%s", argv[2]);
    //printf("%s\n",argv[1]);
    //printf("%s\n",srcfile);
    //printf("%s\n",argv[2]);
    //printf("%s\n",destfile);
    //strcpy(hexBuf, argv[1]);
    FILE* fd = fopen(srcfile,"r");
    FILE* fdw = fopen(destfile,"w");
    if(fd){
        while(!feof(fd)){
           memset(fbuf, 0x00, sizeof(fbuf));
           data = fgets(fbuf,sizeof(fbuf)-1,fd);
           if(data){
                memset(tobuf, 0x00, sizeof(tobuf));
                len = strlen(data);
                for (i = 0, j = 0; i < len;){
                   if(!memcmp(data + i,"\\x",2)){
                       memset(ascii, 0x00, 2);
                       memcpy(temp, data + i + 2, 2);
                       //printf("temp: %s\n", temp);
                       hex2ascii(temp, ascii);
                       //printf("ascii: %s\n", ascii);
                       memcpy(tobuf + j, ascii, 1);
                       i += 4;
                       j++;
                       //printf("find \\x string offset %d\n", i); 

                   }else if(!memcmp(data + i,"(0x",3)){
                        memset(var, 0x00, sizeof(var));
                        memset(var1, 0x00, sizeof(var1));
                        memset(varBuf, 0x00, sizeof(varBuf));

                        memcpy(var, data + i, sizeof(var));  
                        //printf("var: %s \n", var);

                        pstr = strchr(var, '(');
                        if ( pstr != NULL)
                        {
                            if( pstr1 = strstr(var, ")")){
                                //printf("find ),\n");
                                varLen = pstr1 - pstr ;
                                //printf("%d\n", varLen);
                                memcpy(var1, var+1,varLen -1);
                                varRet = cal(var1);
                                sprintf(varBuf,"%d",varRet);
                                //printf("%s,%d\n",varBuf,varRet);
                                ilen = strlen(varBuf);
                                memcpy(tobuf + j, varBuf , ilen);
                                j += ilen ;
                                i += varLen + 1;
                            }
                           //else if( pstr1 = strstr(var, ");")){
                           //     printf("find );\n");
                           //     int varLen = pstr1 - pstr ;
                           //     printf("%d\n", varLen);
                           //     memcpy(var1, var+1,varLen -1);
                           //     varRet = cal(var1);
                           //     sprintf(varBuf,"%d;",varRet);
                           //     printf("%s,%d\n",varBuf,varRet);
                           //     int ilen = strlen(varBuf);
                           //     memcpy(tobuf + j, varBuf , ilen + 1);
                           //     j += ilen + 1;
                           //     i += varLen + 1 + 1;
                           // }
                           //else if( pstr1 = strstr(var, ")")){
                           //     printf("find )\n");
                           //     int varLen = pstr1 - pstr ;
                           //     printf("%d\n", varLen);
                           //     memcpy(var1, var+1,varLen -1);
                           //     varRet = cal(var1);
                           //     sprintf(varBuf,"%d",varRet);
                           //     printf("%s,%d\n",varBuf,varRet);
                           //     int ilen = strlen(varBuf);
                           //     memcpy(tobuf + j, varBuf , ilen );
                           //     j += ilen;
                           //     i += varLen + 1;
                           //// }
                        }
                   }else{

                       tobuf[j] = data[i];
                       i++;
                       j++;
                   }

                }
                //printf("%s", data);
                fprintf(fdw,"%s",tobuf);
            }
        }
    }else{
        ERR_EXIT("open file failure");
    }
    fclose(fd);
    //for( i = 0; i < strlen(argv[1]); i++){ 
    //    printf("%c\n", argv[i]);
    //}
    //int ret =  hex2ascii(hexBuf,buf);
    //for( i = 0; i < strlen(buf); i++){ 
    //    printf("%c", buf[i]);
    //}
    //printf("\n");
}

int hex2ascii(char *hex, char *ascii)
{
    int len = strlen(hex), tlen, cnt , i;

    for( i = 0, cnt = 0 ,tlen =0; i < len; i++){
        char c = toupper(hex[i]);

        if(( c >= '0' && c <='9') || ( c >= 'A' && c <= 'F'))
        {
            int  t = ( c >='A') ? c - 'A' + 10 : c - '0';

            if(cnt)
                ascii[tlen++] += t, cnt =0;
            else 
                ascii[tlen] = t << 4, cnt = 1;
                
        }
    }
    return tlen;
}
int cal(char *exprs){

    int x,y,z;
    //printf("%s\n", exprs);
    sscanf(exprs,"%x + %d - %x",&x,&y,&z);
    return CAL(x,y,z); 
}

编译

gcc -o hex2ascii hex2ascii.c

剑法篇

以模式为纲,化复杂为简

◀ 返回

单一职责原则(SRP:Single Responsibility Principle)

一个类只负责完成一个职责或者功能,不要存在多于一种导致类变更的原因。单一职责原则通过避免设计大而全的类,避免将不相关的功能耦合在一起,来提高类的内聚性。同时,类职责单一,类依赖的和被依赖的其他类也会变少,减少了代码的耦合性,以此来实现代码的高内聚、松耦合。但是,如果拆分得过细,实际上会适得其反,反倒会降低内聚性,也会影响代码的可维护性。

假设你在构建一个应用程序,其中有个模块是根据条件搜索顾客并以Excel形式导出。随着业务的发展,搜索条件会不断增加,导出数据的分类也会不断增加。如果此时将搜索与数据导出功能放在同一个类中,势必会变的笨重起来,即使是微小的改动,也可能影响其他功能。所以根据单一职责原则,一个类只有一个职责,故创建两个单独的类,分别处理搜索以及导出数据。

开放-关闭原则(OCP:Open Closed Principle)

添加一个新的功能,应该是通过在已有代码基础上扩展代码(新增模块、类、方法、属性等),而非修改已有代码(修改模块、类、方法、属性等)的方式来完成。

开闭原则并不是说完全杜绝修改,而是以最小的修改代码的代价来完成新功能的开发。

很多设计原则、设计思想、设计模式,都是以提高代码的扩展性为最终目的的。特别是 23 种经典设计模式,大部分都是为了解决代码的扩展性问题而总结出来的,都是以开闭原则为指导原则的。最常用来提高代码扩展性的方法有:多态、依赖注入、基于接口而非实现编程,以及大部分的设计模式(比如,装饰、策略、模板、职责链、状态)。

假设你现在正在开发一个 Web 应用程序,包括一个在线纳税计算器。用户可以访问Web 页面,指定他们的收入和费用的细节,并使用一些数学公式来计算应纳税额。考虑到这一点,你创建了如下类:

public class TaxCalculator
{
    public decimal Calculate(decimal income, decimal deduction, string country)
    {
        decimal taxAmount = 0;
        decimal taxableIncome = income - deduction;
        switch (country)
        {
            case "India":
                //Todo calculation
                break;
            case "USA":
                //Todo calculation 
                break;
            case "UK":
                //Todocalculation
                break;
        }
        return taxAmount;
    }
}

这个方法非常简单,通过指定收入和支出,可以动态切换不同的国家计算不同的纳税额。但这里隐含了一个问题,它只考虑了3个国家。当这个 Web 应用变得越来越流行时,越来越多的国家将被加进来,你不得不去修改 Calculate 方法。这违反了开放封闭原则,有可能你的修改会导致系统其他模块的崩溃。

让我们对这个功能进行重构,以符合对扩展是开放,对修改是封闭的。

根据类图,可以看到通过继承实现横向的扩展,并且不会引发对其他不相关类的修改。这时 TaxCalculator 类中的 Calculate 方法会异常简单:

典籍篇

聚社区之智,传技术之火

◀ 返回

五种基本句式

  1. 主语:我们所有造的句子都有主体

  2. 谓语:主体执行的动作

  3. 系动词:联系动作的动词,连接前边的主语和后边的表语

  4. 表语:描述主语性质、特点、位置的词

  5. 宾语:主语执行动作的对象

  6. 间宾:人叫间宾 7.直宾:物叫直宾

  7. 补:宾语不能完全说明谓语执行的对象的执行结果时需要补充说明

  8. 主+谓 S+V

    the universe remains 宇宙长存

  9. 主+系+表 S+V+P

    the food is delicious 这食物好吃

  10. 主+谓+宾 S+V+O

    he took his bag and left 他拿着他的包离开了

  11. 主+谓+间宾+直宾 S+V+o+O

    her father bought her a dictionary 他的爸爸给他买了一本词典

  12. 主+谓+宾+宾补 S+V+O+C

    We made him our monitor 我们选他当班长

Be动词的形式

be is am are was were being been

  • the man is back
  • They are back
  • He was back
  • They were back
  • They have been back

后面接名次、形容词、地点副词或短语作补足语

法宝篇

工欲善其事,必先利其器

◀ 返回

创建脚本

创建

创建socket script

录制

  • 截取报文 报文

  • 替换空格和换行替换空格和换行

  • 创建socket ![创建socket](/images/工具效率-测试工具-创建socket.png

  • loadrunner gennerator 中ctrl+r 录制发送报文 生成如下内容

参数化流水号,右健所选内容,命名为seqNum_6 格式为%lu6 提取参数

在Action.c 中添加代码

/*********************************************************************
 * Created by Windows Sockets Recorder
 *
 * Created on: Wed Jun 16 11:06:06
 *********************************************************************/

#include "lrs.h"


Action()
{
   
    int rc=0;

	char *Data, *p,*q;
	int Size;
	char index[2];
	char hexStr[20]={0};
	char strByte[20]={0};
	unsigned char hexByte[20]={0};
	unsigned char *unitptr;
	char rSeqNum[20] = {0};
	int len = 0;
	int i,j,k,ret;
	int z = 0;

 
    //设定开始事务
 
    len = strlen(lr_eval_string("{seqNum_6}"));
  
    p = lr_eval_string("{seqNum_6}") ;
    ret = str2hex(rSeqNum,6,p);
    lr_output_message("str=%s, len = %d",p, ret);
    lr_output_message("str=%s, len = %d",rSeqNum, ret);
    HexStrTobyte(p,hexByte,&len);
    for (i =0;i < len ; i++){
    	lr_output_message("str=%02x,",hexByte[i]);
    }
    q = hexStr;
  
   lr_output_message("str=%s",p);
   len = strlen(p);
   for (j=0; j<len/2 ; j++){
   		memcpy(q,"\\x",2);  
   		memcpy(q+2, p,2);  		
   		p+=2;
   		q+=4;	
   }
   
  lr_output_message("str=%s",hexStr);
  lr_save_string(hexStr,"seqN");
  
 #if 1
    lrs_startup(257);
    //创建socketS
    lr_start_transaction("create_socket");
	//
    rc = lrs_create_socket("socket0", "TCP", "RemoteHost=127.0.0.1:32001",  LrsLastArg);
	//判断套接字创建是否成功
 
	if (rc==0){
	
		lr_end_transaction("create_socket", LR_PASS); 
    	lr_output_message("Socket was successfully send ");
		
	}
	else{
		lr_end_transaction("create_socket", LR_FAIL); 
    	lr_output_message("An error occurred while closing the socket, Error Code: %d", rc);
    	
	}
	//判断socket是否链接成功的事务,0表示创建成功 
	lr_start_transaction("send_socket");   
	//发送安全会话建立请求buf0为在data.ws中定义的发送变量     
	lrs_send("socket0", "buf0", LrsLastArg);
 	//设置连接超时时间为1秒
	lrs_set_recv_timeout(45,0);

	if (rc==0){
	
		lr_end_transaction("send_socket", LR_PASS); 
    	lr_output_message("Socket was successfully send ");
		
	}
	else{
		lr_end_transaction("send_socket", LR_FAIL); 
    	lr_output_message("An error occurred while send the socket, Error Code: %d", rc);
    	
	}
	//设置接收超时时间为1秒
    //lrs_set_recv_timeout2(45,0);
	lr_output_message("Socket was successfully send");

	//接收消息,存放在buf1中,buf1是在data.ws中定义的接收数组,注意数组长度一定要大于等于实际接收长度
    lrs_receive("socket0", "buf1", LrsLastArg); 
    //把Socket最后接收的字节数组,长度放在recvlen中,内容放在recvbuf中
    //lrs_get_last_received_buffer("socket0",&recvbuf,&recvlen);
	
	 lr_start_transaction("received_socket");
	//lrs_save_param("socket0", NULL, "F39", 39, 2);
	//lr_message ("F39: %s", lr_eval_string("{F39}"));
    lrs_get_last_received_buffer("socket0",&Data,&Size);
	//lr_message("报文内容:%s",Data);
	//lr_message("应答码第39位:%x",Data[39]);
	//lr_message("应答码第40位:%x",Data[40]);
		//获取流水号000000
    if(Size == 116){
	
		lr_output_message("接收报文长度 116 == %d", Size);
		lr_end_transaction("received_socket", LR_PASS);
	}else{
		
		lr_output_message("接收报文长度不够116 != %d", Size);
		lr_end_transaction("received_socket", LR_FAIL);
	}

	//memcpy(F39,lr_eval_string("{F39}"),2);
	//lr_output_message("recvbuf: %X",recvbuf);
	 lr_start_transaction("ITMP-9121-A0-33");	
	//获取流水号000000
    //if(Data[32]==0x45&&Data[33]==0x34){
    memcpy(rSeqNum, Data+31,3);
    if(!memcmp(Data+31,hexByte,3)){
    	
		lr_log_message("流水号位:%3.3s",Data+32);
		lr_output_message("交易流水一致");
		lr_end_transaction("ITMP-9121-A0-33", LR_PASS);
	}else{
		lr_log_message("流水号4位:%x",Data[33]);
		lr_output_message("交易流水不一致");
		lr_end_transaction("ITMP-9121-A0-33", LR_FAIL);
	}
	 lr_start_transaction("ITMP-9121-A0");
	
	//获取应答码000000
    if(Data[39]==0x41&&Data[40]==0x30){
		lr_output_message("交易成功");
		lr_end_transaction("ITMP-9121-A0", LR_PASS);
	}else{
		
		lr_output_message("交易失败");
		lr_end_transaction("ITMP-9121-A0", LR_FAIL); 
	}
	//关闭socket
	lrs_close_socket("socket0");
	//lrs_free_buffer(lseqNum);
	#endif
	return 0;
} 
void test_printf5(char *str, int length)
{
    int iii;
    printf("the str is:");
    for (iii = 0; iii < length; iii++)
    {
        printf("%02x ", str[iii]);
    }
    printf("\n");
}
/*str to hex,
字符串转换为16进制
利用snprintf 函数
int snprintf(char* dest_str,size_t size,const char* format,...);
功能:将可变参数以format的格式转换到dest_str中,并可以用%s打印出来。
1、dest_str:目标字符串,即输出字符串
2、size: 转换字符控制长度。
(1) 如果格式化后的字符串长度 < size,则将此字符串全部复制到str中,并给其后添加一个字符串结束符('\0');
(2) 如果格式化后的字符串长度 >= size,则只将其中的(size-1)个字符复制到str中,并给其后添加一个字符串结束符('\0'),返回值为欲写入的字符串长度。
3、format :转换为某个格式,例如:%2d,%04X,%02X。
4、...:需要转换的字符串
*/
int str2hex(char *out_string, int length, char *in_string)
{
    int index;
    char *fmt = "%02x";

    for (index = 0; index < length; index++)
    {
        snprintf((char *)&out_string[index << 1], 3, fmt, in_string[index]);
    }
    return (length << 1);
}


int HexStrTobyte(char *str, unsigned char *out, unsigned int *outlen)
{
    char *p = str;
    char high = 0, low = 0;
    int tmplen = strlen(p), cnt = 0;
    tmplen = strlen(p);
    while (cnt < (tmplen / 2))
    {
        high = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;
        low = (*(++p) > '9' && ((*p <= 'F') || (*p <= 'f'))) ? *(p)-48 - 7 : *(p)-48;
        out[cnt] = ((high & 0x0f) << 4 | (low & 0x0f));
        p++;
        cnt++;
    }
    if (tmplen % 2 != 0)
        out[cnt] = ((*p > '9') && ((*p <= 'F') || (*p <= 'f'))) ? *p - 48 - 7 : *p - 48;

    if (outlen != NULL)
        *outlen = tmplen / 2 + tmplen % 2;
    return tmplen / 2 + tmplen % 2;
}
int byteToHexStr(unsigned char byte_arr[], int arr_len, char *HexStr, int *HexStrLen)
{
    int i, index = 0;
    for (i = 0; i < arr_len; i++)
    {
        char hex1;
        char hex2;
        int value = byte_arr[i];
        int v1 = value / 16;
        int v2 = value % 16;
        if (v1 >= 0 && v1 <= 9)
            hex1 = (char)(48 + v1);
        else
            hex1 = (char)(55 + v1);
        if (v2 >= 0 && v2 <= 9)
            hex2 = (char)(48 + v2);
        else
            hex2 = (char)(55 + v2);
        if (*HexStrLen <= i)
        {
            return -1;
        }
        HexStr[index++] = hex1;
        HexStr[index++] = hex2;
    }
    *HexStrLen = index;
    return 0;
}

◀ 返回