Programming issue at work place related to string - java

I have a string which is searched based on the delimiter " (double quote).
So when I enter the string "program", it is able to search the beginning and end of the string based on the delimiter and returns me the string program which I put in a vector.
Now, if I enter a string "program"123"" it returns me substrings like program, 123, 123".
Now the result I want is program"123" which is a valid string as per the usecase but it contains " as part of the string and this is where the search by delimiter fails to distinguish between the beginning and end of the string.
Can someone help with some logic?
The following is the method I am using.
enter code here
public static PVector tokenizeInput(final String sCmd)
throws ExceptionOpenQuotedString
{
if (sCmd == null)
{
return null;
}
PVector rc = new PVector();
if (sCmd.length() == 0)
{
rc.add(StringTable.STRING_EMPTY);
return rc;
}
char chCurrent = '\0';
boolean bInWhitespace = true;
boolean bInQuotedToken = false;
boolean bDelim;
int start = 0;
int nLength = sCmd.length();
for (int i = 0; i < nLength; i++)
{
chCurrent = sCmd.charAt(i); // "abcd "ef"" rtns abdc ef ef"
bDelim = -1 != APIParseConstants.CMD_LINE_DELIMS.indexOf(chCurrent);
if (bInWhitespace) // true
{
// In whitespace
if (bDelim)
{
if ('\"' == chCurrent)
{
start = i + 1;
bInQuotedToken = true;
bInWhitespace = false;
} // if ('\"' == chCurrent)
}
else
{
start = i;
bInWhitespace = false;
} // else - if (bDelim)
}
else
{
// Not in whitespace
boolean bAtEnd = i + 1 == nLength;
if (!bDelim)
{
continue;
}
else
{
if ('\"' == chCurrent)
{
if (!bInQuotedToken)
{
// ending current token due to '"'
if (bAtEnd)
{
// non terminated quoted string at end...
throw new ExceptionOpenQuotedString(
sCmd.substring(start));
}
else
{
rc.add(sCmd.substring(start, i)); // include quote
bInQuotedToken = true;
bInWhitespace = false;
} // if (bAtEnd)
}
else
{
// ending quoted string
//if (!bAtEnd)
{
rc.add(sCmd.substring(start, i)); // don't include quote
bInQuotedToken = false;
bInWhitespace = true;
} // if (bAtEnd)
} // else - if (!bInQuotedToken)
}
else
{
// got delim (not '"')
if (!bAtEnd && !bInQuotedToken)
{
rc.add(sCmd.substring(start, i));
bInWhitespace = true;
} // if (bAtEnd)
} // else - if ('\"' == chCurrent)
} // else - if (!bDelim)
} // else - if (bInWhitespace)
} // for (short i = 0; i < nLength; i++)
if (!bInWhitespace && start < nLength)
{
if (!bInQuotedToken || chCurrent == '"')
{
rc.add(sCmd.substring(start));
}
else
{
throw new ExceptionOpenQuotedString(sCmd.substring(start));
} // else - if (!bInQuotedToken)
} // if (!bInWhitespace && start < nLength)
return rc;
}

You should escape the internal ".
Otherwise, you could check for the position of the first and last " characters and split/cut the string using those positions as delimiters.

Whenever you embed one encoding (all possible strings) inside another (quoted strings) there are only a few basic techniques to allow you to parse them unambiguously:
Disallow certain inputs. For instance, don't allow quote characters. Now you know they are always delimiters. In your case, you could choose a new delimiter besides quote and disallow that in your input. This is rarely desirable, because you often end up wanting to allow the input you previously thought you didn't need.
Include the length of the input in the encoding. For example, instead of quotes you could precede each string with the number of characters in it.
Escaping. Some inputs cannot be represented directly. Instead, at least one character is reserved as the escape character. It indicates that whatever follows it should be interpreted in a different way. In Java strings, the backslash is the escape character. If you only need the escape character for a single reason, you may want to follow the example of some SQL dialects and double it. In SQL, a quote is the quote character for strings, so to include a literal quote character in a string, you type two quotes.

Related

Is it more efficient to use arrays or character?

