Почему мой код заменяет только определенные символы методом замены строки? - PullRequest
3 голосов
/ 10 июля 2020

Для моего задания мне нужно написать код для кодирования / декодирования сообщения. Я близок к концу, когда начал обнаруживать, что всякий раз, когда я набираю сообщение, программа заменяет только определенные символы. Перевод довольно прост: для кодирования вы меняете a на противоположную букву алфавита, поэтому z. b к y, c к x, d к w, et c. Назначение выглядит следующим образом:

Этот проект включает в себя написание программы, которая кодирует и декодирует сообщения. Программа должна предлагать пользователю выбрать, следует ли кодировать или декодировать сообщение, а затем предлагать пользователю ввести сообщение. Пробел используется для разделения каждого слова в сообщении, а точка (.) Используется для обозначения конца предложения. Для кодирования и декодирования входящего сообщения необходимо использовать отдельные методы. Схема кодирования очень проста: кодовый эквивалент буквы A - Z, для B - Y,… и для Z - A, как показано в следующей таблице. Например, если пользователь выбирает кодирование такого предложения, как hello world, закодированным предложением будет svool dliow.

Вот мой код:

import java.util.Scanner ;
public class Project1
{
  public static void main(String[] args)
  {
    Scanner input = new Scanner(System.in) ;

    //prompt user to decide to encode or decode

    System.out.print("Please enter 1 to encode, or 2 to decode the message: ") ;
    int promptNumber = input.nextInt() ;

    if (promptNumber == 1) {
      System.out.println("You have choosen to encode the message.") ;      
      System.out.print("Please enter the message you wish to be encoded: ") ;
      String encode = input.next();
      encode += input.nextLine();
      encode = encodeMessage(encode) ;
      System.out.println("Your encoded message is now: " + encode) ;
    }
    else if (promptNumber == 2) {
      System.out.println("You have choosen to decode the message.") ;
      System.out.print("Please enter the message you wish to decode: ") ;
      String decode = input.next();
      decode += input.nextLine();
      decode = decodeMessage(decode) ;
      System.out.println("Your encoded message is now: " + decode) ;
    }    
    else
      System.out.println("Please enter a value of 1 or 2.") ;
  }

  //method for encoded calculation

  public static String encodeMessage(String message)
  {
    String str = message ;
    for (int i = 0; i < str.length(); i++) {
      switch (str.charAt(i)) {
        case 'a': str = str.replace('a', 'z') ; break ;
        case 'b': str = str.replace('b', 'y') ; break ;
        case 'c': str = str.replace('c', 'x') ; break ;
        case 'd': str = str.replace('d', 'w') ; break ;
        case 'e': str = str.replace('e', 'v') ; break ;
        case 'f': str = str.replace('f', 'u') ; break ;
        case 'g': str = str.replace('g', 't') ; break ;
        case 'h': str = str.replace('h', 's') ; break ;
        case 'i': str = str.replace('i', 'r') ; break ;
        case 'j': str = str.replace('j', 'q') ; break ;
        case 'k': str = str.replace('k', 'p') ; break ;
        case 'l': str = str.replace('l', 'o') ; break ;
        case 'm': str = str.replace('m', 'n') ; break ;
        case 'n': str = str.replace('n', 'm') ; break ;
        case 'o': str = str.replace('o', 'l') ; break ;
        case 'p': str = str.replace('p', 'k') ; break ;
        case 'q': str = str.replace('q', 'j') ; break ;
        case 'r': str = str.replace('r', 'i') ; break ;
        case 's': str = str.replace('s', 'h') ; break ;
        case 't': str = str.replace('t', 'g') ; break ;
        case 'u': str = str.replace('u', 'f') ; break ;
        case 'v': str = str.replace('v', 'e') ; break ;
        case 'w': str = str.replace('w', 'd') ; break ;
        case 'x': str = str.replace('x', 'c') ; break ;
        case 'y': str = str.replace('y', 'b') ; break ;
        case 'z': str = str.replace('z', 'a') ; break ;
        case ' ': continue ;
        case '.': break ;
      }
    }
    return str ;
  }

