ayuda con programa java

Hola! alguien podria decirme como puedo eliminar el texto que esta dentro de /* comentarios */ e imprimir el resto del texto
Por ejemplo asi debe quedar:

Ingresa tu texto:
hola a todos /* necesito de su ayuda para */ poder programar

Tu texto sin comentarios queda asi:
hola a todos poder programar

BUILD SUCCESSFUL (total time: 6 seconds)

ya intente varias cosas pero no me queda, espero puedan ayudarme gracias

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

o.o?

Creo que hacerlo es mas fácil que explicarlo, de todas maneras si no entiendes la lógica del código me dices y te explico.

public static String mensajeSinComentarios(String mensaje){
        String salida = ""; // guardo caracter por caracter lo que no sea comentario
        String[] comentarizado = new String[]{"/*","*/"};
        /*
           comentarizado[0] = caracteres de inicio de comentarios
           comentarizado[1] = caracteres de fin comentario
       */

        int index = 0; /* Es 0 si el caracter no es parte de un comentario y es 1 si lo es. */
       
        for(int count = 0; count < mensaje.length(); count++){
            if(count+comentarizado[index].length()<mensaje.length()){ /*esto es para evitar errores*/
               
            String subMensaje = mensaje.substring(count,
                    count+comentarizado[index].length());
           
            if(subMensaje.equals(comentarizado[index])){
                if(index==0){
                    index = 1;
                }else{
                    count+=comentarizado[index].length();
                    index = 0;
                }  
            }
            }
            if(index==0){
                salida+=mensaje.charAt(count);
            }
        }
        return salida;
    }

Ten en cuenta que este código no funciona muy bien si no se finaliza el comentarizado, ya que no valida el que se finalice, para hacerlo solo añades un IF, suerte.
PD: esta genial lo del blockcode :O

¿Puedes usar expresiones regulares?

 

Utiliza la siguiente expresión regular (   (?s)/\*((?!\*/).)*\*/   ):

public class Main {
        public static void main (String[] args) throws java.lang.Exception {
                String str = "hola a todos /* necesito de su ayuda para */ poder programar";
                System.out.println(str.replaceAll("(?s)/\\*((?!\\*/).)*\\*/", ""));
        }
}

 

Ver demo en línea.

Explicación de la expresión regular:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?s)                     set flags for this block (with . matching
                           \n) (case-sensitive) (with ^ and $
                           matching normally) (matching whitespace
                           and # normally)
--------------------------------------------------------------------------------
  /                        '/'
--------------------------------------------------------------------------------
  \*                       '*'
--------------------------------------------------------------------------------
  (                        group and capture to \1 (0 or more times
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
      \*                       '*'
--------------------------------------------------------------------------------
      /                        '/'
--------------------------------------------------------------------------------
    )                        end of look-ahead
--------------------------------------------------------------------------------
    .                        any character
--------------------------------------------------------------------------------
  )*                       end of \1 (NOTE: because you are using a
                           quantifier on this capture, only the LAST
                           repetition of the captured pattern will be
                           stored in \1)
--------------------------------------------------------------------------------
  \*                       '*'
--------------------------------------------------------------------------------
  /                        '/'

Visualización de la expresión regular:

Aquí hay un excelente tutorial sobre expresiones regulares (en inglés).

~~~

Inicialmente pensé que iba a

Inicialmente pensé que iba a hacer esto muy fácilmente pero me tomó mucho más tiempo del que creí.

Este programa itera una sola vez la entrada y va cambiando de estado dependiendo de donde este al recorrerla y toma acciones:

class RemoveComments {

    enum State {
        INIT, NORMAL, COMMENT_START, COMMENT_END
    }
    public static void main( String ... args ) {

        test("/* comment */", is(""));
        test("/* comment */ text /* some test", is(" text /* some test"));
        test("/* comment */ text */ some test", is(" text */ some test"));
        test("/* comment */ test /* some */ text", is(" test  text"));
        test(" comment */ test /* some */ text", is(" comment */ test  text"));
    }

    private static String removeComments( String input ) {

        StringBuilder cb = new StringBuilder();
        StringBuilder nb = new StringBuilder();
        StringBuilder sb = nb;
       
        char p  = 'x';
        int  l  = input.length();
        State s = State.INIT;
       
        for ( int i = 0 ; i <  l; i++ ) {
            char c  = input.charAt(i);
           
            if ( p == '/' && c == '*') s = State.COMMENT_START;
            if ( p == '*' && c == '/'
                && s == State.COMMENT_START) s = State.COMMENT_END;

            sb.append(p);  
            switch ( s ) {  
                case INIT:
                    s = State.NORMAL;
                    sb.deleteCharAt(i);
                    break;
                case COMMENT_START:
                    sb.deleteCharAt(sb.length()-1);
                    sb = cb;
                    sb.append(p);
                case NORMAL:
                    if ( i == l - 1 ) sb.append(c);
                    break;
                case COMMENT_END:
                    s = State.NORMAL;
                    if ( i + 1 < l )     c = input.charAt(++i);
                    if (cb.length() > 0) cb.delete(0,cb.length());
                    sb = nb;
                    break;

            }
            p = c;
        }

        if ( sb == cb ) {
            nb.append(cb);
            sb = nb;
        }
        return sb.toString();
    }
   
    private static void test( String input, String expected ) {
        String result;
        assert (result = removeComments(input)).equals(expected):
        String.format("got: [%s] expected: [%s]", result, expected);
    }
    private static String is(String s ) {return s;}
}

Definitivamente la version con regexp es la que usaría yo a menos que tuviera que procesar una cadena enorme.

Supongo que tengo que practicar más

RE: Inicialmente pensé que iba a

¿Seguro que tus test cases validan comentarios? Casi creo que te fuiste por la ruta de validar si un comentario está balanceado y si no lo está muestras el texto (lo qué según yo no hace, por ejemplo el compilador de Java).

En mi caso voy aquí:

def replaceComment(st: String): String = {
  val commentStart = st.indexOf("/*")
  if(commentStart == -1){
    st
  }else{
    val sub = st.substring(0, commentStart)
    val subAfter = st.substring(commentStart);
    val commentEnd = subAfter.indexOf("*/")
    if(commentEnd == -1){
      "Error: A comment should be balanced"
    }else{
      val subEnd = subAfter.substring(commentEnd + 2)
      val newString = sub + subEnd;
      replaceComment(newString)
    }
  }
}

/*Tests*/
replaceComment("/* comment */");
replaceComment("/* comment */ text /* some test"); // result => "Error: A comment should be balanced"
replaceComment("/* comment */ text */ some test");
replaceComment("/* comment */ test /* some */ text");
replaceComment(" comment */ test /* some */ text");

En este caso paso todos tus tests excepto el segundo... En dónde estoy viendo si le pongo algo que diga cómo que el comentario está sin balancear (para que se vea más compiler-like :p).

EDIT: Aquí dejo la versión Java.

public class Cosa{
    public static void main(String ... args){
        replaceComment("/* comment */");
        replaceComment("/* comment */ text /* some test");
        replaceComment("/* comment */ text */ some test");
        replaceComment("/* comment */ test /* some */ text");
        replaceComment(" comment */ test /* some */ text");
    }

    static void replaceComment(String st){
        int commentStart = st.indexOf("/*");
        while(commentStart != -1){
            String startString = st.substring(0, commentStart);
            String endString = st.substring(commentStart);
            int commentEnd = endString.indexOf("*/");
            if(commentEnd == -1){
                st = "Error: Unbalanced comment";
            }else{
                String afterComment = endString.substring(commentEnd + 2);
                st = new StringBuilder(startString).append(afterComment).toString();
            }
            commentStart = st.indexOf("/*");
        }
        System.out.println(new StringBuilder("Result is => ").append(st));
    }
}

Si, porque no es un

Si, porque no es un comentario, sino un simple /* ( o */ ) En el caso de un lenguaje de programación el tratamiento es distinto porque quieres sacar instrucciones validas, si un comentario no termina todas las instrucciones después de que se abrió el comentario son invalidas.

