Hola niurkafer, voy a darte mi opinión sin ser ningún experto.
El fallo que tienes es el típico fallo que se suele tener a la hora de visualizar un array.
Un string es un array, es decir, almacena cada carácter en una de sus celdas, de la forma por ejemplo:
[N,I,U,R,K,A,F,E,R]
¿Como accedemos a un caracter entonces?
Simplemente tenemos que saber que la primera posición corresponde a la posicion numero 0 y asi podremos acceder a cada una de ellas. En el ejemplo:
Posición 0 -> N
Posición 1 -> I
Posición 2 -> U
Posición 3 -> R
Posición 4 -> K
Posición 5 -> A
Posición 6 -> F
Posición 7 -> E
Posición 8 -> R
Fíjate que la ultima posición entonces corresponde a la posicion numero 8.
¿Que sucede entonces cuando usas la función .length?
Al aplicar la función length() a una cadena devuelve la longitud de la cadena, no devuelve la posicion del ultimo caracter. Imagina que aplico dicha función al ejemplo, obtendre un 9 pues hay 9 letras.
¿En que concluye esto?
Cuando recorremos un array o un string mediante un bucle no "iremos" desde el 0 hasta su longitud, si no desde el 0 hasta (su longitud -1) y de este modo recorreremos la cadena entera.
Aunque el metodo substring nos evita esta cuenta y nos permite indicarle el numero de caracter en vez de su posición interna.
El error que te da se debe a que el indice que recorre el array toma un valor superior al maximo indice que tiene este y por eso no puede obtener ningún dato, digamos.
Quiero comentarte también que para sentencias while simples como es el caso no es conveniente en absoluto el uso de break. Tu condicion para while es simplemente "true" con lo que creas un bucle que se ejecuta siempre excepto cuando cumples un if que colocas en el interior en cuyo caso hace un break.
Bien, este mismo funcionamiento lo consigues simplemente colocando la condicion de ese IF como condicion del bucle while. Te ahorras tiempo y quebraderos de cabeza y el unico handicap es que la condición es la contraria. Es decir si le dirás que se salga del bucle y haga break cuando sea 10 mejor que le digas al while que se ejecute mientras sea menor que 10 y asi lo hará.
Si añades al while la condicion NOT puedes conseguir el efecto de decirle "mientras no seas 10" haz esto { ... }
Yo por ejemplo aplico el not al while normalmente por manías de un buen profesor que tuve al final son costumbres pero romper la condición mediante un IF como en tu ejercicio no es la manera correcta, aunque se pueda.
Me explico:
FORMA CORRECTA
while (indice < 10) {
//Hago lo que tenga que hacer 10 veces//
indice ++ //incremento indice//
}
o si no
while !(indice >= 10) {
//Hago lo que tenga que hacer 10 veces//
indice ++ //incremento indice//
}
y por tanto no es necesario anidar un IF
INCORRECTO:
i=0
while (1=1) {
//Haces algo//
i++;
if (i >=10) {break;}
}
Te sugiero repetir el ejercicio teniendo lo que te he comentado en cuenta y verás que incluso resulta mas fácil entenderlo.
Saludos!