  //method for decoded calculation

  public static String decodeMessage(String message)
  {
    String str = message ;
    for (int i = 0; i < str.length(); i++) {
      switch (str.charAt(i)) {
        case 'a': str = str.replace('a', 'z') ; break ;
        case 'b': str = str.replace('b', 'y') ; break ; //Error
        case 'c': str = str.replace('c', 'x') ; break ;
        case 'd': str = str.replace('d', 'w') ; break ; //Error
        case 'e': str = str.replace('e', 'v') ; break ;
        case 'f': str = str.replace('f', 'u') ; break ;
        case 'g': str = str.replace('g', 't') ; break ;
        case 'h': str = str.replace('h', 's') ; break ;
        case 'i': str = str.replace('i', 'r') ; break ;
        case 'j': str = str.replace('j', 'q') ; break ;
        case 'k': str = str.replace('k', 'p') ; break ;
        case 'l': str = str.replace('l', 'o') ; break ; //Error
        case 'm': str = str.replace('m', 'n') ; break ;
        case 'n': str = str.replace('n', 'm') ; break ;
        case 'o': str = str.replace('o', 'l') ; break ; 
        case 'p': str = str.replace('p', 'k') ; break ;
        case 'q': str = str.replace('q', 'j') ; break ;
        case 'r': str = str.replace('r', 'i') ; break ;
        case 's': str = str.replace('s', 'h') ; break ;
        case 't': str = str.replace('t', 'g') ; break ;
        case 'u': str = str.replace('u', 'f') ; break ;
        case 'v': str = str.replace('v', 'e') ; break ;
        case 'w': str = str.replace('w', 'd') ; break ;
        case 'x': str = str.replace('x', 'c') ; break ;
        case 'y': str = str.replace('y', 'b') ; break ; //Error
        case 'z': str = str.replace('z', 'a') ; break ;
        case ' ': continue ;
        case '.': break ;
      }
    }
    return str ;
  }
}

Ответы [ 6 ]

2 голосов
/ 10 июля 2020

Кажется, что вы перебираете свою строку по индексу, и вместо изменения текущего индекса вы меняете все вхождения этого конкретного значения в этой строке, независимо от того, изменили ли вы его или все еще нужно изменить это.

Давайте проясним это на примере: «aba» со следующим шифром: a => b, b => a

index 0: a => change all occurrences of a => result: bbb
index 1: b => change all occurrences of b => result: aaa
index 2: a => change all occurrences of a => result: bbb

, хотя вы явно ожидали сдвинуть только каждый индекс один раз. Если мы изменим это в вашем текущем коде, используя, скажем, char[], чтобы изменить значение в текущем индексе, мы получим что-то вроде этого:

public static String encodeMessage(String message) {
    char[] str = message.toCharArray();
    for (int i = 0; i < str.length; i++) {
        switch (str[i]) {
            case 'a':
                str[i] = 'z';
                break;
            case 'b':
                str[i] = 'y';
                break;
            case 'c':
                str[i] ='x';
                break;
            case 'd':
                str[i] ='w';
                break;
            case 'e':
                str[i] =  'v';
                break;
            case 'f':
                str[i] =  'u';
                break;
            case 'g':
                str[i] =  't';
                break;
            case 'h':
                str[i] =  's';
                break;
            case 'i':
                str[i] = 'r';
                break;
            case 'j':
                str[i] =  'q';
                break;
            case 'k':
                str[i] =  'p';
                break;
            case 'l':
                str[i] =  'o';
                break;
            case 'm':
                str[i] =  'n';
                break;
            case 'n':
                str[i] =  'm';
                break;
            case 'o':
                str[i] = 'l';
                break;
            case 'p':
                str[i] = 'k';
                break;
            case 'q':
                str[i] = 'g';
                break;
            case 'r':
                str[i] =  'i';
                break;
            case 's':
                str[i] =  'h';
                break;
            case 't':
                str[i] = 'g';
                break;
            case 'u':
                str[i] = 'f';
                break;
            case 'v':
                str[i] = 'e';
                break;
            case 'w':
                str[i] =  'd';
                break;
            case 'x':
                str[i] = 'c';
                break;
            case 'y':
                str[i] = 'b';
                break;
            case 'z':
                str[i] = 'a';
                break;
            case ' ':
                continue;
            case '.':
                break;
        }
    }
    return new String(str);
}

