Converting the integer representation of a word back to a String - java

This is a homework assignment and I'm having trouble with my output. Everything works as expected except the Integer.toString() isn't giving me the result I want. It is still outputting just a bunch of numbers when I want them to be converted to the actual word. Here's the code and output:
import java.io.*;
public class NumStream extends OutputStream
{
public void write(int c) throws IOException
{
StringBuffer sb = new StringBuffer();
switch(c)
{
case ' ': sb.append(" ");
break;
case '1': sb.append("One");
break;
case '2': sb.append("Two");
break;
case '3': sb.append("Three");
break;
case '4': sb.append("Four");
break;
case '5': sb.append("Five");
break;
case '6': sb.append("Six");
break;
case '7': sb.append("Seven");
break;
case '8': sb.append("Eight");
break;
case '9': sb.append("Nine");
break;
case '0': sb.append("Zero");
break;
default: sb.append(Integer.toString(c));
break;
}
System.out.print(sb);
}
public static void main(String[] args)
{
NumStream ns = new NumStream();
PrintWriter pw = new PrintWriter(new OutputStreamWriter(ns));
pw.println("123456789 and ! and # ");
pw.flush();
}
}
the output is: OneTwoThreeFourFiveSixSevenEightNine 97110100 33 97110100 35 1310
can somebody please tell me how to format code easier in this forum? I had to manually 8 space indent each line and there's got to be an easier way!

For characters that aren't digits, you're taking the character code and converting it to a number. So 97 110 and 100 are the character codes for 'a', 'n', and 'd' while 33 and 35 are ! and #.
What you probably want for your default case is just:
default: sb.append((char)c); break;
Note that creating a new StringBuffer each time the write routine is called is extremely wasteful and inefficient. Since you're only ever appending one string/char to it, you might as well just print that string/char directly rather than copying through a StringBuffer.

You are outputing the ascii code of characters which are not digits in sb.append(Integer.toString(c)).

Related

Multiple args in a java switch

I am expecting my input to be one of three groups of chars and need to decide what to do with it based on which group it falls in. I'm trying to figure out how to define a switch with multiple cases to do this. Here is what I have so far:
while(in.hasNextChar())
{
char test = in.nextChar();
List<Signal> out = new List<Signal>(0);
switch(test)
{
case '1','0','x','X':
out.add(fromString(test));
break;
case ' ','/t':
break;
default:
throw new ExceptionLogicMalformedSignal;
}
}
return out;
}
You have the syntax wrong. You need to take advantage of fall-through:
switch(test) {
case '1':
case '0':
case 'x':
case 'X':
out.add(fromString(test));
break;
case ' ':
case '\t':
break;
default:
throw new ExceptionLogicMalformedSignal;
}
A case is just a label, very similar to what you'd use with a goto (which is essentially what is happening behind the scenes). It's not a statement, since it does nothing itself — it just names an address. So if test is '0', it can happily continue through the 'x' and 'X' cases to reach the actual statement code since there's not anything being done by those labels. Only break "ends" a case.
You can actually insert code between cases even without a break:
switch(test) {
case '1':
System.out.println("This is printed by case '1'");
case '0':
System.out.println("This is printed by both case '1' and case '0'");
break;
case 'x':
case 'X':
System.out.println("This is only printed by the Xs");
break;
default:
break;
}

Switch structure: entering a zip code to associate it with a geographic area but only returning the first digit?

