Strona główna » Algorytmy » Artykuły » Wyświetlacz siedmiosegmentowy
 

Wyświetlacz siedmiosegmentowy

Przykład wykorzystania wyświetlacza siedmiosegmentowego do wyświetlania godziny

Zadanie

Napisz translator przekształcający podaną liczbę w obrazek ASCII wzorując się na wskaźniku siedmiosegmentowym.

kliknij, aby poczytać o wskaźniku siedmiosegmentowym

Przykładowo dla liczby 8 program powinien wypisać:

  1.  _
  2. |_|
  3. |_|
  4.  

kliknij, aby przejść do oryginału zadania dostępnego na jagc.org

Rozwiązanie

Algorytm jest optymalny: zajmuje dosłownie kilka linijek, nie przechowuje dodatkowych danych, a wynik wypisuje na bieżąco.

C++
C#
  1. int main() {
  2.   char m[10] = {245, 144, 121, 217, 156, 205, 237, 145, 253, 221};
  3.   string n;
  4.   cin >> n;
  5.   for(int y = 0; y < 3; cout << endl, y++)
  6.     for(int j = 0; j < n.size(); j++)
  7.       for(int i = y * 3; i < y * 3 + 3; i++)
  8.         cout << ((m[n[j]-'0'] & ((char)pow(2,i-1))) ? (i % 3 == 1) ? '_' : '|' : ' ');
  9.   system("pause");
  10.   return 0;
  11. }

Podczas pisania algorytmu rozpisałem sobie cyfrę wyjściową jako tablice 3x3. Następnie oznaczyłem sobie każdą komórkę po kolei:

(0, 0) [0](1, 0) [1](2, 0) [2]
(0, 1) [4](1, 1) [8](2, 1) [16]
(0, 2) [32](1, 2) [64](2, 2) [128]

Schemat ten wskazuje, że potrzebujemy zapisać aż 9 bitów, aby wiedzieć, które fragmenty wyświetlać, a które nie. Jednak warto zauważyć, że (0, 0) oraz (0, 2) nigdy nie będą wyświetlone. W ten sposób teoretycznie zmniejszyliśmy ilość bitów do zapamiętania do 7.

Teraz możemy przejść do skonstruowania funkcji. Potrzebujemy mieć pierwszą wartość zawsze 0, a każdą kolejną na podstawie bitu pobieranego z liczby przedstawiający schemat świecenia danej cyfry. Kolejne bity możemy pobierać przy pomocy koniunkcji przykładowo, aby pobrać stan 3 bita liczby 0 wystarczy zapisać 245&4 co można rekurencyjnie wywołać w pętli przy pomocy n&pow(2,i), gdzie n to liczba schematu wyświetlania znaku, a i oznaczy, który bit chcemy sprawdzić. Jednak jeśli wywołamy pętle tylko 8 razy będziemy potrzebować dodatkowej linijki kodu dopisującą pusty znak na początku każdej cyfry.

Rozwiązaniem jest tutaj znajomość matematyczno-informatyczna. Jeśli podniesiemy -1 to otrzymamy 0.5, ale zmienne char, int itp. tracą cześć ułamkową w momencie próby przypisania. W ten sposób używając (liczba)&(pow(2,i)) i zaczynając dla i = -1 otrzymamy za pierwszym razem zawsze 0. Pozostaje nam jeszcze uwzględnić drugie puste pole jako 0 drugi bit w zapisie schematu liczby.

Analizując działanie algorytmu to składa się on z zadeklarowanej tablicy m, która przechowuje wszystkie schematy liczb. Schemat liczby to suma wartości pól, które powinny być zapalone wg. tablicy w/w. Następnie przechodzimy do pierwszej pętli, której głównym zadaniem jest kontrola nad kolejnymi wierszami tekstu: wiemy, że będą trzy linijki tekstu i tyle razy wywołujemy następną pętla, która odpowiada za pobranie konkretnego znaku z zadanego ciągu znaków jak argumentu. Jednak to jeszcze nie koniec przygody z pętlami.

Ostatnia pętla jest wywoływana trzy razy - dokładnie tyle ile cyfra ma znaków wszerz. Na podstawie wartości wywołanie pierwszej pętli określa, które znaki potrzebujemy wypisać. aby otrzymać zakres wystarczy nam [y, y+3].

Na podstawie wszystkich parametrów jesteśmy w stanie określić znak, który należy dopisać do wyjścia. Najpierw pobierając odpowiedni bit określamy czy pole jest puste czy nie. Jeśli ma być zapełnione to sprawdzamy czy linia ma być pozioma czy pionowa w tym celu sprawdzamy, który element cyfry chcemy wypisać i sprawdzamy resztę z dzielenia przez 3 czy wynosi 1. W ten sposób (1, 0), (1, 1) i (1, 2) otrzymujemy prawdę, więc wypisujemy "_" w przeciwnym wypadku "|".

Na koniec warto pamiętać, że pierwsza pętla powinna wypisać znak końca linii, aby tekst był rzeczywiście podzielony na trzy wiersze.