Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[AtMega32][C] Wskaźniki, alokacja pamięci

m3 23 Jun 2010 15:51 1758 7
  • #1
    m3
    Level 11  
    witam,

    Mam mały problem do rozwiązania. Z wejścia czytam dowolnie dużą ilość łańcuchów znaków, każdy dowolnie długi. Może się zdarzyć że np. będą 2 łańcuchy nie dłuższe niż 10 znaków, a może się zdażyć że będzie np. 20 łancuchów po 20 znaków (hipotetycznie). Myślałem żeby rozwiązać to na wskaźnikach i dynamicznej alokacji pamięci, np. tak jak poniżej. Co myślicie o tym pomysle? Jeśli idę w dobrą stronę, to czy kod jest ok?



    Code:

    #include <iostream>
    #include <stdlib.h>

    int main()
    {
     int iloscLancuchow;
     // wiem że będzie np. 10 lanuchow, bo kazdy byl oddzielony spacja i
     // w petli to sprawdzilem
     // przydalaby sie wiec tabela[10][x], x bo nie wiadomo ile ma najdl. lancuch
     iloscLancuchow = 10;
     char **lancuch;
     lancuch = (char **) malloc(iloscLancuchow* sizeof(**lancuch));
     // mam zadeklarowane miejsce w pamieci
     // wiec tutaj wrzucam dane do zmiennej lancuch
    }


    program kompiluje się, ale nie wiem czy w dobrą stronę idę.
  • #2
    szelus
    Level 34  
    iosteam na Atmega32?

    Nie do końca chyba rozumiem: jak przeczytałeś je i nigdzie jeszcze nie wrzuciłeś, to raczej już ich nie masz? A jak wrzuciłeś, to ciągle jeszcze potrzebujesz nowej pamięci dla nich?

    Prawidłowo, to chyba musisz mieć jeden bufor na najdłuższy łańcuch, a potem alokować dynamicznie miejsce na ten łańcuch i kopiować.
    Chyba, że chcesz tylko podzielić dane wejściowe na podłańcuchy, to wystarczy Ci tablica wskaźników.
    Quote:

    Code:

    lancuch = (char **) malloc(iloscLancuchow* sizeof(**lancuch));


    Chyba sizeof(*lancuch), jeżeli już. Masz zaalokowaną tablicę wskaźników - a gdzie miejsce na łańcuchy?

    A w ogóle, to mega32 nie ma za dużo pamięci...
  • #3
    flapo213
    Level 21  
    iostream to dla C++.

    Jeśli wykorzystałbyś C++ to możesz użyć vector-ów ułatwi sprawę. Wektory to zaawansowane tablice które mają zdolność do powiększania się automatycznie. Pozdraiwam
  • #4
    m3
    Level 11  
    No z tym iostream to rzeczywiście przesadziłem, to chyba z rozpędu. ;)

    załóżmy że mam
    char p[] = "jakis dlugi tekst";
    i to będę rozbijać, poszczególne wyrazy będą znajdować się w różnych komórkach. A że nie znam dokładnie długości każdego wyrazu i ich ilości to wolałem zaalokować pamięć dynamicznie. No chyba że widzicie jakieś inne, lepsze rozwiązanie mojego problemu?

    szelus wrote:
    iosteam na Atmega32?
    Masz zaalokowaną tablicę wskaźników - a gdzie miejsce na łańcuchy?

    Znaczy jak miejsce na łańcuchy?
  • #5
    szelus
    Level 34  
    Tak jak napisałem, jeżeli tylko rozbijasz tekst w buforze na np. wyrazy, to prawdopodobnie sama tablica wskaźników Ci wystarczy. Ale to jednoznacznie z Twojej pierwszej wypowiedzi nie wynikało.
    Jeżeli wczytujesz ciąg znaków z wejścia, to najpierw musisz zaalokować bufor (tablicę), gdzie ten ciąg wczytasz. Teraz możesz albo przydzielić b. dużą tablicę, wczytać wszystko i następnie podzielić, albo odwrotnie, czytać do małej tablicy wyraz po wyrazie, następnie przydzielać dynamicznie miejsce (a nie tylko wskaźnik) na kolejny wyraz i kopiować. To tak teoretycznie, bo przy ilości pamięci RAM dostępnej na atmega32, zabawa w dynamiczne alokowanie trochę nie ma sensu.
    Wszystko zależy od konkretnego zastosowania.
  • #6
    tmf
    Moderator of Microcontroller designs
    flapo213 wrote:
    iostream to dla C++.

    Jeśli wykorzystałbyś C++ to możesz użyć vector-ów ułatwi sprawę. Wektory to zaawansowane tablice które mają zdolność do powiększania się automatycznie. Pozdraiwam


    A widzałeś je przeportowane na AVR?
    Druga rzecz, to bezsens ich stosowania w systemach z ograniczona ilością pamięci. W większości wypadków poszerzenie takiej tablicy wymaga zaalokowania nowej pamięci i skopiowania pierwotnej tablicy. Jest to nie tylko wolne, ale i wymaga 2xtyle pamięci co największa tablica. AVR to nie systemy ze stronami i pamięcią wirtualną, gdzie zaawansowany alokator mógłby się wykazać.
    Także pytającemu pozostaje określić maksymalną długość stringu i prealokować pamięć. Rozwiązanie najprostsze, najszybsze i najbezpieczniejsze.
  • #7
    m3
    Level 11  
    Trochę się śpieszyłem z napisaniem o co mi chodziło i wydawało mi się że wszystko co istotne napisałem.

    Chodzi o to że z komputera dostaje jakiś łańcuch danych.
    Wiadomo że znak po znaku ląduje to do UDRa. A z UDRa czytam to do jakiegoś chara, np.

    char odczyt;
    odczyt = UDR;

    nie będę pisał tych wszystkich pętli, warunków odczytu itd. bo wiadomo jak to wygląda.

    I teraz chodzi o to, że te wszystkie znaki ze zmiennej odczyt trzeba gdzieś wrzucić. Trzeba z tego znowu posklejać napis. Mógłbym np. zrobić
    char odczyt[20];
    ale nie wiem czy nie przekroczę zakresu. Ciąg może być długi.

    Zastanawiałem się jakby to zrobić. Można niby alokować pamięć, ale znowu nie wiem ile komórek będzie miał ten ciąg znaków. Proszę o pomoc.
    Jak to zrobić w miarę optymalnie?
  • #8
    tmf
    Moderator of Microcontroller designs
    Możesz dynamicznie używając malloc, zakładając, że po utworzeniu bufora żadna inna zmienna nie będzie alkowana przy pomocy malloc i że na stercie jest wystarczająco miejsca, to długość bufora można zmieniać za pomocą realloc.