在Windows批处理中,如何根据ASCII码返回字符

4

我编写了一个批处理文本字符串编码程序。现在,我需要将ASCII代码转换为字符。实际上,我需要做相反的工作。 我已经将字符串的字符分解,并希望将其翻译成ASCII码。 我找到了一个很好的命令来将ASCII转换为字符:

cmd /c exit 65
echo %=exitcodeAscii%

但是,当我将它放在for循环中时,它停止工作。通过for循环迭代,我验证ASCII码(for索引)是否与字符相同。

@echo off
setlocal enableDelayedExpansion
set char=A
for /L %%a in (32,1,126) do (
cmd /c exit %%a
echo %=exitcodeAscii%
if %=exitcodeAscii% EQU %char% echo %%a
)

看起来cmd命令无法正常工作。我该怎么解决?

3个回答

3
@echo off
setlocal enableDelayedExpansion
set char=A
for /L %%a in (32,1,126) do (
  cmd /c exit %%a
  echo !=exitcodeAscii!
  if "!=exitcodeAscii!" EQU "%char%" echo %%a
)

两个小改变:
a)使用延迟扩展(您已经启用它)
b)在if参数周围加上引号,以防止出现空变量的语法错误(特别是在此处为%%a = 32保留空格,if无法独自处理)。


1
这是老板。只需要阅读、放屁和鼓掌。
cls
@echo off
cd /d "%~dp0"
chcp 65001 >nul
set title_script=char to hex
title %title_script%

rem Encode this file script in UTF-8 with BOM and let the first line blank



set ansi_code_page=1252
rem 1250    Central European
rem 1251    Cyrillic
rem 1252    Western European (Latin 1)
rem 1253    Greek
rem 1254    Turkish
rem 1255    Hebrew
rem 1256    Arabic
rem 1257    Baltic
rem 1258    Vietnamese



chcp %ansi_code_page% >nul
set /p character=Character = 
set "character_ascii="
call :function_char_to_ascii character character_ascii
echo Character %character% = %character_ascii%

pause
exit

:function_char_to_hex
    setlocal enabledelayedexpansion
    set character=!%~1!
    set tmp_file=%~dpn0_tmp.txt
    echo !character!> "%tmp_file%"
    set tmp_0_file=%~dpn0_tmp_0.txt
    for %%a in ("%tmp_file%") do fsutil file createnew "%tmp_0_file%" %%~za >nul
    set "character_hex="
    for /f "skip=1 tokens=2" %%a in ('fc /B "%tmp_file%" "%tmp_0_file%"') do set "character_hex=!character_hex!%%a"
    del /f /q "%tmp_file%"
    del /f /q "%tmp_0_file%"
    if /i "%character_hex:~-4%" == "0D0A" set character_hex=%character_hex:~0,-4%
    endlocal & set %~2=%character_hex%
goto :eof

:function_change_base_number
    setlocal enabledelayedexpansion
    set /a input_base=%~1
    set input_number=!%~2!
    set /a output_base=%~3

    for %%i in ("a=A" "b=B" "c=C" "d=D" "e=E" "f=F" "g=G" "h=H" "i=I" "j=J" "k=K" "l=L" "m=M" "n=N" "o=O" "p=P" "q=Q" "r=R" "s=S" "t=T" "u=U" "v=V" "w=W" "x=X" "y=Y" "z=Z") do (
        call set "input_number=!input_number:%%~i!"
    )

    set map=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
    set map_base=!map:~0,%input_base%!
    set /a position=0
    set input_number_check=%input_number%
    :loop_1
        set current_map_base_character=!map_base:~%position%,1!
        set input_number_check=!input_number_check:%current_map_base_character%=!
        if "!input_number_check!" == "" goto next_1
        set /a position+=1
        if "!map_base:~%position%,1!" NEQ "" goto loop_1
        echo Error. Invalid character in base %input_base%.
        echo.
        pause
        exit
    :next_1

    set /a carry_flag=1
    set "input_number_tmp=%input_number%"
    set "result_decimal="
    :loop_2
        set "input_number_tmp_digit=%input_number_tmp:~-1%"
        if %input_number_tmp_digit% LEQ 9 goto next_2
        for /l %%i in (10,1,%input_base%) do (
            if /i "%input_number_tmp_digit%" EQU "!map:~%%i,1!" (
                set "input_number_tmp_digit=%%i"
                goto :next_2
            )
        )
        echo Error.
    :next_2
    set /a result_decimal+=input_number_tmp_digit * carry_flag
    set /a carry_flag *= input_base
    set "input_number_tmp=%input_number_tmp:~0,-1%"
    if defined input_number_tmp goto :loop_2

    set /a input_number_tmp=%result_decimal%
    set "result="
    :loop_3
        set /a "division_remainder=input_number_tmp %% !output_base!"
        set /a "input_number_tmp /= !output_base!"
        set result=!map:~%division_remainder%,1!%result%
        if "%input_number_tmp%" NEQ "0" goto loop_3
    endlocal & set %~4=%result%
goto :eof

:function_char_to_ascii
    setlocal enabledelayedexpansion
    set "character=!%~1!"
    set "character_hex="
    set "character_dec="
    rem Character " is forbidden
    if "%character%" == " " (
        set "character_hex=20"
        set "character_dec=32"
    )
    rem On this line, write a tabulation between the quotes, not 4 spaces.
    if "%character%" == "   " (
        set "character_hex=9"
        set "character_dec=9"
    )
    if "%character%" == ")" (
        set "character_hex=29"
        set "character_dec=41"
    )
    if "%character_hex%" == "" (
        set "character_hex="
        call :function_char_to_hex character character_hex
        set "character_dec="
        call :function_change_base_number 16 character_hex 10 character_dec
    )
    rem echo %character% = %character_dec% (x%character_hex%)
    endlocal & set %~2=%character_dec%
goto :eof

3
虽然这段代码可能解决了问题,但包括说明它是如何解决问题的会真正有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在为未来的读者回答问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加说明并指出适用的限制和假设。 - Dharman

1
当我使用!=exitcodeAscii!进行多字符匹配时,它会执行得非常缓慢,我不知道为什么。
set "ascii_str= #$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
echo %time%
:ascii_multiple
if defined ascii_str (
set "char=!ascii_str:~0,1!"
for /l %%0 in (32, 1, 126) do cmd /c exit %%0 &if "!=exitcodeAscii!" EQU "!char!" echo %%0
set "ascii_str=!ascii_str:~1!"
) else (echo %time% &pause)
goto ascii_multiple

开始时间:11:21:27.00 结束时间:11:22:29.25,大约1分钟。
但是,如果我使用一种新的方法将字符或字符串转换为ASCII:
@echo off &setlocal EnableDelayedExpansion
chcp 1252 >nul

set "ascii_table=   #$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
set "ascii[33]=^!" &set "ascii[34]=""

:main
set /p "string=String:"
call :str_ascii
echo. &goto main

:str_ascii
if defined string (
set "char=!string:~0,1!"
call :char_ascii
set "string=!string:~1!"
) else (exit /b 0)
goto str_ascii

:char_ascii
set /a index=32
if "!char!"=="!ascii[33]!" echo !ascii[33]! = 33 &exit /b 0
if "!char!"=="!ascii[34]!" echo !ascii[34]! = 34 &exit /b 0
if "!char!"=="" exit /b 1
for /l %%0 in (0, 1, 94) do (
if "!char!"=="!ascii_table:~%%0,1!" echo !char! = !index! &exit /b 0
set /a index+=1)
echo cannot find char &exit /b 1

在这个函数中,我可以处理Ascii字符32-126。
在这种情况下,我尝试使用查找表来提高效率。
我认为执行!=exitcodeAscii!需要执行太多命令,因为如果你想找到最后一个字符~,你必须执行94次命令。
所以我把所有的Ascii字符都放在一个字符串里,用!ascii_table:~%%0,1!来获取Ascii表中的单个字符,并设置/a索引来计算十进制值。
就像逐个设置数组并相互匹配字符一样。
set "ascii[32]= "
...
set "ascii[126]=~"

测试字符串:
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

所有字符的运行速度为 19:33:32.19 到 19:33:32.94 - 小于1秒。
如果您想使用小数值来查找字符,也可以更改一些代码:
:main
set /p "enter=Decimal:"
if defined enter set /a dec=%enter% &call :dec_ascii
echo. &goto main

:dec_ascii
set /a index=32
if !dec!==33 echo !ascii[33]! &exit /b 0
if !dec!==34 echo !ascii[34]! &exit /b 0
if not defined dec exit /b 1
for /l %%0 in (0, 1, 94) do (
if !dec!==!index! echo !ascii_table:~%%0,1! &exit /b 0
set /a index+=1)
echo cannot find char &exit /b 1

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接