Whitespace detector returning errors - java

I created a method to basically detect white space characters. I go through a string and check each character for white space. If it is a white space character, I return true, and if it's not, I return false. However, I get a compilation error, stating "missing return statement". As I already have two return statements "true" and "false", I can't see why there is an error. Can you help me out or point me in the right direction? Thanks in advance.
public boolean isWhitespace()
{
for (int i=0; i<string.length(); i++)
{
if (Character.isWhitespace(i))
{
return true;
}
else
{
return false;
}
}
}

Imagine if string.length() were 0. What would get returned?
Also, note that this doesn't do what you stated, which is to go through a string and check each character. It actually isn't checking anything about the string at all because of your use of i. If it were checking the string, it still would only check the first character of the string. If that character is whitespace, true is immediately returned, and if not, false is immediately returned.

You are looping over the length of the String, yet trying to return inside that loop. The logic doesn't make sense.
Think about the problem you are trying to solve - do you want to test if a character is a whitespace, or if an entire String contains at least one whitespace character? For the latter:
boolean hasWhite = false;
for(int i=0; i < string.length(); i++)
{
if(Character.isWhitespace(string.charAt(i)))
{
hasWhite = true;
break;
}
}
return hasWhite;
EDIT: A much simpler approach, if you're into that sorta thing ;-) -
return string.contains(" ");

Here is what your code should look like:
public boolean isWhitespace(String string) { // NOTE: Passing in string
if (string == null) { // NOTE: Null checking
return true; // You may consider null to be not whitespace - up to you
}
for (int i=0; i < string.length(); i++) {
if (!Character.isWhitespace(string.charAt(i))) { // NOTE: Checking char number i
return false; // NOTE: Return false at the first non-whitespace char found
}
}
return true; // NOTE: Final "default" return when no non-whitespace found
}
Note that this caters for the edge cases of a blank (zero-length) string and a null string

Related

Capitalize each word in a string, how does this code check the previous space

