How can I uppercase and lowercase a Char - java

GWT is not allowing me to use Character.toUpperCase(char) and Character.toLowerCase(char). How can I rewrite the method bellow to not use the Character class or any external library
public static String toDisplayCase(String s) {
final String ACTIONABLE_DELIMITERS = " '-/"; // these cause the character following
// to be capitalized
StringBuilder sb = new StringBuilder();
boolean capNext = true;
for (char c : s.toCharArray()) {
c = (capNext)
? Character.toUpperCase(c)
: Character.toLowerCase(c);
sb.append(c);
capNext = (ACTIONABLE_DELIMITERS.indexOf((int) c) >= 0); // explicit cast not needed
}
return sb.toString();
}

If somehow, you are not allowed to use Character class (though that sounds quite crazy), you may add or subtract ASCII values.
eg:
for (char c : s.toCharArray()) {
c = (capNext)
? ( (c>='a'&&c<='z') ? c+32 : c) //to Upper Case
: ( (c>='A'&&c<='Z') ? c-32 : c) //to Lower Case
sb.append(c);
capNext = (ACTIONABLE_DELIMITERS.indexOf((int) c) >= 0); // explicit cast not needed
}

Just use basic operators
if (c >= 'a' && c <= 'z')
c = c - 'a' + 'A'; // lower to upper
if (c >= 'A' && c <= 'Z')
c = c - 'A' + 'a'; // upper to lower

Here are toLower and toUpper using ascii values. Hope it helps.
static char toUpperCase(char c) {
if (97 <= c && c <= 122) {
c = (char) ((c - 32));
}
return c;
}
static char toLowerCase(char c) {
if (65 <= c && c <= 90) {
c = (char) ((c + 32));
}
return c;
}

Related

Java Vigenere Cipher

I'am trying to decipher Vigenere_Cipher
when i enter BEXR TKGKTRQFARI the output is JAVAPROGRAMMING But i want
to put space like JAVA PROGRAMMING.
My Code
public static String VigenereDecipher(String text) {
String keyword = "SECRET";
String decipheredText = "";
text = text.toUpperCase();
for (int i = 0, j = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c < 'A' || c > 'Z') continue;
decipheredText += (char)((c - keyword.charAt(j) + 26) % 26 + 'A');
j = ++j % keyword.length();
}
return decipheredText;
}
You're explicitly ignoring the spaces. You simply need to add this line:
if (c == ' ') {
decipheredText += ' ';
}
Make sure to put it right before this line:
if (c < 'A' || c > 'Z') continue;
You are ignoring the space. Check for space as you are checking for character range 'A' to 'Z' and add it to decipheredText as space only as you don't want space to treated as another character.

String to Unicode in Java

I have a large string I need to convert all the non alphanumeric chars to unicode
For example
Input string : abc12/dad-das/das_sdj
Output String : abc12:002Fdad:002Ddas:002Fdas:002Fsdj
Currently I am using this function
for (char c : str.toCharArray()) {
System.out.printf(":%04X \n", (int) c);
}
Is there a better way to do it ?
Here are two ways to do it:
// Looping over string characters
private static String convert(String input) {
StringBuilder buf = new StringBuilder(input.length() + 16);
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
buf.append(c);
else
buf.append(String.format(":%04X", (int) c));
}
return buf.toString();
}
// Using regular expression
private static String convert(String input) {
StringBuffer buf = new StringBuffer(input.length() + 16);
Matcher m = Pattern.compile("[^a-zA-Z0-9]").matcher(input);
while (m.find())
m.appendReplacement(buf, String.format(":%04X", (int) m.group().charAt(0)));
return m.appendTail(buf).toString();
}
Test
System.out.println(convert("abc12/dad-das/das_sdj"));
Output
abc12:002Fdad:002Ddas:002Fdas:005Fsdj

customize the number of digits when shown the alphabet

The code for displaying all combinations 5 letters is:
for(char alphabet = 'A'; alphabet <= 'Z';alphabet++)
for(char s = 'A'; s <= 'Z';s++)
for(char b = 'A' ; b <= 'Z';b++)
for(char f = 'A'; f <= 'Z'; f++)
for (char d = 'A'; d <= 'Z'; d++)
System.out.println(alphabet+""+s+""+b+""+f+ ""+d );
But my boss wants a version in which you could customize which number of letters is displayed for example if he enters "3" it should display "aaa" and if he enters 5 it should display "aaaaa" and that for all combinations of a to z.
Recursion!:
public static class Main {
public static void main() {
printAll("",3);
}
static void printAll(String prefix, int n) {
if( n==0 ) {
System.out.println(prefix);
} else {
for(char c='A'; c<= 'Z'; c++) {
printAll(prefix+c, n-1);
}
}
}
}
Beware! Only run with small values of n!

How do I shift letters down in a loop

