6

我想实现一个凯撒密码转换,将字符串中的每个字母增加 3。

我收到此错误:

possible loss of precision required char; found int

到目前为止,这是我的代码:

import java.util.Scanner;
import java.io.*;

public class CaesarCipher
{
    public static void main (String [] args) {

        char[] letters = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 
            'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
            'w', 'x', 'y', 'z'};

        char[] message = "onceuponatime".toCharArray();
        char[] eMessage = new char[message.length];
        char shift = 3;

        //encrypting message
        for(int i = 0; i <= message.length; ++i)
        {
            eMessage[i] = (message[i] + shift) % (char) letters.length;
            System.out.println(x);               
        }              
    }
}

是什么导致了这个错误?如何实现凯撒密码移位以将字符串中的每个字母增加 3?

4

7 回答 7

14

Java Shift Caesar Cipher 按shift空格。

限制:

  1. 仅适用于 shift 参数中的正数。
  2. 仅适用于班次小于 26。
  3. 是否 += 会使计算机因超过几千个字符的文本而陷入瘫痪。
  4. 将数字转换为字符,因此除了 ascii 字母之外它会失败。
  5. 只允许字母 a 到 z。无法处理空格、数字、符号或 unicode。
  6. 代码通过重复计算而不是必须的次数违反了 DRY(不要重复自己)原则。

伪代码:

  1. 循环遍历字符串中的每个字符。
  2. 向字符添加移位,如果它落在字母表的末尾,则从字母表中的字母数中减去移位 (26)
  3. 如果移位没有使字符脱离字母表的末尾,则将移位添加到字符。
  4. 将字符附加到新字符串上。返回字符串。

功能:

String cipher(String msg, int shift){
    String s = "";
    int len = msg.length();
    for(int x = 0; x < len; x++){
        char c = (char)(msg.charAt(x) + shift);
        if (c > 'z')
            s += (char)(msg.charAt(x) - (26-shift));
        else
            s += (char)(msg.charAt(x) + shift);
    }
    return s;
}

如何调用它:

System.out.println(cipher("abc", 3));  //prints def
System.out.println(cipher("xyz", 3));  //prints abc
于 2014-02-17T04:47:15.310 回答
7

下面的代码也处理大写和小写,并保留其他字符。

import java.util.Scanner;

public class CaesarCipher
{
    public static void main(String[] args)
    {
    Scanner in = new Scanner(System.in);
    int length = Integer.parseInt(in.nextLine());
    String str = in.nextLine();
    int k = Integer.parseInt(in.nextLine());

    k = k % 26;

    System.out.println(encrypt(str, length, k));

    in.close();
    }

    private static String encrypt(String str, int length, int shift)
    {
    StringBuilder strBuilder = new StringBuilder();
    char c;
    for (int i = 0; i < length; i++)
    {
        c = str.charAt(i);
        // if c is letter ONLY then shift them, else directly add it
        if (Character.isLetter(c))
        {
        c = (char) (str.charAt(i) + shift);
        // System.out.println(c);

        // checking case or range check is important, just if (c > 'z'
        // || c > 'Z')
        // will not work
        if ((Character.isLowerCase(str.charAt(i)) && c > 'z')
            || (Character.isUpperCase(str.charAt(i)) && c > 'Z'))

            c = (char) (str.charAt(i) - (26 - shift));
        }
        strBuilder.append(c);
    }
    return strBuilder.toString();
    }
}
于 2015-07-24T03:11:19.727 回答
1

该警告是由于您尝试将整数 ( int shift = 3) 添加到字符值。char如果您想避免这种情况,可以将数据类型更改为。

Achar是 16 位,anint是 32。

char shift = 3;
// ...
eMessage[i] = (message[i] + shift) % (char)letters.length;

顺便说一句,您可以简化以下内容:

char[] message = {'o', 'n', 'c', 'e', 'u', 'p', 'o', 'n', 'a', 't', 'i', 'm', 'e'}; 

