Board logo

标题: 【练习-030】批处理计算程序运行次数 [打印本页]

作者: batman    时间: 2008-10-23 15:00     标题: 【练习-030】批处理计算程序运行次数

出题目的:
  1、通过解题掌握改写文本技巧
  2、通过解题加强对defined特性的理解
  3、通过解题提高综合运用能力
加分原则:
  1、完善代码加分15分 
  2、其中思路独特基分5分
  3、其中无临时文件基分4分(解题的重要技巧)
  4、其中代码高效基分3分
  5、其中代码简洁基分2分
  6、其中不使用变量延迟基分1分
题目如下:
  要求用纯批处理记录本身运行次数,并在运行时进行提示。如:运行第一次时无提
示,运行第二次时提示已经运行了一次。请在解题时尽量不要使用变量延迟(并不是
不能使用)。
个人请求:
  请版主级会员暂缓贴代码,给新人一段独立思考的时间
总结下:
       通过大家的踊跃跟贴,本题基本得到圆满解决,本人总结了各人的代码分类如下:
       1、通过改写批处理本身来记录运行次数,见4、5、15、28楼的代码,思路都是将运
行次数每次改写到批处理的第一行且均用::来使批处理忽略运行本行代码,这也是大家都认
可的方案;
       2、通过向批处理本身追加数据来记录运行次数,见31、35、36楼的代码,思路都是将
运行次数每次追加到批处理的最后一行,缺点是会让批处理本身越来越大,同时原批处理最
后一行一定要是空行;
       3、通过生成其它文件来记录批处理运行次数,见33楼的代码,思路是将批处理运行的
次数写入其它文件,并每次运行时从记载数据的文件读取一次数据,缺点就是要另处生成临
时文件;
       4、将运行次数记录并写入注册表,在本贴中仍未见相关代码,思路是将批处理支行的
次数当成数据写入注册表的新建项,并在每次运行时从注册表该项中读取一次数据,缺点对
注册表如果不是很熟悉将会造成未知的系统错误。

作者: youxi01    时间: 2008-10-23 15:26

这里我只提示一下 运行 次数记录的一般方法:
1、将次数写入自身文件的最后,当然这种方法不管是读取,还是再更新写入相对都比较麻烦,但数据相对安全一点点。
2、将数据记录到自身文件名,如某文件叫“test.bat”当运行第二次时,就将它的文件名改为test2.bat,依此类推
3、借鉴一般软件的记录方法:
1>写配置文件;
2>将记录写入注册表等
不过第三种方式,似乎楼主有限制....
我不知道这种方式是否属于它的纯批处理的范畴,呵呵。
作者: pusofalse    时间: 2008-10-23 15:36

就这些要求吗?比如说限制代码的最后一行绝对得是空行等。。。
作者: 随风    时间: 2008-10-23 15:51

  1. ::0
  2. @echo off
  3. set /p var=<"%~0"
  4. set "var=%var::=%"
  5. set /a n=var+1
  6. for /f "usebackq delims=" %%a in ("%~0") do (
  7.    if not defined flag (set flag=a&echo ::%n%>"%~0") else echo %%a>>"%~0"
  8. )
  9. ::
  10. if %var% neq 0 echo 已经运行了%var%次
  11. pause
复制代码

[ 本帖最后由 随风 于 2008-10-23 16:27 编辑 ]
作者: terse    时间: 2008-10-23 16:00

  1. :0
  2. @echo off
  3. SET/p N=<%0>nul
  4. if %n::=% gtr 1 echo 已运行 %n::=%次 %~0
  5. set/a n=%n::=%+1
  6. for /f "delims=" %%i in ('type %0') do (
  7.    if not defined str (
  8.    set str=%%i
  9.    >%0 echo :%n%)else >>%0 echo %%i)
  10. ::
  11. echo.&echo.这是第 %n::=%次 到这里 想做什么呢?&echo.&pause
复制代码

[ 本帖最后由 terse 于 2008-10-23 16:35 编辑 ]
作者: terse    时间: 2008-10-23 16:02

出手比我还快  你真快
作者: pusofalse    时间: 2008-10-23 16:11

奇怪。。。到了第九次时出现了奇怪的现象,测试两位的代码:
  1. 'rvar次' 不是内部或外部命令,也不是可运行的程序
  2. 或批处理文件。
  3. 请按任意键继续. . .
复制代码
  1. 已运行 9次 C:\Documents and Settings\Administrator\桌面\terse.bat
  2. '馐堑?10次' 不是内部或外部命令,也不是可运行的程序
  3. 或批处理文件。
  4. 请按任意键继续. . .