I'm trying to create a loop which only returns letters. In my code, I get symbols that I don't want. How do I fix my loop so that when my integer is +3, it only gives me letters?
public static String caesarDecrypt(String encoded, int shift){
String decrypted = "";
for (int i = 0; i < encoded.length(); i++) {
char t = encoded.charAt(i);
if ((t <= 'a') && (t >= 'z')) {
t -= shift;
}
if (t > 'z') {
t += 26;
} else if ((t >= 'A') && (t <= 'Z')) {
t -= shift;
if (t > 'Z')
t += 26;
} else {
}
decrypted = decrypted + t;
}
}
You are subtracting the shift value from the letters. Therefore, the new letter can never be > 'z'. You should check if the it is < 'a' (or 'A', respectively).
StringBuilder decrypted = new StringBuilder(encoded.length());
for (int i = 0; i < encoded.length(); i++)
{
char t = encoded.charAt(i);
if ((t >= 'a') && (t <= 'z'))
{
t -= shift;
while (t < 'a')
{
t += 26;
}
}
else if ((t >= 'A') && (t <= 'Z'))
{
t -= shift;
while (t < 'A')
{
t += 26;
}
}
decrypted.append(t);
}
return decrypted.toString();
Also, you shouldn't be using String concatenation to generate the result. Learn about StringBuilder instead.
EDIT: To make sure the new letter is in the range 'a' .. 'z' for an arbitrary (positive) shift, you should use while instead of if.
I am not giving you exact code. But I can help you in logic:
Check whether you are reaching end points (a, A, z, Z) due to the shift.
If you exceed the end points either way, then compute the distance between end points and shifted t. Add/subtract/modulus (based on the end point) this distance to the other endpoint to get the exact letter.
Something like this? (Warning, untested)
public static String caesarDecrypt(String encoded, int shift) {
String decrypted = "";
for (int i = 0; i < encoded.length(); i++) {
char t = encoded.charAt(i).ToUpper();
decrypted = decrypted + decode(t, shift);
}
}
// call with uppercase ASCII letters, and a positive shift
function decode(char n, int shift)
{
if ((n < 'A') || (n > 'Z')) return ('-');
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var s = str.charAt(((n - 'A') + shift)%26);
return(s);
}
As you are naming your method caesarDecrypt (I assume you mean encrypt), I think you want a shift in the alphabet including wrapping around.
This code will do that for you:
public class Snippet {
public static void main(String[] args) {
System.out.println(caesarShift("This is a Fizzy test.", 5));
System.out.println(caesarShift("Ymnx nx f Kneed yjxy.", -5));
}
public static String caesarShift(String input, int shift) {
// making sure that shift is positive so that modulo works correctly
while (shift < 0)
shift += 26;
int l = input.length();
StringBuffer output = new StringBuffer();
for (int i = 0; i < l; i++) {
char c = input.charAt(i);
char newLetter = c;
if (c >= 'a' && c <= 'z') { // lowercase
newLetter = (char) ((c - 'a' + shift) % 26 + 'a'); // shift, wrap it and convert it back to char
} else if (c >= 'A' && c <= 'Z') { // uppercase
newLetter = (char) ((c - 'A' + shift) % 26 + 'A'); // shift, wrap it and convert it back to char
}
output.append(newLetter);
}
return output.toString();
}
}
This will handle lowercase and uppercase letters. Everything else will be left as it is (like spaces, punctuations, etc).
Please take some time to look at this code to understand how it works. I have put some comments to make it clearer. From your code I think you were a bit confused, so it is important that you understand this code very well. If you have questions, feel free to ask them.
This code
String start = "abcdefghijklmnopqrstuvwxyz";
String encrypted = caesarShift(start, 3);
String decrypted = caesarShift(encrypted, -3);
System.out.println("Start : " + start);
System.out.println("Encrypted : " + encrypted);
System.out.println("Decrypted : " + decrypted);
will give this result
Start : abcdefghijklmnopqrstuvwxyz
Encrypted : defghijklmnopqrstuvwxyzabc
Decrypted : abcdefghijklmnopqrstuvwxyz

ASCII character ranges using for loop

How do I cover the range of all letters lowercase a-z & uppercase A-Z using a for loop? Currently I have:
public static boolean isJavaIdentifierStart (char c) {
if (c == 'a') { //how do I cover the range of all lowercase letters with a for loop?
return true;
} if (c=='Z') { //how do I cover all uppercase letters with a for loop?
return true;
} else if (c == '_') {
return true;
} else if (c == '$') {
return true;
} else
return false;
}
}
If would be much easier to test with the >= and <= operators:
if( c >= 'a' && c <= 'z' ) {
// do something
}
You don't actually need to test all of the values in the range, just make sure c falls inside it somewhere. You can do something similar for uppercase letters.
In fact you can simplify your method into a single return statement:
public static boolean isJavaIdentifierStart (char c) {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c == '_') ||
(c == '$');
}
However, I don't believe that Java identifiers can start with $, so your method is incorrect.
It's hard to guess what you want, but you could use:
for(char c = 'a'; c < 'z'; c++) {
System.out.println(c);
}
Edit to your comment:
Use this expression: (c >= 'a' && c <= 'Z') and similiar for range-
checking.
This works since char is a 16 bit unsigned integer, and therefore can be use in calculations.

Categories