Format string with undefined number of arguments - java

Is it possible to create in java something like this someFunction("%s, %s, %s", 1, true, "qwe"); where result should be 1 true qwe?
I tried it with different approaches such as using PrintStream and some other classes but I can't figure out how to do it.
So far one things that seem certain is the definition:
public static String prepare(String format, Object... arguments) {
return ???
}
But I cannot figure out how to do it past that. Can you give me some advices?

You can use String.format method:
public static String prepare(String format, Object... arguments) {
// do same sanity checks if needed
return String.format(format, arguments);
}

This is what String.format does, but I assume that you know that already, and would like to build your own function.
The header of the function that you have is correct. Now you need to make a counter count initially set to zero, create a StringBuilder, and run a loop that scans the format string.
When your loop encounters a character other than the '%', append that character to the StringBuilder. Otherwise, check the next character for a format that your program recognizes, and grab the object at the position count from the arguments array. Format the object as required, and append the result to StringBuilder; increment count.
Once the loop is over, StringBuilder contains the result string that you return to the callers.
Of course this is only a skeleton of the algorithm. A real implementation needs to take care of many other important things, such as
Checking that the count in the loop does not advance past the end of the arguments array
Checking that the final count is not less than the number of objects in the arguments
Checking that the format specifier can be applied to the object from the arguments array
and so on.

Yes, this is exactly what String.format() does:
public class Test {
public static void main(String[] args) {
System.out.println(format("%s %s %s", 12, "A", true));
}
public static String format(String format, Object ... args) {
return String.format(format, args);
}
}

That's what String.format() is meant for
String.format("%s, %s, %s", 1, true, "666");
In your case,
return String.format(format, arguments);

Related

Multiple string method chained in single code

I am working on this bit of code
public class SimpleStringTest {
public static void main(String args[])
{
String ints="123456789";
System.out.println(ints.concat("0").substring(ints.indexOf("2"),ints.indexOf("0")));
}
As per as my knowledge on java "When the multiple methods are chained on a single code statement, the methods execute from left to right" Then, Why is this bit of code throwing StringIndexOutOfBondsException?
Thanks in advance,
GPAR
Because Strings are immutable.
By invoking concat, you are not modifying ints, you are creating a new String.
Therefore by the time you invoke ints.indexOf("0"), ints is still equal to its former value and the indexOf invocation returns -1, which in turn will be the outer bound of your substring.
Try a counter-example with a mutable CharSequence such as StringBuilder:
StringBuilder ints = new StringBuilder("123456789");
System.out.println(ints.append("0").substring(ints.indexOf("2"),ints.indexOf("0")));
Output
23456789
Because ints.indexOf("0") is applied on the original String ints (not the one you concatenate).
Since there is no "0" indexOf("0") returns -1 and which throws the exception.
Your code is equivalent to this:
String ints="123456789";
int indexOne = ints.indexOf("2");
int indexTwo = ints.indexOf("0");
System.out.println(ints.concat("0").substring(indexOne, indexTwo));

Creating a method that accepts a string and a length (integer) as parameters

I am trying to teach myself more about the relationships between methods. In doing this, I am writing a program that has multiple methods. I have one method (createSpace) that is called from the main method.
It seemingly was straight forward but I realized I needed my createSpace method to
1) accept BOTH a string and an int as parameters,
2) pad the parameter string with designated number of spaces and
3) return a padded string.
Most of this seems pretty good to me. For 2, I will write a for loop that gives the designated number of spaces that I want. For 3, I will designate my method to be a return type. But I am having a bit of trouble with 1, which is frustrating as it it the first part to this.
How does one create a method that accepts two types of values (strings and ints) as parameters?
Hopefully this question makes sense.
You specify them like so, seperated with a comma:
public void genericMethod(int someNumber, String someString) {
//dosomething
}
In case this wasn't clear, I would like to add the following. If you need two different strings, you specify two strings, also seperated by a comma:
public void genericMethod(int someNumber, String someString, String otherString) {
//dosomething
}
Etc, etc.
Simply, you can create a method with a String and int type parameters as follows:-
[your access modifier] [return type] [method name](set of parameters) {
// write your code here
}
for example, i will declare a method test with a string and int paramters which doesn't return any thing :-
public void test(String s , int i){
// write your code here
}
and i recommended you to read this carefully http://docs.oracle.com/javase/tutorial/java/javaOO/methods.html
http://www.tutorialspoint.com/java/java_methods.htm

