[C++] Kilka ćwiczeń dotyczących klasy std::string


(Quentin) #1

Witam!

Skończyłem dział o klasie std::string w Symfonii i zrobiłem kilka ćwiczeń pod koniec działu. Odnośnie 1 mam pytanie, a co do reszty to chciałbym się po prostu dowiedzieć czy algorytm jest w miarę przejrzysty i co można by tam zmienić :slight_smile:

Ćwiczenie 1:

Nie wiem jak zrobić takie banalne ćwiczenie :expressionless: Przychodzi mi do głowy tylko coś takiego:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

int rozpoznaj(string modul);

//////////////////////////////////////////////////

int main()

{


    string nazwa;

    cout << "Podaj nazwe modulu Cluster_: ";

    cin >> nazwa;


    cout << "\n\nModul nr: " << rozpoznaj(nazwa);


}

// *********************************************************************************************

int rozpoznaj(string modul)

{

    // modul.at(8); <--- tutaj jest nasz znak


    if(modul.at(8) == 'A')

        return 0;

    if(modul.at(8) == 'B')

        return 1;


    //itd...

}

To zejdzie nawet szybciej niż wymyślanie zautomatyzowanego kodu, ale jednak chciałbym wiedzieć jak zrobić to inaczej... Nie mam na to wcale pomysłu. Dodatkową przeszkodą jest to, że są to wyrywkowe litery z alfabetu. Ćwiczenie 2:

Oto mój program:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

string analiza(string nazwa);

//////////////////////////////////////////////////

int main()

{


    string tekst;

    cout << "Podaj jakakolwiek nazwe z rozszerzeniem: ";

    cin >> tekst;


    cout << "Zwracana nazwa: " << analiza(tekst);


}

// *********************************************************************************************

string analiza(string nazwa)

{

    string::size_type poz_polig;


    if(nazwa.find(".poly") == string::npos)

    {

        return nazwa.erase();

    }


    if( (nazwa.find(".poly") != string::npos) )

    {

        if((poz_polig = nazwa.rfind("_polygon_")) != string::npos)

        {

            nazwa = nazwa.substr(poz_polig + 9);

            nazwa.erase(nazwa.find('.'));

            return nazwa;

        }

        else

        {

            return nazwa.erase();

        }

    }

}

Jest OK :?: Ćwiczenie 3:

Oto kod:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

void wyswietl(string tekst);

//////////////////////////////////////////////////

int main()

{


    string obiekt;

    cout << "Wpisz jakis dlugi tekst (moze byc podzielony na linijki) i koniec oznacz 'v':\n";

    getline(cin, obiekt, 'v');


    cout << "\n\n";


    wyswietl(obiekt);


}

// *********************************************************************************************

void wyswietl(string tekst)

{

    string linijka("Linia "); //string opisujący nr aktualnej linii

    //------------------------------------------------------------

    string::size_type pozycja;

    int ile_linijek = 1; //ile linijek ma tekst


    //======================

    //1 ma na pewno więc:

    //======================

    char nr_linii = '0' + ile_linijek; //nr aktulanej linijki - tutaj '1'

    tekst.insert(0, (linijka + nr_linii + ": ")); //do aktualnej pozycji wstawiamy string

    //mówiący KTÓRA JEST TO LINIJKA


    string::size_type ostatnia_pozycja_n;


    for(int i = 1 ; /*bez warunku*/ ; i++)

    {


        if(i > 1) //jeżeli pętla została wykonana już 2 raz

        {

            pozycja = tekst.find('\n', ostatnia_pozycja_n+1);

        }

        else

        {

            pozycja = tekst.find('\n');

        }

        if(pozycja == string::npos) //jeżeli nie znaleźliśmy znaku new line

        {

            break; //to wyskakujemy z pętli

        }

        ile_linijek++; //jeżeli znaleźliśmy to inkrementujemy ile_linijek

        nr_linii = '0' + ile_linijek;

        tekst.insert(pozycja+1, (linijka + nr_linii + ": "));

        ostatnia_pozycja_n = pozycja; //chyba nie trzeba tłumaczyć

    }


    cout << tekst;

}

