counting special characters in a user generated string - java

So I have this program that is supposed to to take any user generated string and display the amounts of white space, letters, numbers, and special characters. I do not want to duplicate a question. It seems to be a little more specific then talked about in other posts.
My error lies in the special characters. The specific error is return 0. I referenced stack overflow already in about every discussion they had on the matter. Which helped me form the special character method.
I have to keep the main method clear and call aforementioned methods
public static void main(String[] args) {
Scanner kbd = new Scanner(System.in);
String userInput;
System.out.println("Please enter a string");
userInput = kbd.nextLine();
countletter(userInput);
countnumber(userInput);
countspecial(userInput);
countSpace(userInput);
}
public static void countletter(String userInput) {
int countletter = 0;
for (int i = 0; i < (userInput.length() - 1); i++) {
char location = userInput.charAt(i);
boolean x = Character.isLetter(location);
if (x) {
countletter++;
}
}
System.out.println("The number of Letters is: " + countletter);
}
public static void countnumber(String userInput) {
int countnumber = 0;
for (int i = 0; i < userInput.length() - 1; i++) {
char location = userInput.charAt(i);
boolean x = Character.isDigit(location);
if (x) {
countnumber++;
}
}
System.out.println("The number of digits is: " + countnumber);
}
public static void countSpace(String userInput) {
int countSpace = 0;
for (int i = 0; i < userInput.length() - 1; i++) {
char location = userInput.charAt(i);
boolean x = Character.isWhitespace(location);
if (x) {
countSpace++;
}
}
System.out.println("The number of white spaces is: " + countSpace);
}
public static void countspecial(String userInput) {
if (userInput == null || userInput.trim().isEmpty()) {
return 0;
}
int countSpecial = 0;
for (int i = 0; i < userInput.length(); i++) {
if (userInput.substring(i, 1).matches("[^A-Za-z0-9 ]")) {
countSpecial++;
}
}
System.out.println("The number of special chars is: " + countSpecial++);
}
}
My initial attempt at countSpecial:
public static void countspecial(String userInput) {
int countSpecial = 0;
for (int i = 0; i < (userInput.length() - 1); i++) {
if (userInput.substring(i, 1).matches("[^A-Za-z0-9]")) {
countSpecial++;
}
}
System.out.println("The number of special chars is: " + countSpecial++);
}
}
Where am I going wrong and why?

in your initial attemp you have problem with your substring
substring second parameter would be the index of your last character in the substring +1, and so you need to iterate until userInput.length() not userInput.length() -1.
And i dont know why would you increment the count after printing it , it actually does nothing but still makes no sense.
public static void countspecial(String userInput) {
if (userInput == null || userInput.trim().isEmpty()) {
return ;
}
int countSpecial = 0;
for (int i = 0; i < userInput.length(); i++) {
if (userInput.substring(i, i+1).matches("[^A-Za-z0-9]")) {
countSpecial++;
}
}
System.out.println("The number of special chars is: " + countSpecial);
}
A better way instead of subtring you could use "(userInput.charAt(i)+"").matches".
But a better solution would be counting all the digits and letters and subtract their sum form the total length of the string , this would give you the number of special characters as it is not recommended to use regex for simple requirement like this.

Look at the javadocs for substring.
Some languages that use a flavor of substring(int beginIndex, int length) where beginIndex is where you start the substring and length is how many characters are in the substring.
Java uses substring(int beginIndex, int endIndex) where beginIndex is where you start the substring and endIndex is the position of the ending character.
userInput.substring(i, 1);
Where i = 2 means you want to start the substring at index position 2 and end it at index position 1 and an exception is thrown.