至:

char[] message = "onceuponatime".toCharArray();
于 2013-10-01T05:43:38.280 回答
1

实现凯撒密码的两种方法:

选项 1:将字符更改为 ASCII 数字,然后您可以增加该值,然后将其恢复为新字符。

选项 2:使用 Map 将每个字母映射到这样的数字。

A - 0
B - 1
C - 2
etc...

使用地图,您不必每次都重新计算班次。然后,您可以通过以下映射将明文更改为加密。

于 2013-10-01T06:09:38.453 回答
0

您好...我已经为凯撒密码创建了一个 java 客户端服务器应用程序...我创建了一个可以正确解密文本的新公式...抱歉只适用于小写..!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class ceasarserver extends JFrame implements ActionListener {
    static String cs = "abcdefghijklmnopqrstuvwxyz";
    static JLabel l1, l2, l3, l5, l6;
    JTextField t1;
    JButton close, b1;
    static String en;
    int num = 0;
    JProgressBar progress;

    ceasarserver() {
        super("SERVER");
        JPanel p = new JPanel(new GridLayout(10, 1));
        l1 = new JLabel("");
        l2 = new JLabel("");
        l3 = new JLabel("");
        l5 = new JLabel("");
        l6 = new JLabel("Enter the Key...");
        t1 = new JTextField(30);
        progress = new JProgressBar(0, 20);
        progress.setValue(0);
        progress.setStringPainted(true);
        close = new JButton("Close");
        close.setMnemonic('C');
        close.setPreferredSize(new Dimension(300, 25));
        close.addActionListener(this);
        b1 = new JButton("Decrypt");
        b1.setMnemonic('D');
        b1.addActionListener(this);
        p.add(l1);
        p.add(l2);
        p.add(l3);
        p.add(l6);
        p.add(t1);
        p.add(b1);
        p.add(progress);
        p.add(l5);
        p.add(close);
        add(p);
        setVisible(true);
        pack();
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == close)
            System.exit(0);
        else if (e.getSource() == b1) {
            int key = Integer.parseInt(t1.getText());
            String d = "";
            int i = 0, j, k;
            while (i < en.length()) {
                j = cs.indexOf(en.charAt(i));
                k = (j + (26 - key)) % 26;
                d = d + cs.charAt(k);
                i++;
            }
            while (num < 21) {
                progress.setValue(num);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                }
                progress.setValue(num);
                Rectangle progressRect = progress.getBounds();
                progressRect.x = 0;
                progressRect.y = 0;
                progress.paintImmediately(progressRect);
                num++;
            }
            l5.setText("Decrypted text: " + d);
        }
    }

    public static void main(String args[]) throws IOException {
        new ceasarserver();
        String strm = new String();
        ServerSocket ss = new ServerSocket(4321);
        l1.setText("Secure data transfer Server Started....");
        Socket s = ss.accept();
        l2.setText("Client Connected !");
        while (true) {
            Scanner br1 = new Scanner(s.getInputStream());
            en = br1.nextLine();
            l3.setText("Client:" + en);
        }
    }

