Clarify me how to pass an argument through String args - java

I start saying that my IDE is eclipse. I was trying to do a program that should find the phone number of a specific person through the name. This is the code
class HelloWorld {
public static void main(String args[]) {
String numbers[][] = {
{"Tom", "555-3322"},
{"Mary", "555-8976"},
{"Jon", "555-1037"},
{"Rachel", "555-1400"},
};
int i;
if(args.length != 1)
System.out.println("Usage: java Phone <name>");
else {
for(i=0; i<numbers.length; i++) {
if(numbers[i][0].equals(args[0])) {
System.out.println(numbers[i][0] + ": " + numbers[i][1]);
break;
}
}
if(i == numbers.length)
System.out.println("Name not found");
}
}
}
I found that in some forums that to make work it I have to go to run -> run configuration -> arguments. Hence I set the program argument to "Mary" and the output was the right one, that showed me the name (Mary) and the phone number (555-8976). Is this the right way or is there a better one?

Your code at present works fine with run-time arguments, as you have seen while using a run-config setup in your IDE. You could also just compile this on the command-line (without an IDE) and then execute java Phone Mary.
If you wish to solicit interactive user input (as opposed to run-time arguments) you would have to refactor using something like Scanner.

The way you are doing the argument passing is fine, but sometimes it's better to ask yourself which is the best option to do something in general, instead of just sticking with an idea and ask how to take that idea in particular to the real world.
To perform this type key-value operation, I recommend using a HashMap. If you don't know about them, that's OK, there are other ways to do what you want. I highly recommend learning about them though, because they make these kind of tasks really easy.
Basically, a HashMap is an object that has values stored in it and to access them you need to specify a key. For example:
Key -------Value
Name: -- "Mary"
Number: "12335635"
Age: -----"64"
Keep in mind all the keys have to be the same type(generally we use String) and the values should also be of the same type, that's why I put the numbers inside quotes. Maybe this example isn't the best one but the key type and the value type doesn't have to be the same. You can have your keys be Strings and your values be int.
I recommend this post: HashMap in Java with Examples and of course, the Java Docs.

Related

Design Pattern in Java for Getting Input and Acting on it

I'm trying to make a tic-tac-toe game and I'm encountering a lot of copy-paste work for inputs. I'm trying to figure out what design pattern and implementation works for prompting the user, collecting their input, comparing it and then acting by assigning a value. Right now my code looks like this.
public void promptPlayerCount(BufferedReader in) throws IOException {
String input;
// initial prompt
System.out.println("How many players?");
input = "try again";
while (input.equals("try again")) {
input = in.readLine();
// extract data and check it
switch (Integer.parseInt(input)) {
case 1:
// assignment
playerCount = 1;
break;
case 2:
playerCount = 2;
break;
default:
input = "try again";
// clarified instructions
System.out.println("please enter 1 or 2");
}
}
}
There's a part of me that thinks I could make a function (maybe a factory?) that allows me to generate a function by passing the constructing function the details of the initial prompt, the extraction method, the assignment action and the clarification message.
Would this be best done with lambda functions?
Text input is hard, especially if you can't trust your user (like in a game). Your parseInt will throw a nasty exception right off if your value isn't an integer.
Also standard in is not friendly. I assume this is for an assignment so I won't fault you for using it, but in anything where you don't HAVE to use stdin, don't. The problem is that it's amazingly difficult to get Java to respond to anything less than an entire line with an enter at the end.
When dealing with user input I almost always trim it (Just because they love to insert random white spaces at the beginnings and end) and check to see if it's empty. This could probably be put into a function that also either shows an error or exits the program on "Empty" and otherwise returns a string.
If you often want int values, write a second function that calls the first. Have the second function return an int, but have it catch the exception if the text is invalid and prompt the user again. You could even have this function take a "Range" of integers as a parameter and provide a prompt. So what you have above could look like this:
playerCount = getUserInput("Please enter the number of users", 1, 2);
The rest is wrapped in simple non-redundant functions.
Won't write the code for you because A) it's probably a homework assignment and the fun part is actually coding it and B) someone else probably will provide a full solution with code before I'm done typing this :(
Good luck.