Algorytm jest dobry w miarę ? Ćwiczenie 4: Trzeba tutaj wykorzystać tablice stringów. Jednak o tym w książce wcale nie było... Jak je tworzyć ? Są możliwe jeszcze jakieś inne triki, że tak powiem oprócz:

string obiekty[2] = { "Michal", "Jerzy" };

:?:

____________________________________________________________________________________

No to tyle pytań, z góry wielkie dzięki za pomoc :slight_smile:


(Sawyer47) #2

Ad. 1

Oj szybko by Ci się znudziło pisanie tego tak. Jak już to do takich rzeczy jest switch/case. A poza tym wystarczy raz wywołać string::at i zapisać do zmiennej, a ty wywołujesz string::at od 1 do string::size() razy co jest zbędne (jasne, to może zostać zoptymalizowane, ale nie musi więc lepiej od razu pisać dobry kod).

Napisałbym to raczej tak, że zapisuję tę literę do zmiennej, nazwijmy ją znak, (a raczej stałej?) i sprawdzam, jeśli jest między A..G to zwracasz znak - 'A' , jeśli należy do kolejnego przedziału to znak - 'C' (ponieważ nie ma 'H' i 'I') itd.

Ad. 2

Może być, w sumie to chodzi tylko o przyswojenie sobie działania funkcji. Tylko jeśli zwracasz pusty string wystarczy "return std::string();", po co wymazywać argument i go zwracać?

Ad. 3

Raczej zbyt skompilowałeś kod. Wystarczyłoby iterować po całym stringu, sprawdzać czy litera to znak nowej linii i poprzedzać dalsze wypisywanie wypisaniem "Linia X: ". Wystarczy jedna pętla for, jeden licznik, jeden warunek if.

Ad. 4

Ale w Symfonii C++ jest przecież dużo o tablicach, a to czy to tablica liczb czy obiektów std::string to mała różnica.


(Quentin) #3

Eee nie rozumiem - tam się zwraca numer a nie znak...

Tak mógłbym się posłużyć iteratorami, ale to było (czytanie tego) nieobowiązkowe. Co prawda przeczytałem to, ale autor zawsze pisze ćwiczenia niewymagające znania nadobowiązkowych rzeczy, więc chciałem spróbować bez iteratorów :slight_smile:


(Sawyer47) #4

Ale (unsigned) char to również typ arytmetyczny w C(++), więc można odejmować i dodawać znaki. 'B' - 'A' daje znak o kodzie ASCII 1 (bo tyle wynosi różnica kodów ASCII znaków B i A). Zobacz tabelę znaków ASCII: http://pl.wikipedia.org/wiki/ASCII

Tak więc jeśli dla pierwszej grupy znaków w tym ćwiczeniu, od A..G można napisać static_cast(znak - 'A') i w ten sposób otrzymać liczbę - różnicę kodów ASCII.

A co do trzeciego zadania, to wcale nie chodziło mi o obiekty iteratorów, równie dobrze można napisać for( i = 0; i < str.size(); ++i) jak i mieć indeksy liter jak i for( it = str.begin(); it != str.end(); ++it) i mieć iterator.


([alex]) #5

Czy to co przedstawiłeś jest dobrym kodem - oceń sam, podaje w miarę dobry:

int rozpoznaj(const string &modul)  {   return string("ABCDEFGJKLMNPQR").find(modul.at(8));  }

(Quentin) #6

Hmmm, no tak na początku miałem podobny pomysł, ale był trochę dłuższy od tego. A co do reszty znaków to niestety trzeba już pisać osobno instrukcje. Tak mi to wyszło:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

int rozpoznaj(string modul);

//////////////////////////////////////////////////