If you're defining anything other than a letter, digit or whitespace character to be "special" then you should really test for it in the same way as the other tests so you don't miss anything because of different definitions of what constitutes a letter or digit. Character.isLetter() will return true for any Unicode letter, for example, not just ASCII A-Z or a-z. For consistency you should write:
char c = userInput.charAt(i);
if (!Character.isDigit(c) && !Character.isLetter(c) && !Character.isWhiteSpace(c)) {
countSpecial++;
}
But the problem in your original code is that the second parameter to String.substring() is the 'to' index, not a length. So if you were going to do with a regex it should be
if (userInput.substring(i, i+1).matches("[^A-Za-z0-9 ]")) {
countSpecial++;
}
Is this a practical example or are you asking for help doing an assignment? :-)

Even easier, don't loop. Just replace all non-special chars with nothing and count the length:
int countSpecial = userInput.replaceAll("[A-Za-z0-9\\s]", "").length();
You can apply this technique to all your character categories.

Related

How to identify which characters are mismatching in a user input string

This project is used to identify whether or not a user's input is a palindrome, and if it's not, identifies how many characters don't match and their positions in the string (i.e characters 2 and 4 don't match). I've been able to figure out how to identify whether or not a string is a palindrome, but I'm struggling with how to specifically identify the characters that don't match in a non-palindrome. Here's my code so far:
import java.util.Scanner;
public class Palindrome
{
public static void main(String[] args)
{
String stringInput = "";
String inputReverse = "";
boolean isPalindrome = true;
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter a string: ");
stringInput = keyboard.nextLine();
int stringLength = stringInput.length();
for(int i = stringLength - 1; i >=0; i--)
{
inputReverse = inputReverse + stringInput.charAt(i);
}
if(stringInput.equals(inputReverse))
{
System.out.println(stringInput + " is a valid palindrome.");
}
else
{
System.out.println(stringInput + " is not a valid palindrome.");
}
}
}
the output I want for when a string is not a palindrome is:
"The characters at index 0 and 3 do not match.
goop is not a valid palindrome.
number of invalid character matches: 1 "
I tried to use stringInput.charAt(0) but the user input is unpredictable, so I wouldn't be able to use char 0,1,2,3 etc forever. Any help?
Iterate from both ends of the string, moving toward the center and checking the corresponding characters each time.
int nomatch = 0;
for (int i = 0, j = stringLength - 1; i < j; i++, j--) {
if (stringInput.charAt(i) != stringInput.charAt(j)) {
++nomatch;
System.out.format("The characters at index %d and %d do not match.%n", i, j);
}
}
if (nomatch == 0) System.out.println(stringInput + " is a palindrome.");
else System.out.println(stringInput + " is not a palindrome. Number of invalid character matches: " + nomatch);
As this is home work, I'll only give general hints:
an easy way to reverse a string is inputReverse = new StringBuilder(stringInput).reverse().toString();
you only need to compare each character of the first half of the input with its reverse
use a for loop of int from 0 to half the length and pass it to charAt() for both strings and compare using ==
store the indexes of differences in a List<Integer>

Im having a problem with finding the palindrome of a upper case and lower case version of a word