Trying to use an assert command in conjuntion with arraylist using selenium, but it breaks if the elements are not in the proper order

I have a string that needs to be compared to the names that are on the website. So the first thing I do is get the number of rows (because some arrays have more or fewer than 2 people in them) and then put that size into an int. String[] names come from the names that selenium is supposed to find when it goes to the website to execute this statement assertTrue(assertion.getText().contains(names[i-1])); The problem is: if the names do not appear in the order in which they appear in the array it breaks. In other words, if Mick Jagger is in li[1] and Keith Richards is in li[2], everything runs as expected. But if Keith Richards appears in li[1] it breaks. Furthermore, I am supposed to use the assertTrue command to do this. I have tried sorting, pushing whats on the web into a new ArrayList and I keep getting errors. Anyone know a good way to ensure the order isn't important and still use the assertTrue command?
Thanks,
Scott
WebElement assertion = null;
List<WebElement> assignees = driver.findElements(By.xpath(".//*[#id='assignee']/li"));
int count = assignees.size();
String[] names = {"Mick", "Keith"};
for (int i = 1; i < count; i++)
{
assertion = driver.findElement(By.xpath(".//*[#id='assignee']/li["+i+"]"));
assertTrue(assertion.getText().contains(names[i-1]));
If names represents the full string, you can just flip it. Make sure the text in your assertion (probably should be named something like assignee instead of assertion) is contained in your collection:
assertTrue(Arrays.asList(names).contains(assertion.getText());
Let me know if this won't work because a name is actually a subset of the text in assertion and I'll adjust the answer.
If they don't exactly match (which you have indicated they don't), you could use linq in c# to match this. Since you're using java you can use an additional loop. There may be a more efficient way to do this in java that I'm not aware of.
String assigneeText = assertion.getText();
boolean nameFound = false;
for(String name: names)
{
nameFound = assigneeText.contains(name);
if(nameFound)
{
break;
}
}
assertTrue(nameFound, "None of the expected names were found in the following assignee text: " + assigneeText);

java jar accept multiple arguments on runtime

I have a java jar that need to accept about 3 arguments but I want to pass them as a Q&A type like the following:
1st step run java jar
java -jar myTest.java
2nd step ask questions and wait for answers:
Hi, how old are you?
I type my answer that accepts it and then ask the 2nd question:
nice! what is your name?
type my second answer and the get a third question and so on. how do I achieve this? I know that I can pass arguments to main but what I found is that I have to pass them all when I first run the jar not like what I'm looking for.
Any ideas?
Thanks!
the way to interact with an application depends of the logic in the application itself...
if you need to give parameters that the application needs from the start point then you give those as soon as you run the application
java -jar myTest.java
all those parameters are getting passed to the string[] parameter in the public static void main method...
in your case, (and if I got the question right) you will need more information from the user, and this is given at runtime... so you need another way to do that like Scanner class allowing you to read input from the terminal too...
Use the Scanner class and read the user input from the console..
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("What is your name?");
String input = sc.nextLine();
System.out.println("Hi, " + input + ", where are you from");
input = sc.nextLine();
System.out.println("Ohh, " + input + " is nice place I guess!");
System.out.println("and how old are you??");
...
}
It seems that you are mixing up concepts.
Command line arguments are those strings that you see as String[] args parameter to your main method!
But you want the user to provide "more" input to your application, the typical way is to read them from "stdin" (see here to learn how to do that).
Those two are fundamentally different things; and you should first clarify which one you really intend to use (given your example ... probably the "stdin" option).
Try reading the Java IO tutorial here:
https://docs.oracle.com/javase/tutorial/essential/io/cl.html

Checking error output is on my errorlist

