You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复Flet凯撒密码应用的特殊字符解密异常问题?

凯撒密码加解密应用特殊字符处理异常问题

我用Flet开发的凯撒密码应用,目前正在优化Á、Ã这类特殊字符的加解密逻辑。原应用已解决空格问题,现在通过not_alpha函数读取CSV文件中的特殊字符-符号映射关系实现转换,但解密时出现异常:比如解密'Á'得到的结果是'Áuuwony',而非正确的原字符。尝试将cryp_word改为f-string拼接后,特殊字符后无内容显示,找不到同类案例,寻求解决方案。

相关代码

import flet as ft
import string
import pyperclip3 as pc
import pandas

shift = 6
alphabet = list(string.ascii_lowercase)
# a basic app made in flet


def main(page: ft.Page):

    output = ""
    # this should un mark one of the boxes. Ex. If I clicked cryp and then decryp, the cryp box should return false.

    def not_alpha(e, char):
        """ This should read the csv doc with two columns. One with the "especial letter" and other with the "correspondent
        It's receives char as parameter
        """
        doc = pandas.read_csv("html.csv")
        letter = []
        new_char = ""
        for i in doc["Letters"]:
                letter.append(i)
        not_letter = [] #create a list with the Letters column

        for i in doc["Simbols"]:
            not_letter.append(i)  #create a list with the Simbols column
        char_excetions = zip(letter, not_letter) #put it together

        for i in char_excetions: # verify each element look for the "especial letter"or "correspondent"
            if char == str(i[0]):
                new_char = str(i[1])
            elif char == str(i[1]):
                new_char = str(i[0])
        return new_char

    def crypto(e, text_to_use):
        """Crypto message """
        global shift
        cryp_word = ""
        if shift > 25:
            shift = shift % 25
        for char in text_to_use:
            if char in alphabet:
                char_index = alphabet.index(char)
                cryp_char_index = char_index + shift
                if cryp_char_index > 25:
                    cryp_char_index = cryp_char_index % 25
                cryp_word += alphabet[cryp_char_index]
            else:
                if char == " ":
                    cryp_word += char
                else:
                    new_char = not_alpha(e, char)
                    cryp_word += str(new_char)

        return cryp_word

    def decrypto(e, text_to_use):
        """Decypto message """
        global shift
        decrypt_word = ""
        for char in text_to_use:
            if char in alphabet:
                char_index = alphabet.index(char)
                cryp_char_index = char_index - shift
                if cryp_char_index > 25:
                    cryp_char_index = cryp_char_index % 25
                decrypt_word += alphabet[cryp_char_index]
            else:
                if char == " ":
                    decrypt_word += char
                else:
                    new_char = not_alpha(e, char)
                    decrypt_word += str(new_char)
        return decrypt_word

# will execute the action previously selected.
    def execute(e):
        """catch the input and make it works as selected"""

        text_to_use = list(text.value.lower())
        text.value = ""
        result = ""
        final_text.disabled = False
        if cryp.value and text_to_use:
            decryp.value = False
            result = crypto(e, text_to_use)
        if decryp.value and text_to_use:
            cryp.value = False
            result = decrypto(e, text_to_use)

        final_text.value = str(result)
        output = final_text.value
        page.update()

    def copy(e, *output):
        copied = pc.copy(output)
        print(copied)

    page.title = "O segredo de Cesar"
    page.horizontal_alignment = ft.MainAxisAlignment.CENTER
    page.horizontal_alignment = ft.MainAxisAlignment.CENTER
    page.vertical_alignment = ft.MainAxisAlignment.START
    welcome = ft.Text(" Seja bem-vindo!", text_align=ft.TextAlign.CENTER)
    cryp = ft.Checkbox(label="Criptografar", value=False)
    decryp = ft.Checkbox(label="Descriptografar", value=False)
    text = ft.TextField(label="mensagem", hint_text="Digite ou cole a mensagem aqui", text_align=ft.TextAlign.CENTER, multiline=True, min_lines=1, max_lines=6, border=0)
    button = ft.ElevatedButton(text="Start", on_click=execute)
    final_text = ft.TextField("", text_align=ft.TextAlign.CENTER, multiline=True, min_lines=1, max_lines=6, border=0, disabled=True)
    button_copy = ft.ElevatedButton(text="Copy", on_click=copy)


    page.add(
        ft.Row([welcome], alignment=ft.MainAxisAlignment.CENTER),
        ft.Row([decryp, cryp], alignment=ft.MainAxisAlignment.CENTER),
        ft.Row([text, button], alignment=ft.MainAxisAlignment.CENTER),
        ft.Row([final_text, button_copy], alignment=ft.MainAxisAlignment.CENTER)
    )


ft.app(target=main)

字符映射数据

