Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 29 mar 2024, o 08:51


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 10 ] 
Autor Wiadomość
PostNapisane: 8 cze 2020, o 21:17 
Offline
Użytkownik

Dołączył(a): 07 lut 2015
Posty: 156
Pomógł: 2

Zawsze myślałem, ze stała dosłowna np. string zapisany w programie jako "wyraz1 wyraz2 wyraz3" (czyli w cudzysłowiach), to stała typu const, tylko zapisana gdzieś w pamięci pod adresem, którego programista nie zna, a zna jedynie kompilator.

Jakiesz było moje zdziwienie, kiedy ten string "rozbiłem" przy pomocy funkcji strtok. Okazało się, ze "const" string nie nadawał się do ponownej analizy, bo został z niego "wyraz1".

Myślę, że się nie mylę, co państwo na to?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2020, o 21:39 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Troszkę namieszałeś a w zasadzie to nie pokazałeś w kodzie co próbowałeś zrobić i teraz trzeba się domyślać - żeby coś podpowiedzieć. Pokaż zatem co tam napłodziłeś w kodzie jak zadajesz takie pytanie ;) ... Na razie nie do końca może rozumiesz co to jest literał (stała dosłowna w postaci tekstu) i jak jest ona w zależności od kodu przechowywana w pamięci czy to RAM czy FLASH. Dużo zależy od zapisu właśnie w kodzie.

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 8 cze 2020, o 21:46 
Offline
Użytkownik

Dołączył(a): 07 lut 2015
Posty: 156
Pomógł: 2

Już ten cały mój kod usunąłem, ale spróbuję go jutro odtworzyć ( bo zdziwiony byłem ogromnie). Co być może zdziwi też jakiegoś "starego" forumowicza?

------------------------ [ Dodano po: 2 minutach ]

P.S. Zapisywana była w RAM-ie.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 cze 2020, o 07:41 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 29 lis 2019
Posty: 147
Pomógł: 37

Więcej lektury standardu języka a będzie mniej takich zdziwień.
Literał tekstowy co do zasady jest niezmienny ale pozostawiono swobodę w sposobie implementacji. A więc ten ten sam program na różnych kompilatorach i platformach może dać inne wyniki.

_________________
Think for yourself and question authority.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 cze 2020, o 08:47 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

fofex napisał(a):
A więc ten ten sam program na różnych kompilatorach i platformach może dać inne wyniki.

Właśnie dlatego mówiłem, żeby autor pokazał kod - bo wtedy można byłoby wyjaśnić o co chodzi z tą implementacją i co dokładnie oznacza literał.

------------------------ [ Dodano po: 1 minucie ]

fofex napisał(a):
Więcej lektury standardu języka a będzie mniej takich zdziwień.

ale z takimi stwierdzeniami to proszę spokojniej - bo nikt kto się dopiero uczy i zaczyna, nie zjadł od razu wszystkich języków świata i często uczy się na własnych błędach albo obserwacjach. A dopytać zawsze warto - po to jest m.in to forum ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 9 cze 2020, o 22:23 
Offline
Użytkownik

Dołączył(a): 07 lut 2015
Posty: 156
Pomógł: 2

Wrzucam fragment programu testowego.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Dodam, że chodziło mi o sprawdzenie jak się będzie przesuwał tekst na ekranie.
Wywołuje funkcję get_sms_test().
W tekście "wyraz1 wyraz2 wyraz3 wyraz4" szukam tokenów spacji i każdy wyraz wyświetlam w oddzielnej linii.
Enkoderem chcę tekst przesuwać w górę/dół.

Efekt mam taki:
Na ekranie mam każdy wyraz w oddzielnym wierszu, ok,
ale przekręcenie enkoderem powoduje, że zostaje na ekranie tylko wyraz1, który oczywiście mogę przesuwać.

Nie rozumiem tego, że przecież jak wchodzę do funkcji show_sms_test(..), to ponieważ jest tam wsk= strtok_mk( "wyraz1 wyraz2 wyraz3 wyraz4", " " ) ciągle ten cały tekst
i mimo, że ciągle go niszczę przez szukanie tokenów, to powinienem jednak dostawać wyraz1, wyraz2 itd.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2020, o 05:27 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Nef.ID napisał(a):
"wyraz1 wyraz2 wyraz3 wyraz4"

To jest Literał ;) ale przy takim zapisie jest on przez AVR GCC umieszczony w pamięci RAM, a tak naprawdę to i w pamięci FLASH (która jest tu zmarnowana) bo we flash jest tylko po to żeby przed startem main, został skopiowany do RAM w jednej z sekcji inicjalizacyjnych. A jak już jest w RAM to zachowuje się normalnie jak każda inna zmienna tablicowa tego typu i dlatego możesz na niej wykonywać operacje. W tym wypadku korzystasz z funkcjonalności C, gdzie zapis "xxxxx" jest literałem w RAM ale jednocześnie zapis ten zwraca wskaźnik do tej tablicy, dokładniej mówiąc do pierwszego elementu tej tablicy.

to jest mniej więcej dokładnie tak jakbyś napisał w zmiennych globalnych

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


a później w kodzie

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


tyle że tu masz jawną nazwę tablicy ;) a w twoim wypadku funkcja strtok dostaje ją niejawnie, czyli od razu adres do pierwszego elementu.

A skoro tak...