复制代码
编码未变,仍旧是ansi。
两位的代码都是同样的问题,唯有第9次不行。。。
作者: 随风    时间: 2008-10-23 16:29     标题: 回复 7楼 的帖子

找到原因了,以改。
加一句注释行就可以了,可能是因为改变了原文件,for下面的第一行无法正确运行。
作者: Batcher    时间: 2008-10-23 16:37

你们这么快就贴代码,摆明了不给新人机会嘛,嘿嘿^_^
作者: terse    时间: 2008-10-23 16:37

看来如随风兄说的  改变了原文件的缘故 序号升一位就有这个问题  FOR前是好的
作者: batman    时间: 2008-10-23 17:03

两位出手不可谓不快,但是否这样等于剥夺了新人们独立思考的机会呢?所以暂时全部
屏蔽。。。

[ 本帖最后由 batman 于 2008-10-23 17:05 编辑 ]
作者: 随风    时间: 2008-10-23 17:10

一看到有 batman 的回帖就估计是批评我们的了。。 ^_^
不过此题,说难不难,说易也不易,下次出题能否声明一下针对人群呢?
作者: batman    时间: 2008-10-23 17:15

原帖由 随风 于 2008-10-23 17:10 发表
一看到有 batman 的回帖就估计是批评我们的了。。 ^_^
不过此题,说难不难,说易也不易,下次出题能否声明一下针对人群呢?

真的是对不起,本人是一边做报表一边出的题,终于还是有所遗漏:没能事先做出声明。
是本人的错,请各位见谅了。。。
作者: rat    时间: 2008-10-23 17:26

用临时文件夹能行么,嘻嘻~
作者: youxi01    时间: 2008-10-23 20:09

与随风兄的代码思路一样,测试代码:
  1. ::-1
  2. @echo off 2>nul 3>nul
  3. set /p n=<"%~0"
  4. set "n=%n::=%"
  5. set /a n+=1,1/n && call echo 程序已经运行%%n%%次
  6. for /f "delims=" %%i in ('echo ::%n%^&more +1^<"%~0"') do (
  7.         if not defined flag (set flag=a&echo %%i>"%~0") else echo %%i>>"%~0"
  8. )
  9. pause
复制代码
不过以下代码还有两个目的:
1、2>nul 3>nul
2、不生成临时文件修改自身文件内容除了有随风兄的写法外,还可以这样:
  1. for /f "delims=" %%i in ('echo ::%n%^&more +1^<"%~0"') do (
  2.         if not defined flag (set flag=a&echo %%i>"%~0") else echo %%i>>"%~0"
  3. )
复制代码

作者: zqz0012005    时间: 2008-10-23 20:33

靠,给新手出的题都被你们这些超级老鸟抢答了,新手看着伤心啊。

我看这样的题目新手几乎没有机会了

再有版主及以上级别的妄言者统统禁言!
作者: youxi01    时间: 2008-10-23 21:11

呵呵,他们几个人的帖子不是全部被屏蔽了吗?
作者: 随风    时间: 2008-10-23 21:14

认错,以后这类帖子留给新人
作者: batman    时间: 2008-10-23 21:52

———期望的身影(致新人)
我亲爱的朋友们,
你们可曾知道?
我是多么的渴望:
渴望触碰你们活跃的思想
渴望聆听你们讨论的声音
渴望拜读你们个性的文章
于是,我发出诚心的请柬
在等待中默默守望。。。
等待依然是那样的漫长
看到的还是熟悉的脸庞
无数次声音在心中响起:
算了吧,你还是将此遗忘
可为了你们,我还是毅然如常
但,我亲爱的人们啊
不要总叫我苦苦思量
不要总让我次次失望
叫我听到你们的声音
叫我看到你们的模样
叫我感到你们的成长
要知道
你们的身影是我最长的期望。。。
作者: qq641255849    时间: 2008-10-23 22:05

真有教书育人的味道,各位大大辛苦了!
作者: 随风    时间: 2008-10-23 22:07     标题: 回复 19楼 的帖子

一直以为 namejm 文采飞扬,原来 batman 兄也是满腹经纶啊!  ^_^
作者: more    时间: 2008-10-24 00:26

  1. :0
  2. @echo off
  3. for /f "delims=" %%a in ('type %0') do (set "str=%%a"&goto :out)
  4. :out
  5. set "str=%str::=%"
  6. set /a "str+=1"
  7. for /f "delims=" %%a in ('type %0') do (
  8.    if not defined god (
  9.       set god=hell
  10.       >%0 echo :%str%
  11.    ) else (
  12.        >>%0 echo %%a
  13.    )
  14. )
  15. if %str% gtr 1 (echo %str% times already) else (echo This is the first time)
  16. rem 如果上面这行有中文会出错,不解...
  17. set "god="&pause>nul&goto :%str%
