Why is this not a run time error - java

substring returns a string starting with the specified index number all the way to the end.
Can you tell me why the following is not a run time error?
String s = "Hello";
s.substring(5);
The length of the string is 5 but the last index is 4 so why do I not get an exception for range? I get one when I say s.substring(6);
Please help!

s.substring() doesn't actually throw a method if you call an index 1 above the last index. This is very helpful, because then you don't need to worry with forloops like this:
for(int i = 0; i < string.length - 1; i++) {
System.out.println(s.substring(i, i+1));
}
No need to have a special check for the very last index, it'll just work.
You can see the Java Docs for the more technical answer - s.substring() will only throw an error if the index is greater than the LENGTH of the string, not just the number of indices.
See this question for more info too.

From the documentation:
Throws: IndexOutOfBoundsException - if beginIndex is negative or larger than the length of this String object.
5 is equal to the length of "Hello", so it's permitted.

The reason why it does not throw an exception is because in the two parameter version:
substring(int beginIndex, int endIndex)
endIndex is exclusive. When the single parameter version you're using specifies the length of the string, the behavior is consistent with the two parameter version, so its treated as exclusive. The result is an empty string.
The actual implementation of the single parameter version is:
public String substring(int beginIndex) {
return substring(beginIndex, count);
}
For reference, the actual implementation of the two parameter version is:
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count))
? this
: new String(offset + beginIndex, endIndex - beginIndex, value);
}

This is expected behaviour, API gives a similar example:
"emptiness".substring(9) returns "" (an empty string)

Related

