Исходя из исходного кода OP, существует проблема с циклом for
, заключающаяся в том, что проверка следующего символа переполняет конец строки, что приводит к ошибке времени выполнения.
Что касаетсяотсутствие вывода для последней записи в данном String box
, это связано с тем, что вывод производится в цикле for
самого box.length()
.Таким образом, когда в конце есть символ, который повторяется, он никогда не отображается.Я подозреваю, что та же самая проблема (без заключительного символа) может быть замечена с чем-то вроде AAABBBC
, который должен отображать A3B3C
, но не будет иметь последний C
.
Слегка измененный алгоритм будетвсегда отображать символ при его изменении, а затем добавлять счетчик при необходимости.
private static void MarkerCutt(Queue<String> kolejkaWyrazow)
{
// the string we are processing from the queue
String box;
// number of repeats for a character in the string
int countRepeats;
while (!kolejkaWyrazow.isEmpty()) {
box = kolejkaWyrazow.remove();
countRepeats = 0;
// we hold the current character and the previous character;
// at entry, set the prevChar to something that cannot be matched
char curChar, prevChar = '\0';
// loop over the whole string; as we are not looking ahead, we
// use the full length of the String
for (int k = 0; k < box.length(); k++) {
// get the character
curChar = box.charAt(k);
// if we are not the same as the previous, then we
// may need to output the count; but output the character
// we just found, regardless
if (curChar != prevChar) {
outputCount(countRepeats);
countRepeats = 0;
System.out.print(curChar);
}
else {
++countRepeats;
}
prevChar = curChar;
}
// have to output the end of the string
outputCount(countRepeats);
System.out.println();
}
}
private static void outputCount(int countRepeats)
{
if (countRepeats > 0) {
System.out.print(countRepeats + 1);
}
}
Вывод на основе показанных входов (плюс AAABBBC
и 'AAABBBCC`:
AS3D3A3
A3L3O3L3
A3B3C
A3B3C2
В более широкой теме я хотел бы рассмотреть вопрос об удалении фактического вывода из метода MarkerCutt
и вместо этого иметь метод, возвращающий строку. Обычно рекомендуется отделить вывод от логики. Итак:
private static void MarkerCutt(Queue<String> kolejkaWyrazow)
{
while (!kolejkaWyrazow.isEmpty()) {
String box = kolejkaWyrazow.remove();
String repString = changeToRepeatCount(box);
System.out.println(repString);
}
}
private static String changeToRepeatCount(String box)
{
// number of repeats for a character in the string
int countRepeats = 0;
// We build into this structure
StringBuilder sb = new StringBuilder();
// we hold the current character and the previous character;
// at entry, set the prevChar to something that cannot be matched
char curChar, prevChar = '\0';
// loop over the whole string; as we are not looking ahead, we
// use the full length of the String
for (int k = 0; k < box.length(); k++) {
// get the character
curChar = box.charAt(k);
// if we are not the same as the previous, then we may need
if (curChar != prevChar) {
outputCount(countRepeats, sb);
countRepeats = 0;
sb.append(curChar);
}
else {
++countRepeats;
}
prevChar = curChar;
}
// have to output the end of the string
outputCount(countRepeats, sb);
return sb.toString();
}
private static void outputCount(int countRepeats, StringBuilder sb)
{
if (countRepeats > 0) {
sb.append(countRepeats + 1);
}
}
Этот последний подход позволяет проводить более качественное / автоматизированное тестирование, потому что затем можно написать драйвер, который выполняет что-то вроде:
String inp = "ASSSDDDAAA";
String exp = "AS3D3A3";
String res = changeToRepeatCount(inp);
if (! exp.equals(res)) {
System.err.println("Test Failed!");
}
(или лучше использовать JUnit или что-то в этом роде). Это значительно упростит разработкучем необходимость каждый раз вводить значение для проверки кода. Просто немного пищи для размышлений.