复制代码


[ 本帖最后由 more 于 2008-10-24 00:52 编辑 ]
作者: jellyhk    时间: 2008-10-24 01:26

more兄的代码貌似有点问题!
按任意键却继续运行程序?不好吧!
作者: jellyhk    时间: 2008-10-24 05:01


@echo off
echo i love bathome.net
if exist 1.txt goto b
if not exist 1.txt goto a

:a
>1.txt echo 1
goto :eof
:b
set /p i=<1.txt&&>2.txt echo 1&&set /p o=<2.txt
set /a a=%i%+%o%
echo %a% >1.txt
type 1.txt&del 2.txt
pause
goto :eof
pause

碍与我没时间了不能完善!就只能这样了!
本人思路:
把次数加在文件里。在拿出来
缺点:没掉出框框,因为我这里不能用msg命令不知道为什么!就没测试了!
=================================================================
做代码的时候搞出了1个问题请教!
-----
把代码

echo i love bathome.net

:a
>1.txt echo 1
goto :eof
:b
set /p i=<1.txt&&>2.txt echo 1&&set /p o=<2.txt
set /a a=%i%+%o%
echo %a% >1.txt
type 1.txt&del 2.txt
pause
goto :eof
if exist 1.txt goto b
if not exist 1.txt goto a

pause

蓝色的地方换了个位子就不能在1.txt文件里递加了!里面的内容一直是1
难道是运行了
:a标签后的 ?不过:a标签为什么可以运行?不是我用代码限制了吗?
if not exist 1.txt goto a


[ 本帖最后由 jellyhk 于 2008-10-24 05:09 编辑 ]
作者: qq641255849    时间: 2008-10-24 13:15

  1. @echo off
  2. set code=你们的身影是我最长的期望
  3. for /l %%a in (10 -1 0) do (
  4. for /f "skip=2 tokens=*" %%b in ('find "%code%%%a" %0') do (if not "%%b" equ "" (set /a
  5. t=%%a,n=%%a+1&goto :a)))
  6. :a
  7. if "%t%" equ "0" (echo 我不会让你看见"%code%"的) else (echo 这是你第%t%次看见"%code%")
  8. >>%0 echo 你们的身影是我最长的期望%n%
  9. pause>nul
  10. 你们的身影是我最长的期望0
复制代码
不知道这样是否符合要求.
按照版主大大的要求改了一下,期待高效率的方法出现!!

[ 本帖最后由 qq641255849 于 2008-10-24 18:38 编辑 ]
作者: pusofalse    时间: 2008-10-24 13:58     标题: 回复 22楼 的帖子

回复more兄,好像看错题意了。第一次运行时什么也不会输出,到运行第二次时才输出“已经运行1次”。25楼同是如此的问题。
作者: shqf    时间: 2008-10-24 21:40

  1. @echo off
  2. set name=%~n0
  3. set num=%name:~4%
  4. if not "%num%" == "0" (echo 你已经运行本程序%num%次了&&goto count)
  5. :count
  6. set /a num=%num%+1
  7. copy %0 test%num%.bat>nul
  8. echo 欢迎光临 WWW.bathome.net
  9. echo 按任意键结束本程序...&pause>nul
  10. del %0
复制代码

[ 本帖最后由 shqf 于 2008-10-24 21:41 编辑 ]
作者: batman    时间: 2008-10-24 21:42     标题: 给出本人的解了

  1. ::0
  2. @echo off
  3. set /p num=<%~fs0
  4. set "num=%num:~2%"
  5. if %num% neq 0 echo.&echo 程序已运行了%num%次
  6. set /a num+=1&pause>nul
  7. for /f "delims=" %%i in (%~fs0) do (
  8.     if not defined flag (
  9.        echo ::%num%>%~fs0&set "flag=a"
  10.        ) else (
  11.        echo %%i>>%~fs0
  12.     )
  13. )
复制代码

作者: batman    时间: 2008-10-24 21:45

原帖由 shqf 于 2008-10-24 21:40 发表
@echo off
set name=%~n0
set num=%name:~4%
if not "%num%" == "0" (echo 你已经运行本程序%num%次了&&goto count)

