【新书推荐】7.3 for语句

本节必须掌握的知识点:

    示例二十四

        代码分析

        汇编解析

        for循环嵌套语句

        示例二十五

7.3.1 示例二十四

for语句语法形式:

for(表达式1;表达式2;表达式3)

{

语句块;

}

●语法解析:

第一步:执行表达式1,表达式1初始化循环变量;

第二步:执行表达式2,表达式2条件判断语句,如果表达式条件为真,则执行循环体内的语句块,否则退出for语句;

第三步:执行循环体内的语句块;

第四步:执行表达式3后置表达式;

第五步:继续执行下一轮循环,直到表达式2的条件为假,跳出for循环语句。

执行顺序:表达式1->表达式2->循环语句块->表达式3->表达式2->循环语句块->表达式3->表达式2->循环语句块……一直循环下去,直到到表达式2为假时,停止循环。接下来我们示例二十四来理解for语句的执行流程。

示例代码二十四

●第一步:分析需求,设计程序结构框架。

分析需求:构建一个for循环语句,当i<= 5时,重复执行for语句内的重复块。

设计程序结构框架:循环结构for语句。

       ●第二步:数据定义,定义恰当的数据结构;

       int i;//定义一个int类型的整型局部变量i,并将其初始化为0,作为循环变量。

       ●第三步:分析算法。

       利用for语句,当i<= 5时,重复执行for语句内的重复块。先判断后执行。

       ●第四步:编写伪代码,即用我们自己的语言来编写程序。

       int main(void) {

    定义一个int类型整型循环变量i;

表达式1:将循环变量i初始化为0;

表达式2:当i <= 5时执行大括号内的循环语句块

表达式3:执行完printf语句后,循环变量i加1

    for (i = 0; i <= 5; i++){

        调用printf函数打印信息"i = %d\n"                                     

}

调用printf函数打印信息"i = %d\n" 

system("pause");

    return 0;                                                                                                    

}

       ●第五步:画流程图,使用Visio、Excel或者其他绘图工具绘制算法流程和逻辑关系图; 如图7-3所示。

图7-3 示例二十四for循环语句

●第六步:编写源程序,其实就是将我们的伪代码翻译成计算机语言;

