一、前言

在学习一些项目代码时,尤其涉及到命令行传参的代码,经常遇到getopt相关的函数,对这一类函数可以说是既陌生又熟悉。陌生是因为不知道它是干啥的,熟悉呢,是因为经常遇到。于是乎在追踪了多天ipsec配置文件解析流程之后,准备学习下这一类命令行解析利器。

这么多命令行参数,需要解析,想象都让人头大,如果再没有一个好的解析方式,那就雪上加霜了。辛亏有了一类命令行解析函数,可以让这些解析操作变得容易一点点。下面就简单的介绍下这一类函数,主要有getopt、getopt_long、getopt_long_only。

Man 手册信息如下:

NAME
       getopt, getopt_long, getopt_long_only, optarg, optind, opterr, optopt - Parse command-line options SYNOPSIS
       #include <unistd.h>
       int getopt(int argc, char * const argv[],
                  const char *optstring);        extern char *optarg;
       extern int optind, opterr, optopt;        #include <getopt.h>
       int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);        int getopt_long_only(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);

先从最简单的,最基本的getopt函数开始。然后再介绍增强版的getopt_long函数。

二、getopt函数

2.1 函数简介:

int getopt(int argc, char * const argv[], const char *optstring);

各项参数解释如下:

函数功能

用来解析命令行选项参数,只适用于短选项:-d /root; 不能解析长选项--arch, --help等

Argc

通过命令行传给main函数参数的个数

argv

通过命令行传给main函数参数组成的字符串指针数组

optstring

选项字符串。用来告诉getopt可以解析哪些选项,哪些选项需要参数以及函数返回值等(字符后面紧跟一个冒号则需要参数,而两个则表示参数可选)

返回值

如果成功返回选项字母;命令行解析完毕返回-1;如果选项未定义,则提示错误信息,并返回'?';如果参数缺失,第一个字符是':'则返回':', 否则返回'?'

对于optstring字符串格式做一个简单说明:

单个字符,表示没有参数

单个字符紧跟1个冒号,表示必须有参数,格式:-d xxx或者-dxxx

单个字符紧跟2个冒号,表示参数可选,格式:-dxxx

Char *optstring="ab:c::";

说明:此选项指定了三个选项,分别为'a'、'b'、'c'。其中

a选项无需参数,格式:-a即可

b选项必须有参数,格式:-d xxx

c选项参数可选,格式:-c ooo

在此类函数中,需要几个重要的变量共同配合才能完成命令行参数解析工作:

变量名称

作用

Char *optarg

指向当前选项参数的指针

Int optind

用来记录当前已遍历选项的索引,方便下次调用时直接找到下一个选项

Int opterr

正常情况,解析失败会有错误信息,如果不需要此错误信息,将opterr置0即可

Int optopt

最后一个未知选项

2.2 举例说明:

代码如下:


/*************************************************************************
> File Name: getopt.c
> Author: Toney
> Mail: vip_13031075266@163.com
> Created Time: 2021年01月30日 星期六 21时50分45秒
************************************************************************/ #include <stdio.h>
#include <unistd.h>
#include <getopt.h> void main(int argc, char **argv)
{
int flags, opt; while((opt = getopt(argc, argv, "ab:c::")) != -1){ switch(opt){
case 'a':
printf("Input %d parameter is -a=%s\n", optind, optarg);
break;
case 'b':
printf("Input %d parameter is -b=%s\n", optind, optarg);
break;
case 'c':
printf("Input %d parameter is -c=%s\n", optind, optarg);
break;
default:
printf("Not match!!!");
}
} return ; }

三、getopt_long函数

3.1 函数简介:

int getopt_long(int argc, char * const argv[], const char *optstring,const struct option *longopts, int *longindex);

各项参数解释如下:

函数功能

用来解析命令行选项参数,除了getopt函数支持的短选项,还支持长选项,如--help, --prefix

Argc

通过命令行传给main函数参数的个数

argv

通过命令行传给main函数参数组成的字符串指针数组

optstring

选项字符串。用来告诉getopt可以解析哪些选项,哪些选项需要参数以及函数返回值等(字符后面紧跟一个冒号则需要参数,而两个则表示参数可选)

