[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

choice.exe高仿版

本帖最后由 happy886rr 于 2016-12-6 16:21 编辑

[2016/12/06]修复一处设计错误。

由于微软的choice.exe无法实现小于1秒的延时,遂用C语言高仿了choice.exe,功能、性能与微软原版毫无差别,但支持0.0几秒延迟,需要的可以自行编译下面的源码。
  1. /*
  2. CONSOLE KEY TOOL, COPYRIGHT@2016~2018 BY HAPPY
  3. High imitation CHOICE.EXE
  4. VERSION 1.0
  5. */
  6. #include <stdio.h>
  7. #include <Windows.h>
  8. #include <conio.h>
  9. #include <time.h>
  10. #define HELP_INFORMATION "\
  11.   CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]\n\n\
  12.   Description:\n\
  13.      This tool allows users to select one item from a list \n\
  14.      of choices and returns the index of the selected choice.\n\n\
  15.   Parameter List:\n\
  16.      /C    choices       Specifies the list of choices to be created.\n\
  17.                          Default list is \"YN\".\n\n\
  18.      /N                  Hides the list of choices in the prompt.\n\
  19.                          The message before the prompt is displayed\n\
  20.                          and the choices are still enabled.\n\n\
  21.      /CS                 Enables case-sensitive choices to be selected.\n\
  22.                          By default, the utility is case-insensitive.\n\n\
  23.      /T    timeout       The number of seconds to pause before a default \n\
  24.                          choice is made. Acceptable values are from 0.000 to \n\
  25.                          9999... If 0 is specified, there will be no pause \n\
  26.                          and the default choice is selected.\n\n\
  27.      /D    choice        Specifies the default choice after nnnn seconds.\n\
  28.                          Character must be in the set of choices specified\n\
  29.                          by /C option and must also specify nnnn with /T.\n\n\
  30.      /M    text          Specifies the message to be displayed before \n\
  31.                          the prompt. If not specified, the utility \n\
  32.                          displays only a prompt.\n\n\
  33.      /?                  Displays this help message.\n\n\
  34.      NOTE:\n\
  35.      The ERRORLEVEL environment variable is set to the index of the\n\
  36.      key that was selected from the set of choices. The first choice\n\
  37.      listed returns a value of 1, the second a value of 2, and so on.\n\
  38.      If the user presses a key that is not a valid choice, the tool \n\
  39.      sounds a warning beep. If tool detects an error condition,\n\
  40.      it returns an ERRORLEVEL value of 255. If the user presses \n\
  41.      CTRL+BREAK or CTRL+C, the tool returns an ERRORLEVEL value\n\
  42.      of 0. When you use ERRORLEVEL parameters in a batch program, list\n\
  43.      them in decreasing order.\n\n\
  44.   Examples:\n\
  45.      CHOICE /?\n\
  46.      CHOICE /C YNC /M \"Press Y for Yes, N for No or C for Cancel.\"\n\
  47.      CHOICE /T 10 /C ync /CS /D y \n\
  48.      CHOICE /C ab /M \"Select a for option 1 and b for option 2.\"\n\
  49.      CHOICE /C ab /N /M \"Select a for option 1 and b for option 2.\"\n"
  50. /***************功能函数群***************/
  51. //帮助信息
  52. void HelpInfomation(int code)
  53. {
  54.     fputs(HELP_INFORMATION, stdout);
  55.     exit(code);
  56. }
  57. //核心函数
  58. int ChoiceCore(const unsigned char FLAG, char* list, char* text, clock_t timeout, unsigned char deft)
  59. {
  60.     unsigned char KEY_V;
  61.     char* p;
  62.     //选择列表为空则退出
  63.     if(list==NULL)
  64.     {
  65.         fputs("Missing choice list\n", stdout);
  66.         exit(255);
  67.     }
  68.     //警告/T开关和/D开关必须同时指定,或同时未指定
  69.     if((((FLAG&0x04)>>2)^((FLAG&0x08)>>3))==0x01)
  70.     {
  71.         fputs("The /T swith and /D swith must be specified at the same time,\nType \"CHOICE /?\" for usage.\n", stdout);
  72.         exit(255);
  73.     }
  74.     //显示/M开关之后的消息
  75.     if(text!=NULL)
  76.     {
  77.         fputs(text, stdout);
  78.         fputc( ' ', stdout);
  79.     }
  80.     //如未开启CS开关,则将选择列表转为大写
  81.     if((FLAG&0x01) ==0x00)
  82.     {
  83.         list=strupr(list);
  84.         deft=('a'<=deft && deft<='z')?deft-32:deft;
  85.     }
  86.     //如未开启N开关,则显示/M之后的消息
  87.     if((FLAG&0x02) ==0x00)
  88.     {
  89.         p=(char*)list;
  90.         fputc('[', stdout);
  91.         fputc( *p, stdout);
  92.         while( *(++p) !='\0')
  93.         {
  94.             fputc(',', stdout);
  95.             fputc( *p, stdout);
  96.         }
  97.         fputs("]?", stdout);
  98.     }
  99.     clock_t start=clock();
  100.     do
  101.     {
  102.         if(kbhit())
  103.         {
  104.             KEY_V=getch();
  105.             p=(char*)list;
  106.             while(*p!='\0')
  107.             {
  108.                 if(
  109.                     ((FLAG&0x01)==0x00 && (*p==KEY_V-32)) ||
  110.                     (*p ==KEY_V)
  111.                 )
  112.                 {
  113.                     fputc(  *p, stdout);
  114.                     fputc('\n', stdout);
  115.                     return p-list+1;
  116.                 }
  117.                 p++;
  118.             }
  119.         }
  120.         //缓解CPU占用
  121.         Sleep(1);
  122.     }
  123.     while(clock()-start <timeout || timeout==-255);
  124.     //超时则抛出/D开关指定的默认选项
  125.     fputc(deft, stdout);
  126.     fputc('\n', stdout);
  127.     p=(char*)list;
  128.     while(*p!='\0'){
  129.         if(*p==deft){break;}
  130.         p++;
  131.     }
  132.     if(*p=='\0'){return 255;}
  133.     return p-list+1;
  134. }
  135. /*************MAIN主函数入口*************/
  136. int main(int argc, char** argv)
  137. {
  138.     unsigned char FLAG=0;
  139.     unsigned char deft='Y';
  140.     clock_t timeout=(clock_t)(-255);
  141.     char* list="YN";
  142.     char* text=NULL;
  143.     int i=0;
  144.     while(++i<argc)
  145.     {
  146.         if(argv[i][0]!='/')
  147.         {
  148.             continue;
  149.         }
  150.         else if(argv[i][1]=='?')
  151.         {
  152.             //显示帮助消息
  153.             HelpInfomation(255);
  154.         }
  155.         else if(
  156.             (argv[i][1]=='C'||argv[i][1]=='c') &&
  157.             (argv[i][2]=='S'||argv[i][2]=='s')
  158.         )
  159.         {
  160.             //区分大写小
  161.             FLAG|=0x01;
  162.             continue;
  163.         }
  164.         else if(argv[i][1]=='N'||argv[i][1]=='n')
  165.         {
  166.             //隐藏选项列表
  167.             FLAG|=0x02;
  168.             continue;
  169.         }
  170.         else if(i+1 >=argc ||argv[i+1][1]=='/')
  171.         {
  172.             fputs("Missing parameters\n", stdout);
  173.             return 255;
  174.         }
  175.         switch(argv[i][1])
  176.         {
  177.             //从选择列表选择一项并返回选项索引
  178.         case 'C':
  179.         case 'c':
  180.             list=argv[i+1];
  181.             break;
  182.             //做出默认选择之前,暂停的秒数
  183.         case 'T':
  184.         case 't':
  185.             timeout=(clock_t)(atof(argv[i+1])*1000);
  186.             FLAG|=0x04;
  187.             break;
  188.             //在等待...秒之后指定默认选项
  189.         case 'D':
  190.         case 'd':
  191.             deft=(unsigned char)argv[i+1][0];
  192.             FLAG|=0x08;
  193.             break;
  194.             //指定提示之前要显示的消息
  195.         case 'M':
  196.         case 'm':
  197.             text=argv[i+1];
  198.             break;
  199.             //错误反馈
  200.         default:
  201.             fputs("Error option\n", stdout);
  202.             return 255;
  203.         }
  204.         i++;
  205.     }
  206.     //调用核心函数
  207.     return ChoiceCore(FLAG, list, text, timeout, deft);
  208. }
复制代码
使用说明:
  1. -----------------------------------------------------------------------------
  2. CHOICE [/C choices] [/N] [/CS] [/T timeout /D choice] [/M text]
  3. -----------------------------------------------------------------------------
  4. 参数列表:
  5.    /C    choices        "YN"。
  6.    /N                  在提示符中隐藏选项列表。提示前面的消息得到显示,
  7.                        选项依旧处于启用状态。
  8.    /CS                 允许选择分大小写的选项。在默认情况下,这个工具
  9.                        是不分大小写的。
  10.    /T    timeout       做出默认选择之前,暂停的秒数。可接受的值是从0.000
  11.                        到 9999...。如果指定了 0,就不会有暂停,默认选项
  12.                        会得到选择。
  13.    /D    choice        在 nnnn 秒之后指定默认选项。字符必须在用 /C 选
  14.                        项指定的一组选择中; 同时,必须用 /T 指定 nnnn。
  15.    /M    text          指定提示之前要显示的消息。如果没有指定,工具只
  16.                        显示提示。
  17.    /?                  显示此帮助消息。
  18. -----------------------------------------------------------------------------
复制代码
2

评分人数

可以出个跟ms-dos的choice语法一样的
新手上路!

TOP

返回列表