Before everything else, here's the code I came up with:
package decision;
import java.util.Scanner;
public class ZIP {
public static void main(String[] args) {
Scanner input=new Scanner (System.in);
char zipCode;
System.out.println("Enter your zip code number: ");
zipCode=input.next().charAt(0);
switch (zipCode) {
case 0: case 2: case 3:
System.out.println(zipCode + " is on the East Coast.");
break;
case 4: case 5: case 6:
System.out.println(zipCode + " is in the Central Plains Area.");
break;
case 7:
System.out.println(zipCode + " is in the South.");
break;
case 8: case 9:
System.out.println(zipCode + " is in the West.");
break;
default:
System.out.println(zipCode + " is an invalid ZIP Code.");
}
}
}
(Just learned about switch structures today and wondered where they were when my code was full of nested if's lol.)
Basically, this program is supposed to accept only the first digit of the zip code a user enters (which, he enters in full - five digits) but I want the console to print all five digits of the zip code during output.
For example, the user would put in 87878. The program will only accept the first digit (which is 8) to associate it with a specific area, but when I print it out, I want the console to print: "(zipCode) is in the West."
I've tried changing the data type of zipCode to char, so that I can use the charAt(0) method I learned only very recently, but given the code I provided, the console would print this out:
Enter your zip code number:
20098
2 is an invalid ZIP Code.
What can I do to get my desired output? Thanks in advance!
EDIT:
This is how I want the console to look like:
Enter your zip code number:
20098
20098 is on the East Coast.
The problem is that for example if zipCode is equals to '0', its int value is actually equals to 48 and not 0.
If you do :
char c = '0';
System.out.println((int)c);
You will see that it outputs 48. Why ?
Because in Java, the char data type is a single 16-bit Unicode character (see encoding table below).
If you take a look at this table, you see that 0 is encoded as 0x0030 = 3*16^1 = 48, 1 as 0x0031 = 3*16^1 + 1*16^0 = 49.
So to avoid that :
Change your case labels as case 48: case 50: case 51 (for 0,2,3) and so on
Change your case labels as case '0': case '2': case '3' and so on.
Personally, I would recommend you the second solution which is actually more clear and simple.
Demo here.
If you want to keep testing on integer values in your case labels, you could do :
int zipCode = Character.getNumericValue(input.next().charAt(0));
Edit :
To get the output you want you can store the input of the user in a String variable.
System.out.println("Enter your zip code number: ");
String code = input.next();
char zipCode = code.charAt(0);
switch (zipCode) {
case '0': case '2': case '3':
System.out.println(code + " is on the East Coast.");
break;
/**/
default:
System.out.println(code + " is an invalid ZIP Code.");
}

How can I make this better

Ok here I have a switch case statement which is falling through and trying every option. Basically I want something that if the user enters the letter A in the textbox the background will change to b! if they dont enter the letter A then I want it to stop executing the code. But what has been happening is if the user enters lets say for example the letter Q when the background is letter A then the background will change to letter R instead of telling the user that they are wrong. basically I would like to know how I can stop the background from changing if the user does not enter the letter they are on here is the code.
public void afterTextChanged(Editable s) {
char ch = words.getText().toString().charAt(0);
switch(ch - 'A') {
case 0:
//A;
gestureViewer.setBackgroundResource(R.drawable.lettersb);
break;
case 1:
gestureViewer.setBackgroundResource(R.drawable.lettersc);
break;
case 2:
gestureViewer.setBackgroundResource(R.drawable.lettersd);
break;
case 3:
gestureViewer.setBackgroundResource(R.drawable.letterse);
break;
case 4:
gestureViewer.setBackgroundResource(R.drawable.lettersf);
break;
case 5:
gestureViewer.setBackgroundResource(R.drawable.lettersg);
break;
case 6:
gestureViewer.setBackgroundResource(R.drawable.lettersh);
break;
case 7:
gestureViewer.setBackgroundResource(R.drawable.lettersi);
break;
case 8:
gestureViewer.setBackgroundResource(R.drawable.lettersj);
break;
case 9:
gestureViewer.setBackgroundResource(R.drawable.lettersk);
break;
case 10:
gestureViewer.setBackgroundResource(R.drawable.lettersl);
break;
case 11:
gestureViewer.setBackgroundResource(R.drawable.lettersm);
break;
case 12:
gestureViewer.setBackgroundResource(R.drawable.lettersn);
break;
case 13:
gestureViewer.setBackgroundResource(R.drawable.letterso);
break;
case 14:
gestureViewer.setBackgroundResource(R.drawable.lettersp);
break;
case 15:
gestureViewer.setBackgroundResource(R.drawable.lettersq);
break;
case 16:
gestureViewer.setBackgroundResource(R.drawable.lettersr);
break;
case 17:
gestureViewer.setBackgroundResource(R.drawable.letterss);
break;
case 19:
gestureViewer.setBackgroundResource(R.drawable.letterst);
break;
case 20:
gestureViewer.setBackgroundResource(R.drawable.lettersu);
break;
case 21:
gestureViewer.setBackgroundResource(R.drawable.lettersv);
break;
case 22:
gestureViewer.setBackgroundResource(R.drawable.lettersw);
break;
case 23:
gestureViewer.setBackgroundResource(R.drawable.lettersx);
break;
case 24:
gestureViewer.setBackgroundResource(R.drawable.lettersy);
break;
case 25:
gestureViewer.setBackgroundResource(R.drawable.lettersz);
break;
would it be better if I set the pictures in an array and then went from there? Ive tried including If switch case, but it didnt work at all....
I'd pre-populae an array and invoke:
gestureViewer.setBackgroundResource(myArray[ch - 'A']);
It will make your code much more readable.
You can also do it with a Map<Character,MyImage> - it might allow you to add more features easily in the future.
If you do that, invokation will be using
gestureViewer.setBackgroundResource(myMap.get(ch));
Note that the array/map needs to be populated only once in the application's runtime.
You could, for example, put all the R.drawable.abc inside an Array and then address its index.
int[] bgImg = {R.drawable.a, ... , R.drawable.z}
char ch = words.getText().toString().toUpperCase().charAt(0);
int index = ch - 'A';
if(index > 0 && index < bgImg.length){
gestureViewer.setBackgroundResource(bgImg[index]);
} else {
gestureViewer.setBackgroundResource(R.drawable.standardImage);
}
Also note, that I'm using toUpperCase() to make sure you can substract the capital 'A'
Try:
public void afterTextChanged(Editable s) {
char ch = words.getText().toString().charAt(0);
int id = getResources().getIdentifier("letters" + ch, "drawable", context.getPackageName())
gestureViewer.setBackgroundResource(id);
}
}

Java Switch Statement - Is "or"/"and" possible?

I implemented a font system that finds out which letter to use via char switch statements. There are only capital letters in my font image. I need to make it so that, for example, 'a' and 'A' both have the same output. Instead of having 2x the amount of cases, could it be something like the following:
char c;
switch(c){
case 'a' & 'A': /*get the 'A' image*/; break;
case 'b' & 'B': /*get the 'B' image*/; break;
...
case 'z' & 'Z': /*get the 'Z' image*/; break;
}
Is this possible in java?
You can use switch-case fall through by omitting the break; statement.
char c = /* whatever */;
switch(c) {
case 'a':
case 'A':
//get the 'A' image;
break;
case 'b':
case 'B':
//get the 'B' image;
break;
// (...)
case 'z':
case 'Z':
//get the 'Z' image;
break;
}
...or you could just normalize to lower case or upper case before switching.
char c = Character.toUpperCase(/* whatever */);
switch(c) {
case 'A':
//get the 'A' image;
break;
case 'B':
//get the 'B' image;
break;
// (...)
case 'Z':
//get the 'Z' image;
break;
}
Above, you mean OR not AND. Example of AND: 110 & 011 == 010 which is neither of the things you're looking for.
For OR, just have 2 cases without the break on the 1st. Eg:
case 'a':
case 'A':
// do stuff
break;
The above are all excellent answers. I just wanted to add that when there are multiple characters to check against, an if-else might turn out better since you could instead write the following.
// switch on vowels, digits, punctuation, or consonants
char c; // assign some character to 'c'
if ("aeiouAEIOU".indexOf(c) != -1) {
// handle vowel case
} else if ("!##$%,.".indexOf(c) != -1) {
// handle punctuation case
} else if ("0123456789".indexOf(c) != -1) {
// handle digit case
} else {
// handle consonant case, assuming other characters are not possible
}
Of course, if this gets any more complicated, I'd recommend a regex matcher.
Observations on an interesting Switch case trap --> fall through of switch
"The break statements are necessary because without them, statements in switch blocks fall through:"
Java Doc's example
Snippet of consecutive case without break:
char c = 'A';/* switch with lower case */;
switch(c) {
case 'a':
System.out.println("a");
case 'A':
System.out.println("A");
break;
}
O/P for this case is:
A
But if you change value of c, i.e., char c = 'a';, then this get interesting.
O/P for this case is:
a
A
Even though the 2nd case test fails, program goes onto print A, due to missing break which causes switch to treat the rest of the code as a block. All statements after the matching case label are executed in sequence.
From what I understand about your question, before passing the character into the switch statement, you can convert it to lowercase. So you don't have to worry about upper cases because they are automatically converted to lower case.
For that you need to use the below function:
Character.toLowerCase(c);
Enhanced switch/ case / Switch with arrows syntax (Since Java 13):
char c;
switch (c) {
case 'A', 'a' -> {} // c is either 'A' or 'a'.
case ...
}

is there a utility method for this in commons-lang?

I searched for sometime but I couldn't find any
boolean isAlpha(final char character)
{
char c = Character.toUpperCase(character);
switch (c)
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
return true;
default:
return false;
}
}
Commons Lang has CharUtils.isAsciiAlpha, but perhaps you could just use java.lang.Character.isLetter(char) (javadoc). Not quite the same (the latter matches more than just A-Z ASCII), but may be enough for your needs.
I know this is not from lang, but how about return (c >= 'A' && c <= 'Z')?
You could use StringUtils.isAlpha
That switch is pretty verbose, if I had to write it myself I'd make something like:
boolean isAlpha(final char c) {
return "abcdefghijklmnopqrstuvwxyz".indexOf(Character.toLowerCase(c)) != -1;
}
You want CharUtils.isAsciiAlpha.
It should be faster than StringUtils.isAlpha(String) because you're not creating a new String object.
You avoid the cost of converting to an uppercase char in your original method.
It's more readable then range checks (which is how it's implemented).
java.lang.Character.isLetter(char) will return true for certain non-Latin characters for which your method returns false.
How about Character.isLetter()?
If you simply want to check whether the given character is somewhere between A-Z, an easier way to do this would be to use regular expressions:
Pattern.matches("[A-Z]", input)
Where input is a CharSequence. More information on the Java Pattern class: http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
Don't know how this would compare performance wise to the other options though.
Character class provides many useful APIs. You need not convert the character. Few examples are
Character.isLetter(char ch)
Character.isLowerCase(char ch)
Character.isUpperCase(char ch)
Character.isDigit(char ch)
Character.isLetterOrDigit(char ch)

Categories