客户端类:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class ceasarclient extends JFrame {
    String cs = "abcdefghijklmnopqrstuvwxyz";
    static JLabel l1, l2, l3, l4, l5;
    JButton b1, b2, b3;
    JTextField t1, t2;
    JProgressBar progress;
    int num = 0;
    String en = "";

    ceasarclient(final Socket s) {
        super("CLIENT");
        JPanel p = new JPanel(new GridLayout(10, 1));
        setSize(500, 500);
        t1 = new JTextField(30);
        b1 = new JButton("Send");
        b1.setMnemonic('S');
        b2 = new JButton("Close");
        b2.setMnemonic('C');
        l1 = new JLabel("Welcome to Secure Data transfer!");
        l2 = new JLabel("Enter the word here...");
        l3 = new JLabel("");
        l4 = new JLabel("Enter the Key:");
        b3 = new JButton("Encrypt");
        b3.setMnemonic('E');
        t2 = new JTextField(30);
        progress = new JProgressBar(0, 20);
        progress.setValue(0);
        progress.setStringPainted(true);
        p.add(l1);
        p.add(l2);
        p.add(t1);
        p.add(l4);
        p.add(t2);
        p.add(b3);
        p.add(progress);
        p.add(b1);
        p.add(l3);
        p.add(b2);
        add(p);
        setVisible(true);
        b1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
                    pw.println(en);
                } catch (Exception ex) {
                }
                ;
                l3.setText("Encrypted Text Sent.");
            }
        });
        b3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String strw = t1.getText();
                int key = Integer.parseInt(t2.getText());
                int i = 0, j, k;
                while (i < strw.length()) {
                    j = cs.indexOf(strw.charAt(i));
                    k = (j + key) % 26;
                    en = en + cs.charAt(k);
                    i++;
                }
                while (num < 21) {
                    progress.setValue(num);
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException exe) {
                    }
                    progress.setValue(num);
                    Rectangle progressRect = progress.getBounds();
                    progressRect.x = 0;
                    progressRect.y = 0;
                    progress.paintImmediately(progressRect);
                    num++;
                }
            }
        });
        b2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        pack();
    }

    public static void main(String args[]) throws IOException {
        final Socket s = new Socket(InetAddress.getLocalHost(), 4321);
        new ceasarclient(s);
    }
}
于 2014-01-15T15:16:23.980 回答
0

这是我可以使用凯撒密码进行加密的程序的Java Stream API实现:

public String encrypt(String plaintext) {
  return plaintext.toLowerCase().chars()
    .mapToObj(plaintextLetter -> plaintextLetter == ' ' ? ' ' : applyEncryptionAlgorithm(plaintextLetter))
    .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
    .toString()
    .toUpperCase();  // convention - ciphertext is in uppercase
}

private int applyEncryptionAlgorithm(int plaintextLetter) {
  plaintextLetter -= 'a';
  int ciphertextLetter = (plaintextLetter + 3) % 26;
  return ciphertextLetter + 'a';
}

还有一个单元测试:

@Test
public void testEncrypt() {
  String plaintext = "meet me after the toga party";
  String ciphertext = "PHHW PH DIWHU WKH WRJD SDUWB";

  String result = caesarCipher.encrypt(plaintext);

  assertEquals(ciphertext, result);
}
于 2021-10-27T18:42:39.537 回答
0

//我们可以使用 char 作为整数作为 Java 将每个字符存储为 ascii 整数

字符串旋转密码(字符串输入,整数旋转因子){

    char [] inputArr = input.toCharArray();

    String resultStr = "";

    for (char ch: inputArr ) {
        if(ch < 58 && ch>48){
            int withRotetionFactor = ch + rotationFactor;
            if(withRotetionFactor < 57){
              resultStr = resultStr + (char) withRotetionFactor;
           }else {
                 int looprotation =  withRotetionFactor - 10;
                resultStr = resultStr + (char)looprotation;
            }
        }else  if(ch < 91 && ch>63){
            int withRotetionFactor = ch + rotationFactor;
            if(withRotetionFactor < 91){
                resultStr = resultStr + (char) withRotetionFactor;
            }else {
                int looprotation =  withRotetionFactor - 26;
                resultStr = resultStr + (char)looprotation;
            }
        }else if(ch < 123 && ch>96){
            int withRotetionFactor = ch + rotationFactor;
            if(withRotetionFactor < 123){
                resultStr = resultStr + (char) withRotetionFactor;
            }else {
                int looprotation =  withRotetionFactor - 26;
                resultStr = resultStr + (char)looprotation;
            }
        }else {
            resultStr = resultStr + ch;
        }



    }
    return resultStr;

}
于 2021-07-19T15:54:23.510 回答