C, PHP, VB, .NET

Дневникът на Филип Петров


* Форматиране на низове – примерна задача

Публикувано на 26 януари 2017 в раздел ПИК3 Java.

В долната задача демонстрирам употребата на String.format(). Дадена е следната задача: по подадено число N, да се отпечата чрез стандартния изход матрица с размерност NxN със звезди по диагоналите и празни интервали за останалите елементи.

Обикновено хората започват да търсят решение чрез вложени цикли, например:

public class MatrixStarDiagonals {
    public static void main(String[] args) {
        int N = 10;
        for (int i = 0; i <= N; i++) {
            StringBuilder strb = new StringBuilder(N);
            if (i == N/2 + N%2) continue;
            for (int j = 0; j <= N; j++) {
                if (N%2==1 && i==N/2 && j==N/2) continue;
                else if (N%2==1 && i==N/2+1 && j==N/2+1) continue;
                else if (i==j || N-i==j) strb.append("*");
                else if(j!=N/2+N%2) strb.append(" ");
            }
            System.out.println(strb.toString());
        }
    }
}

Това решение е далеч от оптимално – има вложен цикъл. Вероятно може да се оптимизира като се премахне този проблем, но при всички случаи има много проверки за различни ситуации – четно, нечетно и т.н. Освен това се налага употреба на StringBuilder, за да не се печата символ по символ на екрана.

Чрез форматирани низове същото може да се постигне елементарно, с много по-малко проверки и печатайки директно цели редове и без вложен цикъл:

public class MatrixStarDiagonals {
    public static void main(String[] args) {
        int N = 10;
        for (int i = 1; i <= N; i++) {
            String res = String.format("%" + ((i <= N / 2) ? i : N - i + 1) + "s", "*");
            if (N - 2 * i + 1 != 0) res += String.format("%" + ((i <= N / 2) ? N - 2 * i + 1 : 2 * i - N - 1) + "s", "*");
            System.out.format("%1$-"+ N + "s"+"%n", res);
        }
    }
}

Естествено, изучаването на подобни неща не е нормална част за курс по ООП, но все пак е хубаво упражнение, което показва, че ученето на printf в началния курс по програмиране на C не остава безполезно при преминаване към програмиране от по-високо ниво.

П.П. Едноредово решение (в името на спорта):

public class MatrixStarDiagonals {
    public static void main(String[] args) {
        for (int N=10, i=1; i<=N; i++) System.out.format("%1$-"+ N + "s"+"%n",String.format("%"+((i<=N/2)?i:N-i+1)+"s"+((N-2*i+1!=0)?"%"+((i<=N/2)?N-2*i+1:2*i-N-1)+"s":""), "*", "*"));
    }
}

 

 



5 коментара


  1. Оня с коня каза:

    При варианта с вложените цикли първите две else са излишни. Също така има много излишни проверки.

  2. Оня с коня каза:

    Последните два варианта не запълват матрицата с интервали в дясно от двата диагонали, което не удовлетворява условието на задачата!

  3. Здравей,

    По вторият коментар – добавих padding в примерите и вече поставя интервали вдясно. Забележката беше коректна, въпреки че визуално на екрана няма разлика.

    По първият – споделете по-просто решение без излишните проверки :)

  4. Оня с коня каза:

    //Това решение е лесно за четене и бързо за изпълнение, обхожда всеки елемент на матрицата.

    private static void printMatrixFikri(int n)
    {   for(int i=0; i < n; i++)
        {   for(int j=0; j < n; j++)
                System.out.print((i == j || j == n-1-i) ? '*' : ' ');
            System.out.println();
        }
    }
  5. Изглежда елегантно и разбираемо.

Добави коментар

Адресът на електронната поща няма да се публикува


*