et voila:

Your encoded message is now: svool dliow

1 голос
/ 11 июля 2020

Логически ваши методы декодирования и кодирования абсолютно одинаковы, поэтому вам не нужно создавать для них отдельные методы.

Вы можете использовать Java 8 потоков для более функционального и читаемого кода. Здесь я работал со значениями ASCII каждого символа и получил соответствующее закодированное (или декодированное, в зависимости от того, как вы на него смотрите) значение.

public static String encodeOrDecode(String s) {
    return s.chars() // create int stream
            .map(i -> Character.isAlphabetic(i) ? (Character.isUpperCase(i) ? 155 - i: 219 - i) : i) // encode / decode
            .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) // convert intstream to StringBuilder
            .toString(); // StringBuilder to String
}
1 голос
/ 10 июля 2020

Я предлагаю вам использовать basi c arithmeti c, чтобы избежать слишком длинных switch-case, которые не только выглядят некрасиво, но также трудно отладить в случае каких-либо проблем. Значение ASCII для A равно 65, а Z - 90. Для строчных алфавитов он начинается с 97 и заканчивается 122. Вы можете использовать эти значения для определения формулы для кодирования и декодирования, как показано ниже:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter a sentence: ");
        String message = scanner.nextLine();
        System.out.println("Encoded: " + encodeOrDecodeMessage(message));
        System.out.println("Decoded: " + encodeOrDecodeMessage(encodeOrDecodeMessage(message)));
    }

    public static String encodeOrDecodeMessage(String message) {
        StringBuilder sb = new StringBuilder();
        for (char ch: message.toCharArray()) {
            if (Character.isAlphabetic(ch)) {
                sb.append(Character.isUpperCase(ch) ? (char) (90 + 65 - ch) : (char) (122 + 97 - ch));
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }
}

Пробный прогон:

Enter a sentence: hello world
Encoded: svool dliow
Decoded: hello world

Другой образец запустить:

Enter a sentence: Hello World!
Encoded: Svool Dliow!
Decoded: Hello World!
0 голосов
/ 11 июля 2020

В алфавите 26 букв от а до я. Если в java преобразовать символ в int, мы получим число от 97 до 122.

введите описание изображения здесь

String str = "abc zyx";
    char[] ch = str.toCharArray();
    int a = 97;
    int z = 122;

    LOOP:for (int i =0; i< ch.length; i++) {
        int no = ch[i];

        // if we don't find an alphabetic character, continue iteration
        if ((no < 97) || (no > 122)) continue LOOP;

        // if character is less than half of the alphabet
        // we switch the characters
        if (no <= 109) {
            int findDif = z - no;
            int findLetter = a + findDif;
            char replacedLetter = (char)findLetter;
            ch[i] = replacedLetter;
            continue LOOP;

        }

        // and the other side
        if (no >= 110) {
            int findDif = z - no;
            int findLetter = a + findDif;
            char replacedLetter = (char)findLetter;
            ch[i] = replacedLetter;
            continue LOOP;
        }
    }

    String converted = new String(ch);
    System.out.println(converted);    // [z,y,x, , a,b,c]
0 голосов
/ 10 июля 2020

интересный вопрос. Видя, как все остальные уже выявили проблему, заключающуюся в том, что вы заменяете символы после их кодирования, я не буду беспокоиться об этом. Когда я изучал объектно-ориентированное программирование I, они не разрешали нам использовать что-либо вроде ArrayList. При этом, вот решение, которое не требует импорта.

//method for encoded calculation
public static String encodeMessage(String message) {
 String encoded = message.toUpperCase();
 for (int i = 0; i < message.length(); i++) {
  int c = encoded.charAt(i);
  if (65 <= c && c <= 77) {    // first half of the alphabet
    int numC = 90 - (c - 65);
    char newC = (char) numC;
    encoded = encoded.substring(0, i) + newC + encoded.substring(i + 1);
  }
  if (77 < c && c <= 90) {  // second half of the alphabet
    int numC = 65 + (90 - c);
    char newC = (char) numC;
    encoded = encoded.substring(0, i) + newC + encoded.substring(i + 1);
  }
}
return encoded.toLowerCase();
}

В отличие от случая переключения для каждой буквы алфавита, я написал уравнение, которое использует значения Unicode символы (вызывая .toUpperCase (), чтобы сделать строку единообразной). Возьмем, например, символ C (значение Unicode 67). Уравнение выглядит следующим образом: 90 - (символ - 65) для первой половины алфавита и 65 + (90 - символ) для второй половины. C находится в первой половине алфавита, поэтому уравнение приведет к 90 - (67 - 65) = 88, значение Unicode для «X». Это полезно для кодирования букв, но применяется в обоих направлениях. Скажем, вы должны были вызвать encodeMessage("hello");, результат будет svool, повторное кодирование просто вернет сообщение к исходному. Это означает, что ваш метод decodeMessage представляет собой одну простую строку, в которой вы вызываете encodeMessage.

 // method for decoded calculation

  public static String decodeMessage(String message) {
    return encodeMessage(message);
  }

Если вы хотите узнать больше о Unicode, на этой странице есть удобная таблица. Также я рекомендую прочитать документацию по методу подстроки в классе String здесь . Надеюсь, это поможет, отправьте мне сообщение, если у вас есть вопросы, так как моя репутация недостаточно высока, чтобы отвечать на комментарии.

0 голосов
/ 10 июля 2020

Я дам вам несколько советов, чтобы вы могли поработать над этим, чтобы исправить проблему. Вы использовали метод замены String. Что он делает, так это заменяет все вхождения определенного слова указанным замещающим символом. Скажем, String sample = "aaaaaa"; Когда вы вызываете sample.replace('a','z');, вся строка будет преобразована в zzzzzzz. Это одна из причин, по которой ваш код не работает должным образом. Если вы хотите заменить только первое вхождение, вы можете проверить метод String replaceFirst

В случаях с несколькими переключателями, когда вы заменяете один символ другим, вы заменяете его на g for two characters (q and t), что вызовет логическую ошибку.

Когда вы получаете ввод от пользователя, вы сначала получаете один раз, используя next(), а затем снова nextLine(). Вместо того, чтобы делать это дважды, вы можете просто использовать nextLine(), чтобы получить целое предложение. По умолчанию nextLine() использует новую строку в качестве разделителя, то есть конец строки. Если вы хотите использовать "." в конце строки вы можете использовать его как input.nextLine("."). Таким образом, вы сможете читать каждую строку до полной остановки, удалить next(), который использует " " в качестве разделителя, а также убрать регистр для "." в вашем операторе switch.

Когда вы передаете какое-то значение функции, как вы это делали в:

public static String decodeMessage(String message) {
        //Code
}
and 
public static String encodeMessage(String message) {
        //Code
}

, вы можете напрямую использовать message внутри функции. Нет необходимости повторно назначать его какой-либо другой переменной str.

Наконец, то, что вы пытаетесь реализовать, называется Цезарь Шифр ​​. Вместо того, чтобы иметь много вариантов переключения и реализовывать его, вы можете сделать то же самое гораздо лучше. Если вы обратитесь к статье в Википедии, на которую я ссылаюсь, вы увидите, как то же самое можно сделать с помощью модульной арифметики c. Если вы не уверены, как поступить, посмотрите ASCII . Короче говоря, используя модульную арифметику c и значения ASCII, то же самое можно сделать, используя несколько строк. Поэтому я предлагаю вам изучить это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...