C++ vs Java Memoization Discrepancy [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
So I've been trying to solve the word break Dynamic Programming problem, which basically means that given a dictionary of strings and a string, see if the words in the dictionary can be combined to form the string. For example, given word "applepenapple" and dictionary ["apple","pen"] it should return true.
I have a working java solution, but I'm trying to improve my C++ skills. My problem is even though my code looks extremely similar to the working solution in Java, I am failing a niche test case and I can't figure out why.
C++ code:
bool wordBreak(string s, vector<string> &wordDict) {
vector<int> bArr(s.length(), -1);
unordered_set<string> set(wordDict.begin(), wordDict.end());
return wordBreak(s, bArr, 0, set);
}
bool wordBreak(string s, vector<int> &bArr, int start, unordered_set<string> &set) {
if (start == s.length())
return true;
//If we have a memoized solution to this problem, avoid recurion
if (bArr[start] != -1)
return (bArr[start] == 1);
for (int end = start + 1; end <= s.length(); end++) {
if (set.count(s.substr(start, end)) && wordBreak(s, bArr, end, set)) {
bArr[start] = 1;
return bArr[start] == 1;
}
}
bArr[start] = 0;
return false;
}
Working code using java:
public boolean wordBreak(String s, List<String> wordDict) {
Integer[] memo =new Integer[s.length()];
Arrays.fill(memo,-1);
return word_Break(s, new HashSet(wordDict), 0, memo);
}
public boolean word_Break(String s, Set<String> wordDict, int start, Integer[] memo) {
if (start == s.length()) {
return true;
}
if (memo[start] != -1) {
return memo[start]==1;
}
for (int end = start + 1; end <= s.length(); end++) {
if (wordDict.contains(s.substring(start, end)) && word_Break(s, wordDict, end, memo)) {
memo[start] = 1;
return memo[start] == 1;
}
}
memo[start] = 0;
return false;
}
The C++ code is returning false for "applepenapple" with dictionary ["apple","pen"] and I don't know why since the java return true which is correct. The only major difference (I think) between the two solutions is that my C++ uses a vector instead of a native array in the java code. Initially I thought it might have to do with C++ using automatic storage (stack) vs the free store (heap) which is why I used the vector instead of a C-style array to avoid memory management because of RAII. Despite this change, the bug persists. There is an easier solution avoiding recursion altogether, but I am very curious as to why the C++ is returning different output than the java.
I see a potential problem. From java.lang.String Javadoc (emphasis mine):
public String substring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and extends to the character at index endIndex - 1. Thus the length of the substring is endIndex-beginIndex.
Examples:
"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"
Parameters:
beginIndex - the beginning index, inclusive.
endIndex - the ending index, exclusive.
From cppreference.com documentation on strings:
basic_string substr( size_type pos = 0, size_type count = npos ) const;
Returns a substring [pos, pos+count). If the requested substring extends past the end of the string, or if count == npos, the returned substring is [pos, size()).
Parameters
pos - position of the first character to include
count - length of the substring
That is, in Java you should pass an index as second parameter to String.substring(...), but in C++ you should pass a length to basic_string::substr(...). However, you are doing:
s.substr(start, end)
and
s.substring(start, end)
in both cases.
Maybe adjusting the C++ invocation to
s.substr(start, end - start)
will work?

java substring not working as expected

I'm trying to use substring function in java, but it keeps throwing an error, I want to know why ? the code seems to be good logically speaking but why it is throwing this error
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
What I've read in the documentation substring takes 2 parameter
substring(whereIwantToStart,howManyCharactersToshow)
below is my code
String test = "160994";
System.out.println(test.substring(2,1)); //output should be 09 why error?
Can someone explain me what is wrong ? please I need explanation. Thanks :)
See the doc:
public String substring(int beginIndex, int endIndex)
Returns a new string that is a substring of this string. The substring begins at the specified beginIndex and
extends to the character at index endIndex - 1. Thus the length of the
substring is endIndex-beginIndex.
You need "160994".substring(2, 4) to get 09.
End index should be greater than the Start Index. To get output as '09', you should provide the end index as 4 test.substring(2,4);
Returns a new string that is a substring of this string. The
substring begins at the specified beginIndex and extends
to the character at index endIndex - 1.
Thus the length of the substring is endIndex-beginIndex.
The StringIndexOutOfBoundsException will throw in below cases
beginIndex < 0
endIndex > value.length
endIndex - beginIndex < 0
For your required output use-
System.out.println(test.substring(2,4));
This is the format for the substring in java
public String substring(int beginIndex, int endIndex)
you are specifying start from index 2 and end at index 1 , that's why it's throwing an exception index out of range.
To get the output as 09 you need
System.out.println(test.substring(2,4));
Appendix - Java Docs https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int)
public String substring(int startIndex, int endIndex): This method returns new String object containing the substring of the given string from specified startIndex to endIndex.
Let's understand the startIndex and endIndex by the code given below.
String s="hello";
System.out.println(s.substring(0,2));
Output : he
Notice :
endIndex > startIndex
in your case : change between 1 and 2 place to
String test = "160994";
System.out.println(test.substring(2, 4)); //output should be 09
Output : 09
String test = "160994";
System.out.println(test.substring(2,1));
Substring means (beginIndex, endIndex) and endIndex Should be larger than beginIndex.and your value(09) should be stay between beninIndex(which is starting index) and endIndex(Which is last index).
and you have taken endIndex 1 so you are geting the Error because your beginIndex is larger than endIndex.
if you want to get Ans. 09 then you should have to put endIndex 4.
Line will be:-System.out.println(test.substring(2,4));

In Java, I have a String named string "A"( size 1). Why does string.substring(1) give no exceptions