Nef.ID napisał(a):
Nie rozumiem tego, że przecież jak wchodzę do funkcji show_sms_test(..), to ponieważ jest tam wsk= strtok_mk( "wyraz1 wyraz2 wyraz3 wyraz4", " " ) ciągle ten cały tekst
i mimo, że ciągle go niszczę przez szukanie tokenów, to powinienem jednak dostawać wyraz1, wyraz2 itd.


a co ty niszczysz ? Być może nie do końca wiesz jak się posługiwać funkcją strtok()

normalnie gdybyś zrobił to z tablicą jak pokazałem wyżej to w pierwszym wywołaniu funkcji musiałbyś zapisać to tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


ale każde NASTĘPNE wywołanie trzeba robić TAK:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


żeby parsować kolejne wyrazy poprawnie - widzisz różnicę ?

Cytuj:
wsk= strtok( NULL, " " );


czyli musiałoby być tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Ty zaś za każdym razem ją wywołujesz tak:


Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


czyli tak jakbyś wciąż wywoływał ją tak:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


a w tym wypadku - wciąż będziesz miał wsk = na pierwszy wyraz tej tablicy. I to działa w pełni poprawnie ;) Pamiętaj, że strtok() nie NISZCZY stringa w tym sensie, że jakoś kasuje z niego dane. Jedyne co robi to wstawia ZERO w miejsce gdzie zobaczy pierwszy token. To dzięki temu jak zrobisz sobie później np

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


to wyświetli ci na terminalu tylko pierwszy wyraz - bo jest to tablica "wyraz1" zakończona zerem ;)

Dlatego do swojego ćwiczenia użyj jak się należy wcześniej zdefiniowanej tablicy np:

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


zamiast literału

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2020, o 08:52 
Offline
Użytkownik

Dołączył(a): 07 lut 2015
Posty: 156
Pomógł: 2

Mirek, dzięki za bardzo długie wyjaśnienie.

Faktycznie źle się wyraziłem mówiąc "niszczy", bo doskonale wiem, co robi funkcja strtok czy strtok_mk.

Dodam, że specjalnie TAK wywołuję ten tekst, (bo służył mi to testów- zdanie rozbijam na słowa, sprawdzam, czy mieszczą się we wierszu, jak nie to przenoszę wyraz do nowego wiersza itd. Coś nie dzieliło dobrze, więc musiałem powtarzać. Ale nie jest to tematem dzisiejszych rozważań.)

Najlepsze jest to, że jak zrobiłem jak piszesz, tj. ta definicja na początek pliku

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jest to samo tj. za pierwszym razem na ekranie cztery wiersze: wyraz1, wyraz2 itd., a po przekręceniu enkoderem tylko wyraz1.

To jest zrozumiałe.
Zdefiniowana tablica i zainicjowana tekstem. Później tę tablicę "szatkuję" tokenami i NULL-ami i gdy chcę ponownie ją rozbić to otrzymuję tylko wyraz1 i null.

Ale piszę jeszcze raz wyraźnie, nie o to mi chodziło, dlatego wziąłem stałą dosłowną czyli string w apostrofach, abym mógł go string-tokenować wielokrotnie.

Moje zdziwienie cały czas było i jest, że gdy:

funkcji strtok_mk podaję ciągle ten sam łańcuch dosłowny, a nie za drugim czy kolejnym "wyraz1NULLwyraz2NULLwyraz3NULLwyraz4".
Coś bez mojej zgody robi takie coś z moim łańcuchem?
Tak to rozumiem, chyba, że się gdzieś mylę?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2020, o 08:59 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27212
Lokalizacja: Szczecin
Pomógł: 1041

Nef.ID napisał(a):
Coś bez mojej zgody robi takie coś z moim łańcuchem?
Tak to rozumiem, chyba, że się gdzieś mylę?

No mylisz się albo nie zrozumiałeś - albo ja czegoś nie zrozumiałem....

jeszcze raz krótko, jeśli robisz wciąż tak

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


to nie dziw się, że wciąż pokazuje ci się tylko "wyraz1". Tak ma być i może spróbuj jeszcze raz się wczytać w to co napisałem. A pisałem, że stała dosłowna ląduje w RAM i pierwsze wywołanie strok() wstawia zero po "wyraz1" - więc czemu się dziwisz , że przy kolejnym wywołaniu masz to samo ? Uwaga, wstawiane jest tylko jedno zero

Cytuj:
"wyraz1[NULL]wyraz2 wyraz3 wyraz4"


a nie jak to napisałeś 4 razy, a ty wciąż podajesz wskaźnik na ten sam pierwszy element czyli pierwszą literę "wyraz1" rozumiesz ?

Skopiowanie całego stringa "wyraz1 wyraz2 wyraz3 wyraz4" do RAM jest robione TYLKO RAZ - zrozum, pisałem to wyżej. Jest to robione przed wywołaniem main() i wtedy jest kopiowane z Flash do RAM. Tylko raz i dlatego jak jeden raz chlaśniesz po tym za pomocą strtok, to to już tak zostanie na amen.


Autor postu otrzymał pochwałę

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 10 cze 2020, o 09:43 
Offline
Użytkownik

Dołączył(a): 07 lut 2015
Posty: 156
Pomógł: 2

Dzięki za wyjaśnienie.

Dopiero to do mnie doszło, że kopiowanie stringa do RAM z Flasha jest jest robione przed wywołaniem main() i tylko raz.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 10 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 7 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO