2015-06-06 5 views
3

Я очень новичок в Java и в качестве стартера мне предложили попробовать это дома.Слово в строке java

Напишите программу, которая найдет число вхождений меньшей строки в большую строку как часть ее, а также отдельное слово. Например,

Bigger string = "I AM IN AMSTERDAM", меньшая строка = "AM".

Вывод: В составе строки: 3, как часть слова: 1.

В то время как я сделал гвоздь второй части (как часть слова), и даже если бы мой идти на сначала (поиск слова как части строки), я просто не понимаю, как взломать первую часть. Он продолжает показывать 1 для меня с примером ввода, где он должен быть 3.

Я определенно сделал ошибку - я буду очень благодарен, если вы могли бы указать на ошибку и исправить ее. В качестве запроса я любопытный ученик, поэтому, если это возможно (по вашей воле), пожалуйста, предоставьте объяснение, почему так.

import java.util.Scanner; 
public class Program { 
static Scanner sc = new Scanner(System.in); 
static String search,searchstring; 
static int n; 
void input(){ 
    System.out.println("What do you want to do?"); System.out.println("1.  
Search as part of string?"); 
    System.out.println("2. Search as part of word?"); 
    int n = sc.nextInt(); 
    System.out.println("Enter the main string"); searchstring = 
sc.nextLine(); 
    sc.nextLine(); //Clear buffer 
    System.out.println("Enter the search string"); search = sc.nextLine(); 
} 
static int asPartOfWord(String main,String search){ 
    int count = 0; 
    char c; String w = ""; 
    for (int i = 0; i<main.length();i++){ 
     c = main.charAt(i); 
     if (!(c==' ')){ 
      w += c; 
     } 
     else { 
      if (w.equals(search)){ 
       count++; 
      } 
      w = ""; // Flush old value of w 
     } 
    } 
    return count; 
} 
static int asPartOfString(String main,String search){ 
    int count = 0; 
    char c; String w = ""; //Stores the word 
    for (int i = 0; i<main.length();i++){ 
     c = main.charAt(i); 
     if (!(c==' ')){ 
      w += c; 
     } 
     else { 
      if (w.length()==search.length()){ 
       if (w.equals(search)){ 
        count++; 
       } 
      } 
      w = ""; // Replace with new value, no string 
     } 
    } 
    return count; 
} 
public static void main(String[] args){ 
    Program a = new Program(); 
    a.input(); 
    switch(n){ 
     case 1: System.out.println("Total occurences: " + 
     asPartOfString(searchstring,search)); 
     case 2: System.out.println("Total occurences: " + 
     asPartOfWord(searchstring,search)); 
     default: System.out.println("ERROR: No valid number entered"); 
    } 
    } 
} 

EDIT: Я буду использовать структуру петли.

+0

Ваше желание получить ответы на многие вопросы. Если поставщики компетентны, то все они будут правильными. Потратьте время, чтобы учиться у всех из них. Некоторые из них будут простыми. Некоторые сложные. И другие будут смотреть на проблему совсем по-другому. –

+0

Спасибо за совет, @BrettWalker.Постарайтесь впитаться в лучшем виде. –

+0

Вы хотите перебрать строку самостоятельно или было бы хорошо использовать такое решение, как этот: http://stackoverflow.com/questions/767759/occurrences-of-substring-in-a-string – Pinguin895

ответ

3

Более простой способ будет использовать регулярные выражения (что, вероятно, побеждает идея написать его самостоятельно, хотя изучение регулярных выражений является хорошей идеей, потому что они очень мощные: поскольку вы можете видеть, что ядро ​​моего кода составляет 4 строки в методе countMatches).

public static void main(String... args) { 
    String bigger = "I AM IN AMSTERDAM"; 
    String smaller = "AM"; 

    System.out.println("Output: As part of string: " + countMatches(bigger, smaller) + 
      ", as a part of word: " + countMatches(bigger, "\\b" + smaller + "\\b")); 
} 

private static int countMatches(String in, String regex) { 
    Matcher m = Pattern.compile(regex).matcher(in); 
    int count = 0; 
    while (m.find()) count++; 
    return count; 
} 

Как это работает?

  • мы создаем Matcher, который будет найти определенный шаблон в строке, а затем перебирать, чтобы найти следующий матч, пока не останется ни и приращение счетчика
  • Узоры себя: "AM" найти любое вхождение AM в строке, в любом положении. "\\bAM\\b" будет отвечать только целыми словами (\\b - это разделитель слов).

Возможно, это не то, что вы искали, но я подумал, что было бы интересно увидеть другой подход.Технически, я использую цикл :-)

