действительно простая проблема SML, которую я просто не могу понять (небольшой код) - PullRequest
1 голос
/ 17 апреля 2011

Просто базовый шифр Casaer.Я проверил все подфункции, просто encryptChar () не особенно работает.Я получаю бесконечный цикл.Это должно быть рекурсивным.Вот весь код:

fun replace (str : string, index : int, newChar : char) : string = String.substring(str,0,index) ^ String.str(newChar) ^ String.substring(str,index+1,(size str) - index - 1;

fun encryptChar (msgStr : string, shiftAmnt : int, index : int) : string =   
    let val asciiCode = 0  
    in  
        if (not (String.sub(msgStr, index) = #" ")) then  
        (  
            asciiCode = ord( String.sub(msgStr, index) ) + shiftAmnt;  
            if (asciiCode < ord(#"A")) then asciiCode = asciiCode + 26  
            else if (asciiCode > ord(#"Z")) then asciiCode = asciiCode - 26  
            else asciiCode = asciiCode;  
            msgStr = replace(msgStr, index, chr(asciiCode))  
        )  
        else asciiCode = asciiCode;  
        index = index + 1;  
        if (index < (size msgStr - 1)) then encryptChar(msgStr, shiftAmnt, index)  
        else msgStr  
    end  
;  

fun encrypt(msgStr : string, shiftAmnt : int) : string = encryptChar (String.map Char.toUpper msgStr, shiftAmnt mod 26, 0);

Ответы [ 2 ]

2 голосов
/ 18 апреля 2011

Проблема в том, что вы неправильно используете =. Вне определения переменной = - это просто логическая функция, которая проверяет свои аргументы на равенство. Так, например, если вы сделаете asciiCode = ord( String.sub(msgStr, index) ) + shiftAmnt;, он просто вернет false (потому что asciiCode не равен ord( String.sub(msgStr, index) ) + shiftAmnt), а затем выбросит этот результат (потому что у вас есть дополнительные выражения после ;). Он не переназначит asciiCode.

Переменные в SML неизменны. Если вы хотите эмулировать изменяемые переменные, вы можете использовать ref s и оператор :=. Однако я бы не рекомендовал такой подход, так как он, как правило, не является хорошим функциональным стилем и в этом случае не нужен Предпочтительным подходом было бы переписать код таким образом, чтобы каждая переменная присваивалась только один раз.

1 голос
/ 19 апреля 2011

Это действительно очень просто, и удивительно, что вы столкнулись с ним в такой сложной ситуации.
Вы перенесли это с какого-то другого языка?

Вам нужно забыть все, что вы знаете о программированиииспользование присваиваний.

let val x = y in something

означает более или менее "в пределах чего-либо", замените идентификатор "x" значением "y" ".
Невозможно изменить значениеиз х.

Выполните подстановку (это не фактический порядок оценки или что-то еще, но он должен дать вам представление о том, что происходит):

   encryptChar("THIS", amount, 0)

=>

let val asciiCode = 0  
in  
    if (not (String.sub("THIS", 0) = #" ")) then  
    (  
        asciiCode = ord( String.sub("THIS", 0) ) + amount;  
        if (asciiCode < ord(#"A")) then asciiCode = asciiCode + 26  
        else if (asciiCode > ord(#"Z")) then asciiCode = asciiCode - 26  
        else asciiCode = asciiCode;  
        "THIS" = replace("THIS", 0, chr(asciiCode))  
    )  
    else asciiCode = asciiCode;  
    0 = 0 + 1;  
    if (0 < (size "THIS" - 1)) then encryptChar("THIS", amount, 0)  
    else str 
end ;

=>

        if (not (String.sub("THIS", 0) = #" ")) then  
        (  
            0 = ord( String.sub("THIS", 0) ) + amount;  
            if (0 < ord(#"A")) then 0 = 0 + 26  
            else if (0 > ord(#"Z")) then 0 = 0 - 26  
            else 0 = 0;  
            "THIS" = replace("THIS", 0, chr(0))  
        )  
        else 0 = 0;  
        0 = 0 + 1;  
        if (0 < (size "THIS" - 1)) then encryptChar("THIS", amount, 0)  
        else str  

=>

        if (not (String.sub("THIS", 0) = #" ")) then  
        (  
            0 = ord( String.sub("THIS", 0) ) + amount;  
            if true then false
            else if false then false
            else true;
            false
        )  
        else true;  
        false;  
        if (0 < (size "THIS" - 1)) then encryptChar("THIS", amount, 0)  
        else "this" 

->

        if (not false) then  
        (  
            false;
            false;
            false
        )  
        else true;  
        false;  
        if true then encryptChar("THIS", amount, 0)  
        else "THIS" 

=>

        (  
            false;
            false;
            false
        )  
        false;  
        encryptChar("THIS", amount, 0)

=>

    encryptChar("THIS", amount, 0)

Отсюда и появился ваш бесконечный цикл.

Вы бы хорошо заполучили вводный текст о программировании ML.

...