首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TCL:如何在TCL中将超长字符串转换为ASCII

TCL:如何在TCL中将超长字符串转换为ASCII
EN

Stack Overflow用户
提问于 2018-02-01 05:33:59
回答 4查看 1.1K关注 0票数 1

我正在尝试将一个非常长的字符串转换为ASCII十六进制。

我该怎么做呢?

我已经写了这个非常长的switch语句,但我知道有一种更简单的方法来实现这一点。我对所有奇怪的符号都有问题,比如括号,#,$,\等等。在switch语句中。我可以让他们中的一些人使用反斜杠工作,但其他人失败了。

代码语言:javascript
复制
proc Text_to_ASCII {string} {

set Ascii_Word ""

set stringLength [string length $string]

for {set i 0} {$i < $stringLength} {incr i} {

    set Letter [string index $string $i]

    switch -glob $Letter {

        " "     {set hex_ascii 20}

        0   {set hex_ascii 30}
        1   {set hex_ascii 31}
        2   {set hex_ascii 32}
        3   {set hex_ascii 33}
        4   {set hex_ascii 34}
        5   {set hex_ascii 35}
        6   {set hex_ascii 36}
        7   {set hex_ascii 37}
        8   {set hex_ascii 38}
        9   {set hex_ascii 39}

        A   {set hex_ascii 41}
        B   {set hex_ascii 42}
        C   {set hex_ascii 43}
        D   {set hex_ascii 44}
        E   {set hex_ascii 45}
        F   {set hex_ascii 46}
        G   {set hex_ascii 47}
        H   {set hex_ascii 48}
        I   {set hex_ascii 49}
        J   {set hex_ascii 4A}
        K   {set hex_ascii 4B}
        L   {set hex_ascii 4C}
        M   {set hex_ascii 4D}
        N   {set hex_ascii 4E}
        O   {set hex_ascii 4F}
        P   {set hex_ascii 50}
        Q   {set hex_ascii 51}
        R   {set hex_ascii 52}
        S   {set hex_ascii 53}
        T   {set hex_ascii 54}
        U   {set hex_ascii 55}
        V   {set hex_ascii 56}
        W   {set hex_ascii 57}
        X   {set hex_ascii 58}
        Y   {set hex_ascii 59}
        Z   {set hex_ascii 5A}

        a   {set hex_ascii 61}
        b   {set hex_ascii 62}
        c   {set hex_ascii 63}
        d   {set hex_ascii 64}
        e   {set hex_ascii 65}
        g   {set hex_ascii 67}
        h   {set hex_ascii 68}
        i   {set hex_ascii 69}
        j   {set hex_ascii 6A}
        k   {set hex_ascii 6B}
        l   {set hex_ascii 6C}
        m   {set hex_ascii 6D}
        n   {set hex_ascii 6E}
        o   {set hex_ascii 6F}
        p   {set hex_ascii 70}
        q   {set hex_ascii 71}
        r   {set hex_ascii 72}
        s   {set hex_ascii 73}
        t   {set hex_ascii 74}
        u   {set hex_ascii 75}
        v   {set hex_ascii 76}
        w   {set hex_ascii 77}
        x   {set hex_ascii 78}
        y   {set hex_ascii 79}
        z   {set hex_ascii 7A}


        default {set hex_ascii 3F}
    }

append Ascii_Word $hex_ascii

}

return $Ascii_Word
}

所以我一直在尝试这段代码...

代码语言:javascript
复制
proc string2hex {s} {
binary scan $s H* hex
regsub -all (..) $hex {\\x\1}
}

set input_string "lol"

set ascii_string [string2hex $input_string]

返回"\x6c\x6f\x6c“,非常接近我想要的"6c6f6c”如何删除\x?我正在考虑只做两次trimleft来去掉每个字符的\x,也许只需要一次输入一个字符……

想法?

EN

回答 4

Stack Overflow用户

发布于 2018-02-01 19:48:06

这取决于你到底指的是什么。你的意思是真的“将这个字符串转换成ASCII码,并用?替换未知字符”(或其他字符),还是“获取这个字符串中所有字符的Unicode字符代码”?第二个可能是最有可能的:

代码语言:javascript
复制
proc string_to_ascii {string_value} {
    return [lmap c [split $string_value ""] {
        scan $c %c code
        # Make the code the result of this inner script
        string cat $code
    }]
}

这不是最有效的版本。对于长字符串,事实证明,做这个更长的版本是一个巨大的胜利:

代码语言:javascript
复制
proc string_to_ascii {string_value} {
    set map {}
    set result [lrepeat [string length $string_value] DUMMY]
    set idx 0
    foreach c [split $string_value ""] {
        if {![dict exists $map $c]} {
            scan $c %c ch
            dict set map $c $ch
        }
        lset result $idx [dict get $map $c]
        incr idx
    }
    return $result
}

这是一个胜利,原因有两个:

  1. 它会预先分配结果列表。这不是必须的,因为Tcl的列表确实使用了一种摊销的指数增长策略来管理他们支持的C数组,但是我们知道我们将得到的长度,这样我们就可以变得更聪明。
  2. 它共享整数对象(是的,Tcl当然有这些东西;只是Tcl的类型系统通常会让你不需要担心它),所以内存分配的数量大大减少了。这实际上与split命令在拆分字符时使用的策略相同( binary scan也是如此),即使字符串非常短,也能获得巨大的性能优势。

但这一切都要复杂得多。使用第一个版本(或者使用简单的split $str {},如果你不需要立即使用代码点),因为它更容易编写,并且在内部进行了很好的优化。

要强制字符串仅为ASCII,您可以这样做:

代码语言:javascript
复制
encoding convertto ascii $input_string

从技术上讲,结果是一个字节数组,但作为ASCII字符串工作得很好。如果你想检测非ASCII码(例如,你可以抱怨它),那么你可以使用string is ascii

代码语言:javascript
复制
if {![string is ascii -failindex idx $input_string]} {
    error "found non-ASCII char at index $idx \"[string index $input_string $idx]\""
}

如果您不关心坏字符在哪里,那么一个简单的string is ascii $input_string就可以了。

票数 1
EN

Stack Overflow用户

发布于 2018-03-14 05:12:47

这是我的最终代码..。

代码语言:javascript
复制
proc Text_to_ASCII {string} {

binary scan $string H* hex
set Ascii_Word [regsub -all (..) $hex {\1}]

set stackoverflow_users "People who don't have programming jobs because they 
can't write code with crap are the people who have spare time to answer 
programming question on stackoverflow"
}
票数 1
EN

Stack Overflow用户

发布于 2018-02-01 15:08:28

我相信你正在寻找的东西是

代码语言:javascript
复制
binary format a* [encoding convertto ascii $string_value]

结果对我来说肯定像ASCII,尽管我不能确定这就是你想要的。

更新:我仍然对期望的目标以及为什么现有的答案都没有用感到有点困惑。如果预期输入中的字符都不在ASCII范围之外,则UTF-8字符串与ASCII字符串相同:没有要转换的字符。

如果有非ASCII字符:转换很有用:

代码语言:javascript
复制
% encoding convertto ascii abcåäö
abc???

结果是一个UTF-8 / ASCII字符串。

如果需要简单地获取字符串中每个字符的低位字节,并将每个字符掩码为7位:

代码语言:javascript
复制
% join [lmap c [split [binary format a* abcåäö] {}] {format %c [expr {[scan $c %c] & 0x7f}]}] {}
abcedv

如果您想从字符串中获取十六进制代码:

代码语言:javascript
复制
% binary encode hex abcåäö
616263e5e4f6

在这种情况下,不进行转换(当然,如果输入已经是ASCII,则可以进行转换):与其他方法组合以获得纯ASCII,例如:

代码语言:javascript
复制
% binary encode hex [encoding convertto ascii abcåäö]
6162633f3f3f

文档:binaryencoding

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48551814

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档