How to format string output, so that columns are evenly centered?
Here is one way of doing it.
Since you know the longest String
you will have is "Queen of Diamonds"
, you can base your separation on its length. The way you would do this is, for each current string, add spaces to it until its length matches the length of "Queen of Diamonds"
. Then you add whatever separation you want, for example a tab ("\t"
).
Here is a sample program:
static String[] cards = { "3 of Spades", "3 of Diamonds", "Ace of Diamonds",
"9 of Diamonds", "2 of Diamonds", "10 of Diamonds",
"Ace of Spades", "10 of Hearts", "King of Clubs",
"6 of Clubs", "4 of Spades", "Queen of Hearts",
"5 of Diamonds", "2 of Hearts", "7 of Clubs",
"2 of Spades", "Jack of Diamonds", "3 of Hearts",
"5 of Hearts", "4 of Hearts", "7 of Diamonds" };
static String getSeparation(int len) {
String longest = "Queen of Diamonds";
StringBuilder sb = new StringBuilder();
// add spaces to match the longest string
for(int i = 0; i < longest.length() - len; i++) {
sb.append(" ");
}
sb.append("\t"); // add separation tab
return sb.toString();
}
static void print() {
for(int i = 0; i < cards.length; i += 3) {
System.out.println(cards[i] + getSeparation(cards[i].length()) +
cards[i + 1] + getSeparation(cards[i + 1].length()) +
cards[i + 2] + getSeparation(cards[i + 2].length()));
}
}
public static void main(String[] args) {
print();
}
Output:
3 of Spades 3 of Diamonds Ace of Diamonds
9 of Diamonds 2 of Diamonds 10 of Diamonds
Ace of Spades 10 of Hearts King of Clubs
6 of Clubs 4 of Spades Queen of Hearts
5 of Diamonds 2 of Hearts 7 of Clubs
2 of Spades Jack of Diamonds 3 of Hearts
5 of Hearts 4 of Hearts 7 of Diamonds
A shorter solution would be to use String.format
or System.out.printf
to format the output:
static String[] cards = { "3 of Spades", "3 of Diamonds",
"Ace of Diamonds", "9 of Diamonds", "2 of Diamonds",
"10 of Diamonds", "Ace of Spades", "10 of Hearts", "King of Clubs",
"6 of Clubs", "4 of Spades", "Queen of Hearts", "5 of Diamonds",
"2 of Hearts", "7 of Clubs", "2 of Spades", "Jack of Diamonds",
"3 of Hearts", "5 of Hearts", "4 of Hearts", "7 of Diamonds" };
static void print() {
int spacingSeparation = 3; // number of spaces between columns
int longest = "Queen of Diamonds".length(); // length of the widest column
int spacing = longest + spacingSeparation; // total spacing
for (int i = 0; i < cards.length; i += 3) {
System.out.print(String.format(
"%-" + spacing + "s%-" + spacing + "s%-" + spacing + "s\n", // format
cards[i], cards[i + 1], cards[i + 2])); // values
}
}
public static void main(String[] args) {
print();
}
Output:
3 of Spades 3 of Diamonds Ace of Diamonds
9 of Diamonds 2 of Diamonds 10 of Diamonds
Ace of Spades 10 of Hearts King of Clubs
6 of Clubs 4 of Spades Queen of Hearts
5 of Diamonds 2 of Hearts 7 of Clubs
2 of Spades Jack of Diamonds 3 of Hearts
5 of Hearts 4 of Hearts 7 of Diamonds
You use something similar to what you are probably using right now. It looks like you are printing out using System.out.print();
right? If so, you can use System.out.printf();
along with %#
. Let me explain.
It looks like you want to print out something that looks like this.
Column 1 Column 2 Column 3
12 23 1234
Well, the easy way to solve for that would be like this.
int c1 = 12;
int c2 = 23;
int c3 = 1234;
System.out.printf("%-22s%-22s%-22s\n","Column 1","Column 2","Column 3");
System.out.printf("%-22d%-22d%-22d\n",c1,c2,c3);
Let's explain what is going on here, there's a lot of stuff happening. First, whenever you see a %
sign in System.out.printf()
, it means a special (formatting in this case) action is about to follow.
Now, let's look at the parameters of the method. The way System.out.printf()
works is by specifying the format of the output in the first parameter. Then, the actual outputs are the following parameters. Do you see how it starts by specifying the format with "%-22s%-22s%-22s\n"
? Then, it actually outputs them, separated by commas? That's IMO the easiest way to format.
Lastly, let's look some more at that special action thing I mentioned earlier. You see how there are letters and numbers and -
after the %
? Those all serve purposes too. --HERE-- is a good place to learn more but I'll give you the basic rundown.
First, the negative sign specifies which side will receive padding, padding is the space between the columns that makes them look pretty. Since it is negative, it will be on the right side, (FYI, if there was no sign there, padding would be on the left) so it will print out your output, then add spaces to the right... but how many spaces?
That's where that number comes in. The 17's you see are how many spaces there will be subtracted from the length of the output. Long story short, it will plainly and simply make sure each output starts and ends at the same place. The only catch is, make sure that the number, 22, is longer than the maximum possible String. I see the longest one possible would be Queen of Diamonds
so anything bigger than 19 should do it, I chose 22 cuz it looked better IMO.
Next is the letter, that letter, as you can see, changes between the 2 output statements. In this case, one says s, the other says d. Easy way to solve this is, if your output is a String, use s, if it's and int (I don't think you will need it, I just had to for my example cuz mine were ints), use d.
I'm also going with the "format" suggestion, but mine is a little different.
In your program, you're relying on your card's toString
. So make that formatted in a fixed length, and then you can use them anywhere and they will take up the same space.
public String toString() {
return String.format( "%5s of %-8s", rank, suit );
}
When you print this out, you'll have all your cards aligned on the "of" part, which I think is what you were going for in your first output column.
The "%5s" part right-aligns the rank in a field 5 characters wide, and the "%-8s" part left-aligns the suit in a field 8 characters wide (which means there are additional spaces to the right if the suit is shorter than 8 characters).