int main()

{


    string nazwa;


    while(true)

    {   

        cout << "Podaj nazwe modulu Cluster_: ";

        cin >> nazwa;

        if( (nazwa.find("Cluster_") != string::npos) && (nazwa.length() == 9) )

            break;

    }



    cout << "\n\nNumer: " << rozpoznaj(nazwa);


}

// **********************************************************************************************************

int rozpoznaj(string modul)

{

    char znak = modul.at(8); // <--- tutaj jest nasz symbol


    if( (znak >= 'A') && (znak <= 'G') )

        return static_cast(znak - 'A');


    if( (znak >= 'J') && (znak <= 'N') )

        return static_cast(znak - 'C');


    if(znak == 'P')

        return 12;


    if(znak == 'Q')

        return 13;


    if(znak == 'R')

        return 14;


}

W sensie, że co :?: Jest rozszerzenie .polyform, a ona i tak dalej obcina, pomimo, że nie jest samo .poly :?: Ja po prostu miałem ćwiczenie i chciałem je wykonać - nie będę się zastanawiał nad szczegółami... Dam teraz resztę ćwiczeń - wszystkie działają co jest najważniejsze , proszę tylko o ocenę algorytmu. Ćwiczenie 4: Wygląda mi trochę banalnie, ale dam jednak się zapytam.

Oto mój kod:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

string przystanek(int najblizszy_przyst);

//////////////////////////////////////////////////

int main()

{


    cout << "Podaj najblizszy nr przystanku (od zera do 5): ";

    int numer;


    int iteracja = 0;

    while(true)

    {

        if(iteracja >= 1)

            cout << "\n! Nie ma takiego przystanku !\n"

                 << "Wpisz ponownie (0-5):";

        cin >> numer;

        if( (numer >= 0) && (numer <= 5) )

            break;

        iteracja++;

    }


    cout << "\n\n" << przystanek(numer);


}

// *******************************************************************

string przystanek(int najblizszy_przyst)

{

    static string przystanki[7] = { "Rzeszow Rynek", 

                                    "Merkury Market", 

                                    "Zespol szkol ARD",

                                    "ul. Krakowskiego", 

                                    "Tesco", 

                                    "Media Markt",

                                    "ul. Niewodniczanska 5" };


    //-------------------------------------------------------------


    string przyst("Nastepny przystanek: ");


    return przyst + przystanki[najblizszy_przyst + 1];


}

Ćwiczenie 5:

Oto kod:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

string slownie_liczba(int liczba);

//////////////////////////////////////////////////

int main()

{


    cout << "Podaj jakas liczbe z przedzialu 0-99: ";

    int licz;


    int iteracja = 0;

    while(true)

    {

        if(iteracja >= 1)

            cout << "\n! Niedozwolona liczba !\n"

                 << "Wpisz ponownie (0-99):";

        cin >> licz;

        if( (licz >= 0) && (licz <= 99) )

            break;

        iteracja++;

    }


    cout << "\n\nOto Twoja liczba: " << slownie_liczba(licz);


}

// ****************************************************************

string slownie_liczba(int liczba)

{

    //======================================

    //Na początek sprawdzamy parzystość:

    //======================================

    string parzysta_czy_nie;

    if(liczba % 2)

        parzysta_czy_nie = "Liczba jest nieparzysta";

    else

        parzysta_czy_nie = "Liczba jest parzysta";


    //------------------------------------

    //Zamienianie liczby na znak char:

    //------------------------------------


    char dziesiatki = '0' + (liczba / 10); //jeżeli 52 to:

    //52 : 10 = 5.2

    //A ponieważ w C++ brana jest cecha liczby:

    // = 5


    liczba %= 10; //reszta z dzielenia - teraz uwzględniamy

    //zamiast cechy część po przecinku


    char jednostki = '0' + liczba;


    string liczba_do_wstaw("");

    liczba_do_wstaw += dziesiatki;

    liczba_do_wstaw += jednostki;

    liczba_do_wstaw += " ";

    // *******************************

    //Właściwa instrukcja:

    // *******************************

    parzysta_czy_nie.insert(7, liczba_do_wstaw);


    return parzysta_czy_nie;


}