is this the most efficient method to determine that there is a minimum of two unique characters in a String? Should I have used arrays to hold the characters? Thank you
public static Boolean checkPW(String pw) {
Boolean validLower = false, validUpper = false, validNumber = false;
char lowerCompare = '0', upperCompare = '0', numberCompare = 'a';
for(int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if(character >= 'a' && character <= 'z') {
if(lowerCompare == '0')
lowerCompare = character;
else if(lowerCompare != character)
validLower = true;
} // lower-case if END
} // for-loop END
if(validLower)
return true;
else
return false;
} // checkPW END
If I had to do this in Java, in production, I might just use a set here:
String input = "abcdefgzz";
char[] letters = input.toCharArray();
Set<Character> set = new HashSet<>();
boolean valid = false;
for (char letter : letters) {
set.add(letter);
if (set.size() > 1) {
valid = true;
break;
}
}
if (valid) {
System.out.println("Minimum of two unique letters");
}
else {
System.out.println("Only one unique letter");
}
is this the most efficient method to determine that there is a minimum of two unique characters in a String?
No. The loop continues to run after 2 unique valid characters are found, which is unnecessary. It could stop immediately, and then it will be more efficient. Consider for example the string "ab" followed by a million characters. There's no need to go further than the first two.
Should I have used arrays to hold the characters?
The question is not clear. To make it meaningful, you would need to include reasoning for the benefits of both methods. And it's not clear what technique you're referring to.
It would be good to remove all the unnecessary variables from the program.
After fixing the inefficiency, and a bit of cleanup:
public static boolean checkPW(String pw) {
char first = '0';
for (int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if ('a' <= character && character <= 'z') {
if (first == '0') {
first = character;
} else if (first != character)
return true;
}
}
}
return false;
}
I'd do this:
public static boolean checkPW(String pw) {
Character lowerCompare = null;
for (int position = 0; position < pw.length(); ++position) {
char character = pw.charAt(position);
if(Character.isLowerCase(c)) { // this handles non-ASCII lower case characters
if(lowerCompare == null) {
lowerCompare = character;
} else if(lowerCompare != character) {
return true;
}
}
}
return false;
}

how can I check if a string is a floating point number?