:count
set /a num=%num%+1
copy %0 test%num%.bat>nul
echo 欢迎光临 WWW.bathome.net
...

不合题意,不合要求!
作者: Batcher    时间: 2008-10-24 21:53

没有读写注册表的?
作者: rat    时间: 2008-10-24 22:22

  1. @echo off
  2. call :n
  3. calc
  4. exit /b
  5. -------------------------------------------------------------
  6. :n
  7. setlocal&set m="%~f0"
  8. for /f "usebackq" %%a in (%m%)do if defined f (set n=%%a)else if "%%a"=="::n" set f=1
  9. set/an+=1&if %n% geq 1 echo 已经运行了%n%次!&pause
  10. for /f "usebackq delims=" %%a in (%m%)do if defined f (echo.%%a>%m%&set f=)else if defined x (echo.%n%>>%m%&goto:eof)else echo.%%a>>%m%&if "%%a"=="::n" set x=1
  11. ::n
  12. 0
复制代码

作者: qq641255849    时间: 2008-10-24 22:52

为啥各位大大都喜欢将代码写得那么紧凑?看得很辛苦哦...
作者: mkl    时间: 2008-10-24 22:52

  1. @echo off
  2. if not exist time echo 0 >time
  3. set/p a=<time
  4. set/a a+=1
  5. echo 这是第%a%次运行程序
  6. echo %a% >time
  7. pause
复制代码

[ 本帖最后由 mkl 于 2008-10-25 11:00 编辑 ]
作者: batman    时间: 2008-10-24 23:06

原帖由 mkl 于 2008-10-24 22:52 发表
@echo off
if not exist time echo 0>time
set/p a=time
pause

echo 0>time只会生成一个空文件
作者: pusofalse    时间: 2008-10-24 23:07

来个会越来越长的:
  1. @echo off
  2. rem 最后一行不能是空行。
  3. for /f %%a in ('findstr /v $ "%~f0"') do set /a n=%%a+1 & if "%%a" neq "pause" echo 已经运行%%a次
  4. >>"%~f0" (echo\& <nul set /p=%n%)
  5. pause & exit /b
复制代码

作者: youxi01    时间: 2008-10-24 23:32

再来一个越来越长的,呵呵
  1. @echo off 2>nul 3>nul
  2. for /f "delims=" %%i in (%~0) do set "n=%%i"
  3. set /a n+=1,1/n && call echo 第%%n%%次运行
  4. pause>nul
  5. >>%~0 echo %n%
  6. goto :eof
  7. -1
复制代码

作者: Batcher    时间: 2008-10-24 23:44     标题: 回复 32楼 的帖子

别学他们乱用&、&&、||之类的命令连接符
这样会让代码的可读性降低
保持你的风格即可
作者: more    时间: 2008-10-25 09:25

原帖由 pusofalse 于 2008-10-24 13:58 发表
回复more兄,好像看错题意了。第一次运行时什么也不会输出,到运行第二次时才输出“已经运行1次”。25楼同是如此的问题。

我这里显示没有问题呀:
This is the first time
2 times already
3 times already
4 times already
5 times already
6 times already

作者: shqf    时间: 2008-10-25 10:08

之前一直认为批处理是难以改写文本文件的,最多会在文尾添加一句,但那样在本题中文本文件会越来越长。细细体会了
  1. for /f "usebackq delims=" %%a in ("%~0") do (
  2.    if not defined flag (set flag=a&echo ::%n%>"%~0") else echo %%a>>"%~0"
  3. )
复制代码
这一句,知道文件第一句也是可以改写的。那如果在文件中间的,能改写吗?
作者: mkl    时间: 2008-10-25 11:03

原帖由 batman 于 2008/10/24 23:06 发表

echo 0>time只会生成一个空文件

已经改过了,请再看看
  1. @echo off
  2. if not exist time echo 0 >time
  3. set/p a=<time
  4. set/a a+=1
  5. echo 这是第%a%次运行程序
  6. echo %a% >time
  7. pause
复制代码

作者: more    时间: 2008-10-25 11:27     标题: 回39楼 shqf

这样算吗?
  1. @echo off
  2. set "str=echo 这里是中间那段"
  3. for /f "delims=" %%a in ('type %0') do (
  4.    if not defined god (
  5.       set "god=hell"
  6.       >%0 echo %%a
  7.    ) else (
  8.       if not "%%a"=="%str%" (
  9.          >>%0 echo %%a
  10.       ) else (
  11.          >>%0 echo echo 这里是已经改写的中间那段
  12.       )
  13.    )
  14. )
  15. echo 这里是中间那段
  16. pause
