• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Pokazanie na ekranie tekstu + animacja | C++

VPS Starter Arubacloud
0 głosów
1,831 wizyt
pytanie zadane 20 lutego 2017 w C i C++ przez WireNess Stary wyjadacz (11,240 p.)

Witam!

Mam pewien problem. Chcę napisać program który będzie pokazywał tekst...

 

Nie nie! Nie chodzi mi o instrukcje cout :) Chcę aby dany tekst pojawiał się znak po znaku w odstępie 100 milisekund :) Chcę to zrobić w funkcji, aby było jak najmniej pisania.

 

Przepraszam za tak chaotyczny post - śpieszy mi się :D

2 odpowiedzi

+3 głosów
odpowiedź 20 lutego 2017 przez draghan VIP (106,230 p.)
wybrane 22 lutego 2017 przez WireNess
 
Najlepsza
#include <iostream>
#include <thread>


void write(const std::string& sentence)
{
    using namespace std::chrono_literals; // do zapisu 100ms (potrzeba wsparcia C++14)

    for(auto letter : sentence)
    {
        std::cout << letter;
        std::cout.flush();
        std::this_thread::sleep_for( 100ms );
    }
}

int main()
{
    write("Hello, world!");
}

 

komentarz 20 lutego 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
Wytłumaczysz jak co dziala?
1
komentarz 20 lutego 2017 przez draghan VIP (106,230 p.)

Nie ma tu za wiele do tłumaczenia. Dodam komentarz.

/* Przekazuję do funkcji referencję do stałego std::string.
    Plusy? Nie ma kosztownego kopiowania łańcucha i nie ma obawy o to,
    że funkcja zmodyfikuje oryginał. */
void write(const std::string& sentence)
{
    using namespace std::chrono_literals; // do zapisu 100ms (potrzeba wsparcia C++14)
 
    /*  Zakresowa pętla for. "Przeleci" po każdym elemencie stringa 'sentence' i zapisze 
        go do (na czas trwania jedne iteracji) do zmiennej letter, której typ kompilator sobie
        sam wydedukuje (auto). */
    for(auto letter : sentence)
    {
        std::cout << letter;
        
        /* Wyrzucam literę na ekran. W niektórych przypadkach bez tego nie zobaczymy 
            "animacji", tylko całość od razu (standardowe wyjście jest buforowane). */
        std::cout.flush(); 
        
        /* Wersja 'Sleep'  zdefiniowana w standardzie C++. 
            Bezpieczna, użyteczna i przenośna, w przeciwieństwie do 'Sleep'.
            Używam tutaj literału 'ms', zdefiniowanego w standardzie C++14. */        
        std::this_thread::sleep_for( 100ms );
    }
}

Czy coś jeszcze jest niejasne?

komentarz 20 lutego 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
edycja 20 lutego 2017 przez QizmoPL
wszystko jasne, oprocz std::cout.flush();, this_thread tyczy sie dokladnie tego wątku, skad kompilatoro ma wiedziec jak skakac po stringu?
1
komentarz 20 lutego 2017 przez draghan VIP (106,230 p.)

Wykonując tylko std::cout<<something; nie ma gwarancji, że something zostanie pokazane na ekranie od razu.

Standardowe wyjście (i wejście zresztą też) jest buforowane, tzn. że zanim coś dostanie się na ekran konsoli, najpierw trafia do pewnego bufora. Dopiero kiedy zostaną spełnione pewne warunki (np. będzie sporo znaków w buforze wyjścia lub wykorzystamy sprzężony strumień wejścia [std::cin]... lub wywołamy std::cout::flush()), zawartość bufora zostanie wypchnięta na ekran.

Przy robieniu takich wizualnych manipulacji nie chcemy, żeby coś trafiało do bufora, tylko od razu na ekran. Stąd po każdym znaku wrzuconym do std::cout, wywołuję std::cout::flush.

1
komentarz 20 lutego 2017 przez draghan VIP (106,230 p.)

this_thread tyczy sie dokladnie tego wątku, skad kompilatoro ma wiedziec jak skakac po stringu?

Trochę nie rozumiem. Kompilator nie "skacze" po stringu. To dzięki pętli for sekwencyjnie przetwarzamy każdy jego znak. A std::this_thread::sleep_for() to po prostu uśpienie wątku na określony czas. A że mamy tylko jeden wątek, to cały program stoi.

komentarz 20 lutego 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
Dobra, w jaki sposob kompilator rodziela stringa na osobne znaki?
1
komentarz 20 lutego 2017 przez draghan VIP (106,230 p.)
edycja 20 lutego 2017 przez draghan

Żeby napisać to w starym stylu, zrobiłbyś tak:

std::string sentence;

for(size_t i = 0; i < sentence.size(); ++i)
{
    std::cout << sentence[i];
}