/*

   for语句

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i;

    for (i = 0; i <= 5; i++)

    {

        printf("i = %d\n", i);

    }

printf("i = %d\n", i);

    system("pause");                                        

    return 0;                          

}    

●输出结果:

i = 0

i = 1

i = 2

i = 3

i = 4

i = 5

i = 6

●第七步:调试程序,修复程序中可能出现的BUG;

参见反汇编代码。

●第八步:优化代码,尝试更好的设计方案,效率更高的算法,逻辑更为清晰简洁明了。

(无)

7.3.2 代码分析

分析for语句执行流程:

第一步:执行 int i = 0;

第二步:执行 i<=5;0<5条件为真,继续往下执行 ;

第三步:执行printf(“i = %d”,i);输出 i = 0;

第四步:执行i++; i=0+1,i=1;

第五步:执行i<=5;1<5条件为真,继续往下执行;

第六步:执行printf(“i = %d”,i);输出 i =1;

第七步:执行i++;i=1+1,i=2;

第八步:执行i<=5;2<5条件为真,继续往下执行;

第九步:执行printf(“i = %d”,i);输出 i =2;

第十步:执行i++;i=2+1,i=3;

第十一步:执行i<=5;3<5条件为真,继续往下执行;

第十二步:执行printf(“i = %d”,i);输出 i =3;

第十三步:执行i++;i=1+3,i=4;

第十四步:执行i<=5;4<5条件为真,继续往下执行;

第十五步:执行printf(“i = %d”,i);输出 i =4;

第十六步:执行i++;i=1+4,i=5;

第十七步:执行i<=5;5=5条件为真,继续往下执行;

第十八步:执行printf(“i = %d”,i);输出 i =5;

第十九步:执行i++;i=1+5,i=6;

第二十步:执行i<=5;6>5条件为假,退出循环;

退出for循环后,再次输出i的值为6。

这是这个程序的正向分析流程,我们看下它的反汇编是怎么体现的。

7.3.3 汇编解析

汇编代码

;C标准库头文件和导入库

include vcIO.inc

.data

i sdword  ?

.const    

szMsg db "i = %d",0dh,0ah,0

.code     

start:

       mov i,0

NEXT:           

       .while i <= 5

              invoke printf,offset szMsg,i 

              inc sdword ptr i;

              jmp NEXT           

       .endw           

       ;

       invoke printf,offset szMsg,i

       ;     

       invoke _getch

       ret                       

end start

●输出结果:

i = 0

i = 1

i = 2

i = 3

i = 4

i = 5

i = 6

       上述汇编代码使用了.while高级汇编伪指令(没有.for高级汇编伪指令),实现了C语言中的for循环语句。

 

结论

从本质上看,C语言中的for语句就是while语句的简化形式。“mov i,0”语句对应表达式1;条件表达式“i <= 5”对应表达式2;“inc sdword ptr i”语句对应表达式3。

反汇编代码

    int i;

    for (i = 0; i <= 5; i++)

00391838  mov         dword ptr [i],0  ;表达式1:初始化循环变量i=0

0039183F  jmp         main+3Ah (039184Ah);无条件跳转到表达式2语句

00391841  mov         eax,dword ptr [i] 

00391844  add         eax,1              ;表达式3:变量i加一

00391847  mov         dword ptr [i],eax 

0039184A  cmp         dword ptr [i],5  ;表达式2:比较变量i和5的大小

    int i;

    for (i = 0; i <= 5; i++)

0039184E  jg          main+53h (0391863h) ;如果i>5,则跳出for循环,否则执行循环语句

    {

        printf("i = %d\n", i)

00391850  mov         eax,dword ptr [i] 

00391853  push        eax                              

00391854  push        offset string "i = %d\n" (0397B30h) ;循环语句

00391859  call        _printf (039104Bh) 

0039185E  add         esp,8 

    }

00391861  jmp         main+31h (0391841h) ;无条件跳转到表达式3

    printf("i = %d\n", i);

00391863  mov         eax,dword ptr [i]  ;for循环外的下一条语句

00391866  push        eax 

00391867  push        offset string "i = %d\n" (0397B30h) 

0039186C  call        _printf (039104Bh) 

00391871  add         esp,8 

    system("pause");

00391874  mov         esi,esp 

00391876  push        offset string "pause" (0397B38h) 

0039187B  call        dword ptr [__imp__system (039B168h)] 

00391881  add         esp,4 

 

总结

在for语句中:

表达式1基本上是用来定义循环控制变量或者说对循环语句的开始进行控制;

表达式2一般是用来判断条件是否满足的语句,满足条件则继续执行,不满足则退出for语句;

表达式3称为步长,一般是用来控制循环次数的,;

语句块:可以做任何事情。

实验四十八: for语句表现形式1

在VS中新建项目7-3-2.c:

/*

   for语句的表现形式1:省略第一个表达式

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i = 0;         // 在for循环之前初始化

    for (; i < 10; i++)// for语句中省去第一个表达式。但是分号不能少

    {

        printf("■");

    }

    printf("\n");

    system("pause");

    return 0;

}

●输出结果:

■■■■■■■■■■

请按任意键继续. . .

       上述代码中的表达式1放置在for语句之前,for语句内只保留了一个’;’,其他保持不变。接下来我们通过反汇编代码观察一下这种形式的for语句的执行流程。                     

反汇编代码:

    int i = 0;         //  在for循环之前初始化

009B1838  mov         dword ptr [i],0  ;表达式1前置

    for (; i < 10; i++)// for语句中省去第一个表达式。但是分号不能少

009B183F  jmp         main+3Ah (09B184Ah

009B1841  mov         eax,dword ptr [i] 

009B1844  add         eax,1                ;表达式3

009B1847  mov         dword ptr [i],eax 

009B184A  cmp         dword ptr [i],0Ah  ;表达式2

    for (; i < 10; i++)// for语句中省去第一个表达式。但是分号不能少

009B184E  jge         main+4Fh (09B185Fh;当i>=10,退出循环

    {

        printf("■");

009B1850  push        offset string "\xa1\xf6" (09B7B30h) 

009B1855  call        _printf (09B104Bh) 

009B185A  add         esp,4 

    }

009B185D  jmp         main+31h (09B1841h;跳转到表达式3

    printf("\n");

009B185F  push        offset string "\n" (09B80D8h) 

009B1864  call        _printf (09B104Bh) 

009B1869  add         esp,4   

 

结论

由上述反汇编代码可知,表达式1前置,对应for语句的执行流程没有任何改变。

练习

  1. 请读者书写程序7-3-2.c伪代码,并绘制流程图。
  2. 请读者将7-3-2.c翻译成汇编语言实现。
  3. 请读者分析7-3-2.c的反汇编代码。

实验四十九: for语句表现形式2

在VS中新建项目7-3-3.c:

/*

   for语句的表现形式2:省略第二个表达式

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    for (int i = 0;; i++)//变量i的作用域仅限for语句块内

    {

        if (i > 10)

        {

            break;//如果i>10则跳出循环,break是跳出for循环

        }

        printf("■");

    }

    //printf("i = %d\n",i);

    system("pause");

    return 0;

}

       ●输出结果:

■■■■■■■■■■■请按任意键继续. . .

       实验四十九的代码需要注意两点:

       1.变量i的定义放在了for语句内,那么变量i的作用域仅限for语句块。如果将下面的语句“printf("i = %d\n",i);”屏蔽去掉,编译时会提示错误信息“error C2065: “i”: 未声明的标识符”。在C语言中,变量是区分作用域的,也就是有效范围。如果是全局变量,则保存在全局区,在整个程序范围内都是有效的。如果局部变量定义在函数内,则保存在函数堆栈中,仅在函数内有效,函数运行结束后释放堆栈空间,局部变量也就消失了。此外还有两种类型的变量static静态变量和STL线程存储变量,这里暂不做介绍。

       在C语言中,不同作用域的变量名可以相同,因为作用域不同,编译器编译时也会自动区分。

       2.for语句的表达式2是一个条件表达式,其作用是控制循环结束条件。实验四十九中的代码将表达式2放置在循环语句块内,使用if语句判断条件,当i>10时,执行break语句,退出循环。break语句的作用就是退出循环,我们将在本章7.5节继续介绍break语句的使用方法。

【注】for语句中的表达式2分号不可以缺省。

       接下来我们再看一下反汇编代码:

    for (int i = 0;; i++)//变量i的作用域仅限for语句块内

00B01838  mov         dword ptr [ebp-8],0  ;表达式1,[ebp-8]为局部变量i

    for (int i = 0;; i++)//变量i的作用域仅限for语句块内

00B0183F  jmp         main+3Ah (0B0184Ah

00B01841  mov         eax,dword ptr [ebp-8]  ;表达式3

00B01844  add         eax,1 

00B01847  mov         dword ptr [ebp-8],eax 

    {

        if (i > 10);表达式2

00B0184A  cmp         dword ptr [ebp-8],0Ah 

00B0184E  jle         main+42h (0B01852h) 

        {

            break;//如果i>10则跳出循环,break是跳出for循环

00B01850  jmp         main+51h (0B01861h)  ;退出循环

        }

        printf("■");循环语句

00B01852  push        offset string "\xa1\xf6" (0B07B30h) 

00B01857  call        _printf (0B0104Bh) 

00B0185C  add         esp,4 

    }

00B0185F  jmp         main+31h (0B01841h)  ;跳转到表达式3

    //printf("i = %d\n",i);

    system("pause");

00B01861  mov         esi,esp 

       上述反汇编代码中一个明显的变化就是变量i使用[ebp-8]来代替。为了进一步验证变量i的作用域,我们再做一个实验。

实验五十: for语句循环变量作用域

在VS中新建项目7-3-4.c:

/*

   for语句循环变量作用域

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    int i = 20;//作用域main函数内有效

    for (int i = 0;; i++)//变量i的作用域仅限for语句块内

    {

        printf("\ni = %d", i);

        if (i > 10)

        {

            break;//如果i>10则跳出循环,break是跳出for循环

        }

        printf("■");

    }

    printf("\ni = %d\n",i);//i=20

    system("pause");

    return 0;

}

       ●输出结果:

i = 0■

i = 1■

i = 2■

i = 3■

i = 4■

i = 5■

i = 6■

i = 7■

i = 8■

i = 9■

i = 10■

i = 11

i = 20

请按任意键继续. . .

上述代码中存在两个变量i,编译时并没有报错,说明变量名符号没有冲突。再看打印信息,for语句内打印的变量i从0~11。最后一个打印输出的变量i的值为20,显然是第一个变量i的值。

请读者查看一下反汇编代码,第一个变量i使用“[i]”表示,而第二个变量i使用“[ebp-14h]表示”。其余内容和使用四十九相同,不再赘述。

实验五十一: for语句形式3

在VS中新建项目7-3-5.c:

/*

   for语句形式3:缺省表达式3

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    for (int i = 0; i < 10;)

    {

        printf("■");

        i++;

    }

    system("pause");

    return 0;

}

●输出结果:

■■■■■■■■■■请按任意键继续. . .

上述代码将表达式3放置在循环语句块的结尾处,这应该和我们预想的一样,之前for语句的反汇编代码的执行流程就是如此。接下来我们再看一下反汇编代码的执行流程。

●反汇编代码:

    for (int i = 0; i < 10;)

002D1838  mov         dword ptr [ebp-8],0  ;表达式1

    for (int i = 0; i < 10;)

002D183F  cmp         dword ptr [ebp-8],0Ah  ;表达式2

002D1843  jge         main+4Dh (02D185Dh)  ;i>=10跳出循环

    {

        printf("■");循环语句

002D1845  push        offset string "\xa1\xf6" (02D7B30h) 

002D184A  call        _printf (02D104Bh) 

002D184F  add         esp,4 

        i++;表达式3

002D1852  mov         eax,dword ptr [ebp-8] 

002D1855  add         eax,1 

002D1858  mov         dword ptr [ebp-8],eax 

    }

002D185B  jmp         main+2Fh (02D183Fh;继续循环

    system("pause");

002D185D  mov         esi,esp

上述反汇编代码和之前示例中的反汇编代码执行流程稍有不同,表达式3按照正常的代码编写顺序放置在printf语句之后。其实之前的反汇编代码也是按照代码的编写顺序进行编译的。

【注意】for (int i = 0; i < 10;)语句内的最后一个表达式;可以缺省。

实验五十二: for语句形式4

在VS中新建项目7-3-6.c:

/*

   for语句形式4:缺省全部3个表达式

*/

#include <stdio.h>

#include <stdlib.h>

int main(void) {

    for (;;)

    {

        printf("■");

    }

    system("pause");

    return 0;

}

●输出结果:

不停的打印■,陷入死循环。

为什么会是这样呢?因为当表达式全部置空时,相当于没有初始值,没有控制语句,没有后置表达式,那么它将永远的循环下去,直到内存溢出,这就是所谓的死循环。

   ●反汇编代码:

    for (;;)

    {

        printf("■");

011E1838  push        offset string "\xa1\xf6" (011E7B30h) 

    for (;;)

    {

        printf("■");

011E183D  call        _printf (011E104Bh) 

011E1842  add         esp,4 

    }

011E1845  jmp         main+28h (011E1838h;跳到for语句块起始位置

    system("pause");

011E1847  mov         esi,esp 

       上述反汇编代码可以看到,程序中没有循环控制变量,没有循环结束条件,因此陷入了无限循环。我们应绝对避免此类情况的发生。

练习

1、递增显示从0到输入的正整数为止的各个整数(for语句)。

2、输入一个整数,连续显示出该整数个*(for语句)。

3、输入规定数量个整数并显示出它们的合计值和平均值。

4、编写一个程序,求1到n的和。n的值从键盘输入。

5、根据输入的整数,循环显示1234567890,显示的位数和输入的整数值相同。

请输入一个整数:25

1234567890123456789012345

6、显示输入的整数值的所有约数。

7、编写一段程序,输入一个整数值,显示该数值以下的所有奇数。

整数值:15

1 3 5 7 9 11 13 15

8、编写一段程序,输入一个整数值,显示该整数值个‘*'。每显示5个就进行换行。

显示多少个*:12

*****

*****

** 

*

本文摘自编程达人系列教材《汇编的角度——C语言》。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/677018.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW工业监控系统

LabVIEW工业监控系统 介绍了一个基于LabVIEW软件开发的工业监控系统。系统通过虚拟测控技术和先进的数据处理能力&#xff0c;实现对工业过程的高效监控&#xff0c;提升系统的自动化和智能化水平&#xff0c;从而满足现代工业对高效率、高稳定性和低成本的需求。 随着工业自…

BestEdrOfTheMarket:一个针对AVEDR绕过的训练学习环境

关于BestEdrOfTheMarket BestEdrOfTheMarket是一个针对AV/EDR绕过的训练学习环境&#xff0c;广大研究人员和信息安全爱好者可以使用该项目研究和学习跟AV和EDR绕过相关的技术知识。 支持绕过的防御技术 1、多层API钩子&#xff1b; 2、SSH钩子&#xff1b; 3、IAT钩子&#x…

springboot176基于Spring Boot的装饰工程管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

【Make编译控制 01】程序编译与执行

目录 一、编译原理概述 二、编译过程分析 三、编译动静态库 四、执行过程分析 一、编译原理概述 make&#xff1a; 一个GCC工具程序&#xff0c;它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接&#xff0c;然后发布必要的命令。它读出的脚本&#xff08;叫做 …

react中hook封装一个table组件 与 useColumns组件

目录 1&#xff1a;react中hook封装一个table组件依赖CommonTable / index.tsx使用组件效果 2&#xff1a;useColumns组件useColumns.tsx使用 1&#xff1a;react中hook封装一个table组件 依赖 cnpm i react-resizable --save cnpm i ahooks cnpm i --save-dev types/react-r…

开源微服务平台框架的特点是什么?

借助什么平台的力量&#xff0c;可以让企业实现高效率的流程化办公&#xff1f;低代码技术平台是近些年来较为流行的平台产品&#xff0c;可以帮助很多行业进入流程化办公新时代&#xff0c;做好数据管理工作&#xff0c;从而提升企业市场竞争力。流辰信息专业研发低代码技术平…

软件文档测试

1 文档测试的范围 软件产品由可运行的程序、数据和文档组成。文档是软件的一个重要组成部分。 在软件的整人生命周期中&#xff0c;会用到许多文档&#xff0c;在各个阶段中以文档作为前阶段工作成果的体现和后阶段工作的依据。 软件文档的分类结构图如下图所示&#xff1a; …

图灵之旅--二叉树堆排序

目录 树型结构概念树的表示形式 二叉树概念特殊的二叉树二叉树性质二叉树的存储二叉树的遍历前中后序遍历 优先级队列(堆)概念 优先级队列的模拟实现堆的性质概念堆的存储方式堆的创建 堆常用接口介绍PriorityQueue的特性PriorityQueue常用接口介绍优先级队列的构造插入/删除/获…

力扣刷题之旅:进阶篇(六)—— 图论与最短路径问题

力扣&#xff08;LeetCode&#xff09;是一个在线编程平台&#xff0c;主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目&#xff0c;以及它们的解题代码。 --点击进入刷题地址 引言 在算法的广阔天地中&#xff0c;图论是一个非常重要的领域。…

2万字曝光:华尔街疯狂抢购比特币背后

作者/来源&#xff1a;Mark Goodwin and whitney Webb BitcoinMagazine 编译&#xff1a;秦晋 全文&#xff1a;19000余字 在最近比特币ETF获得批准之后&#xff0c;贝莱德的拉里-芬克透露&#xff0c;很快所有东西都将被「ETF化」与代币化&#xff0c;不仅威胁到现有的资产和商…

【linux系统体验】-archlinux折腾日记

archlinux 一、系统安装二、系统配置及美化2.1 中文输入法2.2 安装virtualbox增强工具2.3 终端美化2.4 桌面面板美化 三、问题总结3.1 一、系统安装 安装步骤人们已经总结了很多很全: Arch Linux图文安装教程 大体步骤&#xff1a; 磁盘分区安装 Linux内核配置系统&#xff…

Nginx 配置 SSL证书

成功配置SSL证书后&#xff0c;您将能够通过HTTPS加密通道安全访问Nginx服务器。 一、准备材料 SSL证书绑定的域名已完成DNS解析&#xff0c;即您的域名与主机IP地址相互映射。您可以通过DNS验证证书工具&#xff0c;检测域名DNS解析是否生效。具体操作&#xff1a; 【1】登录…

阿里云幻兽帕鲁服务器免费搭建解决方法,白嫖阿里云

阿里云幻兽帕鲁服务器免费搭建方案&#xff0c;先在阿里云高校计划「云工开物」活动领取学生专享300元无门槛代金券&#xff0c;幻兽帕鲁专用服务器4核16G配置26元1个月、149元半年&#xff0c;直接使用这个无门槛300元代金券抵扣即可免费搭建幻兽帕鲁服务器。阿里云服务器网al…

Python环境下基于指数退化模型和LSTM自编码器的轴承剩余寿命预测

滚动轴承是机械设备中关键的零部件之一&#xff0c;其可靠性直接影响了设备的性能&#xff0c;所以对滚动轴承的剩余使用寿命(RUL)进行预测是十分必要的。目前&#xff0c;如何准确地对滚动轴承剩余使用寿命进行预测&#xff0c;仍是一个具有挑战的课题。对滚动轴承剩余寿命评估…

ctfshow-web11~20-WP

web11 根据提示,查询对ctfshow域名进行dns查询,查看TXT记录 阿里云查询链接:阿里云网站运维检测平台 获取flag成功 web12 根据题目提示,我们访问robots.txt,获取到后台地址 然后我们访问一下后台

Android性能调优 - 应用安全问题

Android应用安全 1.组件暴露&#xff1a; 像比如ContentProvider,BroadcastReceiver&#xff0c;Activity等组件有android:exported属性&#xff1b; 如果是私有组件 android:exported “false”&#xff1b; 如果是公有组件 android:exported “true” 且进行权限控制&…

2、 Scheduler介绍 代码解析 [代码级手把手解diffusers库]

Scheduler简介分类老式 ODE 求解器&#xff08;Old-School ODE solvers&#xff09;初始采样器&#xff08;Ancestral samplers&#xff09;Karras噪声调度计划DDIM和PLMSDPM、DPM adaptive、DPM2和 DPMUniPCk-diffusion 1.DDPM2.DDIM3.Euler4.DPM系列5. Ancestral6. Karras7. …

在Ubuntu22.04上部署ComfyUI

ComfyUI 是 一个基于节点流程的 Stable Diffusion 操作界面&#xff0c;可以通过流程&#xff0c;实现了更加精准的工作流定制和完善的可复现性。每一个模块都有特定的的功能&#xff0c;我们可以通过调整模块连接达到不同的出图效果&#xff0c;特点如下&#xff1a; 1.对显存…

“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【下】(分文件编程)

“智能检测&#xff0c;精准把控。温湿度检测系统&#xff0c;为您的生活带来全方位的健康保障。”#非标协议项目【下】&#xff08;分文件编程&#xff09; 前言预备知识1温湿度检测系统需求2.分文件编程核心思路3.分文件编程操作4利用分文件操作建立uart.c、lcd1602.c、dht11…

windows安装sqlite

windows安装sqlite比linux麻烦很多 1.下载 下载链接&#xff1a;链接 下载dll的zip文件 2.解压并放到文件夹 将压缩包内的文件解压&#xff0c;放到C://sqlite下 3.编辑环境变量 添加到系统变量的path中 4.验证 打开命令提示符&#xff0c;输入 sqlite3有结果就行