Pytanie 5.1: czego zamiast:

string liczba_do_wstaw += dziesiatki;

liczba_do_wstaw += jednostki + " ";

trzeba pisać tak:

string liczba_do_wstaw("");

liczba_do_wstaw += dziesiatki;

liczba_do_wstaw += jednostki;

liczba_do_wstaw += " ";

Bo inaczej wywala błąd: invalid conversion from char' toconst char*' :?: Pytanie 5.2: Z książki wziąłem przykład jak zamienić liczbę na string i go tu wykorzystałem. Początkowo w książce był taki kod:

Po co potrzebne jest to co zaznaczyłem kolorem :?: Bez tego kod działa też dobrze... Ćwiczenie 6: Myślałem, że tego programu nie napiszę ale udało mi się na szczęście :smiley:

Program jest troszkę zawiły ( ale działa w najlepszym porządku ). W tym zadaniu było więcej matematyki niż programowania, no ale cóż... Oto kod:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

string wyswietl_slownie(int liczba);

//////////////////////////////////////////////////

int main()

{


    cout << "Podaj jakas liczbe z przedzialu -9999 do 9999: ";

    int licz;


    int iteracja = 0;

    while(true)

    {

        if(iteracja >= 1)

            cout << "\n! Niedozwolona liczba !\n"

                 << "Wpisz ponownie (-9999 do 9999):";

        cin >> licz;

        if( (licz >= -9999) && (licz <= 9999) )

            break;

        iteracja++;

    }


    cout << "\n\nOto Twoja liczba slownie:\n\n\t" << wyswietl_slownie(licz);


cout << "\n\n\n\n\n\n---------------------------------------------------------------\n";

system("pause");

}

// ************************************************************************************

string wyswietl_slownie(int liczba)

