0
import java.util.regex.Matcher; 
import java.util.regex.Pattern;
import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // your code goes here
        String in = "111111111111111";
        Pattern p = Pattern.compile("(11111)");
        Matcher m = p.matcher(in);
        while (m.find()) {

            System.out.print(m.start() + " ");

        }

    }
}

The output of the above code I am getting is

0 5 10

The output I should be getting is

0 1 2 3 4 5 6 7 8 9 10 

Can somebody tell me what I am doing wrong?

Vishwas Atrey
  • 286
  • 3
  • 9
  • 2
    @Sneftel - your answer would work using `pos = m.start() + 1;` instead. https://ideone.com/ik5d8x I've proposed it as an edit on your answer. – Andy Turner May 24 '19 at 15:17
  • 1
    @AndyTurner Fair enough. I deleted it rather than fixing it because it seemed like resetting `Matcher` to an earlier position was contrary to the spirit of the class, but I suppose it does work, sooo – Sneftel May 24 '19 at 15:25

3 Answers3

12

Can somebody tell me what I am doing wrong?

You're assuming that you will get matches from text that has already been consumed in a match. You won't.

You can do this using a forward-looking assertion:

Pattern p = Pattern.compile("1(?=1111)");

(which means "find a 1 that precedes four 1s", as opposed to "find five 1s")

Ideone demo

But it's easier to do this with indexOf:

int prev = -1;
while ((prev = in.indexOf("11111", prev + 1)) != -1) {
  System.out.println(prev + " ");
}
Andy Turner
  • 137,514
  • 11
  • 162
  • 243
3

Andy Turner's diagnosis of your problem is correct and his suggestion is a good one, but if you need to match with a regex rather than against a fixed string, you can still get it to work. The key is that Matcher.find() has an overload which takes an int specifying the start position. If you set that to just after the previous match's start position, you'll get the desired result, since it forces the matcher to reconsider using those previous 1's.

import java.util.regex.Matcher; 
import java.util.regex.Pattern;
import java.util.*;
import java.lang.*;
import java.io.*;

class Ideone
{
    public static void main (String[] args) throws java.lang.Exception
    {
        // your code goes here
        String in = "111111111111111";
        Pattern p = Pattern.compile("(11111)");
        Matcher m = p.matcher(in);
        int pos = 0;
        while (m.find(pos)) {

            System.out.print(m.start() + " ");
            pos = m.start() + 1;
        }

    }
}
Sneftel
  • 40,271
  • 12
  • 71
  • 104
1

The documentation states clearly

starts [...] at the first character not matched by the previous match

The previous answer already proposes some good alternatives.

Florian H.
  • 143
  • 9