0

Вы можете использовать регулярные выражения, попробуйте ".*<target string>.*" (Заменить target string с тем, что вы ищете.

Посмотрите на Java Doc для "Patterns & Regular Expressions"

Для поиска вхождений в строке, это может быть полезно.

Matcher matcher = Pattern.compile(".*AM.*").matcher("I AM IN AMSTERDAM") 
int count = 0; 

while (matcher.find()) { 
    count++; 
} 
0

Для первой части вашего упражнения это должно работать:

static int asPartOfWord(String main, String search) { 
    int count = 0; 
    while(main.length() >= search.length()) { // while String main is at least as long as String search 
     if (main.substring(0,search.length()).equals(search)) { // if String main from index 0 until exclusively search.length() equals the String search, count is incremented; 
      count++; 
     } 
    main = main.substring(1); // String main is shortened by cutting off the first character 
    } 
    return count; 

Вы можете думать о том, как вы называете переменные:

static String search,searchstring; 
    static int n; 

В то время как поиск и searchstring скажут нам, что имеется в виду, вы должны написать первое слово в нижнем регистре, каждое последующее слово должно быть написано с первой буквой в верхнем регистре. Это улучшает читаемость.

static int n не даст вам большой информации о том, для чего он используется, если вы прочитали свой код снова через несколько дней, вы можете использовать что-то более содержательное здесь.

static String search, searchString; 
    static int command; 
0

Вот альтернатива (и гораздо короче) способ, чтобы заставить ее работать, используя Pattern и Matcher,
или более широко известный как регулярное выражение.

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class CountOccurances { 

    public static void main(String[] args) { 

     String main = "I AM IN AMSTERDAM"; 
     String search = "AM"; 

     System.out.printf("As part of string: %d%n", 
       asPartOfString(main, search)); 

     System.out.printf("As part of word: %d%n", 
       asPartOfWord(main, search));   
    } 

    private static int asPartOfString(String main, String search) { 

     Matcher m = Pattern.compile(search).matcher(main); 
     int count = 0; 
     while (m.find()) { 
      count++; 
     } 
     return count; 
    } 

    private static int asPartOfWord(String main, String search) { 

     // \b - A word boundary 
     return asPartOfString(main, "\\b" + search + "\\b"); 
    } 
} 

Выход:

As part of string: 3 
As part of word: 1 
1

Хотя писать свой собственный код с большим количеством петель для работы вещи могут выполняться быстрее (спорно), то лучше использовать JDK, если вы можете, потому что есть меньше кода для написания, меньше отладки, и вы можете сосредоточиться на материалах высокого уровня, а не на низкоуровневой реализации итераций и сравнения символов.

Это так, инструменты, необходимые для решения этой проблемы, уже существуют, и хотя использование их требует знаний, которых у вас нет, они элегантны, чтобы быть одной строкой кода для каждого метода.

Вот как я бы решить:

static int asPartOfString(String main,String search){ 
    return main.split(search, -1).length - 1; 
} 

static int asPartOfWord(String main,String search){ 
    return main.split("\\b" + search + "\\b", -1).length - 1 
} 

См live demo этого кода работает с входом образца, который (возможно, умышленно) содержит ребро случай (см. Ниже)

Производительность? Вероятно, несколько микросекунд - достаточно быстро. Но реальная выгода - это так мало кода, что совершенно ясно, что происходит, и почти ничего не получается, или что нужно отлаживать.

вещи вы должны знать, чтобы использовать это решение:

  • термина регулярного выражения для «границы слова» является \b
  • split() принимает регулярное выражение в качестве поискового термина
  • 2-й параметр split() управления поведение в конце строки: отрицательное число означает «сохранить пробелы в конце раздвоения», которые обрабатывают крайную строку основной строки, заканчивающуюся меньшей строкой. Без -1 вызов раскола выкинул бы заглушку в этот край.
+0

Ваш подход проще всего, но вы не думаете, что 'split (search, -1)' будет заменен на 'split (search, 0)'. Я получаю правильные результаты с 0 вместо -1 для обоих методов. – Rajesh

+0

@Rajesh 'split (search, 0)' fail. 'split (search, -1)' преуспевает. '0' - это поведение по умолчанию, которое отбрасывает завершающие пробелы из возвращаемого массива. Подробное описание этого поведения см. В [javadoc] (https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int-). Использование '0' для выборочных данных возвращает меньше, чем правильный ответ, когда совпадение находится в конце строки (обратите внимание, что я немного изменил код после моего первоначального сообщения - проверьте, какой код вы используете). – Bohemian