{

    string slownie(""); //dla słownego wyrażenia naszej liczby


    //Działania, które musimy podjąć, jeżeli liczba jest ujemna.

    //Jeżeli ich nie podejmiemy - program się, brzydko mówiąc, spie **** :)


    if(liczba < 0)

    { //A o to jak z liczby ujemnej zrobić liczbę przeciwną:

          liczba = (liczba + (liczba * -2));

          slownie = "- ";

    }



    string jednosci[] = { "zero",

                            "jeden",

                            "dwa",

                            "trzy",

                            "cztery",

                            "piec",

                            "szesc",

                            "siedem",

                            "osiem",

                            "dziewiec" };


    string dalsze_jednosci[] = { "",

                            "jedenascie",

                            "dwanascie",

                            "trzynascie",

                            "czternascie",

                            "pietnascie",

                            "szesnascie",

                            "siedemnascie",

                            "osiemnascie",

                            "dziewietnascie" };


    string dziesiatki[] = { "",

                            "dziesiec",

                            "dwadziescia",

                            "trzydziesci",

                            "czterdziesci",

                            "piedziesiat",

                            "szescdziesiat",

                            "siedemdziesiat",

                            "osiemdziesiat",

                            "dziewiecdziesiat" };


    string setki[] = { "",

                       "sto",

                       "dwiescie",

                       "trzysta",

                       "czterysta",

                       "piecset",

                       "szescset",

                       "siedemset",

                       "osiemset",

                       "dziewiecset" };


    string tysiace[] = { "",

                       "tysiac",

                       "dwa tysiace",

                       "trzy tysiace",

                       "cztery tysiace",

                       "piec tysiecy",

                       "szesc tysiecy",

                       "siedem tysiecy",

                       "osiem tysiecy",

                       "dziewiec tysiecy" };


    //=========================================================

    //=========================================================


    //TYSIĄCE:

    int tys = (liczba / 1000); //żeby wyciągnąć liczbę tysięcy


    //SETKI:

    int set;

    if(tys) //jeżeli nasza liczba zawiera tysiące

    {

        set = ( (liczba - (tys * 1000)) / 100 ); //trochę bardziej skomplikowane działanie

    }

    else //gdy tysięcy nie ma

    {

        set = (liczba / 100); //żeby wyciągnąć liczbę setek

    }


    //DZIESIĄTKI:

    bool czy_sa_tysiace = false; //nie chce mi się tłumaczyć po co to jest...

    int dzies;

    if(tys)

    {

        dzies = ( (liczba - (tys * 1000) - (set * 100)) / 10 );

        czy_sa_tysiace = true;

    }

    if( !czy_sa_tysiace )

    {

        dzies = ( (liczba - (set * 100)) / 10 );

        czy_sa_tysiace = true;

    }

    if( !czy_sa_tysiace )

    {

        dzies = (liczba / 10);

    }


    //I nieszczęsne JEDNOŚCI:

    bool czy_sa_setki = false;

    bool czy_sa_dziesiatki = false;

    int jedn;

    if(tys)

    {

        jedn = (liczba - (tys * 1000) - (set * 100) - (dzies * 10));

        czy_sa_tysiace = true;

        czy_sa_setki = true;

        czy_sa_dziesiatki = true;

    }

    if( !czy_sa_tysiace )

    {

        jedn = ( (liczba - (set * 100)) % 10 );

        czy_sa_setki = true;

        czy_sa_dziesiatki = true;

    }

    if( !czy_sa_setki)

    {

        jedn = ( liczba % 10 );

        czy_sa_dziesiatki = true;

    }

    if( !czy_sa_dziesiatki )

    {

        jedn = liczba;

    }


    //=============================================

    //===========ZAMIANA LICZBY NA SŁOWA===========

    //=============================================



    int dalsze_jedn = (dzies * 10) + jedn;

    if(dalsze_jedn >= 11 && dalsze_jedn <= 19)

    {

             slownie += tysiace[tys];

             slownie += " ";

             slownie += setki[set];

             slownie += " ";

             slownie += dalsze_jednosci[jedn];

    }

    else

    {

            slownie += tysiace[tys];

            slownie += " ";

            slownie += setki[set];

            slownie += " ";

            slownie += dziesiatki[dzies];

            slownie += " ";

            slownie += jednosci[jedn];

    }


    //A teraz operacja, dzięki której po wpisaniu:

    //20

    //nie wyświetli się słowo 'zero'

    if( (tys != 0) || (set != 0) || (dzies != 0) )

    {

        if(slownie.find("zero") != string::npos)

            slownie.erase(slownie.find("zero"));

    }

    return slownie;

}

Ćwiczenie 7:

Prosty program, dzięki radzie nr47 wiem jak go napisać :slight_smile:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////

string litera_alfabetu(int nr_literki);

//////////////////////////////////////////////////

int main()

{


    cout << "Podaj NUMER litery alfabetu angielskiego (1-26): ";

    int numer;


    int iteracja = 0;

    while(true)

    {

        if(iteracja >= 1)

            cout << "\n! Nie ma litery o takim numerze !\n"

                 << "Wpisz ponownie (1-26):";

        cin >> numer;

        if( (numer >= 1) && (numer <= 26) )

            break;

        iteracja++;

    }


    cout << "\n\n" << litera_alfabetu(numer);


cout << "\n\n\n\n\n\n---------------------------------------------------------------\n";

system("pause");

}

// ******************************************************************

string litera_alfabetu(int nr_literki)

