前言 以前写脚本的时候用到过传参:python最简单,直接import argparse。shell中使用$#表示传递到脚本的参数个数,用$*表示以一个单字符串显示所有向脚本传递的参数,如”$*“用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数。bat脚本传参和shell类似,%#表示传递到脚本的参数个数,%*表示参数字符串,*可以是数字。在C语言中可以使用getopt,它是一个标准的C库函数,用于解析命令行参数。它可以帮助你处理短选项(-h)和长选项(—help)。
今天学习 adpcm-xq  看到一个C代码直接用指针操作argv,如*++*argv,能差不多看懂,现在回家再来理一下。
代码片段 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 int  main  (argc, argv)  int  argc; char  **argv;{     int  lookahead = 3 , flags = ADPCM_FLAG_NOISE_SHAPING, blocksize_pow2 = 0 , overwrite = 0 , asked_help = 0 ;     char  *infilename = NULL , *outfilename = NULL ;     FILE *outfile;          encode_only = argc && strstr  (argv [0 ], "encoder" ) && strlen  (strstr  (argv [0 ], "encoder" )) == strlen  ("encoder" );     decode_only = argc && strstr  (argv [0 ], "decoder" ) && strlen  (strstr  (argv [0 ], "decoder" )) == strlen  ("decoder" );          while  (--argc) { #if  defined (_WIN32)         if  ((**++argv == '-'  || **argv == '/' ) && (*argv)[1 ]) #else          if  ((**++argv == '-' ) && (*argv)[1 ]) #endif              while  (*++*argv)                 switch  (**argv) {                     case  '0' : case  '1' : case  '2' :                     case  '3' : case  '4' : case  '5' :                     case  '6' : case  '7' : case  '8' :                         lookahead = **argv - '0' ;                         break ;                     case  'B' : case  'b' :                         blocksize_pow2 = strtol (++*argv, argv, 10 );                         if  (blocksize_pow2 < 8  || blocksize_pow2 > 15 ) {                             fprintf  (stderr , "\nblock size power must be 8 to 15!\n" );                             return  -1 ;                         }                         --*argv;                         break ;                     case  'D' : case  'd' :                         decode_only = 1 ;                         break ;                     case  'E' : case  'e' :                         encode_only = 1 ;                         break ;                     case  'F' : case  'f' :                         flags &= ~ADPCM_FLAG_NOISE_SHAPING;                         break ;                     case  'H' : case  'h' :                         asked_help = 0 ;                         break ;                     case  'Q' : case  'q' :                         verbosity = -1 ;                         break ;                     case  'R' : case  'r' :                         flags |= ADPCM_FLAG_RAW_OUTPUT;                         break ;                     case  'V' : case  'v' :                         verbosity = 1 ;                         break ;                     case  'Y' : case  'y' :                         overwrite = 1 ;                         break ;                     default :                         fprintf  (stderr , "\nillegal option: %c !\n" , **argv);                         return  1 ;                 }         else  if  (!infilename) {             infilename = malloc  (strlen  (*argv) + 10 );             strcpy  (infilename, *argv);         }         else  if  (!outfilename) {             outfilename = malloc  (strlen  (*argv) + 10 );             strcpy  (outfilename, *argv);         }         else  {             fprintf  (stderr , "\nextra unknown argument: %s !\n" , *argv);             return  1 ;         }     }     if  (verbosity >= 0 )         fprintf  (stderr , "%s" , sign_on);     if  (!outfilename || asked_help) {         printf  ("%s" , usage);         return  0 ;     }     if  (!strcmp  (infilename, outfilename)) {         fprintf  (stderr , "can't overwrite input file (specify different/new output file name)\n" );         return  -1 ;     }     if  (!overwrite && (outfile = fopen (outfilename, "r" ))) {         fclose (outfile);         fprintf  (stderr , "output file \"%s\" exists (use -y to overwrite)\n" , outfilename);         return  -1 ;     }     return  adpcm_converter (infilename, outfilename, flags, blocksize_pow2, lookahead); } 
argc argv 知识 C语言中的argc和argv通常用于处理命令行参数。在C程序中,main函数可以接受两个参数,分别是argc(参数计数)和argv(参数向量)。
argc 表示命令行参数的数量(包含命令),它是一个整数。argv 是一个指向字符指针数组的指针,每个指针指向一个字符串,这些字符串是命令行参数的实际内容。argv[0]通常是程序的名称,而argv[1]、argv[2]等则是传递给程序的参数。 
下面是一个简单的例子,展示了如何在C语言中使用argc和argv:
1 2 3 4 5 6 7 8 9 #include  <stdio.h>  int  main (int  argc, char  *argv[])  {    printf ("Number of arguments: %d\n" , argc);          for  (int  i = 0 ; i < argc; i++) {         printf ("Argument %d: %s\n" , i, argv[i]);     }     return  0 ; } 
假设你将上述代码保存在一个名为 example.c 的文件中,然后通过命令行编译并运行:
1 2 gcc example.c -o example ./example arg1 arg2 arg3 
这将输出:
1 2 3 4 5 CopyNumber of arguments:  4 Argument 0:  ./example Argument 1:  arg1 Argument 2:  arg2 Argument 3:  arg3 
这里,argc是4,因为有四个参数(包括程序的名称),而argv包含这四个参数的字符串。
代码分析 接下来我将对代码片段中的argc argv相关代码的逐行分析:
片段1 1 2 3 encode_only = argc && strstr  (argv [0 ], "encoder" ) && strlen  (strstr  (argv [0 ], "encoder" )) == strlen  ("encoder" ); decode_only = argc && strstr  (argv [0 ], "decoder" ) && strlen  (strstr  (argv [0 ], "decoder" )) == strlen  ("decoder" ); 
argc:传递给程序的命令行参数数量;argv[0]:可执行文件的名称(第一个命令行参数)。
char *strstr(const char *haystack, const char *needle); 返回一个指向第一次出现 needle 的指针,如果未找到,则返回 NULL。
strlen用于计算字符串的长度,即字符串中字符的个数,不包括字符串末尾的 null 终止符。
这段代码用于检查可执行文件的名称(从命令行参数 argv[0] 获取)是否以 “encoder” 或 “decoder” 结尾(出现字符通过strstr保证,结尾通过strlen保证)。它根据这些条件设置两个布尔变量 encode_only 和 decode_only。
片段2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16          while  (--argc) { #if  defined (_WIN32)                           if  ((**++argv == '-'  || **argv == '/' ) && (*argv)[1 ]) #else                            if  ((**++argv == '-' ) && (*argv)[1 ]) #endif                                        while  (*++*argv)                                  switch  (**argv) { 
片段3 1 2 3 4 5 case  '0' : case  '1' : case  '2' :case  '3' : case  '4' : case  '5' :case  '6' : case  '7' : case  '8' :    lookahead = **argv - '0' ;	     break ; 
片段4 1 2 3 4 5 6 7 8 9 10 11 12 13 case  'B' : case  'b' :                        blocksize_pow2 = strtol (++*argv, argv, 10 );     if  (blocksize_pow2 < 8  || blocksize_pow2 > 15 ) {         fprintf  (stderr , "\nblock size power must be 8 to 15!\n" );         return  -1 ;     }          --*argv;     break ; 
片段5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 else  if  (!infilename) {         infilename = malloc  (strlen  (*argv) + 10 );     strcpy  (infilename, *argv); } else  if  (!outfilename) {         outfilename = malloc  (strlen  (*argv) + 10 );     strcpy  (outfilename, *argv); } else  {         fprintf  (stderr , "\nextra unknown argument: %s !\n" , *argv);     return  1 ; } 
在没有用解析命令参数库的情况下,竟然可以这样实现一些常见的命令选项功能,佩服!