2

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");
      }
   }
}
Amal K
  • 4,359
  • 2
  • 22
  • 44
Emtae2
  • 21
  • 1
  • 2
  • 2
    I cannot reproduce this issue using the code you have provided. Are you sure this is the code you were testing? – Charlie Armstrong Jul 04 '21 at 00:08
  • `0` is less than `2`, perhaps you could tell us what input you are providing? – Elliott Frisch Jul 04 '21 at 00:09
  • Like Charlie said, your code doesn't contain the issue you're describing. And it is also unable to properly read the input, see: [Scanner is skipping nextLine() after using next() or nextFoo()?](//stackoverflow.com/q/13102045) (but this doesn't cause the described plural issue) – Tom Jul 04 '21 at 00:18
  • 2
    What is more ... "0 N" is bad grammar. In English >correct< grammar would be "0 N's"! But even that is incorrect punctuation, because there shouldn't be an apostrophe in **any** case. – Stephen C Jul 04 '21 at 04:51
  • 1
    The most correct form would be `0 "N"s` or `1 "N"` or `2 "N"s` (or `0 'N's` or `1 'N'` or `2 'N's` if you prefer.) Note: we are using quotes, not an apostrophe. An apostrophe - `s` (usually) indicates possession. – Stephen C Jul 04 '21 at 04:58

4 Answers4

1

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 ) ;
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Can you explain what's input in your example? If input is my inputed String I cannot use toList(). Compiler says "The method toList() is undefined for the type Stream". – Simone Lungarella Jul 04 '21 at 06:55
  • 1
    @SimoneLungarella For Java 15 and earlier, use `.collect( Collectors.toList() )` in place of `.toList()`. – Basil Bourque Jul 04 '21 at 07:01
  • @SimoneLungarella My `input` is the string for which you want to determine the frequency of a particular character. My `targetString` in the string holding the single character of which we will search for matches in the `input` String. In own your code, you will rename these vars as you see fit. – Basil Bourque Jul 04 '21 at 07:09
  • What's the equivalent of "toArray()[0]", in this specific case, in java 11? Using toArray, since it gives back and Objects Array, compiler says I cannot convert from Object to Integer. – Simone Lungarella Jul 04 '21 at 07:14
  • @SimoneLungarella Oops, I am writing code freehand on an iPad with no compiler. I am simply trying to get the code point of the first character from a string that might conceivably have multiple characters. We’ll have to find a different way to do that. Try my revision to that line, dropping the `.boxed()` call. Auto-boxing after we pull the first `int` from array of `int` should give us our desired `Integer` object. – Basil Bourque Jul 04 '21 at 07:16
  • While this may be a better way to do it, this is not the solution to the OP's problem. The question makes no mention of the count being off. The only problem the question describes is the pluralization issue, and this answer does not touch on that at all. – Charlie Armstrong Jul 04 '21 at 17:57
  • 1
    @CharlieArmstrong Thank you for the valid criticism. I added a section up top to directly address the flaw in the Question's code. – Basil Bourque Jul 05 '21 at 06:48
1

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.

Amal K
  • 4,359
  • 2
  • 22
  • 44
0

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();
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
Simone Lungarella
  • 301
  • 1
  • 4
  • 15
  • Are you able to reproduce the issue with the OP's code? If so, please describe the cause of the issue, so that your answer is more than just code. If not, then how do you know that your code will work any better? – Charlie Armstrong Jul 04 '21 at 18:01
  • I'm not sure if I can reproduce the exact OP's problem, what happen to me is caused by the fact that Scanner.next() method does not read the newline character leaving it to the nextLine() method call right after the first one. I removed the call to "next()" and used a mapping of characters to achieve the same result. – Simone Lungarella Jul 04 '21 at 18:18
  • 1
    Yeah, I think the original code is intended to work when you separate the character from the word by a space, and `userWord` would just always start with a space. Either way, the best way to get upvotes on an answer is to add explanation. Also, if it was me, I would avoid writing answers to questions like this, because the way it's written, you can't truly answer the question. This makes it hard for viewers to consider your answer high-quality. Just trying to spread some of the advice I've been given. – Charlie Armstrong Jul 04 '21 at 18:55
0

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.