I recently came across this solution to writing a program that capitalizes each word in a string and I'm trying really hard to understand it, but I can't get over one hurdle.
public class test {
public static void main(String[] args) {
// create a string
String message = "everyone loves java";
// stores each characters to a char array
char[] charArray = message.toCharArray();
boolean foundSpace = true;
for(int i = 0; i < charArray.length; i++) {
// if the array element is a letter
if(Character.isLetter(charArray[i])) {
// check space is present before the letter
if(foundSpace) {
// change the letter into uppercase
charArray[i] = Character.toUpperCase(charArray[i]);
foundSpace = false;
}
}
else {
// if the new character is not character
foundSpace = true;
}
}
// convert the char array to the string
message = String.valueOf(charArray);
System.out.println("Message: " + message);
}
I understand everything in this code except for how it checks if the previous character was a space. The comment says it does this with the if(foundSpace) statement, but I don't see any reason why that would work since it's never specified that it's looking for a space. Any pointers in the right direction would be appreciated
Edit: Thanks for everyone’s answers, I think I finally get it now!
Look at the code inside the loop, stripped down a bit:
for(int i = 0; i < charArray.length; i++) {
if(Character.isLetter(charArray[i])) {
// check space is present before the letter
if(foundSpace) {
// Some code.
foundSpace = false;
}
// Here, foundSpace is false.
} else {
foundSpace = true;
}
}
The code doesn't care about what your variables or methods are called: it's checking if the character meets some criterion (Character.isLetter), and afterwards it has recorded whether or not the character met that criterion (in foundSpace).
This means that foundSpace contains whether the previous character met that criterion, and allows you to decide to do something on the current character based on what the previous one was: in your case, uppercase that character if the previous character didn't meet the criterion.
foundSpace is initially set to true, which means that the loop treats a string which starts with a letter as if there was a space before it, and so that will be capitalized.
Really, there is just a mismatch between the criterion used, and the name of the variable:
If the criterion should be "is it whitespace", use Character.isWhitespace as your criterion, and keep the flag name as foundSpace;
If the criterion really is "is it a letter", use Character.isLetter as your criterion, and name the flag foundLetter (and invert its sense, so check if (!foundLetter) etc, because it's easier to deal with "positive" checks (if (foundLetter)) rather than "negative" checks (if (!foundLetter))).
foundSpace is only set to false if the condition:
(Character.isLetter(charArray[i]))
is triggered.
If the condition is not triggered, aka if the character is not a letter, then foundSpace will be set to True.
This means that anything that is not a letter will set foundSpace equal to true.
As Silvio pointed out, this includes other non space characters such as 1, $, and ".
It would be better instead of checking if the character is a letter, to instead check to see if charArray[i] is equal to a space.
Like so:
boolean foundSpace = Character.isWhitespace(charArray[i])
More info about the Character class can be found below:
https://www.geeksforgeeks.org/character-equals-method-in-java-with-examples/
The code you've shown could have some undesirable side effects - especially if foundSpace is relied upon later on - because it could potentially lead you to believe that a space exists in a word, when it's not a space at all but rather a character that isn't a letter like "$".
In the context of your entire program, this looks like:
public class test {
public static void main(String[] args) {
// create a string
String message = "everyone loves java";
// stores each characters to a char array
char[] charArray = message.toCharArray();
boolean foundSpace = true;
for(int i = 0; i < charArray.length; i++) {
if(Character.isWhitespace(charArray[i])){
foundSpace = true;
}
else{
foundSpace = false;
}
// if the array element is a letter
if(Character.isLetter(charArray[i])) {
// check space is present before the letter
if(foundSpace) {
// change the letter into uppercase
charArray[i] = Character.toUpperCase(charArray[i]);
}
}
else {
// if the new character is not character
// delete this condition if you don't plan to use it
}
}
// convert the char array to the string
message = String.valueOf(charArray);
System.out.println("Message: " + message);
}
Some edits made to the code to fix compilation errors, thanks to those in the comments for your suggestions.

Email format type JAVA

I have a task to write a return type method which takes String as an argument and returns boolean. If the String matches with the requirements it returns true else false.
So it should not have any space, and more then 1 '#'and format must be 2>chars#2>chars.2>chars so it should be xyz#xyz.com is true but if any part of it less then 3 it should return to false. I checked so many forums but all i can find regex and we didn't learn anything about it. I could able to do this much but i just couldn't figure out how can i specifically set length of each part and set it as true or false. I'm missing so many and this is all i able to complete;
public static boolean emailAddress(String str) {
if (str.contains(" "))
return false;
boolean flag = true;
if(str3.length()> 11)
for (int i = 0; i < str3.length(); i++) {
for (int j = i + 1; j < str3.length(); j++) {
if (str3.charAt(i) == str3.charAt(j)) {
flag = false;
break;
}
}
if(flag)
return true;
}
return false;
}
This is how I would approach it:
public static boolean isEmailAddress(String str)
{
if(str.trim().equals("")) // Checking if it is an empty string
{
return false;
}
boolean flag = true;
int atIndex = str.indexOf("#"); // Get the index of #
if (atIndex == -1)
{
return false;
}
// Slice your email str and get only the characters before the #
// Check whether the length and the characters are as you want them.
// Do the same thing about the string between # and .
// and then do the same thing about the sliced string after .
}
Check substring() and indexOf().
For anyone who needs it.
This should be one of the Regex to match your requirement:
[a-zA-Z_0-9]{2,}#[a-zA-Z_0-9]{2,}\.[a-zA-Z_0-9]{2,}
[a-zA-Z_0-9] it requires one of the characters, from a-z,A-Z or 0-9
{2,} it requires two or more from one of the characters inside.
A few hints instead of complete solution:
Check if the input string...
has # and . (there could be two or three period's as some domain uses .co.in)
does not have any white spaces (' ')
does not start with special characters ('#', '^')
If possible, do not check for length of each part, as sometimes .in also valid domain.

Boolean always returns false possibly due to values not increasing

This method, moreVowels, is intended to be able to count the amount of vowels and consonants in the String entered, and return true if the amount of vowels is greater than the amount of consonants. Sadly this code always returns false, and I cannot understand why. Here is the method stated:
public Boolean moreVowels()
{ vowelCount = 0;
consonantCount = 0;
for(int i = 0; i < word.length(); i++)
{
if ("AEOIUY".contains(word.substring(i,i++)) || "aeoiuy".contains(word.substring(i,i++)))
{
vowelCount++;
}
if ("BCDFGHJKLMNPQRSTVWXZ".contains(word.substring(i,i++)) || "abcdefghijklmnopqrstuvwxyz".contains(word.substring(i,i++)))
{
consonantCount++;
}
}
if (vowelCount > consonantCount)
{
return true;
}
else
{
return false;
}
}
I believe it is always returning false due to the loop not actually increasing the counts, but I'm not quite sure why not. Thank you for reading, I'm sure the answer is something silly that I failed to recognize.
First, you should not use substring(i,i++), but substring(i,i+1). Otherwise, you'll increase i, making your code skip letters.
"abcdefghijklmnopqrstuvwxyz".contains(word.substring(i,i+1)) looks like a mistake. It will cause consonantCount to increase in each loop for every lowercase letter.
If you're only dealing with words (no spaces etc.), then every word is either a consonant or a vowel, so you don't need the second if. You could get consonant count by subtracting vowelCount from length.
Furthermore, if you convert the i-th character to uppercase, you can omit the || "aeoiuy".contains(...) part.
The other answer and comment already show the problems with your code. I just want to add a possible stream based solution that can reduce the possibilty for errors by repacing the index based looping and local variables:
private static boolean moreVowels(String word)
{
return word.chars()
.mapToObj(c -> Character.toString((char) c).toUpperCase())
.mapToInt(c -> "AEIOUY".contains(c) ? 1 : "BCDFGHJKLMNPQRSTVWXZ".contains(c) ? -1 : 0)
.sum() > 0;
}
You can apply the use of toUpperCase() to your own implementation as well to make the if statements a bit shorter (again avoiding possible errors).

Why does the default Boolean return value influence my tests outcome

I'm learning Java and while completing exercises I stumbled upon an issue in CodingBats sameStarChar program.
I know this is a simple exercise but the logic behind the different outcome is really bugging me.
When I write :
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.charAt(i) == '*') {
if (str.charAt(i - 1) != str.charAt(i + 1))
return false;
}
}
return true;
}
All results are OK.
But when I change the code and invert the condition in the if block and return false as default return value, the code does not work anymore and some test fail:
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.charAt(i) == '*') {
if (str.charAt(i - 1) == str.charAt(i + 1))
return true;
}
}
return false;
}
Can you please tell me why are the outcomes different? I can`t seem to find an exact explanation for this in any book.
Pay close attention to what the code is doing, in English:
Looping across all characters of a string, starting at 1 and going until 1 before its end
If the character at a given position i is *:
If the characters a position before and a position after are equal:
Return false.
Return true. Assume other scenario has its case exhausted.
The reason you get completely different results is because you completely flip the logic of the program. Here's your code, in English again:
Looping across all characters of a string, starting at 1 and going until 1 before its end
If the character at a given position i is *:
If the characters a position before and a position after are not equal:
Return true.
Return false. Assume other scenario has its case exhausted.
You haven't made false the default return option; you've inverted the entire program's logic. Consider the empty string, which is a valid test case. Your code said that this is invalid, when there's no asterisk to be had in the string (which would be a strange false positive).
The 1st case works because it returns true only if the * is preceded and followed by the same character or if the string doesn't contain a * at all.
The 2nd case doesn't work because it returns true if it contains at-least one * and first instance of * is preceded and followed by the same characters regardless of next instances of *. So if a blank string is passed it should return true but it instead returns false because it doesn't contain *. If another string *xa*a*b is passed the second program will return true because the instance of * follows the convention. The 2nd Program will return true right away, ignoring all the * after the it's first appearance.

Java: Efficient way to determine if a String meets several criteria?

I would like to find an efficient way (not scanning the String 10,000 times, or creating lots of intermediary Strings for holding temporary results, or string bashing, etc.) to write a method that accepts a String and determine if it meets the following criteria:
It is at least 2 characters in length
The first character is uppercased
The remaining substring after the first character contains at least 1 lowercased character
Here's my attempt so far:
private boolean isInProperForm(final String token) {
if(token.length() < 2)
return false;
char firstChar = token.charAt(0);
String restOfToken = token.substring(1);
String firstCharAsString = firstChar + "";
String firstCharStrToUpper = firstCharAsString.toUpperCase();
// TODO: Giving up because this already seems way too complicated/inefficient.
// Ignore the '&& true' clause - left it there as a placeholder so it wouldn't give a compile error.
if(firstCharStrToUpper.equals(firstCharAsString) && true)
return true;
// Presume false if we get here.
return false;
}
But as you can see I already have 1 char and 3 temp strings, and something just doesn't feel right. There's got to be a better way to write this. It's important because this method is going to get called thousands and thousands of times (for each tokenized word in a text document). So it really really needs to be efficient.
Thanks in advance!
This function should cover it. Each char is examined only once and no objects are created.
public static boolean validate(String token) {
if (token == null || token.length() < 2) return false;
if (!Character.isUpperCase(token.charAt(0)) return false;
for (int i = 1; i < token.length(); i++)
if (Character.isLowerCase(token.charAt(i)) return true;
return false;
The first criteria is simply the length - this data is cached in the string object and is not requiring traversing the string.
You can use Character.isUpperCase() to determine if the first char is upper case. No need as well to traverse the string.
The last criteria requires a single traversal on the string- and stop when you first find a lower case character.
P.S. An alternative for the 2+3 criteria combined is to use a regex (not more efficient - but more elegant):
return token.matches("[A-Z].*[a-z].*");
The regex is checking if the string starts with an upper case letter, and then followed by any sequence which contains at least one lower case character.
It is at least 2 characters in length
The first character is
uppercased
The remaining substring after the first character contains
at least 1 lowercased character
Code:
private boolean isInProperForm(final String token) {
if(token.length() < 2) return false;
if(!Character.isUpperCase(token.charAt(0)) return false;
for(int i = 1; i < token.length(); i++) {
if(Character.isLowerCase(token.charAt(i)) {
return true; // our last criteria, so we are free
// to return on a met condition
}
}
return false; // didn't meet the last criteria, so we return false
}
If you added more criteria, you'd have to revise the last condition.
What about:
return token.matches("[A-Z].*[a-z].*");
This regular expression starts with an uppercase letter and has at least one following lowercase letter and therefore meets your requirements.
To find if the first character is uppercase:
Character.isUpperCase(token.charAt(0))
To check if there is at least one lowercase:
if(Pattern.compile("[a-z]").matcher(token).find()) {
//At least one lowercase
}
To check if first char is uppercase you can use:
Character.isUpperCase(s.charAt(0))
return token.matches("[A-Z].[a-z].");

Categories