Cast from Integer to Character without using unsafe conversion - java

I have to write a method that has a parameter of type Integer and has to return an object of type Character.
If the value of the given parameter is presentable as a Character object,
Return it as a Character. Else return null.
My task is poorly formulated it says: "Unsafe conversions (e.g. from int to char) are not allowed in your code" I suppose it is not unsafe but also not allowed somehow?
My Code so far:
public Character methodName (Integer i) {
if (i >= 0 && i <= Character.MAX_VALUE) {
return Character.valueOf((char) i.intValue()); //unsafe conversion
}
else
return null;
}
I tried fixing it by any means but just could not come up with an solution not using the unsafe conversion, thank you very much in advance for helping!
Solution to this weird formulated task:
public Character methodName (Integer i) {
if (i >= 0 && i <= Character.MAX_VALUE) {
return (Character.toChars(i)[0]); //<- solution
}
else
return null;
}

To my mind
if (i >= 0 && i <= Character.MAX_VALUE) {
return Character.valueOf((char) i.intValue());
}
is completely safe according to your teacher's definition of "safe".
SO my teacher said it is indeed unsafe, because the value range of int is 2^32 and of char is 2^16.
The if test ensures that you only cast i.intValue() to a char when i is in the required (safe) range.
The flipside is that if a provably correct range check is not sufficient to make this "safe" enough for your teacher, then AFAIK there isn't a "safe" solution. All other less direct solutions also entail an explicit or implicit range check in some form ... and will therefore also be "unsafe".

Your conversion is safe here.
You're checking if the int is in the Character range
Then you cast using a builtin method
There might be another way but it's trickier and weird:
String iStr = Integer.toString(i.intValue())
char c = iStr.charAt(0)
Character crt = Character.valueOf(c)
I repeat myself but your approach is more than fine... I don't understand what does your teacher expect from you.

Related

Why use bit shifting instead of a for loop?

I created the following code to find parity of a binary number (i.e output 1 if the number of 1's in the binary word is odd, output 0 if the number of 1's is even).
public class CalculateParity {
String binaryword;
int totalones = 0;
public CalculateParity(String binaryword) {
this.binaryword = binaryword;
getTotal();
}
public int getTotal() {
for(int i=0; i<binaryword.length(); i++) {
if (binaryword.charAt(i) == '1'){
totalones += 1;
}
}
return totalones;
}
public int calcParity() {
if (totalones % 2 == 1) {
return 1;
}
else {
return 0;
}
}
public static void main(String[] args) {
CalculateParity bin = new CalculateParity("1011101");
System.out.println(bin.calcParity());
}
}
However, all of the solutions I find online almost always deal with using bit shift operators, XORs, unsigned shift operations, etc., like this solution I found in a data structure book:
public static short parity(long x){
short result = 0;
while (x != 0) {
result A=(x&1);
x >>>= 1;
}
return result;
}
Why is this the case? What makes bitwise operators more of a valid/standard solution than the solution I came up with, which is simply iterating through a binary word of type String? Is a bitwise solution more efficient? I appreciate any help!
The code that you have quoted uses a loop as well (i.e., while):
public static short parity(long x){
short result = 9;
while (x != 9) {
result A=(x&1);
x >>>= 1;
}
return result;
}
You need to acknowledge that you are using a string that you know beforehand will be composed of only digits, and conveniently in a binary representation. Naturally, given those constraints, one does not need to use bitwise operations instead one just parsers char-by-char and does the desired computations.
On the other hand, if you receive as a parameter a long, as the method that you have quoted, then it comes in handy to use bitwise operations to go through each bit (at a time) in a number and perform the desired computation.
One could also convert the long into a string and apply the same logic code-wise that you have applied, but first, one would have to convert that long into binary. However, that approach would add extra unnecessary steps, more code, and would be performance-wise worse. Probably, the same applies vice-versa if you have a String with your constraints. Nevertheless, a String is not a number, even if it is only composed of digits, which makes using a type that represents a number (e.g., long) even a more desirable approach.
Another thing that you are missing is that you did some of the heavy lifting by converting already a number to binary, and encoded into a String new CalculateParity("1011101");. So you kind of jump a step there. Now try to use your approach, but this time using "93" and find the parity.
If you want know if a String is even. I think this method below is better.
If you convert a String too
long which the length of the String is bigger than 64. there will a error occur.
both of the method you
mention is O(n) performance.It will not perform big different. but
the shift method is more precise and the clock of the cpu use will a little bit less.
private static boolean isEven(String s){
char[] chars = s.toCharArray();
int i = 0;
for(char c : chars){
i ^= c;
}
return i == 0;
}
You use a string based method for a string input. Good choice.
The code you quote uses an integer-based method for an integer input. An equally good choice.