(('Á', '&Aacute;'), ('É', '&Eacute;'), ('Í', '  &Iacute;'), ('Ó', '&Oacute;'), ('Ú', '&Uacute;'), ('á', ' &aacute;'), ('é', '&eacute;'), ('í', '&iacute;'), ('ó', '&oacute;'), ('ú', '&uacute;'), ('Â', '&Acirc;'), ('Ê', '&Ecirc;'), ('Ô', '&Ocirc;'), ('â', '&acirc;'), ('ê', ' &ecirc;'), ('ô', '&ocirc;'), ('À', ' &Agrave;'), ('à', '  &agrave;'), ('Ü', '&Uuml;'), ('ü', '&uuml;'), ('Ç', '&Ccedil;'), ('ç', '&ccedil;'), ('Ã', '&Atilde;'), ('Õ', '&Otilde;'), ('ã', '&atilde;'), ('õ', '&otilde;'), ('Ñ', '&Ntilde;'), ('ñ', '&Ntilde;'), ('&', '&gt&;;'), ('“', '&gt";;'), ('‘', "&gt';;"), ('‘', "&gt';;"), ('<', '&lt;'), ('>', '&gt;'))

问题根源分析

  1. 映射逻辑低效且存在缺陷:每次调用not_alpha都重新读取CSV,遍历映射对时若找不到匹配字符,会返回空字符串而非原字符;同时映射数据中存在多余空格(比如' &Iacute;'),导致匹配失败。
  2. 解密逻辑混淆:decrypto函数处理特殊字符时直接调用not_alpha,但凯撒解密是针对字母的位移还原,特殊字符需按反向映射处理,当前逻辑混淆了转换与位移的顺序。
  3. 大小写处理错误:execute中将输入全转小写,破坏了特殊字符的大小写区分,导致映射匹配失败。
  4. 映射数据错误:原映射中存在格式错误(比如('&', '&gt&;;')应为('&', '&amp;')),直接导致转换异常。

解决方案

1. 预加载映射表并优化匹配逻辑

提前加载CSV并生成加密/解密两个字典,避免重复读取文件,同时清理多余空格:

import pandas as pd

# 加载并预处理映射表
def load_mappings():
    doc = pd.read_csv("html.csv")
    # 去除字符和符号中的多余空格
    doc["Letters"] = doc["Letters"].str.strip()
    doc["Simbols"] = doc["Simbols"].str.strip()
    # 加密映射:特殊字符→HTML符号
    encrypt_map = dict(zip(doc["Letters"], doc["Simbols"]))
    # 解密映射:HTML符号→特殊字符
    decrypt_map = dict(zip(doc["Simbols"], doc["Letters"]))
    return encrypt_map, decrypt_map

# 在main函数开头加载映射表
encrypt_map, decrypt_map = load_mappings()

# 替换原not_alpha函数
def get_mapped_char(char, is_encrypt):
    if is_encrypt:
        return encrypt_map.get(char, char)
    else:
        return decrypt_map.get(char, char)

2. 修正加密解密逻辑

调整crypto和decrypto函数,明确特殊字符的转换方向:

def crypto(e, text_to_use):
    global shift
    cryp_word = ""
    shift = shift % 26  # 字母共26个,取余更准确
    for char in text_to_use:
        if char in alphabet:
            char_index = alphabet.index(char)
            cryp_char_index = (char_index + shift) % 26
            cryp_word += alphabet[cryp_char_index]
        elif char == " ":
            cryp_word += char
        else:
            cryp_word += get_mapped_char(char, is_encrypt=True)
    return cryp_word

def decrypto(e, text_to_use):
    global shift
    decrypt_word = ""
    shift = shift % 26
    for char in text_to_use:
        if char in alphabet:
            char_index = alphabet.index(char)
            cryp_char_index = (char_index - shift) % 26
            # 处理负数索引情况
            if cryp_char_index < 0:
                cryp_char_index += 26
            decrypt_word += alphabet[cryp_char_index]
        elif char == " ":
            decrypt_word += char
        else:
            decrypt_word += get_mapped_char(char, is_encrypt=False)
    return decrypt_word

3. 修复大小写处理

execute函数中取消强制转小写,保留原字符的大小写:

def execute(e):
    text_to_use = list(text.value)  # 移除.lower()
    text.value = ""
    result = ""
    final_text.disabled = False
    if cryp.value and text_to_use:
        decryp.value = False
        result = crypto(e, text_to_use)
    if decryp.value and text_to_use:
        cryp.value = False
        result = decrypto(e, text_to_use)
    final_text.value = result
    page.update()

4. 修正复制函数逻辑

原复制函数参数错误,调整为直接获取结果文本:

def copy(e):
    pc.copy(final_text.value)
    # 新增复制提示
    page.snack_bar = ft.SnackBar(ft.Text("已复制到剪贴板"))
    page.snack_bar.open = True
    page.update()

5. 修正映射数据错误

将原映射中的错误条目修正:

  • ('ñ', '&Ntilde;') → ('ñ', '&ntilde;')
  • ('&', '&gt&;;') → ('&', '&amp;')
  • ('“', '&gt";;') → ('“', '&ldquo;')
  • ('‘', "&gt';;") → ('‘', '&lsquo;')

内容的提问来源于stack exchange,提问作者Milla Dma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:00:54