views:

114

answers:

6

This is from Sun's tutorial's exercise area so I suppose it is homework.

I know how to use a for loop to iterate the string, but I wish to learn arrays while I am at it and store them in so. This is what I got so far:

BufferedReader in = new BufferedReader(new FileReader("xanadu.txt"));
int c;
char letters[] = new char[27]; //26 + newline?

while((c = in.read()) != -1){
    letters[(char)c] += 1; //store in index, so letters['a'] = 4 etc..
}

Now for some reason (works in other languages), it does not cast int c to charproperly, and it enters letters[110] or something in decimal ascii instead, of course that is out of bounds of my array.

What way should I tackle THAT problem so I can have a nice index of chars?

+2  A: 

you could use Map.

foret
+3  A: 

Well, first of all, System.out.println((int) 'A'); will not give you 0 or 1, it will give you 65, so you should at least do letters[(char) c - 'A'] += 1.

Still though, you have only considered 27 letters, which only includes lower case? or upper case? no spaces? and so on...

You probably want to do something like

Map<Character, Integer> counts = new HashMap<Character, Integer>();

BufferedReader in = new BufferedReader(new FileReader("data.txt"));
int c;
while((c = in.read()) != -1) {
    int count = counts.containsKey((char) c) ? counts.get((char) c) : 0;
    counts.put((char) c, count + 1);
}
aioobe
Huh? I mean I wish array[(char)65] to become array['A'], I don't get your comment. Can you not store array indexes as letters in java? Does it always default to ascii?
John
Well, arrays in Java are not like associative arrays in for instance PHP. Perhaps it's a Map<Character, Integer> you're looking for.
aioobe
@John: `array[(char)65]` and `array['A']` will indeed be the same thing - they will access array index 65. An array is fixed-length map from integers to values, starting at 0.
Jon Skeet
@aioobe: I had seen the `c - 'A'` thing before in examples in C to work with ASCII, I'll try both out and see which sticks, I like the example +1.
John
@Jon: Lesson learned.
John
+2  A: 

I'd be intrigued to know which languages this does work in. Every language I've ever used will convert character values to integers using either Unicode (like Java) or the native character encoding, which is usually ASCII-compatible. Which language would convert 'a' to 0 or 1?

Anyway, the simplest change to make your code work in all situations would be:

// char values in Java are in the range 0-65535.
int letters[] = new int[65536];

Note that I've changed the type of the array from char to int, because each element should be a count, not a character.

Alternatively, you could leave it as an array of size 27 (preferably still using int though) and then have some sort of mapping function from char to int.

However, to get value from this exercise you should really work out why you expected the code to work, and what this means in terms of your understanding of Java. Were you expecting an array to act as an arbitrary key/value map?

Jon Skeet
@"I'd be intrigued to know which languages this does work in": I learned PHP first, which I guess has fake multidimensional arrays (I think, it's nothing like Perl or C), I was just confused that my thought to work thing didn't. Much to learn to change my ways. :P
John
Storing by unicode value is nice way actually, as it's a character occurance count, not a "US alphabet count" rather.. Thanks.
John
@John: I think it's not so much multidimensional arrays as *associative* arrays, known as maps or dictionaries elsewhere. Basically a very different concept to a Java/C/C#/etc array :(
Jon Skeet
+1  A: 

I don't think Java supports that kind of indexing of array (like PHP does). Only numbers and only starting at zero until size-1.

So an array is not a good solution here. As foret suggests you'll have to use a Map, like a Hashmap.

Matthijs Wessels
+1  A: 

Why don't you make letters as an array of integers and secondly I think (letters[(char)c]) would return the ASCII value , so probably something like

letters[c-97] += 1 would do the trick

Egalitarian
+1  A: 

letters[(char)c] += 1; //store in index, so letters['a'] = 4 etc..

As I get it, you want your letters array to be like this letters['a']=(some value) letters['b']=(some value)

In Java, arrays can be indexed only by integers, or in other data types ( they will be promoted to 'int' )Java Language Spec

The nearest you could use is a Maps - HashMap or TreeMap