why am i getting this "the type of the expression must be an array type but resolved to string" in JAVA [duplicate]

I am getting the "Must be an array type but it resolved to string" error in my code. It also says that i (in the code below) cannot be resolved to a variable which I don't get.
public class DNAcgcount{
public double ratio(String dna){
int count=0;
for (int i=0;i<dna.length();i++);
if (dna[i]== "c"){
count+= 1;
if (dna[i]=="g"){
count+=1;
double answer = count/dna.length();
return answer;
}
}
}
}
Could you guys please help me figure out where the problem lies? I'm new to coding in Java so I am not entirely comfortable with the format yet.
Thanks a lot,
Junaid
You cannot access a String's character using subscript (dna[i]). Use charAt instead:
dna.charAt(i) == 'c'
Also, "c" is a String, 'c' is a char.
One more thing - integer division ( e.g. int_a / int_b ) results in an int, and so you lose accuracy, instead - cast one of the ints to double:
double answer = count/(double)dna.length();
Use {} to define the scope of the loop. Also, as others already pointed out, use charAt instead of [] and use ' for characters, and use floating point division for the ratio.
for (int i = 0; i < dna.length(); i++) {
if (dna.charAt(i) == 'c') {
count += 1;
}
if (dna.charAt(i) == 'g') {
count += 1;
}
}
Or a bit shorter, use || to or the two clauses together
if (dna.charAt(i) == 'c' || dna.charAt(i) == 'g') {
count += 1;
}
I think you are currently a bit weak at brackets , this is what i understood from your code and corrected it;
public class DNAcgcount{
public double ratio(String dna){
int count=0;
for (int i=0;i<dna.length();i++){
if (dna.charAt(i)== 'c')
count+= 1;
if (dna.charAt(i)=='g')
count+=1;
}
double answer = count/(double)dna.length();
return answer;
}
}
After if we have to close the brackets when what you want in if is finished . I think you wanted count to be the number of time c or g is present in the dna.
You also did some other mistakes like you have to use 'c' and 'g' instead of "c" and "g" if you are using .charAt(i) because it will be treated like a character and then only you can compare .
You may view this link
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html
and you may also have a look at works you can do with string like charAt.
It seems like that you have a few problems with the main syntax of basic java functions like loops or if-else statement. Click here for a good tutorial on these.
You must correct your for-loop and your if-statement:
for(int i=0;i<dna.length();i++){
if(...){
...;
}
if(...){
...;
}
}
Now you wont get the Cant be resolved to a variable... exception.
Second thing is the usage of your string. You have to use it like this:
for(int i=0;i<dna.length();i++){
if(dna.charAt(i) == 'c'){
count += 1;
}
if(dna.charAt(i) == 'g'){
count += 1;
}
}
Now all your exceptions should be eleminated.
Your problem is with syntax dna[i], dna is a string and you access it as it would be an array by []. Use dna.charAt(i); instead.
You using String incorrectly. Instead of accessing via [] use dna.charAt(i).
Altough logically a string is an array of characters in Java a String type is a class (which means it has attributes and methods) and not a typical array.
And if you want to compare a single character to another enclose it with '' instead of "":
if (dna.charAt(i) == 'c')
.
.
There are two errors:
count should be double or should be casted do double answer = (double)count / dna.length();
and as mentioned above you should replace dna[i] with dna.charAt(i)

Why does java require a double equals sign?