Return two Strings from method

I'm a beginner in Java programming, and I'm trying to make a voting machine program, where you can vote for Republicans or Democrats. My question is, how can I edit my method so I would be able to return two strings with two distinct values?
For example, look at my code all the way in the bottom. It's wrong, but I wanted the tester to be able to print out Democrats: (some number) and Republicans: (some number) in one method. How can I do that?
import java.lang.String;
public class VotingMachine1 {
private double Democrats;
private double Republicans;
public VotingMachine1() {
Democrats = 0;
Republicans = 0;
}
public void voteRepublican() {
Republicans = Republicans + 1;
}
public void voteDemocrat() {
Democrats = Democrats + 1;
}
public void clearMachineState() {
Republicans = 0;
Democrats = 0;
}
//this is where I'm having difficulties. I know its wrong
public double getTallies() {
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
}
No return is necessary there, since you aren't leaving a function. To do what you seem to want to do, just replace that last method with the following:
public void getTallies()
{
System.out.println("Democrats: " + Double.toString(Democrats));
System.out.println("Republicans: " + Double.toString(Republicans));
}
Also, since your votecounts should only ever be integers, there's no reason to declare them as doubles instead of ints.
What you are looking for here is a format string. A format string is used when you know what your output should look like, and only have a few "holes" where unknown data should be filled in. To output your data using format strings, you would use the System.out.format(String, Object...) method:
System.out.format("Democrats: %f\n", Democrats);
System.out.format("Republicans: %f\n", Republicans);
In this case, the %f indicates that a floating-point number (since your variables are declared as double) will be printed instead of the %f. However, you may wish to consider declaring them as int (or long) instead, in which case you would use %d instead of %f in the format strings.
Finally, you ought to change your getTallies() method to return void instead of double, as you are printing the values, not returning them.
Your code and your description are so contradictory, it is not clear that you even know what you are trying to do. I believe that this is the real root of your problems.
Here goes:
public double getTallies()
{
System.out.println("Democrats: ", return Democrats);
System.out.println("Republicans: ", return Republicans);
}
First, your question says that you want to "return two strings with two values" ... but you have declared the method as returning one double.
Next, your code is printing values ... not returning them.
You've also made some major mistakes at the syntactic level, largely (I believe) because you are trying to do contradictory things:
return Republicans is not a valid Java expression, so you can't use it as a argument to the println method.
The println method can't be called with two arguments, as your code is trying to do. There is a zero argument version and a number of one argument overloads ... but no overloads with two or more arguments.
Basically, you need to start by making up your mind about what this method is supposed to do. Is it supposed to:
return the tallies (as two doubles)?
return a string representing the two tallies?
return nothing ... and output the two tallies to standard output?
do something else?
Once you've made up your mind:
code the method to do what you've decided it should do, and
chose a method name that correctly reflects what it is supposed to do. Hint: a method that starts with get is conventionally a "getter" that returns the attribute or attributes themselves ... not a String rendering.
double is a bad choice of type for a vote count too:
You cannot have a fractional vote.
You want to represent vote counts precisely and floating point types (like double) are not precise. (Or at least, not in the sense that you require.)
When you attempt to format or output a double, the resulting character string is likely to include a pesky decimal point ... or worse.
You should use int or long instead of double.
Finally, this is a serious Java style violation, and should get you a significant penalty if your marker is paying attention.
private double Democrats;
private double Republicans;
Variable names in Java should start with a LOWER CASE letter.
A few more random comments:
import java.lang.String; is superfluous as all classes in package java.lang are automatically imported in every Java source file.
Votes can not be fractional. People can't vote 0.75 candidate A, and 0.25 candidate B. If you use integer datatypes (int or long), you will be reflecting this fact better. Also, you will be saving yourself a lot of headache when you start obtaining results like 379857.999999. This is because floating point types have a better range, but worse precision (especially noticeable when working with pure integers).
According to Java usual naming conventions, variable names should start with a lowecase letter.
A better name for function getTallies is printTallies.
For output purposes, it's much better to use string formatting than concatenation. Some advantages are: multiple formats supported, ease of use, and internationalization.
Putting all together:
private int democratVotes;
private int republicanVotes;
public void printTallies() {
System.out.format("Democrats: %,d%n",democratVotes);
System.out.format("Republicans: %,d%n",republicanVotes);
}
In this particular case, votes will be printed with thousand separation (ex: 3,345,623 instead of 3345623). Check Java's Formatting Numeric Print Output tutorial.
Thinking better about it, there are some alternatives where getTallies would effectively be returning some form of value:
1) Make it to return a String with both tallies. It would be hard and inefficient to separate the tallies later, though.
public String getTallies() {
return "Democrats: %,d votes. Republicans: %,d votes.%n".format(democratVotes,republicanVotes);
}
2) Make it to return an array.
public int[] getTallies() {
return new int[2]{ democratVotes, republicanVotes };
}
public int[] getTallies1() { // Same as getTallies, but written step by step.
int[] result= new int[2] ;
result[0]= democratVotes ;
result[1]= republicanVotes ;
return result ;
}
3) Make it to return a class.
public VotingMachineResults getTallies() {
return VotingMachineResults(democratVotes,republicanVotes) ;
}
public static class VotingMachineResults {
private int democratVotes;
private int republicanVotes;
public VotingMachineResults(democratVotes,republicanVotes) {
this.democratVotes= democratVotes ; // `this` required to disambiguate field democratVotes from parameter democratVotes.
this.republicanVotes= republicanVotes ;
}
public int getDemocratVotes() {
return democratVotes ;
}
public int getRepublicanVotes() {
return republicanVotes ;
}
}
As you can see, this class is very similar to VotingMachine1, but it does not accept internal state changes. It is a "value" class.
In Java, you concatenate Strings with the + operator. Proper syntax for what you were trying to do looks like this:
System.out.println("Democrats: " + Democrats);
System.out.println("Republicans: " + Republicans);
A return statement is only used when you want to return some object or value to a method that called your current method. It is not appropriate in this place since you're only passing a value to another method (println()).
ALSO, you need to fix your getTallies() method. Make it return void instead of double since you aren't returning anything.
Here's something completely different: why not override toString()?
Presumably, any instance of VotingMachine1 will apply for all votes that you care about for that instance. That is to say, you don't create a new instance of a VotingMachine1 every time someone casts a vote.
So, what you can do is override the toString() method. We'll also use String.format() to handle the numerical values.
#Override
public String toString() {
// assumes that Democrats and Republicans are declared as int
// since it's pointless to indicate percentages of a vote
return String.format("Democrats: %d\nRepublicans: %d", Democrats, Republicans);
}
Now, whenever you vote, you can use the toString() method to get the information (which is called whenever one does System.out.println(object).
VotingMachine1 voter = new VotingMachine1();
voter.voteDemocrat();
voter.voteRepublican();
System.out.println(voter);
/* This prints:
Democrats: 1
Republicans: 1
*/
A less specific answer to your question would be to return an Object called (say) Votes
public class Vote {
int democratVotes
int republicanVotes
}
and then make your VotingMachine class simply return an instance of this object (suitably changed to make it immutable).
On my project we have created a generic version of this called a Tuple that returns a pair of values in a single object - it has an overloaded toString method for easy printing.
you can return an array with [0] and [1] as key and devide it on the basis of your need..
like
returnArray[0]="first string";
returnArray[1]="second string";
and use it ur way...

Java: String.equalsIgnoreCase(. . .) not working

I am developing a small application in Java. The following if condition never becomes true, does any body be knows the actual reason?
public int foo()
{
String sTitle = "title";
if (sTitle.equalsIgnoreCase(MyCustomObject.sTitle))
return 5;
else
return 6;
}
It always returns 6. I ran it in debug mode and saw that both strings contains same value.
I also tried swapping the positions of both strings like:
MyCustomObject.sTitle.equalsIgnoreCase(sTitle)
but that didn't work either.
The actual reason is that MyCustomObject.sTitle does not have the value "title" or any case variants.
Check where and when that variable is assigned.
I'm assuming that MyCustomObject.sTitle is a string as well.
My first attempt at debugging would be to add the following line before you test the equality:
System.out.println("*"+MyCustomObject.sTitle+"*");
and check for whitespace.
Try adding this code to the foo method:
if (sTitle.length() != MyCustomObject.sTitle.length())
{
System.out.println("I hate the truth");
}
else
{
System.out.println("The mystery remains!");
}
EqualsIgnoreCase method
Compares this String to another String, ignoring case considerations. Two strings are considered equal ignoring case if they are of the same length, and corresponding characters in the two strings are equal ignoring case.
Two characters c1 and c2 are considered the same, ignoring case if at least one of the following is true:
The two characters are the same (as compared by the == operator).
Applying the method Character.toUpperCase(char) to each character produces the same result.
Applying the method Character.toLowerCase(char) to each character produces the same result.
Based on the above the value of MyCustomObject.sTitle is not matching any of the above criteria.
as previous authors have written MyCustomObject.sTitle does not return any variant of "title". You could try running this piece of code and you can prove for yourself that it's not the equalsIgnoreCase method that doesn't work.
public static void main(String[] args) {
System.out.println(foo());
}
public static int foo()
{
String sTitle = "title";
if (sTitle.equalsIgnoreCase(MyCustomObject.sTitle))
return 5;
else
return 6;
}
public static class MyCustomObject {
public static String sTitle = "TITLE";
}

public void add(int a, int... b) {

Could someone show me a practical a use of the ... array method delcaration?
Is it just a way to declare an optional parameter instead of passing null value?
public void add(int a, int... b) {
// do something
}
add(1);
add(1,2,3);
String.format is a pretty good practical example. The method doesn't know how many formatters will appear in the format string, so it accepts a variable number of arguments, and there should be a one-to-one mapping of formatters (in the format string) to objects passed into the method.
It's not so much a way of declaring an option parameter rather than null, as it is to declare a method that can deal with multiple arguments. Basing my example off of mine, you could write a sum method that takes a variable number of arguments and sums them all together:
public int sum(int... ns)
{
int sum = 0;
for (int n : ns) {
sum += n;
}
return sum;
}
That way, you could pass in 2, 3, 4, or even 100 numbers to sum, depending on your need at the time.
It's a shorthand for you when you're writing code that will use a function that can take an array as a parameter.
It's generally easier to write add(1,2,3,4); than it is to write add(new int[] {1,2,3,4});, right? It's also clearer when it needs to be read and maintained by future programmers later.
Think about it this way: which function would you call, the one where you have to create an array every time, or the one where you can just pass in as many parameters as you want?
The Formatter class is such a practical use:
Formatter formatter = new Formatter(sb, Locale.US);
formatter.format("%4$2s %3$2s %2$2s %1$2s", "a", "b", "c", "d")
An arbitrary number of parameters can be passed in to be formatted using the first parameter, which is the format string itself.
Before varargs a method that took an arbitrary number of values required you to create an array put the values into the array prior to invoking the method. Example here is how the MessageFormat class to format a message used to look:
Object[] arguments = {
new Integer(7),
new Date(),
"a disturbance in the Force"
};
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.", arguments);
It is still true that multiple arguments must be passed in an array, but the varargs feature automates and hides the process. Furthermore, it is upward compatible with preexisting APIs. So, for example, the MessageFormat.format method now has this declaration:
public static String format(String pattern,
Object... arguments);
The three periods after the final parameter's type indicate that the final argument may be passed as an array or as a sequence of arguments. Varargs can be used only in the final argument position. Given the new varargs declaration for MessageFormat.format, the above invocation may be replaced by the following shorter and sweeter invocation:
String result = MessageFormat.format(
"At {1,time} on {1,date}, there was {2} on planet "
+ "{0,number,integer}.",
7, new Date(), "a disturbance in the Force");
So when should you use varargs? As a client, you should take advantage of them whenever the API offers them. Important uses in core APIs include reflection, message formatting, and the new printf facility. As an API designer, you should use them sparingly, only when the benefit is truly compelling. Generally speaking, you should not overload a varargs method, or it will be difficult for programmers to figure out which overloading gets called.
From: http://java.sun.com/j2se/1.5.0/docs/guide/language/varargs.html
Derived from you example you could make a method to have the sum of all the ints you pass to the method:
public int sum(int a, int... b) {
int sum = a;
for (int i : b) {
sum += i;
}
return sum;
}

Categories