精华内容
下载资源
问答
  • 文章目录4.1 Verilog 条件语句if 语句4.2 Verilog 多路分支语句case语句casex/casez 语句4.3 Verilog 循环语句while 循环for 循环repeat 循环forever 循环4.4 Verilog 过程连续赋值assign, deassignforce, release ...

     本章主要讲解Verilog语言中的语句部分。Verilog 语句块主要包括顺序块和并行块。语句类型有多路分支语句(case语句、casex/casez 语句)、循环语句(while 循环、for 循环、repeat 循环、forever 循环)、过程连续赋值语句(assign, deassign、force, release)等。


    4.1 Verilog 语句块

    Verilog 语句块提供了将两条或更多条语句组成语法结构上相当于一条一句的机制。主要包括两种类型:顺序块和并行块。

    顺序块

    顺序块用关键字 begin 和 end 来表示。
    顺序块中的语句是一条条执行的。当然,非阻塞赋值除外。
    顺序块中每条语句的时延总是与其前面语句执行的时间相关。
    在本节之前的仿真中,initial 块中的阻塞赋值,都是顺序块的实例。

    并行块

    并行块有关键字 fork 和 join 来表示。
    并行块中的语句是并行执行的,即便是阻塞形式的赋值。
    并行块中每条语句的时延都是与块语句开始执行的时间相关。
    顺序块与并行块的区别显而易见,下面用仿真说明。

    仿真代码如下:

    `timescale 1ns/1ns
     
    module test ;
        reg [3:0]   ai_sequen, bi_sequen ;
        reg [3:0]   ai_paral,  bi_paral ;
        reg [3:0]   ai_nonblk, bi_nonblk ;
     
     //============================================================//
        //(1)Sequence block
        initial begin
            #5 ai_sequen         = 4'd5 ;    //at 5ns
            #5 bi_sequen         = 4'd8 ;    //at 10ns
        end
        //(2)fork block
        initial fork
            #5 ai_paral          = 4'd5 ;    //at 5ns
            #5 bi_paral          = 4'd8 ;    //at 5ns
        join
        //(3)non-block block
        initial fork
            #5 ai_nonblk         <= 4'd5 ;    //at 5ns
            #5 bi_nonblk         <= 4'd8 ;    //at 5ns
        join
     
    endmodule
    

    仿真结果如下:
    在这里插入图片描述

    如图所示,顺序块顺序执行,第 10ns 时,信号 bi_sequen 才赋值为 8。
    而并行块,ai_paral 与 bi_paral 的赋值是同时执行的,所以均在 5ns 时被赋值。
    而非阻塞赋值,也能达到和并行块同等的赋值效果。

    嵌套块

    顺序块和并行块还可以嵌套使用。

    仿真代码如下:

    `timescale      1ns/1ns
     
    module test ;
     
        reg [3:0]   ai_sequen2, bi_sequen2 ;
        reg [3:0]   ai_paral2,  bi_paral2 ;
        initial begin
            ai_sequen2         = 4'd5 ;    //at 0ns
            fork
                #10 ai_paral2          = 4'd5 ;    //at 10ns
                #15 bi_paral2          = 4'd8 ;    //at 15ns
            join
            #20 bi_sequen2      = 4'd8 ;    //at 35ns
        end
     
    endmodule
    

    仿真结果如下:
    在这里插入图片描述

    并行块语句块内是并行执行,所以信号 ai_paral2 和信号 bi_paral2 分别在 10ns, 15ns 时被赋值。而并行块中最长的执行时间为 15ns,所以顺序块中的信号 bi_sequen2 在 35ns 时被赋值。

    命名块

    我们可以给块语句结构命名。
    命名的块中可以声明局部变量,通过层次名引用的方法对变量进行访问。

    仿真代码如下:

    `timescale 1ns/1ns
     
    module test;
     
        initial begin: csdn  //命名模块名字为csdn,分号不能少
            integer    i ;       //此变量可以通过test.csdn.i 被其他模块使用
            i = 0 ;
            forever begin
                #10 i = i + 10 ;      
            end
        end
     
        reg stop_flag ;
        initial stop_flag = 1'b0 ;
        always begin : detect_stop
            if ( test.csdn.i == 100) begin //i累加10次,即100ns时停止仿真
                $display("Now you can stop the simulation!!!");
                stop_flag = 1'b1 ;
            end
            #10 ;
        end
     
    endmodule
    

    仿真结果如下:
    在这里插入图片描述
    命名的块也可以被禁用,用关键字 disable 来表示。
    disable 可以终止命名块的执行,可以用来从循环中退出、处理错误等。
    与 C 语言中 break 类似,但是 break 只能退出当前所在循环,而 disable 可以禁用设计中任何一个命名的块。

    仿真代码如下:

    `timescale 1ns/1ns
     
    module test;
     
        initial begin: csdn_d //命名模块名字为csdn_d
            integer    i_d ;
            i_d = 0 ;
            while(i_d<=100) begin: csdn_d2
                # 10 ;
                if (i_d >= 50) begin       //累加5次停止累加
                    disable csdn_d3.clk_gen ;//stop 外部block: clk_gen
                    disable csdn_d2 ;       //stop 当前block: csdn_d2
                end
                i_d = i_d + 10 ;
            end
        end
     
        reg clk ;
        initial begin: csdn_d3
            while (1) begin: clk_gen  //时钟产生模块
                clk=1 ;      #10 ;
                clk=0 ;      #10 ;
            end
        end
     
    endmodule
    

    仿真结果如下:
    在这里插入图片描述
    由图可知,信号 i_d 累加到 50 以后,便不再累加,以后 clk 时钟也不再产生。
    可见,disable 退出了当前的 while 块。需要说明的是,disable 在 always 或 forever 块中使用时只能退出当前回合,下一次语句还是会在 always 或 forever 中执行。因为 always 块和 forever 块是一直执行的,此时的 disable 有点类似 C 语言中的 continue 功能。


    # 4.2 Verilog 条件语句 ## if 语句 条件(if)语句用于控制执行语句要根据条件判断来确定是否执行。 条件语句用关键字 if 和 else 来声明,条件表达式必须在圆括号中。 条件语句使用结构说明如下:
    if (condition1)      	    true_statement1 ;
    else if (condition2)        true_statement2 ;
    else if (condition3)        true_statement3 ;
    else                        default_statement ;
    
    • if 语句执行时,如果 condition1 为真,则执行 true_statement1 ;如果 condition1 为假,condition2 为真,则执行 true_statement2;依次类推。
    • else if 与 else 结构可以省略,即可以只有一个 if 条件判断和一组执行语句 ture_statement1 就可以构成一个执行过程。
    • else if 可以叠加多个,不仅限于 1 或 2 个。
    • ture_statement1 等执行语句可以是一条语句,也可以是多条。如果是多条执行语句,则需要用 begin 与 end 关键字进行说明。

    下面代码实现了一个 4 路选择器的功能。

    module mux4to1(
        input [1:0]     sel ,
        input [1:0]     p0 ,
        input [1:0]     p1 ,
        input [1:0]     p2 ,
        input [1:0]     p3 ,
        output [1:0]    sout);
    
        reg [1:0]     sout_t ;
    
        always @(*) begin
            if (sel == 2'b00)
                sout_t = p0 ;
            else if (sel == 2'b01)
                sout_t = p1 ;
            else if (sel == 2'b10)
                sout_t = p2 ;
            else
                sout_t = p3 ;
        end
        assign sout = sout_t ;
     
    endmodule
    

    仿真结果如下。由图可知,输出信号与选择信号、输入信号的状态是相匹配的。
    在这里插入图片描述
    事例中 if 条件每次执行的语句只有一条,没有使用 begin 与 end 关键字。但如果是 if-if-else 的形式,即便执行语句只有一条,不使用 begin 与 end 关键字也会引起歧义。
    例如下面代码,虽然格式上加以区分,但是 else 对应哪一个 if 条件,是有歧义的。

    if(en)
        if(sel == 2'b1)
            sout = p1s ;
        else
            sout = p0 ;
    

    当然,编译器一般按照就近原则,使 else 与最近的一个 if(例子中第二个 if)相对应。但显然这样的写法是不规范且不安全的。
    所以条件语句中加入 begin 与 and 关键字就是一个很好的习惯。
    例如上述代码稍作修改,就不会再有书写上的歧义。

    if(en) begin
        if(sel == 2'b1) begin
            sout = p1s ;
        end
        else begin
            sout = p0 ;
        end
    end
    

    4.3 Verilog 多路分支语句

    case语句

    case 语句是一种多路条件分支的形式,可以解决 if 语句中有多个条件选项时使用不方便的问题。case 语句格式如下:

    case(case_expr)
        condition1     :             true_statement1 ;
        condition2     :             true_statement2 ;
        ……
        default        :             default_statement ;
    endcase
    
    • case 语句执行时,如果 condition1 为真,则执行 true_statement1 ; 如果 condition1 为假,condition2 为真,则执行 true_statement2;依次类推。如果各个 condition 都不为真,则执行 default_statement 语句。
    • default 语句是可选的,且在一个 case 语句中不能有多个 default 语句。
    • 条件选项可以有多个,不仅限于 condition1、condition2 等,而且这些条件选项不要求互斥。虽然这些条件选项是并发比较的,但执行效果是谁在前且条件为真谁被执行。
    • ture_statement1 等执行语句可以是一条语句,也可以是多条。如果是多条执行语句,则需要用 begin 与 end 关键字进行说明。

    case 语句支持嵌套使用。
    下面用 case 语句代替 if 语句实现了一个 4 路选择器的功能。仿真结果与 testbench 可参考条件语句一章,两者完全一致。

    module mux4to1(
        input [1:0]     sel ,
        input [1:0]     p0 ,
        input [1:0]     p1 ,
        input [1:0]     p2 ,
        input [1:0]     p3 ,
        output [1:0]    sout);
     
        reg [1:0]     sout_t ;
        always @(*)
            case(sel)
                2'b00:   begin      
                        sout_t = p0 ;
                    end
                2'b01:       sout_t = p1 ;
                2'b10:       sout_t = p2 ;
                default:     sout_t = p3 ;
            endcase
        assign sout = sout_t ;
     
    endmodule
    

    case 语句中的条件选项表单式不必都是常量,也可以是 x 值或 z 值。
    当多个条件选项下需要执行相同的语句时,多个条件选项可以用逗号分开,放在同一个语句块的候选项中。
    但是 case 语句中的 x 或 z 的比较逻辑是不可综合的,所以一般不建议在 case 语句中使用 x 或 z 作为比较值。
    例如,对 4 路选择器的 case 语句进行扩展,举例如下:

    case(sel)
        2'b00:   sout_t = p0 ;
        2'b01:   sout_t = p1 ;
        2'b10:   sout_t = p2 ;
        2'b11:   sout_t = p3 ;
        2'bx0, 2'bx1, 2'bxz, 2'bxx, 2'b0x, 2'b1x, 2'bzx :
            sout_t = 2'bxx ;
        2'bz0, 2'bz1, 2'bzz, 2'b0z, 2'b1z :
            sout_t = 2'bzz ;
        default:  $display("Unexpected input control!!!");
    endcase
    

    casex/casez 语句

    casex、 casez 语句是 case 语句的变形,用来表示条件选项中的无关项。
    casex 用 “x” 来表示无关值,casez 用问号 “?” 来表示无关值。
    两者的实现的功能是完全一致的,语法与 case 语句也完全一致。
    但是 casex、casez 一般是不可综合的,多用于仿真
    例如用 casez 语句来实现一个 4bit 控制端的 4 路选择选择器。

    module mux4to1(
        input [3:0]     sel ,
        input [1:0]     p0 ,
        input [1:0]     p1 ,
        input [1:0]     p2 ,
        input [1:0]     p3 ,
        output [1:0]    sout);
     
        reg [1:0]     sout_t ;
        always @(*)
            casez(sel)
                4'b???1:     sout_t = p0 ;
                4'b??1?:     sout_t = p1 ;
                4'b?1??:     sout_t = p2 ;
                4'b1???:     sout_t = p3 ;  
            default:         sout_t = 2'b0 ;
        endcase
        assign      sout = sout_t ;
     
    endmodule
    

    4.4 Verilog 循环语句

    Verilog 循环语句有 4 种类型,分别是 while,for,repeat,和 forever 循环。循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式。

    while 循环

    while 循环语法格式如下:

    while (condition) begin
        …
    end
    

    while 循环中止条件为 condition 为假。
    如果开始执行到 while 循环时 condition 已经为假,那么循环语句一次也不会执行。
    当然,执行语句只有一条时,关键字 begin 与 end 可以省略。

    下面代码执行时,counter 执行了 11 次。

    `timescale 1ns/1ns
     
    module test ;
     
        reg [3:0]    counter ;
        initial begin
            counter = 'b0 ;
            while (counter <= 10) begin
                #10 ;
                counter = counter + 1'b1 ;
            end
        end
     
       //stop the simulation
        always begin
            #10 ;  if ($time >= 1000) $finish ;
        end
     
    endmodule
    

    仿真结果如下:
    在这里插入图片描述

    for 循环

    for 循环语法格式如下:

    for(initial_assignment; condition ; step_assignment)  begin
        …
    end
    
    • initial_assignment 为初始条件。
    • condition 为终止条件,condition 为假时,立即跳出循环。
    • step_assignment 为改变控制变量的过程赋值语句,通常为增加或减少循环变量计数。

    一般来说,因为初始条件和自加操作等过程都已经包含在 for 循环中,所以 for 循环写法比 while 更为紧凑,但也不是所有的情况下都能使用 for 循环来代替 while 循环。

    下面 for 循环的例子,实现了与 while 循环中例子一样的效果。需要注意的是,i = i + 1 不能像 C 语言那样写成 i++ 的形式,i = i -1 也不能写成 i – 的形式

    // for 循环语句
    integer      i ;
    reg [3:0]    counter2 ;
    initial begin
        counter2 = 'b0 ;
        for (i=0; i<=10; i=i+1) begin
            #10 ;
            counter2 = counter2 + 1'b1 ;
        end
    end
    

    repeat 循环

    repeat 循环语法格式如下:

    repeat (loop_times) begin
        …
    end
    

    repeat 的功能是执行固定次数的循环,它不能像 while 循环那样用一个逻辑表达式来确定循环是否继续执行。repeat 循环的次数必须是一个常量、变量或信号。如果循环次数是变量信号,则循环次数是开始执行 repeat 循环时变量信号的值。即便执行期间,循环次数代表的变量信号值发生了变化,repeat 执行次数也不会改变。

    下面 repeat 循环例子,实现了与 while 循环中的例子一样的效果。

    // repeat 循环语句
    reg [3:0]    counter3 ;
    initial begin
        counter3 = 'b0 ;
        repeat (11) begin  //重复11次
            #10 ;
            counter3 = counter3 + 1'b1 ;
        end
    end
    

    下面 repeat 循环例子,实现了连续存储 8 个数据的功能:

    always @(posedge clk or negedge rstn) begin
        j = 0  ;
        if (!rstn) begin
            repeat (8) begin
                buffer[j]   <= 'b0 ;      //没有延迟的赋值,即同时赋值为0
                j = j + 1 ;
            end
        end
        else if (enable) begin
            repeat (8) begin
                @(posedge clk) buffer[j]    <= counter3 ;       //在下一个clk的上升沿赋值
                j = j + 1 ;
            end
         end
    end
    

    仿真结果如下图。
    在这里插入图片描述

    由图可知,rstn 拉高时,buffer 的 8 个向量同时赋值为 0。
    第二个时钟周期后,buffer 依次被 counter3 赋值,实现了连续存储 8 个数据的功能。

    forever 循环

    forever 循环语法格式如下:

    forever begin
        …
    end
    
    • forever 语句表示永久循环,不包含任何条件表达式,一旦执行便无限的执行下去,系统函数 $finish 可退出 forever。
    • forever 相当于 while(1) 。
    • 通常,forever 循环是和时序控制结构配合使用的。

    例如,使用 forever 语句产生一个时钟:

    reg          clk ;
    initial begin
        clk       = 0 ;
        forever begin
            clk = ~clk ;
            #5 ;
        end
    end
    

    例如,使用 forever 语句实现一个时钟边沿控制的寄存器间数据传输功能:

    reg    clk ;
    reg    data_in, data_temp ;
    initial begin
        forever @(posedge clk)      data_temp = data_in ;
    end
    

    4.5 Verilog 过程连续赋值

    过程连续赋值是过程赋值的一种。这种赋值语句能够替换其他所有 wire 或 reg 的赋值,改写了 wire 或 reg 型变量的当前值。
    与过程赋值不同的是,过程连续赋值的表达式能被连续的驱动到 wire 或 reg 型变量中,即过程连续赋值发生作用时,右端表达式中任意操作数的变化都会引起过程连续赋值语句的重新执行。

    过程连续性赋值主要有 2 种,assign-deassign 和 force-release。

    assign, deassign

    assign(过程赋值操作)与 deassign (取消过程赋值操作)表示第一类过程连续赋值语句。赋值对象只能是寄存器或寄存器组,而不能是 wire 型变量。
    赋值过程中对寄存器连续赋值,寄存器中的值被保留直到被重新赋值。
    例如,一个带复位端的 D 触发器可以用下面代码描述:

    module dff_normal(
        input       rstn,
        input       clk,
        input       D,
        output reg  Q
     );
    
        always @(posedge clk or negedge rstn) begin
            if(!rstn) begin   			//Q = 0 after reset effective
                Q <= 1'b0 ;
            end
            else begin
                Q <= D ;       			//Q = D at posedge of clock
            end
        end
    
    endmodule  
    

    下面,用 assign 与 deassign 改写,完成相同的功能。
    即在复位信号为 0 时,Q 端被 assign 语句赋值,始终输出为 0。
    复位信号为 1 时,Q 端被 deassign 语句取消赋值,在时钟上升沿被重新赋值。

    module dff_assign(
        input       rstn,
        input       clk,
        input       D,
        output reg  Q
     );
     
        always @(posedge clk) begin
            Q <= D ;       //Q = D at posedge of clock
        end
     
        always @(negedge rstn) begin
            if(!rstn) begin
                assign Q = 1'b0 ; 	//change Q value when reset effective
            end
            else begin        		//cancel the Q value overlay,
                deassign Q ; 		 //and Q remains 0-value until the coming of clock posedge
            end
        end
     
    endmodule
    

    force, release

    force (强制赋值操作)与 release(取消强制赋值)表示第二类过程连续赋值语句。
    使用方法和效果,和 assign 与 deassign 类似,但赋值对象可以是 reg 型变量,也可以是 wire 型变量
    因为是无条件强制赋值,一般多用于交互式调试过程,不要在设计模块中使用。
    当 force 作用在寄存器上时,寄存器当前值被覆盖;release 时该寄存器值将继续保留强制赋值时的值。之后,该寄存器的值可以被原有的过程赋值语句改变。
    当 force 作用在线网上时,线网值也会被强制赋值。但是,一旦 release 该线网型变量,其值马上变为原有的驱动值。
    为直观的观察两种类型变量强制赋值的区别,利用第一节中的计数器 counter10 作为设计模块,testbench 设计如下。

    `timescale 1ns/1ns
     
    module test ;
        reg          rstn ;
        reg          clk ;
        reg [3:0]    cnt ;
        wire         cout ;
     
        counter10     u_counter (
            .rstn    (rstn),
            .clk     (clk),
            .cnt     (cnt),
            .cout    (cout));
     
        initial begin
            clk       = 0 ;
            rstn      = 0 ;
            #10 ;
            rstn      = 1'b1 ;
            wait (test.u_counter.cnt_temp == 4'd4) ;
            @(negedge clk) ;
            force     test.u_counter.cnt_temp = 4'd6 ;
            force     test.u_counter.cout     = 1'b1 ;
            #40 ;
            @(negedge clk) ;
            release   test.u_counter.cnt_temp ;
            release   test.u_counter.cout ;
        end
     
        initial begin
            clk = 0 ;
            forever #10 clk = ~ clk ;
        end
     
        //finish the simulation
        always begin
            #1000;
            if ($time >= 1000) $finish ;
        end
     
    endmodule 
    

    仿真结果如下。
    在这里插入图片描述

    由图可知,在 cnt_temp 等于 4 时(80ns), cnt_temp 被强制赋值为 6,cout 被强制赋值为 1。

    release 时(120ns), cnt_temp 为寄存器类型,仍然保持原有值不变,直到时钟上升沿对其进行加法赋值操作,值才变为 7 。

    而 120ns 时,由于 cout 是线网型变量,其值不能保存。原码 counter10 模型中存在驱动语句: assign cout = (cnt_temp==4’d9) ,所以 cout 值变为 0 。

    展开全文
  • 标题:多路分支语句、已知次数循环 关键词:语句使用 内容:  A、一句话概括今日目标完成情况  多路分支语句:80%  已知次数循环:60%  B、具体内容:  一、今天学习了多路分支语

    1626-5-刘小铭总结《2016年10月9日》【连续9天总结】

    标题:多路分支语句、已知次数循环

    关键词:语句使用

    内容:

             A、一句话概括今日目标完成情况

                 多路分支语句:80%

               已知次数循环:60%

             B、具体内容:

                 一、今天学习了多路分支语句,也就是switch,这个语句中要注意,(1)运算的表达式可以是整型,字符型,布尔型和枚举型。(2)如果在语句中加入break将跳过所有后续分支。同时,今天知道了调试怎么用。

                二、已知次数的循环也就是for语句for(表达式1;表达式2;表达式3)    表达式1:<变量>=<初始值表达式>    表达式2:表示循环条件          表达式3:表示增量

               三、还有就是循环嵌套,外层循环,内层循环的用法。下面是今天学的语句使用的范例,自己编写一遍,记得更熟一点。

    成绩转换:

    int old_grade,new_grade;
    cin>>old_grade;
    switch(old_grade/10)
    {case 10:new_grade=5;break;
    case 9:new_grade=5;break;
    case 8:new_grade=4;break;
    case 7:new_grade=3;break;
    case 6:new_grade=2;break;
    default:new_grade=1; 
             }

             cout<<new_grade<<endl;

    累加和程序:

    int sum;
    int i,n;
    cin>>n;
    for(sum=0;i<=n;i++)
    {
    sum=sum+i;
    }
    cout<<sum; 

    乘法表:

    int i,j;
    for(i=9;i>=1;i--)
    {
    for(j=1;j<=i;j++)
    {
    cout<<j<<"*"<<i<<"="<<j*i<<'\t';
    }
    cout<<endl;
    }

          C、明日计划

              学习已知条件循环和解一元二次方程实例

             

    展开全文
  • 多路分支 代码 //成绩转换器 #include<iostream> using namespace std; int main() { int OldGrade, NewGrade; cin >> OldGrade; switch (OldGrade/10); //判断成绩除以10后的个位数 { ...

    单路、双路

     多路分支

    代码

    //成绩转换器
    #include<iostream>
    using namespace std;
    
    int main()
    {
    	int OldGrade, NewGrade;
    	cin >> OldGrade;
    	switch (OldGrade/10);			//判断成绩除以10后的个位数
    	{
    	case 10:			//分支语句为空时,自动执行下一句
    	case 9:NewGrade = 5; break;			//break:中断程序,不执行后面的程序
    	case 8:NewGrade = 4; break;
    	case 7:NewGrade = 3; break;
    	case 6:NewGrade = 2; break;
    	default:NewGrade = 1;break;			//其它情况归为一类
    	}
    	cout << NewGrade;
    	system("pause");
    	return 0;
    }
    
    展开全文
  • 1.条件语句 #!/bin/bash if [ $# -ne 1 ] then echo "usage:$0 filename" exit fi if ! [ -e $1 ] then echo "$1 not exist" exit fi if [ -d $1 ] then echo "$1 is a directory!" exit else if [ -f $...

    1.条件语句

    #!/bin/bash
    
    if [ $# -ne 1 ]
    then
        echo "usage:$0 filename"
        exit
    fi
    
       if ! [ -e $1 ]
    then
        echo "$1 not exist"
        exit
    fi
    
    if [ -d $1 ]
    then 
        echo "$1 is a directory!"
        exit
    else
        if [ -f $1 ]
        then
    	echo "$1 is a common file"
        else
    	echo "unknow"
        fi
    fi
    
    

    格式为if…then…else…fi。这里的[ -f $1 ]跟前面的判断语句 test -f $1起一样的作用,注意在左括号后和右括号前要加上空格。shell脚本中的else if叫做elif。

    2.多路分支语句case

    #!/bin/bash
    
    echo -n "please input score?"
    read r
    G=$(expr $r / 10)
    case $G in
        9 | 10)		|分割代表多个选项 
    		echo "A"
    		;;		分号相当于break
        8 | 7)
    		echo "B"
    		;;
        *)
    		echo "C"
    		#;;		最后一个分号可以省略
    esac
    
    
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 329
精华内容 131
关键字:

多路分支语句