Why does java require a double equals sign (==) when comparing Integers in a if statement?
For example
if(x = 3.141)
System.out.println("x is equal to pi.");
is incorrect, it should be
if(x == 3.141)
System.out.println("x is equal to pi.");
I know that "==" is used to compare integers and "=" is used to set an integer value, but why in a if statement does this remain true?
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
Is there any reason anyone would ever want to assign a variable a new value inside an if statement (if so please provide an example)?
This seems like a question that should already have an answer, but I was unable to find one on here or using google, if this is a duplicate question please tell me and I will remove it immediately.
Wouldn't it be confusing if = sometimes did assignment, and sometimes comparison, depending in which context you used it?
That sounds like a bad idea, and would introduce errors.
Plus, the current syntax is compatible with C and C++, so a lot of people are familiar with it.
Is there any reason anyone would ever want to assine a variable a new value inside of an if statement (if so please provide an example)?
It's quite common in while loops:
int b;
while ((b=in.read()) != -1){
=
is used for assignment.
==
is used for comparison.
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
yes it is allowed.
Note what error message you get for if (x = 3.141); it is a type error (cannot convert from double to boolean).
The assignment's type is the type of its both sides; if the type of the assignment is boolean (if (x = true), or even if (x = a.equals(b))), then it is legal to write.
So since it is legal to assign a value to a boolean in the condition, you'd have to use == for comparison.
Is it even allowed to assine a variable a value in an if statement (or initiate a new variable)?
Yes. A common idiom for doing this is:
String line = null;
while ( (line = in.readLine()) != null ) {
// do work
}
In the loop, line is assigned a value and then compared to null. I can't think of an example with ints; it certainly wouldn't be clear there.
History of programming languages 101:
Fortran uses = for both.
Algol introduced := for assignment and used = for comparison. This was required to resolve a grammar ambiguity.
Pascal followed suit.
PL/1 did not.
I can't speak for B or BCPL but by the time we got C it was = for assignment and == for comparison, again to resolve a grammar ambiguity
C++ followed C
Java followed C++ in many respects including this one.
The grammar ambiguity arises because of allowing assignments in expressions. Contrary to your assertion, if (x = true) is legal in Java if x is of type boolean.
== is the identity comparator, which works for both objects and primitives. It answers the question "are the two things the same thing".
= is the assignment operator. It sets the value of the left side to the right side.
Things can turn buggy when using your example with booleans:
boolean b;
if (b = true) // This compiles, but is a bug, because it sets b, not tests it
While other types won't compile with this syntax, boolean and Boolean do, so that's why the following pattern is advised:
if (b)
you can absolutely assign a variable in an if statement. also, that's just the way it works: = always is assignment, and == is always comparison.
So..
= is assignment, and == is comparison, and it is always like this, no matter where they are used.
And assignment is different with "declaration". An assignment statement has its return value, while a declaration doesn't. So you can't write boolean a = false in the () of if statement, but you can write a = false when a has been declared before.
Not all assignments are legal. For example:
int index;
if (index = str.indexOf("something")) {
...
}
It's not legal, because String.indexOf(String) returns an int, while if requires a boolean.
Also, there is a huge difference between "legal" and "making sense".
int index;
if ((index = str.indexOf("something")) != -1) {
...
}
It is legal, as != operation returns a boolean, and it makes sense, as I do want to check if the str contains a substring "something";
However,
int index;
boolean flag;
if ( flag = ((index = str.indexOf("something")) != -1) ) {
...
}
is also legal, as the statement as last returns a boolean; but it DOESN'T make sense, because the != statement already returns a boolean.

Java-Program to reverse upper case and lower case

I have to write a program to input a String str and change the upper case to lower case and vice versa. For example:
input:
"abCD"
output:
"ABcd"
this is what I've got:
l-is the length of the string
for(int b=0;b < l;b++)
{
char let=str.charAt(b);
if(let>97 && let<122)
{char nlet=let-32;
System.out.print(nlet);
}
else if(let>65 && let<90)
{ char t=let+32;
System.out.print(t);
}
}
break;
}
the error coming for this line:"char nlet=let-32;" is:
required:char;found:int;
how do i fix this?
The issue is that 32 is an integer, and let is a char. Java will implicity convert the let value to an int when it encounters let-32 and the result is the int value (for 'a') 96 or whatever.
You need to cast the result back to char:
(char)(let+32)
Try to use the below updated for loop:
for(int b=0;b < l;b++)
{
char let=str.charAt(b);
if (Character.isLowerCase(let))
{
char nlet=Character.toUpperCase(let);
System.out.print(nlet);
} else if(Character.isUpperCase(let))
{ char t=Character.toLowerCase(let);
System.out.print(t);
}
}
break;
}
Without any other classes (like Character for apparently you can't use it), you need to cast into char :
for(int b=0;b < l;b++)
{
char let=str.charAt(b);
if(let>97 && let<122)
{
char nlet=(char) let-32;
System.out.print(nlet);
}
else if(let>65 && let<90)
{
char t=(char)let+32;
System.out.print(t);
}
}
Your compiler told you the answer here :
required:char;found:int
It means your operation, here it is variable assignation has a wrong argument.
When you have
char nlet = xxx
The compiler expects the xxx to be castable into char. Here you give it a int value with let-32 or let+32.
So here you need to cast into char or use a function that output a char from an int; that's where you see all the people here telling you to use Character class that gives you all helper functions to do your homework (which is also way better than manually add/sub 32)
Careful, sometime you can see something like String str = "A string from int: " + 2000
This means your compiler will automatically cast the 2000 into "2000" because the + operation for a String takes 2 string arguments.
The Problem is with your let-32; it will return an integer so you need to implicitly cast it to a char variable.
Change your code to char nlet=(char) (let-32);
Also there is one more problem in your if condition you program will not give the correct output as your are not checking for the alphabets 'a' and 'z'.Change your if -else to check for the boundary conditions.
if(let>=97 && let<=122)
{
}else (let>=65 && let<=90){
}

Java - "String index out of range" exception

I wrote this little function just for practice, but an exception ("String index out of range: 29") is thrown and I don't know why...
(I know this isn't the best way to write this function and can I use regular expressions.)
This is the code:
public String retString(String x)
{
int j=0;
int i=0;
StringBuffer y = new StringBuffer(x);
try
{
while ( y.charAt(i) != '\0' )
{
if (y.charAt(i) != ' ')
{
y.setCharAt(j, y.charAt(i));
i++;
j++;
}
else
{
y.setCharAt(j, y.charAt(i));
i++;
j++;
while (y.charAt(i) == ' ')
i++;
}
}
y.setCharAt(j,'\0');
}
finally
{
System.out.println("lalalalololo " );
}
return y.toString();
}
Are you translating this code from another language? You are looping through the string until you reach a null character ("\0"), but Java doesn't conventionally use these in strings. In C, this would work, but in your case you should try
i < y.length()
instead of
y.charAt(i) != '\0'
Additionally, the
y.setCharAt(j,'\0')
at the end of your code will not resize the string, if that is what you are expecting. You should instead try
y.setLength(j)
This exception is an IndexOutOfBoundsException but more particularly, a StringIndexOutOfBoundsException (which is derived from IndexOutOfBoundsException). The reason for receiving an error such as this is because you are exceeding the bounds of an indexable collection. This is something C/C++ does not do (you check bounds of collections manually) whereas Java has these built into their collections to avoid issues such as this. In this case, you're using the String object like an array (probably what it is in implementation) and going over the boundary of the String.
Java does not expose the null terminator in the public interface of String. In other words, you cannot determine the end of the String by searching for the null terminator. Rather, the ideal way to do this is by ensuring you do not exceed the length of the string.
Java strings are not null-terminated. Use String.length() to determine where to stop.
Looks like you are a C/C++ programmer coming to java ;)
Once you have gone out of range with .charAt (), it doesn't reach null, it reaches a StringIndexOutOfBoundsException. So in this case, you will need a for loop that goes from 0 to y.length()-1.
a much better implementation (with regex) is simply return y.replaceAll("\\s+"," "); (this even replaces other whitespace)
and StringBuffer.length() is constant time (no slow null termination semantics in java)
and similarly x.charAt(x.length()); will also throw a StringIndexOutOfBoundsException (and not return \0 like you'd expect in C)
for the fixed code:
while ( y.length()>i)//use length from the buffer
{
if (y.charAt(i) != ' ')
{
y.setCharAt(j, y.charAt(i));
i++;
j++;
}
else
{
y.setCharAt(j, y.charAt(i));
i++;
j++;
while (y.charAt(i) == ' ')
i++;
}
}
y.setLength(j);//using setLength to actually set the length
btw a StringBuilder is a faster implementation (no unnecessary synchronization)

Categories