logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[bascom] różnica pomiędzy etykietą a podprogramem

dzarek1 26 Lis 2008 18:32 7067 22
  • #1 5786501
    dzarek1
    Poziom 14  
    Witam
    Wiem że to trochę lamerskie pytanie, ale za bardzo nigdzie nie mogę znaleźć na nie rzeczowej odpowiedzi.
    Otóż... kiedy fragment programu, do którego mam się odwoływać umieszczać pod etykieta a kiedy dawać go jako podprogram.
    Pomijając tutaj oczywiście fakt, że "etykietą" może być część np programu głównego lub podprogramu, to czy jest sens używać etykiet w zastępstwie podprogramów ??
  • Pomocny post
    #2 5786619
    ZbeeGin
    Poziom 39  
    Jak chcesz przekazać temu fragmentowi jakieś parametry, to prościej jest napisać procedurę (Declare Sub, i ciało Sub...End Sub). Jak taka procedura ma dodatkowo coś zwrócić to napisz funkcję (Declare Function, i ciała Function...End Function) Jak chcesz tylko tam wskoczyć i wrócić by wykonać powtarzające się operacje to etykieta: i GoSub. Jak chcesz wskakiwać tam przez Goto to nie grzesz wiecej pisząc programy...
  • #3 5786631
    johny_w
    Poziom 23  
    Do etykiety możesz "skoczyć", a podprogram wywołujesz.
    Po skoku do etykiety program leci dalej już od tego miejsca.
    Wywołany podprogram wykonuje się, a następnie uC wraca do miejsca wywołania.
  • #4 5786689
    ZbeeGin
    Poziom 39  
    Jj_Johnys napisał:
    Po skoku do etykiety program leci dalej już od tego miejsca. Wywołany podprogram wykonuje się, a następnie uC wraca do miejsca wywołania.

    Co przy prawidłowo zakończonym kodem z wykorzystaniem GOSUB i RETURN da ten sam efekt co wywołanie podprogramu.
  • #5 5787507
    dzarek1
    Poziom 14  
    ZbeeGin napisał:

    Co przy prawidłowo zakończonym kodem z wykorzystaniem GOSUB i RETURN da ten sam efekt co wywołanie podprogramu.

    i stad właśnie moje pytanie...
  • #6 5787751
    zumek
    Poziom 39  
    To ja jeszcze coś dorzucę, do wypowiedzi kol.ZbeeGin
    Jeżeli zdecydujesz się na użycie etykiety i skoku do niej przez Gosub, a zapomnisz na końcu podprogramu dać Return, to Twój wypieszczony kod poleci w krzaki, bo kompilator Cię nie ostrzeże. Natomiast przy użyciu konstrukcji...
    
    Declare Sub Podprogram()
    '...
    Call Podprogram()
    '...
    
    Sub Podprogram()
    '...
    End Sub
    

    ... kiedy na końcu podprogramu zapomnisz o End Sub, to dostaniesz ostrzeżenie(Error) o braku takowej.
    Wniosek: Lepiej/bezpieczniej deklarować podprogramy nawet wtedy, kiedy nie przekazujemy im żadnych parametrów.

    Piotrek
  • #7 5787834
    tomba
    Poziom 17  
    jeżeli już taka fachowa, wypasiona wypowiedz ma pozostać w tym wątku - to warto by było dodać koledzy wartości - co ile i jak dużo zajmuje w kodzie na bascoma ??? - proszę o takie informacje
  • #8 5787920
    zumek
    Poziom 39  
    tomba napisał:
    ... co ile i jak dużo zajmuje w kodzie na bascoma ???

    A sam, nie możesz sprawdzić :?:
    Tyle samo :-P

    Piotrek
  • #9 5788180
    wader_669
    Poziom 28  
    dzieki za ten temat, wyjasnia duzo moich watpliwosci. A o takich rzeczach malo pisza w helpie i ksiazce.
    A jak to wyglada ze stosem, co on ma wspolnego z tym wszystki?
    Wiem ze czesto uzywanie goto powoduje przepelnienie stosu, dlatego tez unika sie uzywania goto.
    Jak dobrze to rozumiem to na stosie laduja adresy gdzie program zrobil skok, zeby mogl do nich wrocic jak skonczy. zgadza sie, czy zle to rozumiem?
  • #10 5788342
    K_o_n_r_a_d
    Poziom 23  
    wader_669 napisał:
    Wiem ze czesto uzywanie goto powoduje przepelnienie stosu, dlatego tez unika sie uzywania goto.
    GOTO nie używa stosu. GOSUB używa, ale częste używanie nie oznacza, że stos przepełni się. Zagnieżdżanie dużej ilości może spowodować przepełnienie.
    wader_669 napisał:
    Jak dobrze to rozumiem to na stosie laduja adresy gdzie program zrobil skok, zeby mogl do nich wrocic jak skonczy. zgadza sie, czy zle to rozumiem?
    Zgadza się, ale to nie wszystko co na stosie ląduje, np. zmienne lokalne.
  • #11 5789354
    wader_669
    Poziom 28  
    K_o_n_r_a_d napisał:
    Zgadza się, ale to nie wszystko co na stosie ląduje, np. zmienne lokalne.

    no no to jest jasne.

    To nie wiem jak dziala goto i dlaczego zabrania sie uzywania tego.
    A jak sie robi declare sub to nie zapisuje gdzie zrobil skok?

    Gdzie mozna o tym troche poczytac, bo jak widac do konca tego nie rozumiem :P
  • #12 5789394
    K_o_n_r_a_d
    Poziom 23  
    wader_669 napisał:
    To nie wiem jak dziala goto i dlaczego zabrania sie uzywania tego.
    GOTO po prostu przenosi wykonywanie programu w inne miejsce, nic więcej.
    Używanie GOTO nie jest polecane ponieważ program w którym jest dużo GOTO jest nieczytelny i łatwo o pomyłkę, którą później trudno zlokalizować. Wszystko co da się zrobić poprzez GOTO, da się zrobić równie wydajnie w inny sposób, np. poprzez pętlę, warunki itp.
    wader_669 napisał:
    A jak sie robi declare sub to nie zapisuje gdzie zrobil skok?
    DECLARE SUB jest deklaracją zwykłej procedury, jaką znamy np. z Pascala i innych języków. Jest to tak jakby bardziej rozszerzenie możliwości podprogramu, można przekazywać wartości itp. W Bascomie bardzo nieoptymalne - sam prawie nigdy nie używam - zastępuję odpowiednimi podprogramami.
    wader_669 napisał:
    Gdzie mozna o tym troche poczytac, bo jak widac do konca tego nie rozumiem :P
    Hmm... najlepszą drogą do zrozumienia tego jest nauka asemblera :)
  • #13 5789690
    wader_669
    Poziom 28  
    a takie pytanie czy sub w bascomie to cos podobnego do voida w c ? Bo mam ksiazke od c gdzie jest to dokladniej opisane i moze pomoze mi zrozumiec o co lata.
  • #15 5827108
    wader_669
    Poziom 28  
    :please: dziekuje dziekuje za stronke.

    Ok, teraz mam dalsze pytanie do fachowcow, ktory kod jest poprawnie napisany? (jak obydwa to jaka jest roznica pomiedzy nimi? kod byl pisany na forum wiec moga byc bledy, ale chyba wiadomo o co chodzi)

    
    dim adres_main_x as byte
    dim adres_main_y as byte
    
    declare sub lcd_ (byval adres_y as byte, byval adres_x as byte)
    
    do
    
    if s1=0 then
    incr  adres_main_y
    call lcd_ (adres_main_y, adres_main_x )
    
    elseif s2=0 then
    decr adres_main_x
    call lcd_ (adres_main_y, adres_main_x)
    end if
    
    loop
    end
    
    sub lcd_ (byval adres_y as byte, byval adres_x as byte)
    cls
    locate adres_y, adres_x
    lcd "test"
    end sub
    


    czy ten kod?

    
    dim adres_main_x as byte
    dim adres_main_y as bute
    
    declare sub lcd_
    
    do
    if s1 = 0 then
    incr adres_main_x
    call lcd_
    elseif s2 = 0 then
    incr adres_main_y
    call lcd_
    end if
    
    loop
    end
    
    sub lcd_
    cls
    locate adres_mian_y, adres_main_x
    lcd "test"
    end sub
    
    


    Jeszcze mam jedno pytanie, jak bym chcial zrobic zmienna w procedurze ktora jest na stosie i w tej procedurze jest jeszcze jedna procedura, ktora tez korzysta z tej zmiennej, ale po wyjsci z pierwszej procedury zmienna znika ze stosu. Jak to zrobic?

    czy to bedzie wygladac tak? czy jest to poprawnie napisane?

    
    do
    call pierwsza_procedura
    loop
    end
    
    sub pierwsza_procedura 
    local x as byte
    x=99
    lcd "x"
    call druga_procedura
    end sub
    
    sub druga_procedura
    x=100
    lcd "x"
    end sub
    


    Na logike to pierw wszystko bedzie odlozone na stos z pierwszej procedury (ta zmienna tez). Pozniej wywolujemy druga procedure, z czego stos sie nie zwalnia (czyli gdzies tam ta zmienna bedzie) i w tej 2 procedurze zmienna sie zmienia na x=100. Nastepnie jest koniec procedur i caly stos sie zwalnia, zgadza sie?
  • #16 5827772
    ZbeeGin
    Poziom 39  
    wader_669 napisał:
    czy to bedzie wygladac tak? czy jest to poprawnie napisane?

    
    do
    call pierwsza_procedura
    loop
    end
    
    sub pierwsza_procedura 
    local x as byte
    x=99
    lcd "x"
    call druga_procedura
    end sub
    
    sub druga_procedura
    x=100
    lcd "x"
    end sub
    

    Nie, nie jest to poprawne. Zmienna X jest widziana tylko i wyłącznie w procedurze "pierwsza_procedura". Taka jest istota zmiennych lokalnych. Ponadto w tym fragmencie masz poważny błąd. :D

    Cytat:
    Na logike to pierw wszystko bedzie odlozone na stos z pierwszej procedury (ta zmienna tez). Pozniej wywolujemy druga procedure, z czego stos sie nie zwalnia (czyli gdzies tam ta zmienna bedzie) i w tej 2 procedurze zmienna sie zmienia na x=100. Nastepnie jest koniec procedur i caly stos sie zwalnia, zgadza sie?

    Tak nie jest. Zmienna lokalna jest zmienną lokalną danej procedury i normalnie nie dziedziczy się jej. Powód jest prosty. Aby zmienna lokalna w danej procedurze zachowywała swą chwilową wartość, nie może być ona przenoszona do procedur podrzędnych gdzie można ją niechcący zmodyfikować. W procedurze gdzie zmienna powstała może być przecież potrzebna jej niezmieniona wartość gdzieś dalej.
    Jak chcesz zmienną X przekazać by druga procedura mogła ją wykorzystać (i zmodyfikować) musisz to zrobić jawnie, za pomocą parametru:
    Declare Sub Pierwsza_procedura
    Declare Sub Druga_procedura(x As Byte)
    
    
    Do
      Call Pierwsza_procedura
    Loop
    
    End
    
    
    Sub Pierwsza_procedura
     Local X As Byte
     X = 99
     Print "przed    " ; X
     Call Druga_procedura(x)
     Print "po       " ; X
    End Sub
    
    Sub Druga_procedura(x As Byte)
     Print "po wej.  " ; X
     X = 100
     Print "wewnatrz " ; X
    End Sub


    Zauważ, że nie ma ByVal zatem przekazany jest tylko adres.
  • #17 5829114
    wader_669
    Poziom 28  
    ok to zrozumialem czyli bedzie byref domyslnie (nie moge znalezc bledy :P )
    A co z tymi dwoma pierwszymi kodami? bo to w sumie mnie bardziej interesuje.

    chodzi mi ogolnie o to dlaczego sie robi w ten sposob:

    
    dim x as byte
    
    do
    x = 0
    call cos (X)
    loop
    end
    
    sub cos (byref y as byte)
    y=100
    end sub
    


    a nie w ten?

    
    dim x as byte
    
    do
    x = 0
    call cos
    loop
    end
    
    sub cos
    x=100
    end sub
    


    dziala tak samo i nie lokuje zadnej zmiennej na stosie
  • #18 5830304
    ZbeeGin
    Poziom 39  
    wader_669 napisał:
    chodzi mi ogolnie o to dlaczego sie robi w ten sposob:

    
    dim x as byte
    
    do
    x = 0
    call cos (X)
    loop
    end
    
    sub cos (byref y as byte)
    y=100
    end sub
    

    a nie w ten?
    
    dim x as byte
    
    do
    x = 0
    call cos
    loop
    end
    
    sub cos
    x=100
    end sub
    


    Generalnie nie powinno się zmieniać wartości parametrów w procedurach. Chyba, że tego wyraźnie chcesz i teraz w zależności od tego czy zmiana ma wyjść na zewnątrz czy nie; stosuje się odpowiednie przedrostki: ByRef(albo brak) lub ByVal.

    Skoro procedura ma przetwarzać dane to niech przetwarza je jawnie, zatem poprzez przekazanie jej parametrów. Przy bardzo skomplikowanych programach, modyfikowanie niejawne zmiennych globalnych (definiowanych przez DIM) w procedurach i funkcjach zemści się podczas symulacji i wyszukiwaniu błędów.
  • #19 5846100
    wader_669
    Poziom 28  
    jeszcze mam jedno pytanie ktory z tych kodow lepiej wykonac?

    
    do
    locate 1,1
    lcd "x"
    locate 1,2
    lcd"x"
    .....
    .....
    ....
    locate 1,4
    lcd "x"
    loop
    end
    


    czy ten?

    
    dim X as byte
    
    for x=1 to 4
    locate 1, x
    lcd "X"
    next
    end
    


    oczywiscie mam troche bardziej skomplikowana wersje do wykonania.

    Tak jeszcze na marginesie chcialem wam jeszcze wszystkim podziekowac za pomoc, bardzo mi pomogliscie.
  • #20 5849684
    K_o_n_r_a_d
    Poziom 23  
    wader_669 napisał:
    jeszcze mam jedno pytanie ktory z tych kodow lepiej wykonac?
    ...

    1. Nie da się odpowiedzieć, ponieważ te kody wykonują różne zadania. W pierwszysm przypadku będziesz miał "X" na pozycji tej którą wskażesz poleceniem LOCATE a w drugim wypełniasz całą pamięć LCD znakami "X"
    2. Co to znaczy "lepiej"? Szybciej, mniejsza objętość kodu, czytelniej? Szybciej wykona się kod pierwszy a pozostałe "lepiej" sam sprawdź :)
  • #21 5849723
    wader_669
    Poziom 28  
    to ze tam roznica jest to wiem (juz zmienilem kod).
    Szybciej i mniejsza objetosc kodu. Dzisiaj sprawdze jak to wyglada z objetoscia.

    bo pozniej mam ze pobiera jakies znaki ze stringa za pomoca mid, ustawia kursor i wyswietla chcialem to walnac w petle for ale bedzie duzo obliczen i zastanawialem sie czy jak recznie wklepie nie bedzie latwiej.
  • #22 7420399
    wojlej
    Poziom 17  
    Witam.

    Mam pytanie techniczne na które nie znalazłem odpowiedzi.

    Piszę program w Bascom. W programie występuje podprogram "Program1". Problem polega na tym, że ten program musi zostać użyty w różnych miejscach programu. I moje pytanie, dokąd wróci podprogram po komendzie return? Czyu do miejsca z którego został wywołany czy gdzieś indziej?
    
    Do
    Instrukcje....
    
    Gosub Podprogram1
    
    Instrukcje2.......
    
    Instrukcje3.......
    
    Gosub Podprogram1
    
    Instrukcje4.......
    
    Gosub podprogram
    
    Instrukcje5.......
    
    Loop
    
    Podprogram1
    blebleble....
    Return


    Chodzi o to czy w momencie wykonania podprogramu Podprogram1 po instrukcji 4 program powróci z powrotem do tego miejsca czy powróci np do miejsca z instrukcją 2

    Pozdrawiam i z góry dzięki
  • #23 7420869
    xury
    Specjalista automatyka domowa
    Powróci tam skąd został wywołany. Taka właśnie jest jest istota podprogramu. I używa się tego wyłącznie w przypadku wielokrotnego używania tego samego fragmentu kodu. W innym wypadku nie ma w ogóle sensu. Używanie podprogramów w pętli głównej (umieszczonych przed instrukcją END), jest niedozwolone z punktu widzenia jakości kodu, ale możliwe.
    Wielu początkujących pisze też taki oto kod:
    
    Instrukcje1
    ....
    Gosub  etykieta1
    Etykieta1:
    Instrukcje2
    

    Jakby program nie "wiedział", gdzie ma iść dalej :)
REKLAMA