I have the following code for logging all the errors after every command I run in cmd with my tool. (It runs p4 integrate commands, about 1000-1500/task)
if (errorArrayList.size() > 0) {
LoggerSingleton.I.writeDebugInfoTimeStampedLog("[INFO-CMD] CommandExecuter.java -> runAndGetResults: errors happened while running the following command: [ " + commandResultBean.getCommand() + " ]");
for (int i = 0; i < errorArrayList.size(); i++) {
LoggerSingleton.I.writeDebugErrorTimeStampedLog(errorArrayList.get(i));
commandResultBean.addToCLI_Error(errorArrayList.get(i));
}
LoggerSingleton.I.writeDebugInfoTimeStampedLog("[INFO-CMD] CommandExecuter.java -> runAndGetResults: Listing errors of command [" + commandResultBean.getCommand() + "] finished");
}
The feature that I'm working on right now is check the error I get, and if that's on a predefined error list (list of errors that doesn't matter, and in fact not real errors, for example "all revision(s) already integrated") do nothing else, but when it's a "real" error, write it to an other log file too (Because these debug logs way too long for the users of the tool, it's made for the developers more likely).
The question is, what is the best way for this?
I want to avoid big deceleration. I have many commands, but the number of errors less then the commands, but that is not unusual at all that I get 700-800 "irrelevant" errors in one task.
I will use another class to make the I/O part, and that is not a problem to extend the running time in case we catch a "real" error.
The list is constant, it is okay if it can be modified only by coding.
At the moment I don't know what type to use (2-3 single Strings, List, Array ...). What type should I use? I never used enums in Java before, in this one should I?
I guess a for or foreach and errorArrayList.get(i).contains(<myVariable>)in a method is the only option for the checking.
If I'm wrong, there is a better way to do this?
EDIT
If I have an ArrayList<String>called knownErrors with the irrelevant errors (can define only parts of it), and I use the following code will better performance than a method wrote above? Also, can I use it if I have only parts of the String? How?
if (errorArrayList.removeAll(knownErrors) {
//do the logging and stuff
}
ArrayList itself has a method removeAll(Collection c) which removes all the elements which are matching with input collection elements. Below program show it evidently. So if you have the known error to be skipped in arraylist and pass it to removeall method it will remove the known errors and errorArrayList will have only new errors.

How to delete previous character printed to console/terminal?

Is there a way to dynamically change output in Java? For instance, in a terminal window if I have:
System.out.print("H")
and then I have:
System.out.print("I")
The output will be:
HI
Is there a way to assign a position to outputs that allows you to replace characters dynamically? For instance (and I know this would not output what I want, I merely want to demonstrate my thinking) this:
System.out.print("H")
Thread.sleep("1")
System.out.print("I")
And it would first print out
H
and then after a second, replace the H with an I?
I'm sure this sounds stupid, I am just interested in dynamically changing content without GUIs. Can someone point me in the direction for this technique? Thank you very much in advance.
You might want to take a look at
System.out.printf
Look at the example shown here: http://masterex.github.com/archive/2011/10/23/java-cli-progress-bar.html
edit:
printf displays formatted strings, which means you can adapt that format and change it for your needs.
for example you could do something like:
String[] planets = {"Mars", "Earth", "Jupiter"};
String format = "\r%s says Hello";
for(String planet : planets) {
System.out.printf(format, planet);
try {
Thread.sleep(1000);
}catch(Exception e) {
//... oh dear
}
}
Using the formatted string syntax found here: http://docs.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax
As the comment says this solution is only limited to a singular line however dependent on your needs this might be enough.
If you require a solution for the whole screen then a possible solution would be (although quite dirty) would be to hook the operating system using JNA and get a handle on the console window, find its height and then loop println() to "clear" the window then redraw your output.
If you would like to read more then I can answer more questions or here is a link: https://github.com/twall/jna
You can use \b to backspace and erase the previous character.
$ cat T.java
import java.lang.Thread;
public class T {
public static void main(String... args) throws Exception {
System.out.print("H");
System.out.flush();
Thread.sleep(1000);
System.out.print("\bI\n");
System.out.flush();
}
}
$ javac T.java && java T
I
It will output H, then replace it with I after one second.
Sadly, it doesn't work in Eclipse console, but in normal console it does.
This is what you need (uses carriage return '\r' to overwrite the previous output):
System.out.print("H");
Thread.sleep(1000);
System.out.print("\rI");
The C library that is usually used to do this sort of thing is called curses. (Also used from scripting languages that rely on bindings to C libraries, like Python.) You can use a Java binding to it, like JCurses. Google also tells me a pure-Java equivalent is available, called lanterna.

Categories