{

    char lit_alf = 'A' + nr_literki - 1;


    //Na początek zamieniamy nr_literki na string:

    char dziesiatki = '0' + (nr_literki / 10);

    nr_literki %= 10;

    char jednostki = '0' + nr_literki;


    string litera("W alfabecie litera nr "); //<--- tutaj będzie nasz ostateczny string

    if(dziesiatki == '0')

        litera += jednostki;

    else

    {

        litera += dziesiatki;

        litera += jednostki;

    }


    //Po włożeniu liczby do stringu, trzeba napisać, która to

    //litera alfabetu:


    litera += " to: ";

    litera += lit_alf;


    return litera;

}

Ćwiczenie 8:

Oto program:

#include 

#include 

using namespace std;

//////////////////////////////////////////////////


//////////////////////////////////////////////////

int main(int argc, char *argv[])

{


    string rodzaj_miejsca = argv[1];

    string nazwa = argv[2];


    string zdanie("Dane przychodzic beda ");


    cout << "\n\n\t";

    if(rodzaj_miejsca.find("ser") != string::npos)

    {

        zdanie += "z serwera ";

        zdanie += nazwa;

        cout << zdanie;

    }

    else if(rodzaj_miejsca.find("plik") != string::npos)

    {

        zdanie += "z pliku ";

        zdanie += nazwa;

        cout << zdanie;

    }

    else if(rodzaj_miejsca.find("stru") != string::npos)

    {

        zdanie += "ze strumienia ";

        zdanie += nazwa;

        cout << zdanie;

    }

    else 

    {

        cout << "\n\n! Nie poprawny argument wywolania programu !"

             << "\n\nMasz do dyspozycji nastepujace argumenty:"

             << "\n\n\t-ser (jesli dane maja przychodzic z serwera) + nazwa"

             << "\n\n\t-plik (jesli dane maja przychodzic z pliku) + nazwa"

             << "\n\n\t-stru (jesli dane maja przychodzic ze strumienia) + nazwa";

    }


}

_______________________________________________________________________________________

Z góry znowu będę bardzo ale to bardzo wdzięczny za wszelką pomoc :wink:


(Sawyer47) #7

Prosisz o ocenę... jesteś początkujący, to widać. Chyba każdą funkcję dałoby się napisać krócej i czytelniej, a krótszy kod to zazwyczaj szybszy kod (generalizując). Czytelność kodu i własny styl wyrabia się z czasem. Co do szybkości to istnieje taka zasada w programowaniu "Wystrzegaj się przedwczesnej optymalizacji". Ważne, że najpierw napiszesz kod który działa (najlepiej bezbłędnie!), a optymalizacją można zająć się później. Nie warto tracić czasu na pieszczenie kodu, który i tak będzie miał małe znaczenie dla szybkości działania aplikacji. Najważniejsze to skupić się na poprawianiu wydajności wąskich gardeł w programie. Oczywiście nie znaczy to, że można pisać niedbały, brzydki i wolny kod, mam nadzieje, że to oczywiste.

Wyjaśnię jeszcze to:

Drugi kod jest poprawny, bo wywołujesz operator+= w klasie string z różnymi typami argumentów. Natomiast

liczba_do_wstaw += jednostki + " ";

// zostanie zinterpretowane tak:

liczba_do_wstaw += (jednostki + " ");

Co oznacza, że do operatora += klasy string wysyłasz wynik (jednostki + " "). jednostki to u Ciebie typ char, " " to typ const char*, a w C++ nie ma domyślnie zdefiniowanego operatora dodawania znaku do C-stringa. Stąd też ostrzeżenie, kompilator próbuje rzutować typ char do const char* co też sensu nie ma.

Wracając do twojego kodu to nie chcę oceniać algorytmów. Jeśli masz pewność, że działają to są dobre. Natomiast pole do optymalizacji zawsze jest. Zachęcam Cię do jednej rzeczy, która myślę będzie równie ucząca co te zadania. Zmierz czas wykonywania twoich algorytmów na przykładowych danych (niech wykonują się w pętli odpowiednią ilość razy, żeby otrzymać wynik chociaż paro(nasto)sekundowy), a następnie spróbuj je przyśpieszyć.


