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

[Rozwiązano] [AVR][C] Tablice - kopiowanie całych tablic (przez wskaźnik?)

GanzConrad 19 Mar 2017 21:21 2418 20
REKLAMA
  • #1 16357435
    GanzConrad
    Poziom 25  
    Witam,
    Robię coś w rodzaju konsoli na lcd nokii (6 linii po 14 znaków) i nie wiem jak najsprawniej dodać jedną linię tekstu na dole ekranu, jednocześnie przenosząc wyżej poprzednie linie i tracąc pierwszą.
    stworzyłem zmienną przechowującą zawartość ekranu:

    unsigned char LCD_Content [6][15]; // tablica 2 wymiarowa z całą zawartością ekranu 6 wierszy x 14 znaków + null na końcu

    oraz funkcję, która ma dodawać dolną linię.
    Problem niby banalny, ale czy da się to zrobić bez kopiowania znak po znaku w pętli, tylko podmieniać miejscami całe tablice? Z tego co pamiętam wskaźnik do tablicy to tak naprawdę wskaźnik na jej pierwszy element, a ja chciałbym podmienić całą tablicę w miejsce innej. Dokładnie zamienić miejscami tablice jednowymiarowe wewnątrz zmiennej dwuwymiarowej, a następnie na miejscu 6 wstawić tablicę jednowymiarową.
    poniższy kod jest błędny, ale obrazuje o co mi chodzi.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    da się wskaźnikami, czy może jakieś memcopy?

    Dodano po 15 [minuty]:

    znalazłem coś takiego:
    http://www.nongnu.org/avr-libc/user-manual/gr...tring.html#ga5f60008005ea7557430149926cf583d7
    działa, chyba że ktoś ma lepszy pomysł

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • Pomocny post
    #2 16357515
    tmf
    VIP Zasłużony dla elektroda
    @GanzConrad Prościej nic nie kopiować, a tylko wprowadzić wskaźnik na pierwszą wyświetlaną linię i zadbać o jego zawijanie po dojściu do końca tablicy. W takim układzie przesunięcie o jeden wiersz to tylko zmiana tego wskaźnika.
  • REKLAMA
  • #3 16357572
    GanzConrad
    Poziom 25  
    @tmf zawartość wierszy nie ma być zawijana, jeśli będą dłuższe niż 14 znaków (szer LCD) to po prostu będą tracone.
    Całe to kombinowanie jest po to, aby w jednej zmiennej (tablica 2 wym) trzymać zawartość ekranu, przesunąć wszystko w górę (wierszami) i dodać do dolnej linii inną tablicę (1-wym) zawierającą komendy AT przychodzące z USART (będą różnej długości). Jak będą dłuższe od szer. lcd to będą skracane.
    Dlatego myślałem nad kopiowaniem całych wierszy poprzez wskaźnik do pierwszego elementu.
  • Pomocny post
    #4 16357740
    BlueDraco
    Specjalista - Mikrokontrolery
    Przeczytaj jeszcze raz odpowiedź TMF i ją zrozum. To naprawdę dobra rada.
  • #5 16358154
    GanzConrad
    Poziom 25  
    Czy chodzi o to, aby nową, przychodzącą linię tekstu wstawiać za każdym razem w inne miejsce tak aby zastępowała ostatnią znikającą, a wyświetlanie realizować podobnie, czyli za każdym razem od innego wiersza (na innej pozycji, np. od 3), a po dojściu do końca tablicy wyświetlić pominięte wiersze 1 i 2, które tym razem będą ostatnimi ?
    ekran to :
    unsigned char LCD_Content [6][15]
    - wyświetlam od góry, po kolei liniami 0-5, czyli linia 0 jest pierwszą od góry.
    - przychodzi nowa linia (powinna zastąpić ostatnią linię nr 5 w tablicy)
    - wstawiam ją na pozycję 0
    - wyświetlam ekran ponownie od góry, ale zaczynając od linii 1 (zamiast 0), a po dojściu do linii 5, wyświetlam 0
    nast krok:
    - przychodzi nowa linia
    - wstawiam ją na pozycję 1
    - wyświetlam od 2-5, a potem 0 i 1
    - itd...
  • Pomocny post
    #6 16358312
    BlueDraco
    Specjalista - Mikrokontrolery
    Zapewne o to chodzi. Czy Twój wyświetlacz naprawdę ma tylko 15 znaków w wierszu?
  • REKLAMA
  • #7 16358329
    GanzConrad
    Poziom 25  
    BlueDraco napisał:
    tylko 15 znaków

    dokładnie 14, null dodaję na końcu tablicy (miały być operacje na stringach, ale może się ogarnę bez tego)
    to LCD od nokii 3310 na pcd8544
    chciałem "na szybko" zrobić konsolę do usart, bo nie mam drugiego usart do wyświetlania tego co biega po pierwszym, a przesiadanie się na xmega nie ma sensu...
  • Pomocny post
    #8 16358352
    Sparrowhawk
    Poziom 22  
    @tmf: Moim zdaniem potrzebuje dwóch wskaźników. Jeden na wyświetlaną linię, a drugi na linię do modyfikacji. W sumie, to potrzeba jeszcze dwóch z informacją o pierwszym i ostatnim adresie, aby zawijać te wskaźniki.

    Mnie wyszło coś takiego:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #9 16358421
    BlueDraco
    Specjalista - Mikrokontrolery
    Nie rób zmiennych ze stałych - first i last są zbędne.

    Nie deklaruj tablic wewnątrz funkcji - spowalnia to wykonanie i grozi przepełnieniem stosu.
    Nie potrzebujest wskaźników na bufory 15- elementowe - przedeklaruj je jako wskaźniki na char.
  • Pomocny post
    #10 16358588
    Sparrowhawk
    Poziom 22  
    Jeśli chcesz korzystać z więcej niż jednej takiej struktury zmienne first i last jako zmienne są potrzebne. Fakt, że taki bufor z dużym prawdopodobieństwem będzie jeden sprawia, że mogą to być stałe.

    Tablicę zadeklarowałem w main, bo jest to kod testowy, napisany na PC, ale w µc faktycznie będzie to raczej zmienna statyczna o zasięgu plikowym.

    Co do trzeciej uwagi, to nie rozumiem. Przecież operujemy na tablicy tablic typu char, a nie na tablicy stałych literałów znakowych.
  • #12 16358816
    Sparrowhawk
    Poziom 22  
    Zapewne miał na myśli uproszczenie dokonywanych operacji. Zawsze to tylko zabawa z dwoma wskaźnikami, a nie kopiowanie tablic 2D.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    PS. Dlaczego, jak dam podgląd postu, to z kodu usuwane są wszystkie białe znaki?
  • Pomocny post
    #13 16358822
    tmf
    VIP Zasłużony dla elektroda
    Jest prościej, tylko @Sparrowhawk niepotrzebnie komplikuje. Skoro zawsze dopisujesz na końcu nowy element, a tablica ma określoną liczbę elementów to początek i koniec można zidentyfikować jednoznacznie przy pomocy jednego wskaźnika. Drugi powód dla którego jest prościej wynika z uniknięcia wielokrotnego kopiowania danych, co jest czasochłonne. Sama tablica może się składać ze wskaźników na twoje łańcuchy, a tylko funkcja odpowiedzialna za ich przesłanie na LCD będzie brała po prostu pierwszych 14 znaków.
  • Pomocny post
    #14 16358849
    Sparrowhawk
    Poziom 22  
    @tmf Masz rację, cały czas miałem to na końcu ..., ale mi to umykało ;-)

    Wersja z jednym wskaźnikiem:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #15 16398073
    GanzConrad
    Poziom 25  
    Ostatni miałem mało czasu na sen, więc przepraszam za zwłokę.
    Dzięki Panowie za pomoc, zwłaszcza @Sparrowhawk za podanie wszystkiego "na tacy" (potrzebne jedynie drobne modyfikacje).
    Nie do końca rozumiem zwiększanie i zmniejszanie wskaźnika do kolejnych linii:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Czy chodzi o to, że SB_2DCHAR_PTR jest zdefiniowany jako wskaźnik do całej tablicy 1-wymiarowej (cała linia) i samo działanie ++(A) "przesuwa" wskaźnik o wartość całej tablicy? (w tym wypadku będzie się przesuwać wewnątrz tablicy 2 wymiarowej: char text[NUMBER_OF_LINES][LINE_SIZE] )
  • Pomocny post
    #16 16398098
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #17 16398109
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #18 16398121
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #19 16398157
    GanzConrad
    Poziom 25  
    @Piotrus_999 strncpy kopiuje tylko konkretną liczbę znaków (nie więcej). Jeśli długość jest mniejsza to resztę wypełnia zerami (null):

    Cytat:

    The strncpy() function is similar to strcpy(), except that not more than n
    bytes of src are copied. Thus, if there is no null byte among the first n
    bytes of src, the result will not be null-terminated.

    In the case where the length of src is less than that of n, the remainder
    of dest will be padded with nulls.

  • #20 16398189
    Konto nie istnieje
    Konto nie istnieje  
REKLAMA