substring() generates error in Java - java

I am getting a error when using this substring(). I am trying to get initials of first, middle, and last and then convert to upper case.
public String initials() {
String initials = first.substring(0, 1) + middle.substring(0, 1)
+ last.substring(0, 1);
return initials.toUpperCase();
}
That is the code and this is the output it is giving me..
Exception in thread "main" java.lang.NullPointerException
null, null null at name.Name.initials(Name.java:75)
at name.NameDriver.main(NameDriver.java:30)
Java Result: 1
Line 75 is
String initials = first.substring(0, 1) + middle.substring(0, 1)
Line 30 in NameDriver is
System.out.print(name1.initials());

This error is unrelated to the substring method and appears to be because first, middle, and last are null and this method can only be performed on a String.
The easiest way to stop this error occuring would be to add something like this at the start of your initials method:
if(first == null || middle == null || last == null) return "Not all names have been entered";
However, you may also want to consider that not everyone has a middle name.

Like #Andy just replied, just guard against any of these 3 being null.
Maybe just create and auxiliary function like:
private static String firstLetter(String name) {
if (name == null || name.isEmpty()) {
return "";
}
return name.substring(0, 1);
}
Then you can just change your code to:
public String initials() {
String initials = firstLetter(first) + firstLetter(middle) + firstLetter(last);
return initials.toUpperCase();
}

Related

Result not null in my code, if "sorIndex" is invalid

