凯撒密码程序空格处理问题求助:遇空格跳过加密并保留
凯撒密码程序空格处理问题解决
问题描述
编写的凯撒密码程序从文本文件读取输入,当输入字符串包含空格时,程序会错误地对空格进行加密,导致输出异常。例如输入“hello world”、偏移量为4时,实际输出为lippsdasvh,而期望输出为LIPPS ASVPH。需要实现遇到空格时直接保留,不执行加密操作。
问题分析
原代码中没有判断空格的逻辑,当遇到空格时,ALPHABET.indexOf(' ')会返回-1,后续计算encryptPos = (4 + (-1)) %29 =3,会取字母表中索引3的字符,导致空格被错误替换。
解决方案
核心修改点如下:
- 遍历字符时先判断是否为空格,若是则直接添加到结果字符串,跳过加密流程
- 补充解密逻辑(对应
EncrDecrpt变量的使用) - 使用
StringBuilder优化字符串拼接效率 - 处理大小写转换,匹配期望的大写输出
- 避免全局变量,减少不必要的静态变量
修改后的完整代码
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; public class CaesarCipher { // 定义英文字母表,根据需要可替换为土耳其/西班牙字母表 private static final String ENGLISH_ALPHABET = "abcdefghijklmnopqrstuvwxyz"; public static void main(String[] args) throws FileNotFoundException { File inputFile = new File("filename.txt"); Scanner scan = new Scanner(inputFile); while (scan.hasNextLine()) { String line = scan.nextLine(); String[] parts = line.split(":"); if (parts.length != 4) { System.out.println("无效的输入格式,请检查文件内容"); continue; } int shiftNumber = Integer.parseInt(parts[0]); int encrDecrpt = Integer.parseInt(parts[1]); int language = Integer.parseInt(parts[2]); String plainText = parts[3]; // 根据语言选择对应字母表 String alphabet = ENGLISH_ALPHABET; if (language == 1) { // 假设1代表土耳其,可自行调整 // alphabet = "abcçdefgğhıijklmnoöprsştuüvyz"; } else if (language == 2) { // 2代表西班牙 // alphabet = "abcdefghijklmnñopqrstuvwxyz"; } String result = processCaesar(plainText, shiftNumber, encrDecrpt, alphabet); System.out.println("处理结果: " + result); } scan.close(); } public static String processCaesar(String plainText, int shiftNumber, int encrDecrpt, String alphabet) { StringBuilder result = new StringBuilder(); int alphabetLength = alphabet.length(); for (int i = 0; i < plainText.length(); i++) { char c = plainText.charAt(i); // 遇到空格直接添加,跳过加密/解密 if (c == ' ') { result.append(' '); continue; } // 转换为小写后查找索引 char lowerC = Character.toLowerCase(c); int pos = alphabet.indexOf(lowerC); // 如果字符不在字母表中,直接保留原字符 if (pos == -1) { result.append(c); continue; } int processedPos; if (encrDecrpt == 1) { // 1代表加密,可自行调整标识 processedPos = (pos + shiftNumber) % alphabetLength; // 处理负数偏移(如果shiftNumber为负) if (processedPos < 0) { processedPos += alphabetLength; } } else { // 解密 processedPos = (pos - shiftNumber) % alphabetLength; // 确保索引非负 if (processedPos < 0) { processedPos += alphabetLength; } } // 根据原字符的大小写决定输出大小写 char processedChar = alphabet.charAt(processedPos); if (Character.isUpperCase(c)) { processedChar = Character.toUpperCase(processedChar); } result.append(processedChar); } return result.toString(); } }
关键修改说明
- 空格处理:在循环中增加
if (c == ' ')判断,直接将空格追加到结果中,跳过后续加密逻辑。 - 字符合法性判断:如果字符不在字母表中(
pos == -1),也直接保留原字符,增强程序兼容性。 - 解密逻辑实现:根据
encrDecrpt变量判断是加密还是解密,解密时调整偏移量计算方式,确保索引为非负。 - 大小写保持:根据原字符的大小写,将处理后的字符转换为对应大小写,匹配期望的
LIPPS ASVPH格式。 - 性能优化:使用
StringBuilder替代字符串+=操作,避免频繁创建字符串对象,提升效率。 - 代码结构优化:移除不必要的全局静态变量,将字母表定义为常量,增加输入格式校验,提升代码健壮性。
内容的提问来源于stack exchange,提问作者jonathan pascal
相关产品推荐
相关产品推荐