De hecho si, mucho de la complicación que tuve fue para saber que hacer con lo que parecia un comentario que al final no lo fue. De nuevo la expresion regular funciona muy bien en este caso.

Re: Si, porque no es un

Refactorizando...

Quedaría:

public class Cosa{
    public static void main(String ... args){
        replaceComment("/* comment */");
        replaceComment("/* comment */ text /* some test");
        replaceComment("/* comment */ text */ some test");
        replaceComment("/* comment */ test /* some */ text");
        replaceComment(" comment */ test /* some */ text");
    }
    static void replaceComment(String st){
        int commentStart = st.indexOf("/*");
        while(commentStart != -1){
            String startString = st.substring(0, commentStart);
            String endString = st.substring(commentStart);
            int commentEnd = endString.indexOf("*/");
            if(commentEnd == -1)break;
            String afterComment = endString.substring(commentEnd + 2);
            st = new StringBuilder(startString).append(afterComment).toString();
            commentStart = st.indexOf("/*");
        }
        System.out.println(new StringBuilder("Result is => ").append(st));
    }
}

Ah, si mucho mejor y bastante

Ah, si mucho mejor y bastante simple. Creo que se puede mejorar aún más si en vez de crear un nuevo string cada vez usas un solo stringbuilder, pero eso haría más complejo el código para obtener substring / indexof etc.

Se ve bien.

Re: Ah, si mucho mejor y bastante

¡Gracias! (:

En este caso me dejé llevar por la onda esa de que la optimización prematura es la madre de todos los males. Aunque creo que si ayudaría cómo por un buen para el performance eso que sugieres.

Estaría excelente comparar la versión regex, con esta y con la StringBuilder en vez de crear una cadena. Aunque debo ser honesto, hacer esto me pareció un tanto "hereje", estoy muy metido en hacer programación y pensar de manera inmutable (por eso en el primer snippet uso recursividad, trato de que sea tail-recursive). Pero, estoy consiente que para este tipo de cosas programar inmutable es cómo usar un martillo para talar un árbol :p

Deja veo cómo quedaría con el builder para ver si te entendí.

En términos de legibilidad la

En términos de legibilidad la version de regex es más clara ( aunque parezca paradójico ) luego tu versión y luego la mía.

En términos de desempeño creo que los tres tendrían un comportamiento mucho muy similar incluso con entradas muy grandes. La razón por la cual yo lo hice de otra manera ( también pensé intuitivamente en usar substring index of y etc ) es porque quería ver si lo podia hacer con un solo loop (pensando erroneamente que indexOf internamente conlleva otro loop, pero en tu implementación funciona perfectamente.

El otro ejercicio sería hacer tu versión ( la correcta ) pero recursiva, de hecho tu loop es lo que hace precisamente: