Reputation: 71
I am making a program to convert characters to ASCII code.
The user will enter characters and then those characters will be stored into an array and the program will convert those characters to their ASCII value.
Below is my code:
package chartoascii;
import java.io.DataInputStream;
import java.io.IOException;
public class CharToAscii {
public static void main(String[] args) throws IOException
{
DataInputStream in=new DataInputStream(System.in);
int n;
Scanner scan = new Scanner(System.in);
System.out.println("Enter number of Characters you want to insert : ");
n = scan.nextInt();
char character[] = new char[n];
System.out.println("Enter Characters : ");
for (int i=0; i<n; i++)
{
character[i] = in.readChar() ;
} // for loop
for (int i=0; i<character.length; i++)
{
int ascii = (int) character[i];
System.out.println(ascii);
}
}
}
My program runs fine, but the output I get is not the ASCII codes.
This is my output:
Enter number of Characters you want to insert :
4
Enter Characters :
a
b
c
d
24842
25098
25354
25610
Upvotes: 3
Views: 852
Reputation: 25903
Your code has two problems. The bigger issue is that DataInputStream
doesn't read like you think it, the other is that you connect two resources to System.in
, namely DataInputStream
and Scanner
. You should just use the Scanner
for reading all data.
The problem with linking both is that DataInputStream
will also interpret the previous entered 4
since it is only consumed by the Scanner
but not by the DataInputStream
too. That being said I can't reproduce your exact values. If I enter 4
and after that a
, b
, c
then I won't be able to enter d
since the DataInputStream
also reads the 4
(I think the reason is that your machine uses \n
for newline and mine \r\n
). So it's input finally is
4
a
b
c
And if I adjust your loop to also show what it prints (as character):
for (int i = 0; i < character.length; i++) {
int ascii = (int) character[i];
System.out.println(character[i] + " -> " + ascii);
}
I get this:
? -> 24845
? -> 2658
? -> 3338
? -> 25357
Okay, so why all the ?
instead of the correct inputs? Therefore we need to take a look at how DataInputStream#readChar
works. According to its documentation:
Returns: the next two bytes of this input stream, interpreted as a char.
However in order to get the ASCII values we would need to interpret the byte-stream ASCII-like. ASCII is of fixed length too, but with one byte per character instead of not two. However if would also like to be able to read different characters like ä
, é
or even 我
, you will need to interpret the byte-stream not with fixed length but with some encoding scheme like UTF-16. Now note that UTF-16 is not of fixed length.
In order to understand the values let us take a look at the exact byte-stream, we have
01100001 00001101 // ? -> 24845
00001010 01100010 // ? -> 2658
00001101 00001010 // ? -> 3338
01100011 00001101 // ? -> 25357
As you see, if we arrange the bytes like this (always two bytes) we get the corresponding values in decimal format. For ASCII we would need to rearrange the bytes and read like that:
01100001 // a -> 97
00001101 // \r -> 13
00001010 // \n -> 10
01100010 // b -> 98
00001101 // \r -> 13
00001010 // \n -> 10
01100011 // c -> 99
00001101 // \r -> 13
As you see, the byte-stream contains more characters than just a
, b
and c
, namely \r
and \n
. Those two are interpreted as newline-command, therefore see Wikipedia.
The easiest fix would be to use Scanner
and its next
method (documentation). This method automatically blocks until the next complete token was input. This is determined by the delimiter pattern. To set it up for one UTF-16 character we just delimit by an empty String
(therefore take a look at Take a char input from the Scanner):
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("");
After that you can read 4 String
values. However we still have the problem of \r\n
being feed to the Scanner
.
The easiest way of eliminating that is by using Scanner#nextLine
instead (documentation). So instead of just reading one character, we read a whole line. The method automatically throws \r\n
away for us:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter number of Characters you want to insert : ");
int n = Integer.parseInt(scanner.nextLine());
char[] character = new char[n];
System.out.println("Enter Characters : ");
for (int i = 0; i < n; i++) {
// Only use first character of line
character[i] = scanner.nextLine().charAt(0);
}
for (int i = 0; i < character.length; i++) {
int ascii = (int) character[i];
System.out.println(character[i] + " -> " + ascii);
}
Which now correctly prints the ASCII values
a -> 97
b -> 98
c -> 99
d -> 100
To be precise it prints the UTF-16 values, but ASCII is included in UTF-16.
Upvotes: 1
Reputation: 2217
You had typed another character after each letter: a line feed (U000a). This, together with the error mentioned above, that readChar misleadingly does not do what it purports to do by its name, gives the values you have received: 25098 is hexadecimal x620a, x66 being b and x0a being line feed. By using readLine, you get rid of the line feed.
Upvotes: 0
Reputation: 418
After the line:
n = scan.nextInt();
Add the line:
scan.nextLine()
Then, in your first for loop, use
character[i] = scan.nextLine().charAt(0);
The Scanner will get the first character you enter each time, so casting to int later will return its ascii value. Like comments said, DataStream is the issue here.
Upvotes: 1