1

I had posted a question yesterday about this program I have been working on but essentially I've programmed an encoder of sorts that takes a string and an integer and then adds to every character within the string the value of the integer and then finally prints the binary of the string assuming 8 bits for every symbol or character. For example ABC with integer(code) 4 should output 01000101 01000110 01000111 (EFG). Now, I've managed to get super close to completing this project but I've run into an issue when converting each character to binary which I assume is due to how I'm actually calculating the binary. Example: If a binary integer starts with a 0, then obviously I will need to pad the integer with a 0 on the far left. I've managed to do that but there are cases where the integer ends in 0 and I need to do the same thing except on the far right... I'm not sure if I'm making 100% sense but I have posted my code and test result with expected outcome below. As you can see, it converts almost perfectly except the value in the middle (B) adds an extra 2 zeroes instead of just one on the far left and I haven't figured out how to check to add an ending zero. Can someone please help me? How I should go ahead and handle converting to binary(8 bits) from characters?

I also need to figure out how to decode binary into the original message. Example: InputMessage: 01000101 01000110 01000111, InputCode: 4 OriginalMessage: ABC

public class Encoder{

public static void main (String[] args) {

    String msg;
    int code;
    int i;

    msg = getMsg();
    code = getCode();
    getBinaryMsg(getCodedMsg(msg, code));

}

public static String getMsg(){

    String msg;
    System.out.print("Input message: ");
    Scanner input = new Scanner(System.in);
    msg = input.nextLine();
    return msg;

}   

public static int getCode(){

    int code=0;
    System.out.print("Input Code from 1 - 10: ");
    Scanner input = new Scanner(System.in);
    return input.nextInt();

} 


public static String getCodedMsg(String msg, int code){

    int letterOrDigit;
    String codedMessage = "";

    for(int i = 0; i<= msg.length()-1; i++){

        letterOrDigit = msg.charAt(i);

        if(Character.isLetter(letterOrDigit)){
            letterOrDigit = (char)(msg.charAt(i)+code);
        }

        if((Character.isLowerCase(msg.charAt(i)) && letterOrDigit > 'z') || (Character.isUpperCase(msg.charAt(i)) && letterOrDigit > 'Z')){
            letterOrDigit = (char)(msg.charAt(i) - (26 - code));
        }

        if(Character.isDigit(letterOrDigit)){
            letterOrDigit = (char)(msg.charAt(i)+code);
        }       


        if(Character.isDigit(msg.charAt(i)) && letterOrDigit > '9'){
            letterOrDigit = (char)(msg.charAt(i) - (10 - code));
        }


        codedMessage +=(char)letterOrDigit;

    }

    return codedMessage;

}


public static void getBinaryMsg(String codedMessage){

    char[] strChar = codedMessage.toCharArray();
    int character;
    int remainder;
    int binaryInt;
    int revBinInt;
    int firstDigit;
    String paddedWithZero = "";
    String binaryMsg = "";

    for(int i = 0; i < strChar.length; i++){

        binaryInt = 0;
        revBinInt = 0;
        firstDigit = 0;
        character = strChar[i];

            //Calculating 8 binary bits
            for(int j = 0; j <= 7; j++){

                remainder = character % 2;
                binaryInt = binaryInt * 10 + remainder;
                character = character / 2;

            }
            //Reversing the above for loop so that binary is correct
            while(binaryInt != 0){

                remainder = binaryInt % 10;
                revBinInt = revBinInt * 10 + remainder;
                binaryInt = binaryInt / 10;

            }

            firstDigit += revBinInt/(int)(Math.pow(10,(int)Math.log(revBinInt)));

            if(firstDigit == 0 && numOfDigits(revBinInt) <= 7){ 
                binaryMsg += String.format("%8s", Integer.toString(revBinInt)).replace(' ', '0') + " ";
            }

    }   

    System.out.print(binaryMsg);

}

//Counts the number of digits in case binary number starts or ends in 0
public static int numOfDigits(int number){

    int count = 0;

    while(number !=0){

        number = number/10;
        count++;
    }

    return count;

}   

}

Test Result:
Input:    ABC, 4
Output:   01000101 00100011 01000111
Expected: 01000101 01000110 01000111
  • Is your problem formatting or math? We don't need the back story or the large quantity of irrelevant code. Please edit your question to show as few lines as possible to show the problem by reading and following our [MCVE help page](https://stackoverflow.com/help/mcve). – Bohemian Jun 23 '18 at 21:38

