精华内容
下载资源
问答
  • QT串口通信中,我用了一个大容量的QByteArray[1024000]用于存储从串口中读取的数据(回环队列),我所需要的数据包每个都是是以0Xac开头的(0xac就是校验码), 问现在我怎么能找到这个头,我知道array[0]=0xac可以,...
  • 基于FPGA和串口的CRC生成与校验

    千次阅读 2018-11-30 20:32:39
    CRC又称循环冗余校验,是数据通信领域中最常用的一种查错校验码。说是常用,但我在单片机、FPGA的开发中从来没有用过,别说是CRC了,就是串口的奇偶校验都很少用。一个课程设计要做些和通信相关的东西,题目里面好像...

    CRC又称循环冗余校验,是数据通信领域中最常用的一种查错校验码。说是常用,但我在单片机、FPGA的开发中从来没有用过,别说是CRC了,就是串口的奇偶校验都很少用。一个课程设计要做些和通信相关的东西,题目里面好像就只有这个CRC比较有意思,就研究起了这个。

    乍一看起来这个东西好像挺高大上的:还循环、还冗余,要是碰到个语文差点的,冗余的冗都不知道怎么读……开始时我也觉得这个玩意好复杂、看起来好厉害啊,但理解一下发现也不是很难嘛。(以下内容为个人理解,不当之处,还请指出


    1、理论知识部分

    这个校验方式的根本思想是在发送数据的后面拼接上一些额外的数据位,使得这个拼接之后的数据可以被一个固定的数模2整除(这里的模2整除是一种区别于普通的除法的运算方法,也不难理解),之后将数据发送……接收端同样将整个拼接后的数据与之前确定的固定的数据做模2除法,若能整除,则说明传输过程没有出错,若不能整除,则可以根据余数判断是哪一位发生了错误

    上面说到的要发送的数据被称为信息码;额外的数据位被称为校验码;在模2除法中做除数的那个固定的数被称为生成多项式;拼接完成之后的整个数据被称为CRC 码;

    一些关于生成多项式、模2除法的知识在这里就不细说了,可以参考这一篇博客,我也是参考了这篇博客里的好多内容理解的这个CRC:

    http://www.cnblogs.com/BitArt/archive/2012/12/26/2833100.html


    2、实验部分

    首先为了完成这个实验,就需要有CRC数据的编码发送端接收解码端

    发送端:

    信息码数据:使用7位拨码开关来作为数据的输入。

    生成多项式是x^{8}+x^{7}+x^{6}+x^{4}+1 。即 二进制的“111010001”。

    7 位信息码与生成多项式相除就能得到 8 位校验码,将校验码拼接在信息码后就得到 15 位的CRC 码。

    Verilog代码如下:

    
    /*****************获得CRC码部分**************/
    
    reg fd;
    reg [7:0] crc_tmp=8'd0;
    reg [7:0] crc=8'd0;
    integer i;
    
    /*使用1Hz的时钟来控制CRC校验码的生成*/
    always @(posedge clk or negedge rst)
    begin
        if(!rst) 
            crc <= 8'b0;  
        else if(clk_1Hz_posedge==1'b0)
            crc <= crc_tmp;
    end
    
    always@( data_in or crc) begin
    	crc_tmp = 8'd0;
        for(i=6; i>=0; i=i-1) begin
            fd = crc_tmp[7] ^ data_in[i];
            crc_tmp[7]  = crc_tmp[6] ^ fd;
            crc_tmp[6]  = crc_tmp[5] ^ fd;
            crc_tmp[5]  = crc_tmp[4] ;
            crc_tmp[4]  = crc_tmp[3] ^ fd;
            crc_tmp[3]  = crc_tmp[2] ;
            crc_tmp[2]  = crc_tmp[1] ;
            crc_tmp[1]  = crc_tmp[0] ;
            crc_tmp[0]  = fd   ;
         end
    end
    
    //-----------------分频-----1Hz----------------
    reg	[26:0] Count_1Hz;
    reg	clk_1Hz;
    always @ (posedge clk) begin
    	if(Count_1Hz >= 27'd24_999_999) begin
    		Count_1Hz <= 27'd0;
    		clk_1Hz <= ~clk_1Hz;
    	end
    	else
    		Count_1Hz <= Count_1Hz +27'd1;
    end
    
    //--------------采样clk_1Hz的上升沿-------------
    reg     clk_1Hz_d0;
    reg     clk_1Hz_d1;
    wire    clk_1Hz_posedge;
    assign  clk_1Hz_posedge = clk_1Hz_d0 && (~clk_1Hz_d1);
    
    always @ (posedge clk ) begin
        clk_1Hz_d0 <= clk_1Hz;
        clk_1Hz_d1 <= clk_1Hz_d0;
    end
    

    使用modelsim软件仿真得到的波形如图所示:

    在此可以得到生成的8位的校验码“crc”。使用四位数码管的前两位显示信息码“0X2A”,后两位显示计算得到的CRC校验码0X1A:

    为了展示CRC的纠错能力,在已经生成并且计算好的数据上“做个手脚”:使用7个按键控制七位数据码,检测到哪一位按下就将当前位对应的数据取反,得到最终发送给接受端的带有“人为干扰”的数据。

    /*-------------故意制造错误部分-------------*/
    reg [7:0]   Num_Disp1_temp;
    always @ (posedge clk) begin
        Num_Disp1_temp <= Num_Disp1;
        case(key)
            7'b1111110: Num_Disp1_temp[0] <= ~Num_Disp1_temp[0];
            7'b1111101: Num_Disp1_temp[1] <= ~Num_Disp1_temp[1];
            7'b1111011: Num_Disp1_temp[2] <= ~Num_Disp1_temp[2];
            7'b1110111: Num_Disp1_temp[3] <= ~Num_Disp1_temp[3];
            7'b1101111: Num_Disp1_temp[4] <= ~Num_Disp1_temp[4];
            7'b1011111: Num_Disp1_temp[5] <= ~Num_Disp1_temp[5];
            7'b0111111: Num_Disp1_temp[6] <= ~Num_Disp1_temp[6];
        endcase
    end

    将最终的信息码与生成的crc校验码拼接成数据包,通过串口发送到接收端。

    /*---------------串口发送模块--------------*/
    reg bit_flag = 1'd0;
    
    always @ (posedge clk) begin
        if(ready) begin
            if(bit_flag) begin
                bit_flag <= 1'd0;
                txd_data <= Num_Disp1_temp;
                tx_data_en <= 1'd1;
            end
            else begin
                bit_flag <= 1'd1;
                txd_data <= Num_Disp2;
                tx_data_en <= 1'd1;
            end
        end
        else
            tx_data_en <= 1'd0;
    end
    
    reg tx_data_en = 1'd1;
    reg [7:0]  txd_data;
    
    Uart_Txd Uart_U1
    (
    
    	//input
    	.clk_in(clk),
    	.rst_n(rst),
    	.tx_data_en(tx_data_en),
    	.txd_data(txd_data),
    
    	//output
    	.ready(ready),		//空闲状态下ready为1,发送数据时为0
    	.txd(txd)
    );

    接受端:

    数据来源:接收串口发送来的数据

    数据处理:CRC解码

    数据显示:将信息码显示在数码管的前两位上,后两位显示计算后的CRC余数(为0表示传输没有错误)

    串口接收数据:

    /*----------------------串口接收------------------------*/
    wire [7:0]	DATA;
    wire		Uart_Get;
    reg	bit_flag = 1'd1;
    Data_Rece Data_Rece_U1
    (
        //input
        .clk_in(clk),
    	.rst_n(rst_n),
        .rxd(rxd),
    
        //output
        .Data_Out(DATA),
        .Rxd_Data_En(Uart_Get)
    );
    
    reg	[7:0]	UART_DATA1;
    reg	[7:0]	UART_DATA2;
    
    always @ ( posedge clk  ) begin
    	if(Uart_Get_posedge) begin
    		if(bit_flag) begin
    			bit_flag <= 1'd0;
    			UART_DATA1 <= DATA;
    		end
    		else begin
    			bit_flag <= 1'd1;
    			UART_DATA2 <= DATA;
    		end
    	end
    end
    
    //采样Uart_Get的上升沿
    reg     Uart_Get_d0;
    reg     Uart_Get_d1;
    wire    Uart_Get_posedge;
    
    assign  Uart_Get_posedge = Uart_Get_d0 && (~Uart_Get_d1);
    
    always @ (posedge clk ) begin
      Uart_Get_d0 <= Uart_Get;
      Uart_Get_d1 <= Uart_Get_d0;
    end

    得到发送端发来的数据包,此处的数据包使用两个寄存器保存,分别为UART_DATA1和UART_DATA2,DATA1的低7位中存的是信息码,最高位为0,DATA2中是CRC校验码,将两个数据拼接成一个15位的数据传入CRC校验模块,得到余数CRC_DATA。

    /*-----------------------------------CRC校验部分----------------------------------------*/
    wire [7:0] CRC_DATA;
    crc	CRC_U1
    (
        .rst(rst_n),     
        .clk(clk),     
        .data_in( { UART_DATA1[6:0] , UART_DATA2 } ), 
        .crc( CRC_DATA )
    );

    CRC校验模块与发送端的CRC模块不同,此处传入的数据为15个bit,得到的余数位仍然为8位。模块代码如下:

    module crc(
        rst,     
        clk,     
        data_in, 
        crc
    );
    /*************************************/
    
    input            rst;
    input            clk;
    input     [14:0]  data_in;
    output reg[7:0]  crc;
    
    reg feedback;
    reg [7:0] crc_tmp=8'd0;
    wire crc_start;
    
    assign crc_start = clk_1Hz_posedge;
    
    always @(posedge clk or negedge rst)
    begin
        if(!rst) 
            crc <= 8'b0;  
        else if(crc_start==1'b0)
            crc <= crc_tmp;
    end
    
    integer i;
    always@( data_in or crc)
    begin
    	 crc_tmp = 8'd0;
        for(i=14; i>=0; i=i-1)
        begin
            feedback    = crc_tmp[7] ^ data_in[i];
            crc_tmp[7]  = crc_tmp[6] ^ feedback;
            crc_tmp[6]  = crc_tmp[5] ^ feedback;
            crc_tmp[5]  = crc_tmp[4] ;
            crc_tmp[4]  = crc_tmp[3] ^ feedback;
            crc_tmp[3]  = crc_tmp[2] ;
            crc_tmp[2]  = crc_tmp[1] ;
            crc_tmp[1]  = crc_tmp[0] ;
            crc_tmp[0]  = feedback   ;
         end
    end
    
    //----------------------------------------分频-----1Hz-----------------------
    reg	[26:0] Count_1Hz;
    reg	clk_1Hz;
    always @ (posedge clk) begin
    	if(Count_1Hz >= 27'd24_999_999) begin
    		Count_1Hz <= 27'd0;
    		clk_1Hz <= ~clk_1Hz;
    	end
    	else
    		Count_1Hz <= Count_1Hz +27'd1;
    end
    
    //采样clk_1Hz的上升沿
    reg     clk_1Hz_d0;
    reg     clk_1Hz_d1;
    wire    clk_1Hz_posedge;
    
    assign  clk_1Hz_posedge = clk_1Hz_d0 && (~clk_1Hz_d1);
    
    always @ (posedge clk ) begin
      clk_1Hz_d0 <= clk_1Hz;
      clk_1Hz_d1 <= clk_1Hz_d0;
    end
    
    endmodule

    仿真波形如图:CRC码为0x2A1A,校验完成后得到的crc余数为0,表明数据传输没有错误。

    实际的板子上的显示情况与之一致:后两位显示0x00;

    手动制作一个错误,按下第5个按键,对应的第五位数取反,发送的数据成了0x0A,而此时校验码不变,还是为0x1A,仿真波形如图:发现CRC余数不为0,为0x40

    此时电路板上的显示为0x0A40(0A表示手动制造误差后的数据,40表示CRC余数):

    查阅余数与出错位置表可以验证正好是按键按下的第五位发生了错误

    至此,CRC的产生与验证便完成了。


    来张合照留个念:

    2018//11/30

    展开全文
  • 一旦头检查到进出门卡片将实时上传本数据帧。 2.实时上传错误信息 同步字 /长度 /命令字/ 数据区 / 校验 0xAA - 0x10 错误 错误信息 - 参数: 错误(1字节): 错误信息(1字节):错误对应的错误...
  • 一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下: 首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对...
  • 一个完整的协议帧包括10部分:系统识别、整帧长度、包序号、帧类型、源地址长度、源地址、目的地址长度、目的地址、帧类型、帧校验。 CRC32 CRC16 系统 识别 整帧长度 包序号 帧类型 源地址长度 源地址 ...
  • dr7各域作用 & 异常 现在网上很多网络游戏,当我们修改网络游戏的内存时,哪怕是只修改一个字节. 都会被游戏都会检测到... 有的说是CRC校验,有的说是内存效验. 总之,不管他怎么效验.. 我们都...

    http://hi.baidu.com/bjblcracked/item/0139c1f289a26e10c6dc4551

    dr7各域作用 & 异常码



    现在网上很多网络游戏,当我们修改网络游戏的内存时,哪怕是只修改一个字节.

    都会被游戏都会检测到...

    有的说是CRC校验,有的说是内存效验. 总之,不管他怎么效验..

    我们都可以用 dr硬读 + VEH异常来过效验...

    为什么用VEH,不用 UEF 或者 SEH  .?

    原因很简单.

    1. VEH 更底层. 执行级别最优先.

    2. VEH 在堆中,不在栈中. (SEH 一般都是在Function里面使用)

    3. VEH 有自己的链表. 而且当我们addvectoredexceptionhandler(1, xx)时,总是最先处理异常..

    也就是说,我们在后面添加的异常过程,总是在游戏之前运行...

    Help

    The AddVectoredExceptionHandler function registers a vectored exception handler.

    PVOIDAddVectoredExceptionHandler(ULONGPVECTORED_EXCEPTION_HANDLER);Parameters
    FirstHandler
    Specifies the order in which the handler should be called. If the parameter is nonzero, the handler is the first handler to be called. If the parameter is zero, the handler is the last handler to be called.
    VectoredHandler
    Pointer to the handler to be called. For more information, see .
    展开全文
  • DLT645-2007exe.rar

    2020-03-17 12:07:36
    动力来自于想随时知道自家到底用电功率是多少,这样才能够知道怎么节约用电啊。 过程:找标准看,直接下载DL/T645-2007,看了半天,几十页过去了,有点眉目,然后就着手测试。还算顺利,把本次调测心得写下来。 1...
  • 动力来自于想随时知道自家到底用电功率是多少,这样才能够知道怎么节约用电啊。 过程:找标准看,直接下载DL/T645-2007,看了半天,几十页过去了,有点眉目,然后就着手测试。还算顺利,把本次调测心得写下来。 1、...
  • 今天就花费30分钟时间,带领大家从另一个角度去剖析匹配的目的,理解匹配的思路,一步一步抽丝剥茧去学会怎么写正则表达式(正则表达式远比写正则表达式要困难的多)。 二、理解正则要干的事情 正则要干的

    一、前言

    正则表达式,对大家来说既熟悉又陌生。熟悉是因为工作中有很多场景能用到,比如手机号、邮箱、密码等规则校验。

    陌生则是因为正则表达式看上去就是一堆乱码,且一眼看上去很难看懂匹配规则。有时候在网上去找一个特定规则的正则表达式,搜出来的结果各不相同,执行效果更是不尽人意,想自己去修改,感觉也无从下手。

    今天就花费30分钟时间,带领大家从另一个角度去剖析匹配的目的,理解匹配的思路,一步一步抽丝剥茧去学会怎么写正则表达式(读正则表达式远比写正则表达式要困难的多)。

    二、理解正则要干的事情

    正则要干的事情,可以总结为以下灵魂三问:

    Q1、匹配啥?

    Q2、匹配不是啥?

    Q3、匹配多少次?

    Q1、匹配啥?

    这个比较好理解,比如想匹配字符a,那就直接写/a/,只要字符串某个位置是a就可以匹配上:

    /a/.test("javascript") //true
    复制代码

    匹配以a开头的字符串,就加上元字符^(开始位置标识),/^a/

    /^a/.test("javascript") //不是以a开头返回false
    /^a/.test("abc") //是以a开头返回true
    复制代码

    匹配以a结尾的字符串,就加上元字符$(结束位置标识),/a$/

    /a$/.test("javascript") //不是以a结尾返回false
    /a$/.test("cba") //是以a结尾返回true
    复制代码

    匹配字符a或b,可以把对应的字符放入中括号里/[ab]/,只要字符串包含a或者b就可以匹配上:

    /[ab]/.test("byte") //true
    复制代码

    匹配字符串abc或xyz,/abc|xyz/

    /abc|xyz/.test("aabbxyz") //本字符串包含xyz,所以返回true
    复制代码

    ① 匹配啥前面的(前瞻)

    exp1(?=exp2):匹配exp2前面的exp1,匹配结果不包含exp2

    比如要匹配字符串中script前面的部分java, /java(?=script)/

    /java(?=script)/.test("javascript,javaee,typescript") //字符串中javascript符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /java(?=script)/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["java", index: 0, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是java,index是0,说明找到了的是javascript中script前面的java
    复制代码

    ② 匹配啥后面的(后顾)

    (?<=exp2)exp1:匹配exp2后面的exp1,匹配结果不包含exp2

    比如要匹配字符串中java后面的ee, /(?<=java)ee/

    /(?<=java)ee/.test("javascript,javaee,typescript") //字符串中javaee符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /(?<=java)ee/.exec("javascript,javaee,typescript") 
    //2、得到匹配结果如下:
    ["ee", index: 15, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是ee,index是15,说明找到了的是javaee中java后面的ee
    复制代码

    Q2、匹配不是啥?

    匹配不是啥,意思就是取反,只要不是这些的都可以匹配,比如不想匹配字符a,正则写法为/[^a]/,是在中括号里面加上元字符^,这样只要字符串满足有不是这个集合里面的字符,都可以被匹配上:

    /[^a]/.test("aaa") //字符串全是a,返回false
    /[^a]/.test("abc") //字符串不全是a,返回true
    复制代码

    匹配不是以a开头的,跟之前匹配啥类似,加上元字符^/^[^a]/

    /^[^a]/.test("javascript") //此字符串不是以a开头,返回true
    /^[^a]/.test("abc") //此字符串是以a开头,返回false
    复制代码

    匹配不是以a结束的,也跟之前匹配啥类似,加上元字符$/[^a]$/

    /[^a]$/.test("javascript") //此字符串不是以a结束,返回true
    /[^a]$/.test("cba") //此字符串是以a结束,返回false
    复制代码

    不匹配字符a、b、c,可以把对应的字符都放入中括号里/[^abc]/

    /[^abc]$/.test("abccba") //此字符串的字符全部都不符合,返回false
    复制代码

    ① 匹配后面不是啥的(负前瞻)

    exp1(?!exp2):匹配后面不是exp2的exp1,匹配结果不包含exp2

    比如要匹配字符串中后面不是script的java, /java(?!script)/

    /java(?!script)/.test("javascript,javaee,typescript") //字符串javaee符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /java(?!script)/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["java", index: 11, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是java,index是11,说明找到了的是javaee中的java,因为这个java后面是ee
    复制代码

    ② 匹配前面不是啥的(负后顾)

    (?<!exp2)exp1:匹配前面不是exp2的exp1,匹配结果不包含exp2

    比如要匹配字符串中前面不是java的script,/(?<!java)script/

    /(?<!java)script/.test("javascript,javaee,typescript") //字符串中typescript符合规则 会返回ture
    
    //1、用exec方法来验证下匹配的结果
    /(?<!java)script/.exec("javascript,javaee,typescript")
    //2、得到匹配结果如下:
    ["script", index: 22, input: "javascript,javaee,typescript", groups: undefined]
    //3、会发现匹配到的是script,index是22,说明找到了的是typescript中type后面的script
    复制代码

    ③ 不匹配包含abc的字符串

    这是一个比较特殊的匹配行为,如果只是写成/[^abc]/的话,这只意味着字符串不能全是由a、b、c这三个组成的,跟需求不匹配。

    那我们要从另外一个角度去分析,字符串的任意一个位置开始都不能连续出现abc,我们可以利用负前瞻的特性来匹配,然后一步一步来实现这个正则:

    1. 位置后面不能是abc,使用负前瞻匹配位置:/(?!abc)/
    2. 从开始到结束每个位置都要覆盖到,添加开始结束标记:/^(?!abc)/$
    3. 这个位置后面可以是其他的字符,用\w来表示:/^(?!abc)\w$/
    4. 满足上面情况后的位置,可以连续出现多个,用+来表示数量:/^((?!abc)\w)+$/
    /^((?!abc)\w)+$/.test("cbacbac") //本字符串中不包含连续的abc,结果返回true
    /^((?!abc)\w)+$/.test("cbacbabc") //本字符串中包含连续的abc,结果返回false
    复制代码

    Q3、匹配多少次?

    匹配一次可以什么都不用定义,比如匹配一个数字/\d/,如果要匹配连续三个数字最简单的方式就是连续写三次:/\d\d\d/,这样写本身是没有问题的,能正确匹配。

    但是如果次数太多或者次数不确定,这么写肯定不行,所以可以加上长度规则:

    *:匹配任意次

    +:最低匹配1次

    ?:匹配1次或者0次

    {m}:匹配m次

    {m,}:最低匹配m次

    {m,n}:最低匹配m次,最多匹配n次,m需要小于等于n

    正则默认是贪婪匹配,就是符合条件的会一直匹配,如果想阻止贪婪匹配,可以在长度规则后面加一个?,比如:

    /\d{2,}/.exec("1234567890")
    //得到匹配结果如下,会匹配到所有数字:
    ["1234567890", index: 0, input: "1234567890", groups: undefined]
    
    //1、添加?,阻止非贪婪匹配后
    /\d{2,}?/.exec("1234567890")
    //2、得到匹配结果如下,只会匹配2个数字:
    ["12", index: 0, input: "1234567890", groups: undefined]
    复制代码

    ① 使用分组

    如果想匹配多次某个单词如regregregregregreg时候怎么办,我们看到reg连续出现了6次,如果傻傻的把6个reg写在了正则表达式中肯定不合适,我们就可以利用分组来实现,我们把reg放在括号里面,然后让这个分组重复6次,/(reg){6}/

    /(reg){6}/.test("regregregregregreg") //匹配成功,返回true
    复制代码

    不过这样利用分组是有个前提,就是知道要匹配的字符串就是reg,然后重复这个分组。如果想匹配类似8899或者5522这种重叠类型的字符怎么办呢?那我们可以把重叠的第一个放入分组,再通过\n捕获这个分组内容来匹配下一个:

    /(\d)\1(\d)\2/.exec("2345566789")
    //得到匹配结果如下,返回了5566,分组对应的5、6也被返回
    ["5566", "5", "6", index: 3, input: "2345566789", groups: undefined]
    复制代码

    ② 分组捕获

    默认的分组是可以被捕获的,上面的\1\2是在正则表达式内部捕获的分组。如果想在外部去捕获分组匹配的数据可以使用RegExp.$1-$9来获取。只要正则匹配了就会有。可以使用testexec或者str的replace方法来获取$1-$9

    使用test:

    /([a-z]{2})(\d{2})/.test("xyz123")
    RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
    RegExp.$2 //返回第二个分组表达式匹配到的内容 12
    复制代码

    使用replace:

    "xyz123".replace(/([a-z]{2})(\d{2})/,'$2$1')
    //会返回结果:x12yz3,就是把第一个分组匹配到的内容yz和第二个分组匹配到的内容12互换了
    复制代码

    ③ 分组不捕获

    如果不想捕获分组,只需要在分组内加上?:就可以了

    /([a-z]{2})(?:\d{2})/.test("xyz123")
    RegExp.$1 //返回第一个分组表达式匹配到的内容 yz
    RegExp.$2 //分组未被捕获 返回空字符串
    复制代码

    三、总结

    本文不去赘述元字符的含义以及组合使用方法,这些是需要记死背硬的东西。而是教给大家一种如何切入正则表达式的思维,怎么去一步步分析要匹配的需求,把长的、复杂的需求拆成短的、简单的,正向不行的就逆向去分析,一点一点去组合,然后回归灵魂三问:匹配啥?匹配不是啥?匹配多少次? ,去完成符合要求的正则表达式。

    本文首发于前端黑洞网,csdn同步跟新

     

    展开全文
  • c语言编写单片机技巧

    2009-04-19 12:15:17
    答:汇编语言是一种用文字助记符来表示机器指令的符号语言,是最接近机器的一种语言。其主要优点是占用资源少、程序执行效率高。但是不同的CPU,其汇编语言可能有所差异,所以不易移植。 C语言是一种结构化的...
  • 听说你还在手写复杂的参数校验? 如何自制一个Spring Boot Starter并推送到远端公服 Spring Boot应用缓存实践之:Ehcache加持 自然语言处理工具包 HanLP在 Spring Boot中的应用 基于Spring Boot实现图片上传/加...
  • 图书修改或增加有数据合法性校验(有模式窗口,只能操作最前的窗口) 读者管理:同样实现了增删改查和搜索功能 管理员不能进行人员管理 管理员管理:admin不是超级管理员,换了个账号,可直接改其他管理员信息...
  • 《阿里巴巴 Java开发手册》后感 JVM如何从入门到放弃的? 记一次愚蠢的操作--String不可变性 记一次愚蠢的操作--线程安全问题 小白入门学习打日志 最近学到的Lambda表达式基础知识 手把手带你体验Stream流 几个...
  • 深入浅出MFC【侯捷】

    2015-06-10 09:07:42
    侯捷怎么说 我怎么说 别人怎么说 为什么使用Application Framework Microsoft Foundation Classes(MFC) 白头宫女话天宝:Visual C++与MFC 纵览MFC General Purpose classes CObject 数据处理类(collection ...
  • 侯捷- -深入浅出MFC

    2010-07-28 16:55:58
    对话框数据交换与校验(DDX&DDV) 如何唤起对话框 本章回顾 第11章 View功能的加强与重绘效率的提高 同时修改多个Views:UpdateAllViews和OnUpdate 在View中定义一个hint 把hint传给OnUpdate 利用hint增加重绘效率 ...
  • golang面试官:for select时,如果通道已经关闭会怎么样?如果只有一个case呢? 进阶 包管理 学go mod就够了! 优化 golang面试题:怎么避免内存逃逸? golang面试题:简单聊聊内存逃逸? 给大家丢脸了,...
  • 深入浅出MFC 2e

    2010-05-25 22:43:24
    对话框数据交换与校验(DDX&DDV) 如何唤起对话框 本章回顾 第11章 View功能的加强与重绘效率的提高 同时修改多个Views:UpdateAllViews和OnUpdate 在View中定义一个hint 把hint传给OnUpdate 利用hint增加重绘效率 ...
  • 深入浅出MFC 简体中文

    2009-08-18 10:52:54
    对话框数据交换与校验(DDX&DDV) 如何唤起对话框 本章回顾 第11章 View功能的加强与重绘效率的提高 同时修改多个Views:UpdateAllViews和OnUpdate 在View中定义一个hint 把hint传给OnUpdate 利用hint增加重绘效率 ...
  • 深入浅出MySQL数据库开发、优化与管理维护

    千次下载 热门讨论 2014-01-21 15:48:01
     20.3.7 InnoDB在不同隔离级别下的一致性及锁的差异   20.3.8 什么时候使用表锁   20.3.9 关于死锁   20.4 小结   第21章 优化MySQLServer   21.1 查看MySQLServer参数   21.2 影响MySQL性能...
  • 我用的keil3编译环境,51单片机,电力线载波芯片是MI200E,测试接收0xaa是通过8个led灯(也用串口显示过,和led灯显示相匹配)第一次提问题,不知道怎么把MI200E的数据手册和应用手册贴出来,在代码后贴出了文档在...
  • VC++常用功能实例

    2010-01-25 23:28:46
    ◆在调试中怎么样MESSAGEBOX一个数字◆ 16 ◆如何控制控件的焦点◆ 16 ◆如何对析构函数中对象进行释放◆ 16 ◆如何关闭一个模态窗口◆ 17 ◆如何将一个提示的声音发到声卡上◆ 17 ◆如何得到打开exe的带的参数◆ 17...
  • ◆在调试中怎么样MESSAGEBOX一个数字◆ 16 ◆如何控制控件的焦点◆ 16 ◆如何对析构函数中对象进行释放◆ 16 ◆如何关闭一个模态窗口◆ 17 ◆如何将一个提示的声音发到声卡上◆ 17 ◆如何得到打开exe的带的参数◆ 17...
  • Linux 操作系统基础教程 清华大学信息学院计算机系 目 录 前言..........................................................................................................................................
  • c#学习笔记.txt

    2008-12-15 14:01:21
    另外他对我上一集中说Microsoft越来越不要脸也极为生气,因为相比之下,Sun也不怎么样,微软已经将C#提交设在日内瓦的ECMA(European Computer Manufacturers' Association,国际标准化机构欧洲电子计算机工业会)并...
  • 如果没有这些用户根本不知道怎么用你设计的这个系统。在设计的调试过程中也无法顺利的完成调试工作。有了一个清晰简单的菜单和一些提示信息这后,调试过程完成的非常顺利。 予我耐心解答的老师和同学,是他们为我...
  • 最新Java面试宝典pdf版

    热门讨论 2011-08-31 11:29:22
    6、从类似如下的文本文件中取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序: 71 7、写一个Singleton出来。 75 8、递归算法题1 77 9、递归算法题2 78 10、排序都有哪几种方法?请列举。用JAVA...
  • Java面试宝典-经典

    2015-03-28 21:44:36
    6、从类似如下的文本文件中取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序: 71 7、写一个Singleton出来。 75 8、递归算法题1 77 9、递归算法题2 78 10、排序都有哪几种方法?请列举。用JAVA...
  • Java面试宝典2012版

    2012-12-03 21:57:42
    6、从类似如下的文本文件中取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序: 71 7、写一个Singleton出来。 75 8、递归算法题1 77 9、递归算法题2 78 10、排序都有哪几种方法?请列举。用...
  • java面试宝典2012

    2012-12-16 20:43:41
    6、从类似如下的文本文件中取出所有的姓名,并打印出重复的姓名和重复的次数,并按重复次数排序: 78 7、写一个Singleton出来。 81 8、递归算法题1 84 9、递归算法题2 85 10、排序都有哪几种方法?请列举。用JAVA...

空空如也

空空如也

1 2 3
收藏数 48
精华内容 19
关键字:

校验码怎么读