Emtae2
Emtae2

Reputation: 21

Cannot count characters properly

I'm supposed to have two inputs: One is a character, the other is a string.

I have to write a program that outputs the amount of times the character appears in the string.

In the end, I have been able to get the program to display the proper amount of times the character input appears in the string.

However the problem is I have to be able to output the plural form of the input character if necessary. I do not know what I am doing wrong here, but sometimes it will make something plural when it shouldn't be... basically, if there are 0 n's in that word, it should display 0 n... but it displays 0 n's.

Sorry if my description was terrible.

import java.util.Scanner;

public class LabProgram {
    public static void main(String[] args) {
      Scanner scnr = new Scanner (System.in);
      char userLetter;
      String userWord;
      
      userLetter = scnr.next().charAt(0);
      userWord = scnr.nextLine();
      
      int wordCount = 0;
      
      for (int i = 0; i < userWord.length(); i=i+1) {
         if (userWord.charAt(i) == userLetter){
            wordCount = wordCount + 1;
         }}
         
      if (wordCount < 2) {
         System.out.println(wordCount + " " + userLetter);
      }
      else if (wordCount == 0) {
         System.out.println(wordCount + " " + userLetter);
      }
      else {
         System.out.println(wordCount + " " + userLetter + "'s");
      }
   }
}

Upvotes: 2

Views: 7076

Answers (4)

netdevmike
netdevmike

Reputation: 1

Your word count is correct, but the if statement has a few issues.

  if (wordCount == 1) {
     System.out.println(wordCount + " " + userLetter);
  }
  else {
     System.out.println(wordCount + " " + userLetter + "'s");
  }

The question says that if wordcount is anything but 1, add a 's to the end of the answer.

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 338406

Unreproducible

As commented by Charlie Armstrong your problem is not reproducible. You should provide a MCVE.

Your if cascade is faulty. The first if tests for wordCount being less than two.

if (wordCount < 2) {         // <--- Condition met for count of 0 or 1. 

Zero is less than two. So the first test succeeds, and its code runs.

Your second if test for less than zero is redundant. That second if:

else if (wordCount == 0) {   // <--- Never reaches this point for 0 or 1.

…will never execute for a wordCount of 0 or 1. The first test if (wordCount < 2) { will be true for a wordCount of zero (or one), so its System.out.println will run, and the if cascade ends. So we never have a chance to test if the count is zero.

For your rule of "if there are 0 n's in that word, it should display 0 n", change your code to:

  if ( wordCount > 1 ) {  // For a count of 2 or more.
     System.out.println(wordCount + " " + userLetter + "'s");
  }
  else {  // Else use singular for count of 0 or 1. (Ignoring negative numbers.) 
     System.out.println(wordCount + " " + userLetter);
  }

As commented by Stephen C, you should be using the plural with both zero and with more than one. So your logic could be reduced checking if the count is not one, in which case you append the plural s. See code example further down in this Answer.

By the way, we can replace much of your code by letting Java do the heavy lifting via Collections.frequency. Read on.

Avoid char

The char type is obsolete, unable to represent even half of the characters defined in Unicode.

Unicode code point

Instead, learn to use Unicode code point integer numbers when working with individual characters.

You can turn a string into an IntStream to get a series of int values, each value being the code point of a character in that string.

Call boxed to convert each streamed int primitive into a Integer object.

List< Integer > codePoints = "Java".codePoints().boxed().toList() ;  // Prior to Java 16, use `.collect( Collectors.toList() )` in place of `.toList()`.
Integer codePoint = "a".codePoints().toArray()[0] ;
int frequency = Collections.frequency( codePoints , codePoint ) ;

frequency = 2

If result is other than one, append s

Report result.

As Stephen C commented, in proper English your target letter should be wrapped in quotes, ideally curly-quotes, without any use of an apostrophe. Append an s for a count of zero or more than one, but omit the s for a result of one.

String output = String.valueOf( frequency ) + " ‘" + Character.toString( codePoint ) + "’" ;
if ( frequency!= 1 ) {
    output = output + "s" ; 
}

See this code run live at IdeOne.com.

2 ‘a’s

import java.util.*;
import java.lang.*;
import java.io.*;

import java.util.stream.* ;

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        List< Integer > codePoints = "Java".codePoints().boxed().collect( Collectors.toList() ) ;
        Integer codePoint = "a".codePoints().toArray()[0] ;
        int frequency = Collections.frequency( codePoints , codePoint ) ;
    
        String output = String.valueOf( frequency ) + " ‘" + Character.toString( codePoint ) + "’" ;
        if ( frequency!= 1 ) {
            output = output + "s" ; 
        }
    
        System.out.println( output ) ;
    }
}

Upvotes: 1

Amal K
Amal K

Reputation: 4874

One of the alternatives to avoid any branching in the first place would be to always append "(s)" in the end.:

System.out.println(wordCount + " " + userLetter + "(s)");

As Stephen C mentioned, an apostrophe "", although sometimes used in the sense you have, would usually indicate a possession as in n 's length or even n 's frequency. This brings me to more alternatives:

System.out.println(userLetter + "'s frequency" + ": " + wordCount);

OR

System.out.println("The number of times the letter " + userLetter + " appears is " + wordCount);

In addition to the pluralization issue, it is worth noting that after the execution of this line:

userLetter = scnr.next().charAt(0)

a trailing new line is left in the input source. This is a subtle but one of the most common programming errors. When the next line is executed:

userWord = scnr.nextLine();

It reads in that trailing new line and ignores your second input and your nextLine() returns a string with whitespace. You can verify this by printing the values of userLetter and userWord to the console.

Change the former line to:

userLetter = scnr.nextLine().charAt(0);

This will consume the input with the trailing newline without leaving any traces.

Upvotes: 1

Simone Lungarella
Simone Lungarella

Reputation: 333

I tried to follow some of the proposed solutions but they didn't work for me, I managed to find another solution that may fit your intention:

public static void main(String[] args) {

    Scanner scnr = new Scanner(System.in);

    System.out.print("Enter the word: ");
    String userWord = scnr.nextLine();

    System.out.print("Enter the letter: ");
    String userLetter = scnr.nextLine();

    List<Character> chars = userWord.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
    Character targetChar = userLetter.charAt(0);

    final int frequency = Collections.frequency(chars, targetChar);

    if (frequency < 2) {
        System.out.println(frequency + " " + userLetter);
     }
     else if (frequency == 0) {
        System.out.println(frequency + " " + userLetter);
     }
     else {
        System.out.println(frequency + " " + userLetter + "'s");
     }

    scnr.close();
}

Upvotes: 0

Related Questions