典籍篇

聚社区之智,传技术之火

◀ 返回

五种基本句式

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

◀ 返回

画卷篇

以代码为笔,绘用户界面之韵

事件循环

浏览器有哪些进程和线程

  1. 浏览器进程: 主要负责界面显示、用户交互、子进程管理等。浏览器进程内部会启动多个线程处理不同的任务。
  2. 网络进程: 负责加载网络资源,网络进程内部会启动多个线程处理不同的网络任务
  3. 渲染进程:一个标签页一个进程,渲染进程启动后,会开启一个渲染主线程,主线程负责执行 html、css、js 代码,默认情况下浏览器会为每个标签页开启一个新的渲染进程,以保证不同标签页之间互不影响。

渲染主线程是如何工作的

  • 解析 html
  • 解析 css
  • 计算样式
  • 布局
  • 处理图层
  • 每秒把页面画 60 次
  • 执行全局 js 代码
  • 执行事件处理函数
  • 执行计时器的回调函数

排队

渲染主线程

  1. 最开始的时候渲染主线程会进入一个无限循环
  2. 每一次循环会检查消息对列中是否存有任务存在,如果有,就获取第一个任务执行,执行完一个后进入下一个循环;如果没有,则进入休眠状态
  3. 其他线程(包括其他进程的线程)可以随时向消息队列添加任务。新任务会加到消息队列的末尾。在添加新任务时,如果主线程是休眠状态,则会将其唤醒以继续循环拿取任务。

  这样任务就有条不紊,持续执行下去,整个过程称之为事件循环(消息循环)

代码

何为异步

执行代码中,会遇到一些无法立即处理的任务,比如:

  • 计时完成后需要执行任务:setTimeout、setInterval
  • 网络通信完成后需要执行任务:XHR、 Fetch
  • 用户操作后需要执行的任务: addEventListener 如果让主线程等待这些任务的时机到达,就会导致主线程长期处于阻塞状态,从而导致浏览其卡死。

异步任务 渲染主线程承担着机器重要的工作,无论如何不能阻塞

因此浏览器选择异步任务来解决问题 image

使用异步的方式,渲染主线程用不阻塞

# Q:如何理解 JS 的异步?
Ajs 是一门单线程的语言这是因为它运行在浏览其的渲染主线程中而渲染主线程只有一个
渲染主线程承担着诸多的工作渲染页面执行 js 代码都在其中运行
如果使用同步的方式就有可能导致主线程阻塞从而导致消息队列中的很多其他任务无法得到执行
这样一来一方面导致繁忙的主线程任务白白消耗时间另一个方面无法及时更新给用户造成卡死现象
所以浏览器采用异步的方式来避免具体的做法是当某些任务发生是比如计时器网络事件监听,
主线程江南任务交给其他线程去处理自身立即结束任务执行转而执行后续代码
当其他线程完成是将事先传递的回调函数包装程任务
加入到消息队列的末尾等待主线程调度执行
在这种异步模式下浏览器永不阻塞从而最大限度的保证了单线程的流畅执行

js 为何会阻塞渲染

<html lang="en">

<body>
    <h1>run block</h1>
    <button> change</button>
    <script>
        var h1 = document.querySelector('h1');
        var btn = document.querySelector('button');

        //死循环指定的时间
        function delay(duration) {
            var start = Date.now();
            while (Date.now() - start < duration) { }

        }
        btn.onclick = function () {
            h1.textContent = "blocking";
            delay(3000);
        };
    </script>
</body>

</html>

任务有优先级吗

任务没优先级,消息队列有 FIFO 根据 W3C 解释:

棋谱篇

C语言趣味算法

◀ 返回

汉诺塔

汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从上往下按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新排在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

#include <stdio.h>

void move(char x, char y)
{
    static int cnt = 0;
    printf("%d %c => %c\n", ++cnt, x, y);
}

void hanno(int n, char a, char b, char c)
{
    if ( n == 1 )
        move(a, c);
    else {
        hanno(n-1, a, c, b);
        move(a, c);
        hanno(n-1, b, a, c);
    }
}

int main( void )
{
    hanno(3, 'A', 'B', 'C');
    return 0;
}

百鸡百钱

今有鸡翁一,值钱伍;鸡母一,值钱三;鸡鶵三,值钱一。凡百钱买鸡百只,问鸡翁、母、鶵各几何?

#include <stdio.h>

int main( void )
{
    int x;
    int y;
    int z;

    for (x=0; x<=100; x++)
    {
        for (y=0; y<=100; y++)
        {
            z = 100-x-y;
            if (z%3==0 && 5*x+3*y+z/3==100)
            {
                printf("公鸡%d,母鸡%d,小鸡%d\n",
                    x, y, z);
            }
        }
    }

    return 0;
}

常胜将军

现有21根火柴,两人轮流取,每人每次可以取走1至4根,不可多取,也不能不取,谁取最后一楰火柴谁输。请编写一个程序进行人机对弈,要求人先取,计算机后取;计算机一方为“常胜将军”

棋谱篇

路线规划

◀ 返回

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

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