Strona główna » Kursy » Kurs C# » Efektywne Tworzenie Napisów
Aa
 

Efektywne Tworzenie Napisów

Wstęp

Do przechowywania tekstów w języku C# używa się typu danych string. Jest to jednak typ, który nie pozwala na edycję zawartości. Do efektywnego tworzenia napisów służy klasa StringBuilder. W tym artykule zostanie przedstawione jak poprawnie tworzyć teksty złożone z bardzo dużej ilości znaków, albo bardzo często dopisywanych.

Opis problemu

Typ do przechowywaniu tekstów string nie pozwala na edycję zawartości. Podczas łączenia go z innymi zmiennymi tego typu tworzona jest nowa zmienna, a przypisany zostaje jej połączony tekst. Oznacza to, że za każdym razem trzeba przepisywać dane w pamięci. Przykładowo w poniższym kodzie:

  1.   string tekst = "";
  2.   for (int i = 0; i < 10000; i++) {
  3.     tekst += "Uczę się jak szybko tworzyć teksty w języku C#\n";
  4.   }

Zmienna jest tworzona od nowa, aż 10 000 razy. Im dłuższy tekst tym większy ma to wpływ na wydajność programu. Przykładowo powyższy kod wykonuje zadanie ponad 4 sekundy. Podczas, gdy alternatywna klasa StringBuilder jest w stanie wykonać to samo zadanie w zaledwie 2 ms. Oto przykład zastosowania wspomnianej klasy:

  1.   StringBuilder builder = new StringBuilder();
  2.   for (int i = 0; i < 10000; i++) {
  3.     builder.Append("Uczę się jak szybko tworzyć teksty w języku C#\n");
  4.   }

Skąd taka duża różnica? Otóż klasa StringBuilder pozwala na edycję swojej zawartości, więc zmienna nie jest tworzonaza każdym razem podczas dopisywania kolejnych fragmentów tekstu. Ponadto klasa ta dostarcza wiele metod, które ułatwiają tworzenie tekstów.

Tworzenie tekstu

W poprzednim przykładzie została wykorzystana metoda Append(), która pozwala na dopisanie dowolnego fragmentu tekstu. W tym przypadku należy pamiętać o dopisaniu na końcu znaku nowej linii. Można tego uniknąć korzystając z metody AppendLine(), która znak nowej linii doda automatycznie na koniec dopisywanego fragmentu. Nie jest wtedy jednak możliwe jak w przypadku poprzedniej metody podanie znaku oraz ile razy powinien zostać powielony. Oto przykład:

  1.   StringBuilder tekst = new StringBuilder();
  2.   tekst.Append("Pierwsza linijka\n");
  3.   tekst.AppendLine("Druga linijka");
  4.   tekst.Append('*', 10);
  5.   Console.WriteLine(tekst.ToString());
  1. Pierwsza linijka
  2. Druga linijka
  3. **********

Ponadto klasa StringBuilder pozwala na usunięcie wybranego fragmentu tekstu metodą Remove(), która przyjmuje dwa argumenty: początek miejsca usuwania oraz długość usuwanego tekstu. Tekst można również modyfikować poprzez wstawienie tekstu bezpośrednio na wybraną pozycję poleceniem Insert(). Tutaj wpierw należy podać gdzie tekst ma zostać wstawiony, a potem sam tekst. Przykładowo:

  1.   tekst.Remove(0, tekst.Length);
  2.   tekst.Append("Nowy do wyświetlenia");
  3.   tekst.Insert(5, "tekst ");
  4.   Console.WriteLine(tekst.ToString());
  1. Nowy tekst do wyświetlenia

n znaków

Takie tworzenie tekstu jest wydajne, ponieważ klasa automatycznie rezerwuje więcej miejsca w pamięci niż rzeczywiście może istnieć potrzeba. W przypadku, gdy docelowy tekst się nie zmieści klasa znajduje kolejną przestrzeń na tekst. W przypadku, gdy z góry znany jest rozmiar tekstu warto podać to podczas tworzenia obiektu. Dzięki temu uniknie się sytuacji kiedy program musi zaalokować dodatkową pamięć. Przykładowo poniżej tworzony jest obiekt, który od razu rezerwuje miejsce na 10 000 znaków:

  1.   StringBuilder dane = new StringBuilder(10000);

Oczywiście podanie rozmiaru tekstu nie powoduje, że będzie można zapisać maksymalnie n znaków.

Zadania

Zadanie 1

Napisz program, który najpierw narysuje pudełko złożone z gwiazdek jak poniżej:

  1. ********************
  2. *                  *
  3. ********************

następnie program powinien wstawić 'do pudełka' tekst "Tekst w pudełku!", aby uzyskać następujący rezultat:

  1. ********************
  2. * Tekst w pudełku! *
  3. ********************

Szerokość pudełka wynosi dokładnie 20 znaków.