Przeglądanie element po elemencie za pomocą for to bardzo częsta operacja, nie tylko dla łańcuchów, ale też np. dla tablic, std::vector, itp. Biblioteka standardowa dostarcza mechanizm iteratorów dla kontenerów standardowych, żeby można było wykonywać na nich algorytmy. Bardzo wygodne - dla różnych kontenerów mamy jednolity sposób wykonania pewnych operacji. Iteratory można interpretować jako wskaźniki, które pozwalają poruszać się po danym zbiorze danych (tablicy, vectorze, stringu...).

To, co powyżej zapisałem z użyciem indeksowania, można z pomocą iteratora zapisać tak:

std::string sentence;

for(std::string::iterator it = sentence.begin(); it != sentence.end(); ++it)
{
    std::cout << *it; // trzeba dokonać dereferencji (iteratora używa się podobnie jak wskaźnik)
}

Twórcy C++ wprowadzili pewne udogodnienie, pętlę zakresową. Opiera się ona na iteratorach właśnie. Zauważyli że dla każdego typu, dostarczającego własny iterator, pętla przeglądająca wszystkie jego elementy wygląda dokładnie tak samo:

for(typ_kontenera::iterator nazwa_iteratora = nazwa_kontenera.begin(); nazwa_iteratora != nazwa_kontenera.end(); ++nazwa_iteratora)

więc uproszczono zapis do prostego:

for( typ_elementu nazwa_elementu : nazwa_kontenera) {}.

Ja, zamiast typ_elementu (który dla std::string mógłby być char, ale wcale nie musiałbym o tym wiedzieć) napisałem auto. Kazałem kompilatorowi wybrać odpowiedni typ elementu, żebym ja nie musiał sprawdzać, czy to jest char, czy może jednak nie char.
W pętlach zakresowych bardzo często stosuje się auto, bo tak naprawdę programiście najczęściej nie zależy na tym, żeby musiał dokładnie i precyzyjnie określić typ elementu, tylko zależy na tym, żeby po prostu przejrzeć cały kontener i coś zrobić z elementami tego kontenera.

komentarz 20 lutego 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
Dzieki bardzo, o to mi chodzilo, teraz rozumiem
komentarz 20 lutego 2017 przez draghan VIP (106,230 p.)
Na zdrowie. :)
0 głosów
odpowiedź 20 lutego 2017 przez Marchewka900 Bywalec (2,970 p.)

Myślę o dwóch funkcjach. 
Pierwsza (ta prostsza):

cout<<"z"; 
Sleep(100); 
cout<<"n";
Sleep(100); 
cout<<"a"; 
Sleep(100); 
cout<<"k";

Pewnie nad nią myślałeś... Wyświetla słowo literka po literce. Druga, bardziej skomplikowana, ale uniwersalna:
(Nie, nie podam ci gotowca)

Funkcja otrzymuje słowo oraz ilość liter w nim.
Tworzy pętle wyświetlającą kolejne elementy tablicy tego słowa (string to tablica, czyli np. word[0], word[1] byłyby pierwszym i drugim znakiem w słowie).
Pętla ta wykonuje się tyle razy, ile podaliśmy jako ilość liter w słowie.
W środku pętli jest wyświetlenie jednego znaku i odczekanie 100 milisekund.

cout<<word[i];
Sleep(100);

No i funkcja gotowa. Z takim opisem to jakbym ci dał gotowca, ale co tam.
Jakby coś było nie jasne to mów ;>
 

 

komentarz 20 lutego 2017 przez WireNess Stary wyjadacz (11,240 p.)
Mam nadzieję, że żartowałeś z tą pierwszą funkcją - wkońcu pisanie tego wszystkiego zajeło by wieki :D

 

Próbowałem z for, ale nie pomyślałem o tablicach! Jak mi się uda dam znać!
komentarz 20 lutego 2017 przez Marchewka900 Bywalec (2,970 p.)
W sumie to zależy. Jeśli chcesz zrobić malutki programik, na przykład kalkulator w konsoli to wiesz :)
komentarz 20 lutego 2017 przez WireNess Stary wyjadacz (11,240 p.)
No nie :) To nie są moje początki :D Sądzę, że sam program zajmnie około 3k lini kodu, więc to nie ma najmniejszego sensu :D

Podobne pytania

+1 głos
2 odpowiedzi 248 wizyt
pytanie zadane 5 grudnia 2020 w HTML i CSS przez nowa Początkujący (450 p.)
0 głosów
3 odpowiedzi 1,219 wizyt
pytanie zadane 16 listopada 2015 w C i C++ przez maciek061 Gaduła (4,490 p.)
0 głosów
1 odpowiedź 549 wizyt
pytanie zadane 1 lutego 2018 w HTML i CSS przez Hardwell Dyskutant (8,960 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...