(Quentin) #8

No tak - każdy z nich działa bez zarzutu. Ale czy sens jest optymalizować tak krótkie programy ? Przy dzisiejszych komputerach i przy TAKICH programach to nigdy nie zrobi różnicy w działaniu.

A jest jakieś dobre narzędzie do mierzenia czasu wykonywania programu :?: Szukałem trochę i znalazłem coś o GetTickCount i timeGetTime. Czy może jest jeszcze coś lepszego :?: Odnośnie tych ostatnich to nigdzie nie mogę znaleźć przykładu ich użycia.


(Sawyer47) #9

Dla sportu i wprawy :wink: Natomiast w prawdziwych programach i bardziej złożonych algorytmach jak najbardziej, żeby potem użytkownicy nie narzekali, że program X działa wolno. I nigdy nie mów, że dziś komputery są szybkie, bo np. ja mam komputer o ~5 letniej konfiguracji (patrz podpis), a bardzo wiele ludzi używa jeszcze wolniejszych maszyn. Nigdy więc nie postępuj jak twórcy Windows Vista i nie zakładaj, że użytkownik kupi dla twojego programu nowy komputer! :stuck_out_tongue:

Co do mierzenia czasu pod wszelkimi uniksopodobnymi najprościej wykorzystać program time, to o wiele wygodniejsze niż wstawianie mierzenia czasu w kodzie i rekompilacja. Pod Windows pewnie znajdzie się odpowiednik, albo pewnie można zainstalować z MSYS/MinGW/cygwin.


(somekind) #10

Bardzo mądrze napisane. Szkoda tylko, że niektórzy "eksperci" o tym nie wiedzą ;]


([alex]) #11

Nie wiem kto daje takie bzdurne rady. Ta rada może przyspieszyć czas wykonania projektu tylko jeżeli:
1. [*:269ii5qa]Piszesz niewielka aplikacje dla której szybkość jest nieważna[*:269ii5qa]Piszesz aplikacje pod dobre komputery i nie obchodzą cie że ktoś kto będzie miał komputer z przed 10 lat (częsty przypadek) będzie długo czekał na wyniki[*:269ii5qa]Nie jest to aplikacja pod wolne procesory w której liczy się czas reakcji: (komórki,układy scalone)[*:269ii5qa]Piszesz w języku kompilowanym a nie interpretowanym (np. PHP)

Właściwie ta lista (mocno skrócona) ogranicza do kilku języków programowania, kilku platform i kilku rodzajów aplikacji. Więc, prawdziwy ekspert potrafi od razu pisać optymalny (lub prawie optymalny) kod, ponieważ jeżeli nabędzie złych nawyków to w większości przypadków będzie zmuszony optymalizować to co już napisał, a to z kolei może istotnie zwiększyć czas wykonania całego projektu. Poza tym często zdarza się następujący scenariusz (u pseudo ekspertów od programowania którzy najpierw robią a potem ewentualnie myślą):

  • [*:269ii5qa]Aplikacja szybko napisana ale jest zbyt powolna albo nie dla każdego możliwego zestawu działa poprawnie[*:269ii5qa]Następuje kilka iteracji, klient wskazuje gdzie zbyt wolne i/lub dla jakiego zestawu danych aplikacja przestaje działać poprawnie[*:269ii5qa]W czasie kolejnych poprawek często się okazuje, że pseudo ekspert robi pewne nieprzemyślane "protezy"[*:269ii5qa]Po nastu iteracjach klient rezerwuje z usług pseudo eksperta i dzwoni do prawdziwego eksperta

Przykład podobnego scenariusza był na tym forum: viewtopic.php?f=23&t=312470

Tylko że nie było klienta który by zrezygnował :smiley:

