[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
  十多年没碰这些集合符号了,都有点忘记了这些符号的含义,楼主最好能在顶楼说一下各种符号的具体含义,比如我对 [20,30] 和 [20-30] 之间的差别都不甚了解。
  另,这些集合中是否可能存在 (20,30) 这种不包含边界数值的情形?请一并明示。
尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

  尝试着用纯批处理写了段代码。

  思路:
  1、把每个集合展开,列举集合中的每一个数,分别放入临时文件A.txt和B.txt,并求出每一集合中的最大数值max_A和max_B;
  2、求合集时:
    ① 先把展开的数据放入同一临时文件tmpAB.txt,以tmpAB.txt中每行数据为变量名的一部分,对变量 num_%%i 赋值,从而得到变量名合集;
    ② 求出max_A和max_B中的最大值max,然后,检测从1到max的变量 num_%%i 是否已被赋值,把已经赋值过的数字输出到临时文件tmpAB↑.txt,从而得到升序排列的A和B的交集数据文本;
    ③ 读取tmpAB↑.txt中的数据,按照格式输出A和B的和集表达式;
  3、求A交非B的交集时:
    ① 读取B.txt,对每一行数据赋值,赋值方法同第2点第②小点,然后,从1到max_B列举数值,把那些没有赋值过的数据输出到临时文件 —B.txt ;
    ② 用 findstr /beg:—B.txt A.txt 得到按照升序排列的A交非B的数据文本 tmpA—B↑.txt
    ③ 按照格式输出交集表达式

  使用限制:
  1、应为使用了 set /a 操作,可处理的数值范围为 1~2^32-1;
  2、因为通过判断变量是否被赋值来排序,而系统有变量名个数的限制,从而导致实际能检测到的数值范围进一步缩小,具体范围尚未测试出来。

  代码:
  1. @echo off
  2. set A={1,[3,6],10,[20,30],[32,60],[200,3000],5000,[6000,8000],9000,9500}
  3. set B={2,5,31,[300,500],[8000,9000],9500}
  4. md tmp 2>nul
  5. pushd tmp 2>nul||exit
  6. setlocal enabledelayedexpansion
  7. echo %time%
  8. call :expand_num A %A:~1,-1%
  9. call :expand_num B %B:~1,-1%
  10. set /p=A∪B={<nul
  11. call :A∪B A B
  12. :—B
  13. :: 生成非B集合数据文本
  14. for /f "delims==" %%i in ('set num_ 2^>nul') do set %%i=
  15. for /f %%i in (B.txt) do set num_%%i=0
  16. (for /l %%i in (1,1,%max_B%) do (
  17.     if not defined num_%%i echo %%i
  18. ))>—B.txt
  19. findstr /beg:—B.txt A.txt>tmpA—B↑.txt
  20. set /p=A交非B={<nul
  21. call :format_str A —B
  22. popd
  23. pause
  24. exit
  25. :A∪B
  26. :: 合并两文本,对每个数值赋值,然后从1开始检测哪些数值已经被赋值,由小到大写入临时文件
  27. copy %1.txt+%2.txt tmp%1%2.txt>nul
  28. if %max_A% gtr %max_B% (
  29.     set max=%max_A%
  30. ) else set max=%max_B%
  31. for /f "delims==" %%i in ('set num_ 2^>nul') do set %%i=
  32. for /f %%i in (tmp%1%2.txt) do set num_%%i=0
  33. (for /l %%i in (1,1,%max%) do (
  34.     if defined num_%%i echo %%i
  35. ))>tmp%1%2↑.txt
  36. :format_str
  37. :: 检测相邻两行数值的差值是否为1,若为1,则是连续数;若不为1,则数值不连续
  38. set /p num=<tmp%1%2↑.txt
  39. set begin=
  40. for /f %%i in (tmp%1%2↑.txt) do (
  41.     if %%i neq !num! (
  42.         set /a diff=%%i-!num!
  43.         call :judge_range %%i !num! !diff!
  44.     )
  45.     set num=%%i
  46. )
  47. if defined begin (
  48.     set /p=[!begin!,%num%]}<nul
  49. ) else set /p=%num%}<nul
  50. echo,&echo %time%
  51. goto :eof
  52. :expand_num
  53. :: 把字符串格式化,然后按顺序展开
  54. set begin=&set end=
  55. (for /f "tokens=1*" %%i in ("%*") do (
  56.     for %%x in (%%j) do (
  57.         set str=%%x
  58.         if "!str:~0,1!"=="[" (
  59.             set num_begin=!str:~1!&set begin=yes
  60.         )
  61.         if "!str:~-1!"=="]" (
  62.             set num_end=!str:~0,-1!&set end=yes
  63.         )
  64.         if not defined begin echo %%x
  65.         if defined end (
  66.             for /l %%y in (!num_begin!,1,!num_end!) do echo %%y
  67.             set begin=&set end=
  68.         )
  69.         set max_%1=%%x
  70.     )
  71. ))>%1.txt
  72. goto :eof
  73. :judge_range
  74. :: 判断数值范围的临界值,根据临界值输出格式化字符串
  75. if %3 equ 1 (
  76.     if not defined begin set begin=%2
  77. ) else (
  78.     if defined begin (
  79.         set /p=[!begin!,%2],<nul
  80.         set begin=
  81.     ) else (
  82.         set /p=%2,<nul
  83.     )
  84. )
  85. goto :eof
复制代码
  由于有大量的 set /a 操作,速度比较慢,当数据量增大时尤其明显,暂时只把功能完成,尚未优化。
1

评分人数

尺有所短寸有所长,学好批处理没商量;
考虑问题复杂化,解决问题简洁化。

心在天山,身老沧州。

TOP

返回列表