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

时间:2017-11-21 08:02:25

标签: string list haskell

我是Haskell的新手,我正在尝试使用shifting ASCII值来加密纯文本,如果我的纯文本包含数字,那么它必须通过放置一个特殊符号来编码每个数字像(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 '&'

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

    |
    | lexical error in string/character literal at character ' '
21  | isNumber c = blah blah blah..
    |

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

2 个答案:

答案 0 :(得分:7)

你写道:

else if (c == 1) then '\'

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

else if (c == 1) then '\''

话虽如此,这是一个很好的级联if - then - else s。

由于cChar,您无法执行c == 1,因为等价函数(==) :: Eq a => a -> a -> Bool因此会比较两个a s(所以相同类型)。所以我们需要写它:

else if (c == '1') then '\''

现在我们有一长串if - then - else s。这不是很优雅,也很难理解。我们可以使用模式匹配

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' = '&'

我们还可以定义值列表,Char的列表是String

digittrans = "*'~!@#$%^&"

然后我们可以使用digittrans !! i查找 i -th索引。因此,通过使用Int将字符串“4”解析为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 = "*'~!@#$%^&"

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

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

答案 1 :(得分:5)

这是你的问题:

if (c == 1) then '\'

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

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

如果您正在尝试为反斜杠字符编写字符文字,那么您需要使用反斜杠来转义反斜杠,让Haskell将其作为反斜杠字符文字中读取而不是反斜杠修改下一个字符的解释。所以:'\\'

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