C

剑法篇

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;
		}

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

法宝篇

工欲善其事,必先利其器

◀ 返回

创建脚本

创建

创建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;
}

◀ 返回

棋谱篇

路线规划

◀ 返回

Grid-Based Route (Re-)Planning

路线规划用于自主代理的导航,例如自动驾驶车辆、机器人和人类(考虑地图服务)基于网格的路由规划研究在二维空间中,将一个初始单元到一个目标单元的路由划分为阻塞或空的网格单元的问题.图1a显示了一个由10行10列组成的示例网格,第0行和第0列的初始单元格由I表示(是的,我们从零开始计算),第9行和第9列的目标单元格由G表示。绿色箭头显示了从I到G的计划移动,阻塞路段显示为橙色正方形的块。

路线规划图1

随着环境的变化,即块被移除或放置在一些新的单元上,计划的路由可能变得无效如图所示。例如一个机器人,按照计划的路线从图1a到达图1b网格中的单元格I和单元格g,它将被阻塞,故需要并重新规划绕过障碍物,如图1c所示。

Input Data

输入数据从文件中获取,如图2所示,第1行为表格大小,第2行为起始坐标,第3行为目的坐标。第三行开始为路线障碍节点坐标直到读取有“$”。之后行指示的是路线。 路线规划图2

  • Reading and Analyzing Input Data

解决问题的第一步,读取文件数据并分析。将各节点关键信息如下方式显示:

[localhost]>ass2-soln<test0.txt ==STAGE 0======================================= The grid has 10 rows and 10 columns. The grid has 9 block(s). The initial cell in the grid is [0,0]. The goal cell in the grid is [9,9]. The proposed route in the grid is: [0,0]->[0,1]->[0,2]->[0,3]->[0,4]-> [1,4]->[2,4]->[3,4]->[4,4]->[5,4]-> [6,4]->[7,4]->[8,4]->[9,4]->[9,5]-> [9,6]->[9,7]->[9,8]->[9,9]. The route is valid!

Drawing and Replanning

进入第二阶段,当路线中遇到障碍时需要重新规划路线。首先打印路线如图3所示: 重新规划的路线的整体思路是:如何图1f所示,将遇到障碍点为原点扩散,离原点的距离。我们通过上下左右的方式遍历可访问的每个节点放入唯一队列当中,并判别放入的节点是否等于阻塞点的下个节点。如果相等则遍历结束,并获取了重新规划的路线。将队列的课访问路线添加到之前的路线当中。 路线规划图3

  • coding

下列是我遍历路线的代码: