字符''中字符串/字符文字中的词汇错误?

lær*_*n91 2 string haskell list

我是Haskell的新手,我试图通过使用shiftingASCII值来加密纯文本,如果我的纯文本包含数字,那么它必须通过用特殊符号代替数字来编码每个数字(0=*,1=',2=~,3=!,4=@,5=#,6=$, 7=%,8=^,9=&).所以这是我的加密代码

import Data.Char

canEncrypt :: Char -> Bool
canEncrypt c = isLower(c) && isAscii(c)

encryptChar :: Char -> Char -> Char
encryptChar shift c
 | canEncrypt c = chr(ord(c)+ord(shift))
 | isUpper c = c
 | isNumber c = if (c == 0) then '*'
                 else if (c == 1) then '\'
                       else if (c == 2) then '~'
                             else if (c == 3) then '!'
                                   else if (c == 4) then '@'
                                         else if (c==5) then '#'
                                               else if (c==6) then '$'
                                                     else if (c==7) then '%'
                                                           else if (c==8) then '^'
                                                                 else '&'
Run Code Online (Sandbox Code Playgroud)

是的,它是一个小的意大利面条代码,但是当我编译它时,它显示如下的错误

    |
    | lexical error in string/character literal at character ' '
21  | isNumber c = blah blah blah..
    |
Run Code Online (Sandbox Code Playgroud)

我认为我在做一些非常错误的事情,我不知道是什么.所以不要犹豫这样一个愚蠢的问题我只是初学者所以任何帮助都会受到赞赏,还有其他任何实现来实现这种if-else问题吗?谢谢

Wil*_*sem 7

你写:

else if (c == 1) then '\'
Run Code Online (Sandbox Code Playgroud)

根据您的问题,您想要返回一个引号(').你通过转义引号来做到这一点,但你需要一个char标记结束.所以我们应该写'\''

else if (c == 1) then '\''
Run Code Online (Sandbox Code Playgroud)

话虽如此,这是一个很好的级联if- then- elses.

由于c是a Char,你不能执行a c == 1,因为等价函数(==) :: Eq a => a -> a -> Bool因此比较两个as(所以相同的类型).所以我们需要写它:

else if (c == '1') then '\''
Run Code Online (Sandbox Code Playgroud)

现在我们有一个很长的级联if- then- elses.这不是很优雅,也很难理解.我们可以使用模式匹配:

encryptChar :: Char -> Char -> Char
encryptChar shift c
 | canEncrypt c = chr (ord c + ord shift)
 | isUpper c = c
encryptChar _ '0' = '*'
encryptChar _ '1' = '\''
encryptChar _ '2' = '~'
encryptChar _ '3' = '!'
encryptChar _ '4' = '@'
encryptChar _ '5' = '#'
encryptChar _ '6' = '$'
encryptChar _ '7' = '%'
encryptChar _ '8' = '^'
encryptChar _ '9' = '&'
Run Code Online (Sandbox Code Playgroud)

我们还可以定义一个值列表,一个列表Char是String:

digittrans = "*'~!@#$%^&"
Run Code Online (Sandbox Code Playgroud)

然后我们就可以查找了我有个指标:digittrans !! i.因此,通过解析字符串"4"的Int对应与read "4",我们可以得到正确的值:

encryptChar :: Char -> Char -> Char
encryptChar shift c
 | canEncrypt c = chr (ord c + ord shift)
 | isUpper c = c
 | isDigit c = digittrans !! read [c]
    where digittrans = "*'~!@#$%^&"
Run Code Online (Sandbox Code Playgroud)

我们还需要考虑一个结果机制,以防所有上述检查失败(某些东西不可加密,也不是大写,也不是数字).在这种情况下,我们可以例如决定返回角色本身:

encryptChar :: Char -> Char -> Char
encryptChar shift c
 | canEncrypt c = chr (ord c + ord shift)
 | isUpper c = c
 | isDigit c = digittrans !! read [c]
    where digittrans = "*'~!@#$%^&"
encryptChar _ c = c
Run Code Online (Sandbox Code Playgroud)

  • 怎么样`| isNumber c = dict !! 读 [c] where dict = "*'~!@#$%^&"` 而不是这个巨大的模式匹配? (2认同)

Ben*_*Ben 5

这是你的问题:

if (c == 1) then '\'
Run Code Online (Sandbox Code Playgroud)

反斜杠是字符串和字符文字中的特殊字符; 它用于转义以下字符,以便您可以在字符串和字符文字中使用其他特殊字符.

因此'\',Haskell解析器将其读作单个引号,从字符文字开始,然后在字符文字内部使用反斜杠转义的单引号,但是没有未转义的单引号来正确结束字符文字,这就是为什么它会抱怨下一个字符是"字符串/字符文字中的词法错误".

如果你想写一个字符文字的反斜杠字符,那么你需要使用反斜杠转义反斜线有哈斯克尔它读成一个反斜杠在字符文字,而不是一个反斜杠修改下一个字符的解释.所以:'\\'

如果您正在尝试为单引号字符编写字符文字,那么您对字符文字内的引号使用反斜杠转义单引号字符是正确的,但您仍需要添加非转义引号来终止字符文字.所以:'\''