I would need some guidance from You, at the moment I have this challenge with this exercise:
The aim of this code would be, to split a String(szoveg) to rows and give back the result row(sorIndex) as a result, if sorIndex is in the range of the String Array(String szoveg is splitted into this array).
If the requested number of the row is not in the valid range(0-length of the array) it should give back a null value. The IDE for testing the excercise returns a mistake, which is the following(Hungarian + English):
"A getSor() metódus nem működik jól. Nem létező sorIndexet megadva
null-t kell visszaadjon a metódus. A konstruktor paramétere:"
"The getSor() method is not working properly. Given a not valid
sorIndex, the method should return null. The parameter of the
constructor:" -there is nothing after this part in the IDE.
public String getSor(int sorIndex) {
int sorok= szoveg.split("\n").length;
String sor;
if (sorIndex >= 0 && sorIndex <= sorok) {
String[] stringTomb = new String[sorok];
stringTomb = szoveg.split("\n");
sor = stringTomb[sorIndex];
} else {
sor = null;
}
return sor;
}
Does anyone have any idea where did I made the mistake?
Thank you!
The error message tells you that if an invalid sorIndex is passed, then a null should be returned. This means that instead of getting into the else branch in your logic, it goes into the if in an invalid manner.
The reason of this is that arrays are 0-indexed, so you should compare against rows (sorok) in a srict manner:
if (sorIndex >= 0 && sorIndex < sorok) {
That should fix the issue. However, your code computes split several times and is superfluous. I would refactor it to:
public String getSor(int sorIndex) {
if (szoveg == null) return null; // Handling the case when szöveg is not properly initialized
String stringTomb[] = szoveg.split("\n");
return ((sorIndex >= 0) && (sorIndex < szoveg.length)) ? stringTomb[sorIndex] : null;
}
I used the ternary operator to make this more readable, concise and short.

StringIndexOutOfBounds when removing adjacent duplicate letters

Here is my code:
public static String removeAdjDuplicates(String s) {
if(s == "" || s == null || s.isEmpty())
return s;
if(s.length() < 2)
return s;
if(s.charAt(0) != s.charAt(1))
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
if(s.charAt(0) == s.charAt(1)) //line 37
return removeAdjDuplicates(s.substring(2));
return s;
}
With the input string "ull", I get the following error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1
at java.lang.String.charAt(String.java:658)
at GFG.removeAdjDuplicates(File.java:37)
at GFG.main(File.java:16)
I read and tried answers given to similar questions, but I'm not sure what is wrong.
Judging from the exception that you get, removeAdjDuplicates returns an empty string, invalidating all indexes past zero.
Although your code performs length checking at the top, it also performs this assignment when the two initial characters are different:
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
This means that s can become a one-character string if removeAdjDuplicates returns an empty string.
As you Try to pass this string "ull" to the method the last letter in the String should be the letter "u" because you use this
if(s.charAt(0) != s.charAt(1))
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
as you dont return the String back like the other conditions in the method it will continue to the next condition at line 37
and u have only one letter while the condition checking the first and the second characters ... there is no second letter so you get this error .. so the solution is to return s like this
if(s.charAt(0) != s.charAt(1)){
s = s.charAt(0) + removeAdjDuplicates(s.substring(1));
return s;
}
I think the source of the error is sufficiently explained by #dasblinkenlight's answer.
Although not clearly stated in the question, it looks like you're trying to remove adjacent duplicate letters recursively (one of your comments mentions that you would expect output s for input geegs).
Here's an alternative way to do it:
while(!s.equals(s = s.replaceAll("(.)\\1", "")));
It uses a regular expression to match and remove duplicate characters, and the while loop keeps executing this until the string is no longer being modified by the operation.
You should simplify your code:
public static String removeAdjDuplicates(String s) {
if (s == null || s.length() < 2)
return s;
if (s.charAt(0) != s.charAt(1))
return s.charAt(0) + removeAdjDuplicates(s.substring(1));
return removeAdjDuplicates(s.substring(2));
}
Changes
The first two if statements do the same thing (return s;) and can be combined into one. Some of the conditions are redundant and can be eliminated.
The third if statement should immediately return instead of continuing into the fourth if statement (or you can instead change the fourth if statement into an else), because removedAdjDuplicates can return an empty String making s a length-one String when the fourth if is expecting at least a length-two String.
The fourth if can be eliminated because if (s.charAt(0) != s.charAt(1)) failed in the third if, then the only alternative is that (s.charAt(0) == s.charAt(1)), so the check for that isn't necessary.

java: code keeps looping

The below code is giving me a headache: It's supposed to jump out of the do--while loop after replacing all \n's, but it doesn't. Any ideas how to solve this?
public String invoerenTemplate(){
String templateGescheiden = null;
String teHerkennenTemplate = Input.readLine();
String uitvoer = teHerkennenTemplate;
do {
templateGescheiden = teHerkennenTemplate.substring(0, teHerkennenTemplate.indexOf(" "));
templateGescheiden += " ";
if (templateGescheiden.charAt(0) == '\\' && templateGescheiden.charAt(1) == 'n') {
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
}
teHerkennenTemplate = teHerkennenTemplate.substring(teHerkennenTemplate.indexOf(" "));
System.out.println(uitvoer);
} while (teHerkennenTemplate.length() > 0);
return uitvoer;
}
EDIT:
I now placed this line: teHerkennenTemplate.trim(); just beneath my if-statement, but now it gives me a StringIndexOutOfRange: 0 error at my first line of my if-statement
I have noticed a couple of problems with the above code, although it is difficult to tell why you are taking the approach that you are to the solution.
The main thing I noticed is that your replace statements do NOT remove the \n characters
teHerkennenTemplate = teHerkennenTemplate.replace(templateGescheiden, "\n");
uitvoer = uitvoer.replace(templateGescheiden, "\n");
From Java Documentation:
replace(char oldChar, char newChar):
Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
So, you are replacing your string templateGescheiden with \n each time you loop.
Another issue would be the improper shortening of your teHerkennenTemplate string each loop, which is causing it not to terminate correctly. It will always shorten from the next space character to the end of the string (inclusive) - meaning it will never be an empty string, but will always have a " ".
My advice would be to debug and go step-by-step to see where the shortening and string manipulation is not doing what you want, then evaluate why and modify the code appropriately
There's a variety of things wrong with the code:
the index of a carriage return is found in the string with indexOf("\n").
the substring of teHerkennenTemplate isn't taking into account that it starts with a space, which cause the loop to continue forever.
The simplest way to do what you want is with a regular expression:
"test \n test \n".replaceAll("\n", "")
Will return:
"test test "
If you're set on using a loop then this will do the same:
public static String invoerenTemplate(String teHerkennenTemplate)
{
StringBuilder result = new StringBuilder();
while (teHerkennenTemplate.length() > 0)
{
int index = teHerkennenTemplate.indexOf("\n");
result.append(index > -1 ? teHerkennenTemplate.substring(0, index) : teHerkennenTemplate);
teHerkennenTemplate = teHerkennenTemplate.substring(index + 1, teHerkennenTemplate.length());
}
return result.toString();
}

How to verify if a string.split() returns null

I am reading data from a file:
Some Name;1|IN03PLF;IN02SDI;IN03MAP;IN02SDA;IN01ARC
Some Other Name;2|IN01ALG;IN01ANZ
Another Name;3|
Test Testson;4|IN03MAP;IN01ARC;IN01ALG
I use string.split() for every line I read from that file, like this:
String args[] = line.split("\\|");
String candidatArgs[] = args[0].split(";");
if (args[1] != "" || args[1] != null) {
String inscrieriString[] = args[1].split(";");
Thing is: when I reach Another Name;3| after .split("\\|") the second part (args[1]) should be empty, either null or "" (I don't really know).
However I get an Array index out of bounds error on if (args[1] != "" || args[1] != null) (again, at: Another Name;3|)
The args will only have one element in it.
if (args.length > 1) {
String inscrieriString[] = args[1].split(";");
}
You need to check the length of your args array.
String.split() returns an array of length 1 for your third line, so that args[1] is out of bounds.
You should also use String.isEmpty() instead of != "".
Most likely, you can even skip your additional checks - checking the array length should be sufficient:
if (args.length > 1) {
String inscrieriString[] = args[1].split(";");
...
}
Check the length of args when splitting and only access the other index if the length allows it (if the args.length > 1).
In this case:
String line = "Another Name;3|"; //simplified for the example
line.split("\\|");
It will return this array:
{ "Another Name;3" }
try
String args[] = line.split("\\|",2);
String candidatArgs[] = args[0].split(";");
if (args.length==2)
String inscrieriString[] = args[1].split(";");
args[1] isn't empty or null. It is out of bounds in the array.
System.out.println("Another Name;3|".split("\\|").length);
You would need to check the length of the array before using it.
I think you can test the length of args and it should return 1 or 2. If it's 1 you know that there's no args[1].

Compression class error - Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1

I've created this simple compression class for a client server TCP data connection and it all looks fine to me with no build errors however I am getting a run time error that I cannot correct. The error I am getting is Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1.
Code:
import java.io.Serializable;
import java.util.ArrayList;
public class CompressedMessage implements Serializable
{ // this instance variable will store the original, compressed and decompressed message
private String message;
public CompressedMessage(String message)
{
// begin by coding this method first - initialise instance variable message with the original message
this.message = message;
}
public String getMessage()
{
return this.message;
}
private boolean punctuationChar(String str)
{
// Hint: check if the last character in the string is a punctuation
int length = str.length();
str = str.substring(length -2,length-1);
if(str.equals(",") || str.equals("!") || str.equals(".") || str.equals("?"))
{
return true;
}
else
{
return false;
}
}
private String getWord(String str)
{ // Hint: if last character in string is punctuation then remove
if(punctuationChar(str)== true)
{
//remove punctuation of last char
str = str.substring(0,str.length()-1);
}
return str;
}
public void compress()
{ /* read through section 3 of the practical 5 document
to get you started. This is called by the server,
have a look at the server code where it is called */
ArrayList<String> newMessage = new ArrayList<String>();
String[] words = message.split(" ");
for (String word : words)
{
getWord(word);
//if word has already appeared replace with position of previous word
if(newMessage.contains(word))
{
String str = Integer.toString(newMessage.indexOf(word));
str = str + " ";
newMessage.add(str);
}
else
{
word = word + "";
newMessage.add(word);
}
//if word had a punctuation at the end add it back in
//System.out.println(word);
}
this.message = newMessage.toString();
System.out.println("****************COMPRESSING*****************");
System.out.println(newMessage);
}
public void decompress()
{ /* read through section 3 of the practical 5 document
to get you started. This is called by the client,
have a look at the client code where it is called */
ArrayList<String> decompMessage = new ArrayList<String>();
String[] words = message.split(" ");
for (String word : words)
{
getWord(word);
if(word.substring(0,1).matches("[0-9]"))
{
int num = Integer.parseInt(word);
decompMessage.add(decompMessage.get(num));
}
else
{
decompMessage.add(word);
}
}
this.message = decompMessage.toString();
System.out.println("****************DECOMPRESSING*****************");
System.out.println(decompMessage);
}
}
Error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1952)
at CompressedMessage.punctuationChar(CompressedMessage.java:24)
at CompressedMessage.getWord(CompressedMessage.java:40)
at CompressedMessage.compress(CompressedMessage.java:61)
at P5_Server.waitForData(P5_Server.java:72)
at P5_Server.main(P5_Server.java:159)
I have tried changing the way a calculated the strings based on the length() but it didn't reduce the errors.
Can anyone see what I'm doing wrong?
What if you str is length 0 (empty string ) or length 1? In that case str = str.substring(length -2,length-1); will result into exception.
You need to put a length check before performing the substring:
if(length > 1){
str = str.substring(length-2,length-1);
}
Since you are trying to get only one character, I think you can simply do as:
if(length > 1){
str = String.valueOf(str.charAt(length-2))
}
Please make sure that str is not null otherwise put a null handling as well.
This is happening because you're passing an empty string to punctuationChar.
Oh, and as you're just using the last character in str, it might be easier to convert it to a character.
Try this:
private boolean punctuationChar(String str) {
if (str.length() > 0) {
char lastChar = str.charAt(lastChar.length() - 1);
// Returns true if the character is anything other than a letter, digit or space
return !(Character.isLetterOrDigit(lastChar)) || Character.isWhitespace(lastChar);
}
else {
return false;
}
}
}
I'm using isLetterOrDigit here, then inverting the result. So this method will return true for any string that contains anything other than A-Z, a-z or 0-9 at the end. I'm also counting spaces as not being punctuation.
This would be even easier if Oracle had thought of putting an "isPunctuation" method in!
The Character class in Java's pretty great for checks like this, definitely worth taking a look at the next time you're doing something similar.
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Character.html
you can make that punctuation check easier:
private boolean punctuationChar(String str) {
if (str != null && str.length() > 0) {
char c = str.charAt(str.length()-1);
return c == '.' || c =='?'||c==',' || c =='!';
} else {
return false;
}
}
In general, try to avoid string operations as they are slow. and if you need to work with substrings or a string index, always make sure to be prepared for null, empty or short strings

Categories