So, I'm meant to get two version of a word given by user input, a version with just the lower case letters and then a version with just the upper case letters. Im then meant to find out if both of the words are palindromes. For example if the word was 'HEllO', the words HEO and ll would be created and then the output "HEO is not a palindrome, ll is a palindrome" would be printed. Im pretty sure my code makes sense but it won't say if either version of the original word is a palindrome. The following is the code.
public class comp1
{
public static void main(String []args)
{
Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
String lower = lowerCaseLetters(input);
String upper = upperCaseLetters(input);
palindromeUpper(upper);
palindromeLower(lower);
}
public static String lowerCaseLetters(String input)
{
char[] ar = new char[input.length()];
for(int i = 0; i < input.length(); i++)
{
if(Character.isLowerCase(input.charAt(i)))
{
ar[i] = input.charAt(i);
}
}
String lowercase = new String(ar);
return lowercase;
}
public static String upperCaseLetters(String input)
{
char[] ar = new char[input.length()];
for(int i = 0; i < input.length(); i++)
{
if(Character.isUpperCase(input.charAt(i)))
{
ar[i] = input.charAt(i);
}
}
String uppercase = new String(ar);
return uppercase;
}
public static void palindromeUpper(String sent)
{
String reverse = "";
for(int i = sent.length()-1; i >= 0; i--)
{
reverse += sent.charAt(i);
}
if(sent.equals(reverse))
{
System.out.println("Upper case " + sent + " is a palindrome");
}
else
{
System.out.println("Upper case " + sent + " is not a palindrome");
}
}
public static void palindromeLower(String sent)
{
String reverse = "";
for(int i = sent.length()-1; i >= 0; i--)
{
reverse += sent.charAt(i);
}
if(sent.equals(reverse))
{
System.out.println("Lower case " + sent + " is a palindrome");
}
else
{
System.out.println("Lower case " + sent + " is not a palindrome");
}
}
}```
arrays don't skip 'empty' values. In fact, there's no such thing as an empty slot; char[] ar = new char[input.length()]; gives you a char array with length slots, and each slot is filled with an actual character: The NUL character.
You then copy over all lowercase letters to their appropriate position, which means all non-lowercase letters still have the NUL character. You then turn this back into a string, which will be a string with lots of NUL characters, and those NUL characters will then prevent the rest of your code from working properly; ll is a palindrome, sure. but \0\0ll\0 is not.
You can't resize arrays, you need to create them at the right size. Thus, you have two options:
loop through the string twice. First time, you just count lowercase letters, that is all you do. Second time, you copy over the lowercase letters, and not to position i, but to a counter you maintain (the first l occurs at i=2, but needs to go into ar[0]. The second l occurs at i=3, and needs to go into ar[1]).
Don't use a char array; use a StringBuilder instead, which grows on demand. just .append any lowercase letters.
2 is probably easier, but involves the use of another class (java.lang.StringBuilder).
Note then that your palindromeLower and palindromeUpper methods are identical, other than the messaging.

Finding substring in a given string by changing into char array

i am working on the following program. but its not giving me the correct output for string "nameiskhan" and substring as"name".
i know this might be a duplicate question but i couldn't find the desired answer in those questions.
import java.util.*;
import java.lang.String;
public class CheckingSubstring2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Please enter a String: ");
String string1 = input.next();
System.out.println("Please enter a second String: ");
String substring = input.next();
if (isSubstring(string1, substring)) {
System.out.println("The second string is a substring of the first.");
} else {
System.out.println("The second string is NOT a substring of the first.");
}
}
public static boolean isSubstring(String string1, String substring) {
char c[]=string1.toCharArray();
char d[]=substring.toCharArray();
boolean match = true;
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < d.length; j++) {
if (c[i] == d[j]) {
match = true;
} else {
match = false;
}
}
}
return match;
}
}
As you want to do it without contains, how about this?
What I do here is that going through the original string one pass and check if the substring can be found as consecutive characters in the main String.
public static boolean isSubstring(String string1, String substring) {
char c[]=string1.toCharArray();
char d[]=substring.toCharArray();
for (int i = 0; i < c.length; i++) {
if(c[i] == d[0]){
boolean match = false;
for(int j = 0; j < d.length; j++){
if(c[i+j] != d[j]){
match = false;
break;
} else{
match = true;
}
}
if(match) return true;
}
}
return false;
}
I would suggest becoming familiar with different debugging techniques. A very quick and easy one is a print statement. For example, you can print the values that you are comparing to make sure it looks reasonable. It will also give you an indication of how many times your loop is running. Stepping through the algorithm, the first two characters to be compared are c[0] = 'n' and d[0] = 'n'. That's good. The next two are c[0] = 'n' and d[1] = 'a'. That's not. Also, I assume you intend for the program to stop running if it finds a substring, but it doesn't appear that it would do so. Likewise, you might consider not comparing every element of the substring if a comparison has already been false.

Can't figure out what is wrong with my code

This is the instructions i got from my teacher:
Write your code in the file WordCount.java. Your code should go into a method with the following signature. You may write your own main method to test your code. The graders will ignore your main method:
public static int countWords(String original, int minLength){}
Your method should count the number of words in the sentence that meet or exceed minLength (in letters). For example, if the minimum length given is 4, your program should only count words that are at least 4 letters long.
Words will be separated by one or more spaces. Non-letter characters (spaces, punctuation, digits, etc.) may be present, but should not count towards the length of words.
Hint: write a method that counts the number of letters (and ignores punctuation) in a string that holds a single word without spaces. In your countWords method, break the input string up into words and send each one to your method.
This is my code:
public class WordCount {
public static void main(String[] args)
{
System.out.print("Enter string: ");
String input = IO.readString();
System.out.print("Enter minimum length for letter: ");
int length = IO.readInt();
IO.outputIntAnswer(countWords(input, length));
}
public static int countWords(String original, int minLegth)
{
int count = 0;
int letterCount = 0;
for(int i = 0; i < original.length(); i++)
{
char temp = original.charAt(i);
if(temp >= 'A' && temp <= 'Z' || temp >= 'a' && temp <= 'z')
{
letterCount++;
}
else if(temp == ' '|| i == original.length()-1)
{
if(letterCount >= minLegth)
{
count++;
}
letterCount = 0;
}
}
return count;
}
}
My college uses an autograder to grade project and i am keep getting one of the test case wrong. Can someone help me figure out what the problem is?
I figured the problem that your code is not able to compare the last character.It expects a space after the last character so that it can compare the last character since java doesn't use null character terminator for string termination.I have emulated the same code using Scanner class as I was having some trouble with io.So I have done the following change:
Scanner sc1,sc2;
sc1=new Scanner(System.in);
String input = sc1.nextLine()+" ";
I don't know if its possible to do:
String input = IO.readString()+" ";
but i think you should try appending blank space " " at the end of the string

Input sentence and print out number of words that are above min length requirement in java

My goal is to create a code that accepts a string, and the minimum number of characters allowed for each word. The output will be an int that tells the users the number of words in their sentence that was above or equal to the min they entered.
Now, my approach to this was to break the sentence up into individual word in the main method, then send each of those words into another method that will count the number of characters.
I am having difficulties in my main method, specifically splitting the sentence into individual words. I want to achieve this without using an array, only loops, substring and indexOf, etc. I commented the section of code that I am having issues with. I tested the rest of my code using a string with only one word, and my letterCounter method seems to be working fine. I know the answer is probably simple, but I am still having trouble figuring it out.
Any help would be wonderful! Thank you!
Here is my code:
public class Counter
{
public static void main(String [] args)
{
int finalcount = 0;
System.out.print("Enter your string: ");
String userSentence = IO.readString();
System.out.print("Enter the minimum word length: ");
int min = IO.readInt();
//Error checking for a min less than 1
while(min < 0)
{
IO.reportBadInput();
System.out.print("Enter the minimum word length: ");
min = IO.readInt();
}
int length = userSentence.length(); // this will get the length of the string
for(int i = 0; i < length; i ++)
{
if (userSentence.charAt(i) == ' ')
{
/* I dont know what to put here to split the words!
once I split the userSentence and store the split word into
a variable called word, i would continue with this code: */
if((letterCounter(word)) >= min)
finalcount++;
else
finalcount = finalcount;
}
}
IO.outputIntAnswer(finalcount);
}
//this method counts the number of letters in each word
public static int letterCounter (String n)
int length = n.length();
int lettercount= 0;
for(int i = 0; i < length; i ++)
{
boolean isLetter = Character.isLetter(n.charAt(i));
if (isLetter)
{
if ((n.length()) >= length)
{
lettercount++;
}
}
}
return lettercount;
}
}
Have a a look at String.split()
You could use string.split() like this to accomplish this:
String [] splittedString = inputString.split(" ");
for(int i = 0;i< splittedString.length; i++){
String currentWord = splittedString[i];
if(currentWord.length() >= min){
finalcount++;
}
}

Categories