复制代码

作者: shqf    时间: 2008-10-25 12:40     标题: 回复 41楼 的帖子

还真是行的,谢谢指教。

[ 本帖最后由 shqf 于 2008-10-25 20:00 编辑 ]
作者: 523066680    时间: 2008-10-26 13:43

@echo off
set n=0
goto :a
  :add
   set /a n+=1
  goto :eof
:a
call :call
if %n% gtr 0 (echo,曾经打开%n%次)
echo,call :add>>tt1.bat
pause

:call
作者: a794685135    时间: 2008-10-30 17:31

  1. @echo off
  2. for /f "skip=9" %%i in ('type %0') do set a=%%i
  3. >>%0 echo 1
  4. if "" EQU "%a%" (pause &goto :eof)
  5. for /f %%i in ('echo %0') do set b=%%~zi
  6. set /a c=(%b%-%a%)/3-80
  7. echo 程序已经运行了%c%次
  8. pause&goto :eof
  9. ::此行号为skip所用
复制代码

不要改里面的东西哇, 不燃会有错误, 呵呵
最后需要有一行空行


  1. @echo off
  2. for /f "skip=9" %%i in ('type %0') do set a=%%i
  3. >>%0 echo 1
  4. if "" EQU "%a%" (pause &goto :eof)
  5. for %%i in (%0) do set b=%%~zi
  6. set /a c=(%b%-%a%)/3-76
  7. echo 程序已经运行了%c%次
  8. pause&goto :eof
  9. ::此行号为skip所用
复制代码

应该是这个 , 上面的错了


[ 本帖最后由 a794685135 于 2008-11-2 16:16 编辑 ]
作者: yslyxqysl    时间: 2008-10-30 17:38

不改都有错误。
程序已经运行了-80次
请按任意键继续. . .

作者: netbenton    时间: 2009-4-28 07:55     标题: 最简单的,[会越来越长]

  1. @echo off
  2. set/a n=%~z0-110
  3. if %n% gtr 0 echo 程序已经运行了:%n%次
  4. set/p =a>%~f0
  5. pause
  6. goto :eof
  7. ::
复制代码

作者: 523066680    时间: 2009-11-20 08:57

hi, netbenton也来拉
现在如果做的话打算用 assoc 关联一个特殊项,该项记录着次数。
assoc .次数=n
估计实际上是根改注册表差不多

[ 本帖最后由 523066680 于 2009-11-20 08:58 编辑 ]
作者: ak47b21b21    时间: 2009-12-10 00:07

@echo off
for /f "tokens=2" %%i in (%~nx0) do (set sx=%%i)
if %sx%==0 goto 1
echo 文件已经运行%sx%次
:1
set /a sx+=1
echo aloc %sx% >>%~nx0
pause>nul&&exit
aloc 0

注意代码最后有1空行。。
作者: dn119    时间: 2012-2-11 15:18

回复 28# batman

回复 28# batman

这个代码有点问题,直接关掉程序的话不会计数,应该改一下才可以.
  1. ::3
  2. @echo off
  3. set /p num=<%~fs0
  4. set "num=%num:~2%"
  5. if %num% neq 0 echo.&echo 程序已运行了%num%次
  6. set /a num+=1
  7. for /f "delims=" %%i in (%~fs0) do (
  8.     if not defined flag (
  9.        echo ::%num%>%~fs0&set "flag=a"
  10.        ) else (
  11.        echo %%i>>%~fs0
  12.     )
  13. )
  14. pause>nul
复制代码
pause>nul 这个放在计数后面,不然不按键盘,直接把程序关掉的话不会计数.
作者: QIAOXINGXING    时间: 2012-2-29 17:16

注册表我也不熟,试一下:
  1. @echo off
  2. REG QUERY hkcr\.$$$ /v "cishu" 1>nul 2>nul||reg add hkcr\.$$$ /v "cishu" /d "0" /f >nul
  3. for /f "tokens=1-3" %%a in ('REG QUERY  hkcr\.$$$ /v "cishu"') do (set "cishu=%%c")
  4. if not "%cishu%"=="0" echo 已经运行了 %cishu% 次
  5. set /a "cishu+=1"
  6. reg add hkcr\.$$$ /v "cishu" /d "%cishu%" /f >nul
  7. echo.
  8. set /p "a=按 回车 直接退出;空格 + 回车 清除运行记录。 "
  9. if defined a reg delete  hkcr\.$$$ /f & pause
复制代码





欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2