In java, I have a String named string with the value "A".
i.e. String string = "A";
Its size is 1 and we know that characters in a string are 0 indexed. They are represented as a Char array.
Then, why does NOT string.substring(1); give me an exception?
If you look at code of substring(int beginIndex) :
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
There is no condition to specify that if length is 1 and index is 1, an exception should be thrown. Infact, a new empty string is returned.
System.out.println("A".substring(1).equals("")); returns true because of last line in the method.
Based on the JavaDocs for String#subString(int)
Throws: IndexOutOfBoundsException - if beginIndex is negative or larger than the length of this String object".
A String with a single character has a size of 1, therefore 1 == length
As you can se in the code of substring
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
it will only throw an exception if then lenght of the spring is lower then ie begin index.
In your case the begin index is equals the length and thats why you do not get an exception.
Others have quoted the rule, but I wanted to point out the implications. If you say s.substring(n), then n can be anywhere from 0 to s.length(), inclusive. That means that if s has length len, there are len+1 (rather than len) possible ways to call s.substring with one parameter. This makes sense, because if you have the string "abcde", for example, and you're using substring(n) to get a suffix of the string, there are six possible suffixes: "abcde", "bcde", "cde", "de", "e", "".
This is helpful in practice, because you can code things like
while (<something>) {
if (s.beginsWith(prefix)) {
... do some other stuff ...
s = s.substring(prefix.length());
// This sets "s" to the remainder of the string, after the prefix.
// It works even if there is no more text in the string, i.e.
// prefix.length() == s.length(), so that the remaining text is "".
}
In my experience, the ability to have things work this way is very beneficial. It avoids forcing to you write special logic to handle this boundary case, since the boundary case's handling is consistent with the non-boundary cases.

Why is substring() function in returning a value when it should be returning an overflow message

I am trying to solve a problem which goes like this:-
Given a string, return a "rotated left 2" version where the first 2 chars are moved to the end. The string length will be at least 2.
left2("Hello") → "lloHe"
left2("java") → "vaja"
left2("Hi") → "Hi"
I have written two functions for this:-
public String left2(String str)
{
String str1 = str;
if(str.length()>2)
str1 = str.substring(2)+str.substring(0,2);
return str1;
}
public String left2(String str)
{
return str.substring(2)+str.substring(0,2);
}
Both of the functions are correct. I wanted to know that if the first parameter of substring() function is an index, then am I not getting an overflow error in the second function? I am asking this because Java doesn't end in a NULL character so I think there be an error in the second function.
That's because your Substring logic works only if the text length is greater than 2. See here:
if(str.length()>2)
str1 = str.substring(2)+str.substring(0,2);
This is the source code for substring method in java:
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
From experience, documentation may lie, but code doesn't. StringIndexOutOfBoundsException is thrown only if
a. beginIndex is less than 0(that is, is negative) or
b. endIndex is greater than count or
c. beginIndex is greater than endIndex.
The reason the second function
return str.substring(2)+str.substring(0,2);
works is that you never tried passing a string that is shorter than two characters. If you did, you would have received an exception (demo).
The reason this works when you pass a string of two characters is that the index that you pass is allowed to be equal to the length of the string (in this case, 2). When you pass an index that equals the length of the string to substring that takes one parameter, you get an empty string. When you pass an index that equals the length of the string to two-parameter substring, it takes the string up to and including the last character.

Misleading javadoc comment on StringBuilder indexOf?

I'm trying to understand the following comment from the javadoc of the StringBuilder class's indexOf(String str,
int fromIndex) method.
It says:
Returns the index within this string of the first occurrence of the specified substring, starting at the specified index. The integer returned is the smallest value k for which:
k >= Math.min(fromIndex, str.length()) &&
this.toString().startsWith(str, k)
If no such value of k exists, then -1 is returned.
Now, I can't see the reason for str.length() in Math.min(fromIndex, str.length()) since it would allow for a String to be found on an index < fromIndex. Am I missing something, or this is simply a misleading/wrong commment?
Edit: as pointed below this is the comment from the Java 7 javadoc; java 6 has the right comment.
It's a mistake. It's supposed to be this.length() instead of str.length().
That allows for fromIndex to be greater than this.length() in the case where str is empty.
Example:
StringBuilder sb = new StringBuilder("Example");
System.out.println(sb.indexOf("", 1234)); //Outputs sb.length(), which is 7.
Note: String#indexOf(String, int) behaves the same way.
No the condition basically boils down to the first k such that k is at least fromIndex and less than or equal to str.length(), at which the string contains the desired substring.
If str.length() < fromIndex, then the startsWith condition will always be false, because str.length() is not a valid index to the generated string.

Categories