In my program I'm going to store user input in an array then going to check each character to see if it's a digit or dot or E or negative sign after that I'll store it in to an array called temps.
Now I have problem in my fleating method () that don't how should I make my condition for the pattern of floating number digit-digit-dot-digit-digit (e.g 12.22)
I have my work here:
public void sorting(String data) {
String[] temps = new String[200];
int cpos = 0;
int tpos = 0;
Arrays.fill(temps, null);
if (str.isEmpty() == false) {
char char1 = str.charAt(cpos);
int i = 0;
while (i < str.length()) {
char1 = str.charAt(cpos);
char1 = str.charAt(tpos);
System.out.println("the current value is " + char1 + " ");
tpos++;
if (Character.isDigit(char1)) {
temps[cpos] = "Digit";
// System.out.println(" this number is digit");
cpos++;
} else if (char1 == 'e' || char1 == 'E') {
temps[cpos] = "s_notaion";
cpos++;
} else if (char1 == '-') {
temps[cpos] = "negative";
cpos++;
} else if (char1 == '.') {
temps[cpos] = ".";
cpos++;
}
i++;
}
}
}
here is the method for floating number
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (data[i]== "Digit" )
&& data[i]=="." && data[i]"Digit"){
// here is the problem for the condition
}
}
return false;
}
If I understood correctly, the Data array has stuff like ["Digit","Digit",".","Digit"]
So you want the
private static boolean floating(String [] data) {
method to return true if the array only has "Digit" entries and exactly one "." entry? is that it?
If so:
boolean foundLeDigit = false;
for (int i = 0; i < data.length; i++) {
if (data[i].equals("Digit") == false && data[i].equals(".") == false {
//we found something other than a Digit or . it's not a float
return false;
}
if(data[i].equals(".")) {
if(foundLeDigit) { return false; //as we found 2 "." }
foundLeDigit = true
}
}
return foundLeDigit;
The easiest way to test if a String can represent a float is to try to parse it:
String testString = "1.2345";
double result;
try {
result = Double.parseDouble(testString);
System.out.println("Success!")
}
catch (NumberFormatException nfe) {
// wasn't a double, deal with the failure in whatever way you like
}
The questions lacks a bit of context, so for my answer I'm going to presume that this is homework requiring a manual solution, and that all floating point numbers are supposed to be accepted.
Your approach (while over-engineered) is half-right: you are reducing the input string into classes of characters - digit, sign, exponent marker. What is missing is that now you have to make sure that these character classes come in the right order.
Identify the various parts of float numbers (just look at 0, -1.0, 400E30, 42.1E-30) and you'll see that they come in a specific order, even if some are optional, and that each part imposes restrictions on what characters are allowed there. For example, if there is an 'E' in the number, it has to be followed by a number (with optional sign).
So as you step through the characters of the string, think about how you could keep track of where you are in the number, and base your character validation on that (this is the state machine #JonKiparsky was mentioning).
A few small things:
Don't compare strings with '==' - use equalsTo().
Think about what it means if sorting() finds a character which is neither a digit, a sign, or the exponent 'E'?
You allocate the temps array for 200 entries, but the input string could be larger.
using the regular expression is the best way to Handel this problem
private static boolean floating(String [] data) {
int count =0;
boolean correct = false;
for (int i = 0; i < data.length; i++) {
if (str.matches("((-|\\+)?[0-9]+(\\.[0-9]+)?)+")){
System.out.println(" it's a floating number ");
correct= true;
break;
}else
correct = false;
}if (correct ==true){
return true;
}else
return false;
}

Returning a string minus a specific character between specific characters

I am going through the Java CodeBat exercises. Here is the one I am stuck on:
Look for patterns like "zip" and "zap" in the string -- length-3, starting with 'z' and ending with 'p'. Return a string where for all such words, the middle letter is gone, so "zipXzap" yields "zpXzp".
Here is my code:
public String zipZap(String str){
String s = ""; //Initialising return string
String diff = " " + str + " "; //Ensuring no out of bounds exceptions occur
for (int i = 1; i < diff.length()-1; i++) {
if (diff.charAt(i-1) != 'z' &&
diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
}
return s;
}
This is successful for a few of them but not for others. It seems like the && operator is acting like a || for some of the example strings; that is to say, many of the characters I want to keep are not being kept. I'm not sure how I would go about fixing it.
A nudge in the right direction if you please! I just need a hint!
Actually it is the other way around. You should do:
if (diff.charAt(i-1) != 'z' || diff.charAt(i+1) != 'p') {
s += diff.charAt(i);
}
Which is equivalent to:
if (!(diff.charAt(i-1) == 'z' && diff.charAt(i+1) == 'p')) {
s += diff.charAt(i);
}
This sounds like the perfect use of a regular expression.
The regex "z.p" will match any three letter token starting with a z, having any character in the middle, and ending in p. If you require it to be a letter you could use "z[a-zA-Z]p" instead.
So you end up with
public String zipZap(String str) {
return str.replaceAll("z[a-zA-Z]p", "zp");
}
This passes all the tests, by the way.
You could make the argument that this question is about raw string manipulation, but I would argue that that makes this an even better lesson: applying regexes appropriately is a massively useful skill to have!
public String zipZap(String str) {
//If bigger than 3, because obviously without 3 variables we just return the string.
if (str.length() >= 3)
{
//Create a variable to return at the end.
String ret = "";
//This is a cheat I worked on to get the ending to work easier.
//I noticed that it wouldn't add at the end, so I fixed it using this cheat.
int minusAmt = 2;
//The minus amount starts with 2, but can be changed to 0 when there is no instance of z-p.
for (int i = 0; i < str.length() - minusAmt; i++)
{
//I thought this was a genius solution, so I suprised myself.
if (str.charAt(i) == 'z' && str.charAt(i+2) == 'p')
{
//Add "zp" to the return string
ret = ret + "zp";
//As long as z-p occurs, we keep the minus amount at 2.
minusAmt = 2;
//Increment to skip over z-p.
i += 2;
}
//If it isn't z-p, we do this.
else
{
//Add the character
ret = ret + str.charAt(i);
//Make the minus amount 0, so that we can get the rest of the chars.
minusAmt = 0;
}
}
//return the string.
return ret;
}
//If it was less than 3 chars, we return the string.
else
{
return str;
}
}

Searching if String differs by one character

I'm trying to determine if a word entered differs by one character in a text file. I have code that works, but unfortunately only for words that are two characters or less which obviously isn't very useful, and the code itself looks a bit messy. Here's what I have so far:
if(random.length() == word.length()){
for(int i = 0; i < random.length(); i++){
if( (word.charAt(i) == random.charAt(i))){
str += word+"\n";
count++;
}
}
}
With random being the word that was entered by the user, and word being the word to search for in the text file.
If I changed my second if statement to something along the lines of
if( (word.charAt(i) == random.charAt(i)) && (word.charAt(i -1) == random.charAt(i-1)))
and if I change int i to be = 1 instead, I seem to get more of what I'm looking to accomplish, but then my code is searching for only if the first two letters are the same and not if the last two are as well, which it should be doing.
I assume you need a function like this? I just wrote and tested it.
static boolean equals(String word1, String word2, int mistakesAllowed) {
if(word1.equals(word2)) // if word1 equals word2, we can always return true
return true;
if(word1.length() == word2.length()) { // if word1 is as long as word 2
for(int i = 0; i < word1.length(); i++) { // go from first to last character index the words
if(word1.charAt(i) != word2.charAt(i)) { // if this character from word 1 does not equal the character from word 2
mistakesAllowed--; // reduce one mistake allowed
if(mistakesAllowed < 0) { // and if you have more mistakes than allowed
return false; // return false
}
}
}
}
return true;
}
Your code seems to be working to me, you just may be interpreting its results incorrectly.
This may be more obvious:
int count = 0; if(random.length() == word.length()) {
for(int i = 0; i < random.length(); i++)
{
if( (word.charAt(i) != random.charAt(i) ))
{
if(count == 0)
{
System.out.println("Found first difference!");
}
if(count != 0)
{
System.out.println("Strings are more than one letter different!");
}
count++;
}
} }
If you want to check Strings of different lengths, you'll need to delete characters from the longer one until it's the same size as the shorter.
For example:
If String1 = "abc";
and String2 = "zzzabcdef";
You'll need to delete 6 characters from the second string and test for every combination of 6 characters deleted. So you would want to test the strings: def, cde, abc, zab, zza, zzz, zzb, zzc, zzd, zze, zzf, zaf, zae, zad, zac, zab, zza, zzf, zze, ..., ..., on and on, the list is of size 9 choose 6, so it's definitely not optimal or recommended.
You can however, check to see if a string which is one character longer than the other is just the other string with one added letter. To do this, you want a for loop to grab two substring from 0 to i, and from i+1 to the end. This will leave out the ith character, and looping for the size of the string - 1, will give you first the full string, then the string without the first letter, then missing the second letter, and so on. Then test that substring in the same fashion we did above.
Comment if this was not what you're looking for.
EDIT
To see how many words in a file are one letter different than a variable word, you need to loop through the file, getting each word. Then testing if that was string was one letter off. It would be something like this:
String testAgainst = "lookingForWordsOneLetterDifferentThanThisString";
int words = 0;
Scanner scan = new Scanner(fileName);
while(scan.hasNext())
{
String word = scan.next();
if( isOneDifferent(word, testAgainst) )
{
words++;
}
System.out.println("Number of words one letter different: " + words);
}
public boolean isOneDifferent(String word, String testAgainst)
{
if(word.length() != testAgainst.length())
{
return false;
}
int diffs = 0;
for(int i = 0; i < word.length(); i++)
{
if(word.charAt(i) != testAgainst.charAt(i))
{
diffs++;
}
if(diffs > 1)
{
return false;
}
}
if(diffs == 1)
{
return true;
}
else
{
return false;
}
}

Password validation - adding additional requirments

I have some code that currently checks for minimum and maximum lentgh. I want to also require uppercase, lowercase, special char, and numeric. Any suggestions on what to add to this or where I can find some examples? I've been Googling and looking thru this forum and have been trying to add the additional password requirments and have been unsuccessful.
This is what I want to require.
At least eight characters in length
No more than 20 characters in length
at least lower-case letter and one upper-case
at least one special character from: !##$%^&*()~`-=_+[]{}|:";',./<>?
at least one number [0-9] character
Cannot match the account login name or email address
My current password validation code
public static final int MIN_PASSWORD_LENGTH = 8;
public static final int MAX_PASSWORD_LENGTH = 20;
public static boolean isAcceptablePassword(String password)
{
if(TextUtils.isEmpty(password))
return false;
int len = password.length();
if(len < MIN_PASSWORD_LENGTH || len > MAX_PASSWORD_LENGTH)
return false;
for(int i = 0; i < len; i++)
{
char c = password.charAt(i);
if (Character.isWhitespace(c))
return false;
}
return true;
}
When you're analyzing String data, you should erase the whitespaces on the right and left. This is done by the Strimg#trim function like this:
password = password.trim();
To analize every character of the String, you can transform it to a char array, so it will be easier to fulfill your requirements:
char[] arrPassword = password.toCharArray();
Now you can evaluate a char using these functions: Character#isUpperCase, Character#isLowerCase, Character#isDigit.
Last but not least, you can have a String with the special characters you need to check, and check if the actual character you're evaluating is inside that String. This could be achieved using String#indexOf and String#valueOf, this las one to convert the char to a String type.
Here is a code sample for all this explanation:
public static final String SPECIAL_CHARACTERS = "!##$%^&*()~`-=_+[]{}|:\";',./<>?";
public static final int MIN_PASSWORD_LENGTH = 8;
public static final int MAX_PASSWORD_LENGTH = 20;
public static boolean isAcceptablePassword(String password) {
if (TextUtils.isEmpty(password)) {
System.out.println("empty string.");
return false;
}
password = password.trim();
int len = password.length();
if(len < MIN_PASSWORD_LENGTH || len > MAX_PASSWORD_LENGTH) {
System.out.println("wrong size, it must have at least 8 characters and less than 20.");
return false;
}
char[] aC = password.toCharArray();
for(char c : aC) {
if (Character.isUpperCase(c)) {
System.out.println(c + " is uppercase.");
} else
if (Character.isLowerCase(c)) {
System.out.println(c + " is lowercase.");
} else
if (Character.isDigit(c)) {
System.out.println(c + " is digit.");
} else
if (SPECIAL_CHARACTERS.indexOf(String.valueOf(c)) >= 0) {
System.out.println(c + " is valid symbol.");
} else {
System.out.println(c + " is an invalid character in the password.");
return false;
}
}
return true;
}
The System.out.println(c + " is an invalid character in the password."); sentence is just to check the result of analyze the actual character.
How about some good old regular expressions? This seems to work correctly, although might have made slip in the escaping for special char check
Pattern[] checks = {
Pattern.compile("[!##\\$%^&*()~`\\-=_+\\[\\]{}|:\\\";',\\./<>?]"),
Pattern.compile("\\d+"),
Pattern.compile("[A-Z]+"),
Pattern.compile("[a-z]+"),
Pattern.compile("^.{8,20}$") };
for (String test : new String[] { "password", "Password1",
"Password1&", "toolongtoolongtoolong" }) {
boolean ok = true;
for (Pattern check : checks) {
ok = ok && check.matcher(test).find();
}
System.out.println(test + " " + ok);
}
Stephen is right with a bit of searching you would have found your answers easily around here. But the thread Stephen refers to is using a thirdparty library.
If you want to implement this yourself then before starting the for-loop initialize 4 booleans for your requirements with false. While looping check for all four requirements until one is true. Set the corresponding boolean to true.
How to check the 4 requirements:
The length req you already implemented.
Character(yourChar).isLowerCase()
Character(yourChar).isUpperCase()
Special character: see here: Java String Special character replacement - you can choose a similar approach
After the loop check for the 4 booleans and react accordingly.

Categories