2 Answers2

1

As you say, you were almost done. But the binary encoding wasn't working as expected. Here is my suggestion:

  public static void getBinaryMsg(String codedMessage) {
    String binary = toBinary(codedMessage);
    System.out.println(binary);
  }

  private static String toBinary(String codedMessage) {
    String binary = codedMessage.chars().boxed().map(c -> pad(Integer.toBinaryString(c), 8, '0') + " ").collect(Collectors.joining());
    return binary;
  }

  private static String pad(String s, int n, char c) {
    return String.format("%"+n+"s", Integer.parseInt(s)).replace(' ', c);
  }

Using Integer.toBinaryString(int i) you don't have to reinvent the wheel. The only thing you have to add is the padding, to get every binary formatted to eight bits. You did it well according to: How to get 0-padded binary representation of an integer in java?

LuCio
  • 5,055
  • 2
  • 18
  • 34
  • This seems like a very elegant answer but could you please explain what .boxed().map() does? I assume it's mapping each character in the string and converting it to it's binary equivalent with proper padding but that's all I can get from it. Is it possible to explain it in more simpler terms? – countercoded Jun 23 '18 at 22:14
  • Starting with a `String s` invoking `s.chars()`you get an `IntStream`. The `map`-method on an `IntStream` is restricted to return an `IntStream`again. But in this case we want to map the integer (which is representing a character) to a `String`. Using `boxed()`we get an ordinary `Stream` where we can `map` to the binary string representation. – LuCio Jun 23 '18 at 22:26
0

Here's a piece of code that trims zeros on both ends of a binary string:

String s = "00010111110100";
Pattern p = Pattern.compile("(1+[01]*1+)|(1)");
Matcher m = p.matcher(s);
if (m.find()) {
    System.out.println(m.group());
}

It uses a regular expression (1+[01]*1+)|(1).

| in the epression means or, so it says (1+[01]*1+) or (1).

In (1+[01]*1+) 1+ means one or more repetitions of 1 and [01]* means 0 or more repetitions or 1 or 0.

(1) means just 1, to handle the case where your string looks like this: 00010000.

Edit: note that you can actually use (1[01]*1)|(1), since [01]* will handle the case of multiple 1's.

Coder-Man
  • 2,391
  • 3
  • 11
  • 19
  • @countercoded what exactly does "properly" mean? – Coder-Man Jun 23 '18 at 20:43
  • Thank you for your input. I am trying to make it so that the zeroes are accurately placed within each binary string. Example: 'B' with code 4 -> 01000110 BUT I'm getting 100011. I need to ADD one zero to the left and ADD one zero to the right. Example: 'A' with code 4 -> 01000101 but again I am getting 1000101. I created a method to check the number of digits in the string and if it was less than 7 (like 'A'), I padded one zero to the left. – countercoded Jun 23 '18 at 20:52
  • @countercoded, ah, okay, you add zeroes, and what is your problem exactly? Why do you add zeroes to both ends? – Coder-Man Jun 23 '18 at 20:55
  • My problem is that I have to calculate 8-bits for every shifted character code and pad it with zeroes if the converted character code is less than 8 bits. I think the way I'm calculating my binary conversion is incorrect and need to rethink how to do it.. Any thoughts? – countercoded Jun 23 '18 at 21:01
  • @countercoded yes, it is incorrect if you pad on both ends. You should only pad on the left, consider 3 bit binary strings, for example 11 you pad it on the left and it becomes 011, but you should not pad it on the right! Why? because 011 = 0 * (2^2) + 1 * (2 ^ 1) + 1 * (2^0) = 3, same for 11 = 1 * (2^1) + 1 * (2 ^ 0) = 3. But what about 110? 110 = 1 * (2 ^ 2) + 1 * (2 ^ 1) + 0 * (2 ^ 0) = 6. – Coder-Man Jun 23 '18 at 21:17
  • 1
    All in all, when you add a zero on the left it has no effect, but when you add a zero on the right the effect is multiplication by 2. For example, consider binary strings 1, 10, 100, 1000, 1 is 1, 10 is 2, 100 is 4 and 1000 is 8. Don't do this and always pad on the left. In your case if you pad on the left and have strings 1, 01, 001, and 0001, they are all equal to 1. – Coder-Man Jun 23 '18 at 21:18
  • Thank you very much. That makes a ton of sense – countercoded Jun 23 '18 at 21:57