longopts

长选项参数的名称、属性、以及解析后的返回值等结构信息

longindex

用来记录解析到的当前长选项的索引,也就是longopts的下标。

返回值

对于短选项,返回值同getopt函数;对于长选项,如果flag是NULL,返回val,否则返回0;对于错误情况返回值同getopt函数

Struct option结构体:

struct option {
const char  *name;       /* 参数名称 */
int          has_arg;    /* 指明是否带有参数 */
int          *flag;      /* flag=NULL时,返回value;不为空时,*flag=val,返回0 */
int          val;        /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值 */
};

其中has_arg类型取值有如下几种:

No_argument

不需要参数

Required_argument

必须带参数

Optional_argument

参数可选

在此类函数中,需要几个重要的变量共同配合才能完成命令行参数解析工作:

变量名称

作用

Char *optarg

指向当前选项参数的指针

Int optind

用来记录当前已遍历选项的索引,方便下次调用时直接找到下一个选项

Int opterr

正常情况,解析失败会有错误信息,如果不需要此错误信息,将opterr置0即可

Int optopt

最后一个未知选项

3.2 ipsec项目中的一个例子:

先看看在openswan源码中,有关使用getopt_long解析命令行的一个例子(各位把住坐稳了):

static const struct option long_opts[] = {
# define OO OPTION_OFFSET
/* name, has_arg, flag, val */ { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
{ "optionsfrom", required_argument, NULL, '+' },
{ "label", required_argument, NULL, 'l' }, { "ctlbase", required_argument, NULL, OPT_CTLBASE + OO },
{ "name", required_argument, NULL, OPT_NAME + OO },
{ "connalias", required_argument, NULL, OPT_CONNALIAS + OO }, { "keyid", required_argument, NULL, OPT_KEYID + OO },
{ "addkey", no_argument, NULL, OPT_ADDKEY + OO },
{ "pubkeyrsa", required_argument, NULL, OPT_PUBKEYRSA + OO }, { "myid", required_argument, NULL, OPT_MYID + OO }, { "route", no_argument, NULL, OPT_ROUTE + OO },
{ "unroute", no_argument, NULL, OPT_UNROUTE + OO }, { "initiate", no_argument, NULL, OPT_INITIATE + OO },
{ "terminate", no_argument, NULL, OPT_TERMINATE + OO },
{ "delete", no_argument, NULL, OPT_DELETE + OO },
{ "deletestate", required_argument, NULL, OPT_DELETESTATE + OO + NUMERIC_ARG },
{ "crash", required_argument, NULL, OPT_DELETECRASH + OO },
{ "listen", no_argument, NULL, OPT_LISTEN + OO },
{ "unlisten", no_argument, NULL, OPT_UNLISTEN + OO },
{ "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO }, { "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO },
{ "rereadcacerts", no_argument, NULL, OPT_REREADCACERTS + OO },
{ "rereadaacerts", no_argument, NULL, OPT_REREADAACERTS + OO },
{ "rereadocspcerts", no_argument, NULL, OPT_REREADOCSPCERTS + OO },
{ "rereadacerts", no_argument, NULL, OPT_REREADACERTS + OO }, { "rereadcrls", no_argument, NULL, OPT_REREADCRLS + OO },
{ "rereadall", no_argument, NULL, OPT_REREADALL + OO },
{ "status", no_argument, NULL, OPT_STATUS + OO },
{ "shutdown", no_argument, NULL, OPT_SHUTDOWN + OO },
{ "xauthname", required_argument, NULL, OPT_XAUTHNAME + OO },
{ "xauthuser", required_argument, NULL, OPT_XAUTHNAME + OO },
{ "xauthpass", required_argument, NULL, OPT_XAUTHPASS + OO },
{ "tpmeval", required_argument, NULL, OPT_TPMEVAL + OO }, { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO },
{ "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO }, { "asynchronous", no_argument, NULL, OPT_ASYNC + OO }, /* list options */ { "utc", no_argument, NULL, LST_UTC + OO },
{ "checkpubkeys", no_argument, NULL, LST_CHECKPUBKEYS + OO },
{ "listpubkeys", no_argument, NULL, LST_PUBKEYS + OO },
{ "listcerts", no_argument, NULL, LST_CERTS + OO },
{ "listcacerts", no_argument, NULL, LST_CACERTS + OO },
{ "listacerts", no_argument, NULL, LST_ACERTS + OO },
{ "listaacerts", no_argument, NULL, LST_AACERTS + OO },
{ "listocspcerts", no_argument, NULL, LST_OCSPCERTS + OO },
{ "listgroups", no_argument, NULL, LST_GROUPS + OO },
{ "listcrls", no_argument, NULL, LST_CRLS + OO },
{ "listocsp", no_argument, NULL, LST_OCSP + OO },
{ "listpsks", no_argument, NULL, LST_PSKS + OO },
{ "listevents", no_argument, NULL, LST_EVENTS + OO },
{ "listpairs", no_argument, NULL, LST_HOSTPAIRS + OO },
{ "listhostpairs", no_argument, NULL, LST_HOSTPAIRS + OO },
{ "listall", no_argument, NULL, LST_ALL + OO }, /* options for an end description */ { "host", required_argument, NULL, END_HOST + OO },
{ "id", required_argument, NULL, END_ID + OO },
{ "cert", required_argument, NULL, END_CERT + OO },
{ "ca", required_argument, NULL, END_CA + OO },
{ "groups", required_argument, NULL, END_GROUPS + OO },
{ "ikeport", required_argument, NULL, END_IKEPORT + OO + NUMERIC_ARG },
{ "nexthop", required_argument, NULL, END_NEXTHOP + OO },
{ "client", required_argument, NULL, END_CLIENT + OO },
{ "clientwithin", required_argument, NULL, END_CLIENTWITHIN + OO },
{ "clientprotoport", required_argument, NULL, END_CLIENTPROTOPORT + OO },
{ "dnskeyondemand", no_argument, NULL, END_DNSKEYONDEMAND + OO },
{ "srcip", required_argument, NULL, END_SRCIP + OO },
{ "updown", required_argument, NULL, END_UPDOWN + OO },
{ "tundev", required_argument, NULL, END_TUNDEV + OO + NUMERIC_ARG }, /* options for a connection description */ { "to", no_argument, NULL, CD_TO + OO }, { "psk", no_argument, NULL, CD_PSK + OO },
{ "rsasig", no_argument, NULL, CD_RSASIG + OO }, { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
{ "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
{ "compress", no_argument, NULL, CD_COMPRESS + OO },
{ "overlapip", no_argument, NULL, CD_OVERLAPIP + OO },
{ "tunnel", no_argument, NULL, CD_TUNNEL + OO },
{ "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO },
{ "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO },
{ "pfs", no_argument, NULL, CD_PFS + OO },
{ "sha2_truncbug", no_argument, NULL, CD_SHA2_TRUNCBUG + OO },
{ "aggrmode", no_argument, NULL, CD_AGGRESSIVE + OO },
{ "disablearrivalcheck", no_argument, NULL, CD_DISABLEARRIVALCHECK + OO },
{ "initiateontraffic", no_argument, NULL
, CD_SHUNT0 + (POLICY_SHUNT_TRAP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
{ "pass", no_argument, NULL
, CD_SHUNT0 + (POLICY_SHUNT_PASS >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
{ "drop", no_argument, NULL
, CD_SHUNT0 + (POLICY_SHUNT_DROP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
{ "reject", no_argument, NULL
, CD_SHUNT0 + (POLICY_SHUNT_REJECT >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
{ "failnone", no_argument, NULL
, CD_FAIL0 + (POLICY_FAIL_NONE >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
{ "failpass", no_argument, NULL
, CD_FAIL0 + (POLICY_FAIL_PASS >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
{ "faildrop", no_argument, NULL
, CD_FAIL0 + (POLICY_FAIL_DROP >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
{ "failreject", no_argument, NULL
, CD_FAIL0 + (POLICY_FAIL_REJECT >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
{ "dontrekey", no_argument, NULL, CD_DONT_REKEY + OO },
{ "forceencaps", no_argument, NULL, CD_FORCEENCAPS + OO },
{ "dpddelay", required_argument, NULL, CD_DPDDELAY + OO + NUMERIC_ARG },
{ "dpdtimeout", required_argument, NULL, CD_DPDTIMEOUT + OO + NUMERIC_ARG },
{ "dpdaction", required_argument, NULL, CD_DPDACTION + OO },
#ifdef XAUTH
{ "xauth", no_argument, NULL, END_XAUTHSERVER + OO },
{ "xauthserver", no_argument, NULL, END_XAUTHSERVER + OO },
{ "xauthclient", no_argument, NULL, END_XAUTHCLIENT + OO },
#endif
#ifdef MODECFG
{ "modecfgpull", no_argument, NULL, CD_MODECFGPULL + OO },
{ "modecfgserver", no_argument, NULL, END_MODECFGSERVER + OO },
{ "modecfgclient", no_argument, NULL, END_MODECFGCLIENT + OO },
#ifdef MODECFG_DNSWINS
{ "modecfgdns1", required_argument, NULL, CD_MODECFGDNS1 + OO },
{ "modecfgdns2", required_argument, NULL, CD_MODECFGDNS2 + OO },
{ "modecfgwins1", required_argument, NULL, CD_MODECFGWINS1 + OO },
{ "modecfgwins2", required_argument, NULL, CD_MODECFGWINS2 + OO },
{ "modeconfigserver", no_argument, NULL, END_MODECFGSERVER + OO },
{ "modeconfigclient", no_argument, NULL, END_MODECFGCLIENT + OO },
#endif
#endif
{ "metric", required_argument, NULL, CD_METRIC + OO + NUMERIC_ARG },
{ "mtu", required_argument, NULL, CD_CONNMTU + OO + NUMERIC_ARG },
{ "sendcert", required_argument, NULL, END_SENDCERT + OO },
{ "certtype", required_argument, NULL, END_CERTTYPE + OO + NUMERIC_ARG },
{ "ipv4", no_argument, NULL, CD_CONNIPV4 + OO },
{ "ipv6", no_argument, NULL, CD_CONNIPV6 + OO }, { "ikelifetime", required_argument, NULL, CD_IKELIFETIME + OO + NUMERIC_ARG },
{ "ipseclifetime", required_argument, NULL, CD_IPSECLIFETIME + OO + NUMERIC_ARG },
{ "rekeymargin", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },
{ "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG }, /* OBSOLETE */
{ "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
{ "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
{ "ike", required_argument, NULL, CD_IKE + OO },
{ "ikealg", required_argument, NULL, CD_IKE + OO },
{ "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO },
{ "esp", required_argument, NULL, CD_ESP + OO },
{ "remote_peer_type", required_argument, NULL, CD_REMOTEPEERTYPE + OO},
#ifdef HAVE_NM
{ "nm_configured", no_argument, NULL, CD_NMCONFIGURED + OO},
#endif
#ifdef HAVE_LABELED_IPSEC
{ "loopback", no_argument, NULL, CD_LOOPBACK + OO},
{ "labeledipsec", no_argument, NULL, CD_LABELED_IPSEC + OO},
{ "policylabel", required_argument, NULL, CD_POLICY_LABEL + OO },
#endif
#ifdef DEBUG
{ "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
{ "debug-all", no_argument, NULL, DBGOPT_ALL + OO },
{ "debug-raw", no_argument, NULL, DBGOPT_RAW + OO },
{ "debug-crypt", no_argument, NULL, DBGOPT_CRYPT + OO },
{ "debug-parsing", no_argument, NULL, DBGOPT_PARSING + OO },
{ "debug-emitting", no_argument, NULL, DBGOPT_EMITTING + OO },
{ "debug-control", no_argument, NULL, DBGOPT_CONTROL + OO },
{ "debug-lifecycle", no_argument, NULL, DBGOPT_LIFECYCLE + OO },
{ "debug-klips", no_argument, NULL, DBGOPT_KLIPS + OO },
{ "debug-netkey", no_argument, NULL, DBGOPT_KLIPS + OO },
{ "debug-xfrm", no_argument, NULL, DBGOPT_KLIPS + OO },
{ "debug-dns", no_argument, NULL, DBGOPT_DNS + OO },
{ "debug-oppo", no_argument, NULL, DBGOPT_OPPO + OO },
{ "debug-oppoinfo", no_argument, NULL, DBGOPT_OPPOINFO + OO },
{ "debug-whackwatch", no_argument, NULL, DBGOPT_WHACKWATCH + OO },
{ "debug-controlmore", no_argument, NULL, DBGOPT_CONTROLMORE + OO },
{ "debug-pfkey", no_argument, NULL, DBGOPT_PFKEY + OO },
{ "debug-nattraversal", no_argument, NULL, DBGOPT_NATT + OO },
{ "debug-natt", no_argument, NULL, DBGOPT_NATT + OO },
{ "debug-nat_t", no_argument, NULL, DBGOPT_NATT + OO },
{ "debug-nat-t", no_argument, NULL, DBGOPT_NATT + OO },
{ "debug-x509", no_argument, NULL, DBGOPT_X509 + OO },
{ "debug-dpd", no_argument, NULL, DBGOPT_DPD + OO },
{ "debug-private", no_argument, NULL, DBGOPT_PRIVATE + OO }, { "impair-delay-adns-key-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER + OO },
{ "impair-delay-adns-txt-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER + OO },
{ "impair-bust-mi2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MI2 + OO },
{ "impair-bust-mr2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MR2 + OO },
{ "impair-sa-fail", no_argument, NULL, DBGOPT_IMPAIR_SA_CREATION + OO },
{ "impair-die-oninfo", no_argument, NULL, DBGOPT_IMPAIR_DIE_ONINFO + OO },
{ "impair-jacob-two-two", no_argument, NULL, DBGOPT_IMPAIR_JACOB_TWO_TWO + OO },
{ "impair-major-version-bump", no_argument, NULL, DBGOPT_IMPAIR_MAJOR_VERSION_BUMP + OO },
{ "impair-minor-version-bump", no_argument, NULL, DBGOPT_IMPAIR_MINOR_VERSION_BUMP + OO },
{ "impair-retransmits", no_argument, NULL, DBGOPT_IMPAIR_RETRANSMITS + OO },
{ "impair-send-bogus-isakmp-flag", no_argument, NULL, DBGOPT_IMPAIR_SEND_BOGUS_ISAKMP_FLAG + OO },
{ "whackrecord", required_argument, NULL, OPT_WHACKRECORD + OO},
{ "whackstoprecord", no_argument, NULL, OPT_WHACKSTOPRECORD + OO},
#endif
# undef OO
{ 0,0,0,0 }
};

这是whack命令解析时的一个结构信息,可以想象它的配置命令是有多少,而具体实现差不多800行左右的C代码。这里需要注意的是:struct option结构中的val取值通常是单个字符或者数字。由于单字符数量有限,参数比较少时可以使用字符,但是如果像上面辣么多参数,通常采用枚举类型,方便扩展。

四、getopt_long_only函数

getopt_long_only 函数与 getopt_long 函数使用相同的参数表,在功能上基本一致,只是 getopt_long 只将 --name 当作长参数,但 getopt_long_only 会将 --name 和 -name 两种选项都当作长参数来匹配。getopt_long_only 如果选项 -name 不能在 longopts 中匹配,但能匹配一个短选项,它就会解析为短选项。

命令行解析函数:getopt_long、getopt的更多相关文章

  1. C语言命令行解析函数:getopt/getopt_long

    命令行工具下的参数选项有两种,长选项和短选项.短选项以-开头,后面跟单个字母:长选项以--开头,后面可跟多个字母. 一. getopt() 1.功能:解析命令行短选项参数 2.函数原型: #inclu ...

  2. 命令行解析函数:getopt/getopt_long

    参考: http://blog.csdn.net/zhangyang0402/article/details/5671410 http://www.cnblogs.com/gnuhpc/archive ...

  3. 【C】命令行参数解析——getopt、getopt_long及getopt_long_only

    前言 在linux下学习开源代码Webbench,遇到get_long等函数的用法,一时有点懵,故想深入了解这类命令行解析函数,并记此博文. 1.getopt getopt主要用来处理短命令行选项,例 ...

  4. [转]Python 命令行参数和getopt模块详解

    FROM : http://www.tuicool.com/articles/jaqQvq 有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Pyt ...

  5. Python 命令行参数和getopt模块详解

    有时候我们需要写一些脚本处理一些任务,这时候往往需要提供一些命令行参数,根据不同参数进行不同的处理,在Python里,命令行的参数和C语言很类似(因为标准Python是用C语言实现的).在C语言里,m ...

  6. linux 中解析命令行参数(getopt_long用法)

    linux 中解析命令行参数(getopt_long用法) http://www.educity.cn/linux/518242.html 详细解析命令行的getopt_long()函数 http:/ ...

  7. shell 命令行参数(getopt和getopts)

    getopt 命令 使用getopt命令,可以解析任何命令行选项和参数,但是用法比较复杂.getopt的命令用法如下: $ getopt --help 用法: getopt optstring par ...

  8. 命令行参数处理-getopt()和getopt_long()

    在实际编程当中,自己编写代码处理命令行参数是比较麻烦且易出错的.一般我们会直接使用getopt()和getopt_long()函数,下文将介绍具体的使用方法. getopt() getopt()用于处 ...

  9. 命令行解析getopt_long

    getopt_long函数可以轻松的解析main函数的命令行参数. int getopt_long(int argc,char * const argv[],const char *optstring ...

随机推荐

  1. 学习笔记-CCS-MSP430F5529[快速入门篇二]

    由于2021的全国电赛延期了,从今天开始打算好好整理一下使用CCS编程的经验,本篇笔记会好好整理一下我备赛期间用CCS写的程序,包括外部中断,定时器部分的定时中断,定时器输入捕获,PWM波输出,UAR ...

  2. YOLO-v4 口罩识别

    YOLO-v4 口罩识别 一.YOLO-v4概念 如果想要了解和认识yolo-v4的基本概念,首先要提的就是它的基础版本yolo-v1,对于yolo来说,最经典的算是yolo-v3.如果想要了解它的由 ...

  3. Netty 源码分析系列(二)Netty 架构设计

    前言 上一篇文章,我们对 Netty做了一个基本的概述,知道什么是Netty以及Netty的简单应用. Netty 源码分析系列(一)Netty 概述 本篇文章我们就来说说Netty的架构设计,解密高 ...

  4. 单片机学习(一)项目的建立和vscode代码编辑环境的设置

    目录 Keil项目的建立 使用vscode进行开发 工欲善其事必先利其器,因此我们先搭建一个比较舒服的开发环境. Keil项目的建立 打开Keil软件点击Project/New uVision Pro ...

  5. SQL语句(四)联表查询

    目录 一.关联查询的分类 按年代分 按功能分 二.sql92语法的连接 语法 1. 简单应用 2. 为表起别名 3. 加入筛选 4. 加入分组 5. 三表连接 6. 非等值连接 7. 自连接 三.sq ...

  6. 【学习笔记】Expression表达式目录树

    Expression表达式目录树:一个能拼装能解析的数据结构,语法树. 一.手动拼装表达式目录树 示例1: /// <summary> /// 展示表达式树,协助用的 /// 编译lamb ...

  7. WPF 线程开启等待动画

    public static Dictionary<string, object> Dic = new Dictionary<string, object>();//定义一个字典 ...

  8. tomcat 配置http跳转https

    web.xml增加配置 <security-constraint> <web-resource-collection > <web-resource-name >S ...

  9. AI+云原生,把卫星遥感虐的死去活来

    摘要:遥感影像,作为地球自拍照,能够从更广阔的视角,为人们提供更多维度的辅助信息,来帮助人类感知自然资源.农林水利.交通灾害等多领域信息. 本文分享自华为云社区<AI+云原生,把卫星遥感虐的死去 ...

  10. MySQL-13-日志管理

    常用日志参数 经常用到的有错误.快慢查询.二进制等日志 错误日志 1 作用 记录启动\关闭\日常运行过程中,状态信息,警告,错误,排查MySQL运行过程的故障 2 错误日志配置 默认就是开启的: /数 ...