Był jeszcze jeden taki przykład na tym forum, ale wyjaśnienia dotyczące algorytmu doprowadzili do tego że pupilek moderatorów okazał się w niekorzystnym świetle, więc cały temat wylądował w śmietniku (i nikogo nie obchodzi że takie wyjaśnienia mogą komuś się przydać).

Więc każdy sobie wybiera sam: być ekspertem z dziedziny programowania czy tez słuchać wyżej wymienionej rady i być zwykłym koderem. Ciekawostką jest to, że tacy koderze uważają siebie za prawdziwych ekspertów, są też zatrudniani w renomowanych firmach ponieważ są tańsze od prawdziwych ekspertów (zatrudnienie eksperta kosztuje tyle co 3-ch do 5-ciu koderów), ale tylko w takich firmach których nie obchodzą losy użytkowników programów napisanych przez rzeszę tanich koderów.


(Xwars) #12

Knuth, najwyraźniej nie zna się na programowaniu, wszechwiedzący alex wie od niego lepiej.


(Sawyer47) #13

[alex] naprawdę nie słyszałeś o takich zasadach jak "Wystrzegaj się przedwczesnej optymalizacji" albo "DRY"? Uczulam tu na słowo "przedwczesnej". To nie oznacza tyle co "Wystrzegaj się optymalizacji", a mam wrażenie, że tak to odebrałeś po części. Zostałem zapytany czy warto optymalizować pojedyncze funkcje, więc wtrąciłem o tej zasadzie. W początkowym cyklu życia programu optymalizacje to strata czasu (choć doświadczony programista od razu będzie pisał wydajniejszy kod, zgoda jak najbardziej). Poza tym i tak najważniejsza jest optymalizacja wąskich gardeł (choć nic nie zastąpi idei i dobrego projektu w pierwszej kolejności rzec jasna). Mały offtop się robi, wydaje mi się, że Quentin już otrzymał pomoc. A dalsze miejsce dyskusji o wyższości "ekspertów" nad koderami jest w "Na Luzie" lub na PW, ale ja więcej do dodania w sumie nie mam.


(somekind) #14

  1. Piszesz coś naprawdę poważnego, a nie implementację prostego algorytmu, który został już dawno rozwiązany na wiele sposobów - czyli w większości przypadków.

Hohoho, mocny zarzut. Podpada pod regulamin forum punkt 2.18. Chyba wiem, o czym mówisz i mogę się założyć, że tamten temat poleciał za nic niemówiącą nazwę Panie Poszukiwaczu Spisków :stuck_out_tongue_winking_eye:

A skoro już mowa o tamtym:

Dlaczego zatem, Prawdziwy Ekspercie, zajmujesz się optymalizacją tego, co i tak zoptymalizuje kompilator, zamiast użyć lepszego algorytmu? ;]

Żeby tylko jeden Knuth, ale o tym mówią i wiedzą wszyscy. (No, z małymi wyjątkami :wink: )


([alex]) #15

Przeważnie nie zajmuję się optymalizacją ponieważ od samego początku piszę optymalnie (przynajmniej prawie) oraz przewidując wszystkie możliwe kombinacji danych wejściowych (też prawie zawsze, ale komu się nie zdarza?).

Tak, oczywiście !!


(somekind) #16

Jeśli chodzi o liczby pierwsze, to nie użyłeś wcale optymalnego algorytmu, więc cała Twoja teoria jest o kant potłuc. Twoja optymalizacja ogranicza się w zasadzie do wyręczania w tym kompilatora. Ergo - jesteś koderem, nie programistą.

Miło, że wciąż tu jesteś i nadal dostarczasz darmowej rozrywki :slight_smile:


([alex]) #17

Jak napiszesz coś bardziej optymalnego niż to co ja tam podałem to możemy na ten temat dyskutować, dopóki tego nie zrobiłeś to rzucanie twierdzeń bez pokrycia jest przynajmniej śmieszne. Stąd pytanie - kto tu dostarcza darmowej rozrywki :lol: