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.

Deklarowanie tablicy dynamicznejw C++

alexiel 23 Jan 2004 07:49 10925 27
  • #1
    alexiel
    Level 15  
    Witam .
    Chodzi mi jak zadeklarować tablicę w której nie wiem ile będzie elementów. Podobno jest to tablica dynamiczna.
  • #2
    Gavian
    Level 14  
    O ile i wiadomo do rezerwowania pamięci w C++ uzywa sie funkcji new
    Code:
    char *pointer;
    
    pointer=new char[10];  //deklaruje 10 zmiennych typu char
    pointer[0]=10;
    pointer[5]=11;
    delete []pointer;          //zwalnia zadeklarowana pamięc
    Wielkim błedem jest zwalnianie nie zadeklarowanej pamięci. Deklarowanie tablic wielowymiarowych było juz gdzieś opisane. Poszukaj.

    Pozdrawiam.
  • #3
    h-doc
    Level 27  
    z kolei w ANSI służyła do tego funkcja malloc
  • #4
    tmpat
    Level 14  
    Sorrki, że się wtrące, C++ miałęm jedynie na 1 sem i raczej programuje w Delphim ale o ile mi wiadomo to C++ nie ma możliwości zadeklarowania wprost tablicy dynamicznej, kompilator musi mieć ścisle powiedziane jaki będzedzie długi ciąg elementów, zresztą do tego służy funkcja malloc() w C (jak wspomniał jeden z kolegów) lub new() w C++. Ale żeby zrobić faktycznie tablice "bez ograniczeń" to trzeba sie już raczej zabawić w listy.

    Jeżeli sie myle poprawcie.

    POZDRAWIAM:multi:
    patryk
  • #5
    elektryk
    Level 42  
    tmpat wrote:
    o ile mi wiadomo to C++ nie ma możliwości zadeklarowania wprost tablicy dynamicznej
    Dokładnie tak jest, ale wystarczy prosty trick, trzeba zadeklarować wskaźnik do tablicy i zaalokować mu pamięć. O reszte się martwi już system operacyjny, albo przydzieli pamięć albo nie.
  • #6
    tmpat
    Level 14  
    No tak ale co z ograniczeniami, pamiętam że można zarezerwować tylko ogranicznon obszar pamięci, to było chyba związane z stronnicowaniem. A takiego problemy nie ma już z listami :)

    POZDRAWIAM :multi:
    patryk
  • #7
    Nemo
    Level 31  
    :arrow: elektryk: Napisz proszę coś więcej, jak to zrobić. Ostatnio bawiłem się z pewnym programem w C++ i nie udało mi się zrobić tablicy większej niż 38kB (taka tablica stałych, wpisywanych na etapie pisania programu). Nie pomogło nawet przeniesienie stałych do obszaru kodu - kompilator nie ma ochoty tego zrobić. W przypadku wskaźnika i operatora new największy rozmiar to 0xFFFF (czyli 65535B) i guzik. A jak zrobić np. tablicę 1MB? Pomijam tworzenie 20 tablic po 64kB.
    Pozdrawiam.
  • #8
    h-doc
    Level 27  
    hmmm....
    ja przy pomocy funkcji malloc() robiłem tablice 2MB (512x512x8 bajtów) pod VC++ i nie było żadnych problemów.
  • #9
    elektryk
    Level 42  
    Nemo wrote:
    nie udało mi się zrobić tablicy większej niż 38kB (taka tablica stałych, wpisywanych na etapie pisania programu)
    Hmm, to pewnie problem kompilatora, a wątek jest o tablicach dynamicznych.
  • #10
    Nemo
    Level 31  
    Druga część mojej wypowiedzi jest właśnie o dynamicznych. Wprowadziłem i statyczne bo liczyłem, że może ktoś mi pomoże i tutaj.
    :arrow: h-doc: Jak robiłeś taką deklarację? Może przykładzik...
    Pozdrawiam.
  • #11
    visitors
    Level 12  
    //DEKLARACJA
    char **BIG;
    int j;

    //ALLOKACJA

    BIG = new char*[512];
    for (j=0; j<512; j++)
    BIG[j] = new char [512];

    //I KASOWANIE

    for (j = 0; j < 512; j++)
    delete[] BIG[j];
    delete[] BIG;
  • #12
    Nemo
    Level 31  
    He, mnie chodziło o 1 dużą tablicę, a nie setkę małych. Tyle to i ja wiem :) Liczyłem na wypowiedź h-doc w tym temacie z alokacją.
    Pozdrawiam.
  • #13
    h-doc
    Level 27  
    no, znalazłem:



    #define DOUBLE double

    typedef DOUBLE BITMAP_64[512][512];

    BITMAP_64* picture;

    picture = (BITMAP_64*)malloc(sizeof(BITMAP_64));

    if (picture==NULL) {
    MessageBox( hWnd,
    ErrorMessages[app_params.language][ERROR_MEMORY_ALLOCATION],
    ErrorMessages[app_params.language][ERROR_TITLE],
    MB_OK|MB_ICONWARNING);
    return E_FAIL;
    }



    zwróć uwagę, że należy sprawdzić, czy system przydzielił programowi pamięć. Jeśli nie - to program należy zatrzymać.

    Zwalnianie pamięci w ANSI odbywa się również poprzez wywołanie funkcji - free(pointer)

    pozdrawiam!
  • #14
    visitors
    Level 12  
    Chyba jest wyraźnie napisane 512x512x8
    To jak chcesz odwołać się do takiej tablicy z pomocą jednego wskaźnika?
    Jak chcesz jednowymiarową, to deklarujesz *char i wszystko. Jak chcesz tablice naprawdę dużą to wpisz tam ile ci się podoba jeżeli ci tylko kompilator pozwoli. A jaki masz kompilator, jaki system, ile pamięci. I zadaj sobie pytanie czy taka tablica ci jest potrzebna. Moja największa tablica miała wymiar 3000x100x3.
  • #15
    visitors
    Level 12  
    Na moje zezowate oko to picture jest wskaźnikiem na tablicę dwuwymiarową. A więc po co ta cała afera. Tak na marginesie to każdą taką tablicę można traktować jako jednowymiarową. Ważne tutaj jest tylko przesunięcie [i][j]...[ik] od początkowego wskażnika.
  • #16
    elektryk
    Level 42  
    Nemo wrote:
    Liczyłem na wypowiedź h-doc w tym temacie z alokacją.
    To wszystko zależy w jakim trybie działa procek, jesli z rzeczywistym to jest ograniczenie do tablic 64kB i tylko sztuczkami matematycznymi i alokacją wielokrotną da się to obejść. A jeśli chodzi o systemy 32bit takie jaki linux czy windows (chyba od 98 w góre). To można chyba zaalokować do 4GB pamięci (w linuxie 3GB, bo reszta jest dla jądra, żeby nie trzeba było przełączać segmentów przy dostępie do jądra). To wszystko to jest dopiero potem mapowane na pamięc fizyczną przez system operacyjny, ale z punktu widzenia programy te 4GB to jest ciągły obszar pamięci i tam można deklarować tablice.
  • #17
    alexiel
    Level 15  
    Dziekuje wszystkim za wypowiedzi. Może skorzystam z operatora new.
    Pozdrawiam
  • #18
    Nemo
    Level 31  
    Ja również bardzo dziękuję, szczególnie h-doc.

    Kompilator to Borland C++ 4.52 (stary jak świat). Program pisany jest pod Win16, nie sprawdzałem go pod Win32, bo są wstawki asemblerowe i kompilator nie chce ich przełożyć na ten system. Cóż, bywa.
    Nie mam wpływu na tryb pracy procesora, albo prędzej nie wiem, jak to zrobić. Może ktoś mi podpowie?
    Jeśli chodzi o rozmiar tablicy, to czasami jest potrzeba zrobić jedną dużą, niż kilka małych. Rozczłonkowanie wymagałoby pisania dłuższych procedur obsługi i w efekcie spowolniłoby program. Przy milionach odwołań do tablicy, jest to istotne.
    Pozdrawiam.
  • #19
    elektryk
    Level 42  
    Nemo wrote:
    Kompilator to Borland C++ 4.52 (stary jak świat).
    No to już ustaliliśmy kompilator, teraz do wyjaśnienie by się przydał jeszcze ten wątpliwy kod który stwarza problemy.
  • #20
    h-doc
    Level 27  
    Nemo - tutaj już Ci chyba nie pomogę - pracuję tylko pod MS Visual C++ i dziobię aplikacje pod Win32. Zaproponuję Ci jeszcze pokombinować ze wstawkami asemblerowymi - pod VC++ wstawki w asm chodzą, chociaż jak na razie próbowałem pisać tylko krótkie podprogramy (kilkanaście linijek). Może uda Ci się przenieść te procedury na VC++ ?
  • #21
    Kriti
    Level 15  
    Rozwiązuje za pomocą C++ zagadnienia polowe z elektrotechniki metodą elementów skończonych czy różnic skońćzonych i potrzebuje wówczas tworzyć macierz współczynników wielkości powiedzmy 2000x2000xdouble(8 bajtó) i nie ma problemu ale robie aplikacje konslowa pod windows, kwestia jest tylko taka ze jak przekrocze rozmiar dostepnej fizycznie ramu to zaczyna sie jazda po pliku wymiany i to trwa. Znajomy przeprowadzil pozytywnie oblicznia z tablica 11000x11000xdouble.
  • #22
    Nemo
    Level 31  
    Piszę z pamięci, może być gdzieś błąd:

    char dane = {"hgtsdgshd... itd. lub szesnastkowo 64kB danych, albo więcej"};

    To tylko deklaracja. Reszta programu nie stwarza problemu.
    Czegoś takiego kompilator nie deklaruje. Wywala błąd i koniec. Próba deklaracji dwóch osobnych tablic kończy się tym samym - przekroczenie rozmiaru segmentu danych. Być może jest to wina aplikacji Win16. Jak będę miał czas, potestuję na Win32 i dam znać.
    Pozostaje chyba przesunięcie tablicy do pliku, ale to dodatkowa strata czasu.
    Pozdrawiam.
  • #23
    h-doc
    Level 27  
    Mi takiego czegoś kompilator też nie łyka. Wywala błąd:
    error C2026: string too big, trailing characters truncated
    Spróbuj zrobić coś innego - przekształć sobie jakimś programikiem ten strumień danych z postaci:
    abcde
    na:
    'a', 'b', 'c', 'd', 'e'
    Weź to potem w klamry i zadeklaruj jako tablicę - może zadziała.
  • #24
    visitors
    Level 12  
    W powyższym przykładzie trzeba zastosować typ *char zamiast char. Wtedy kompilator traktuje to jako ciąg znaków w pamięci("string" popularny). Modyfikowanie takiego stringa poprzez dane[] jest jaknajbardziej możliwe. Programiści traktują takią modyfikację jako błąd, gdyż rozmiar takiej tablicy z punktu widzenia programu jest nieznany i odwołanie może prowadzić do buffer overflow (co wystąpić może również w normalnej tablicy). Niektórzy programiści traktują *char jako stałą. :D
  • #25
    Nemo
    Level 31  
    :arrow: h-doc: Taki string to nie problem. U mnie ma on ponad 2000 linii jedna pod drugą. String taki generuje np. program Hexplorer. Z tym nie ma problemu.

    Jeśli chodzi o drugi post, to muszę sprawdzić, jak jest w rzeczywistości. Obawiam się, że u mnie jest właśnie wskaźnik do tablicy i nie da się tak deklarować. Upewnię się jeszcze. Jeśli coś z tego wyjdzie, dam znać.
    Dzięki za sugestie.
    Pozdrawiam.
  • #26
    krzychoo_soft
    Level 17  
    zawsze można traktować plik jako tablicę ;)
    i uzyskujemy praktyczne niewyobrażalną przestrzeń...
    taką na ile starczy miejsca na dysku ;)
    100MB = 10x10 milionów dla char, czyli:
    char tablica [10000000][10000000];
    a co dopiero 1GB :twisted:
    ale po co to potrzebne?
  • #27
    Nemo
    Level 31  
    Wszystko pięknie, ale gdy potrzeba zrobić wielokrotne przeliczenia takiej tablicy, to znacznie szybciej będzie ona chodzić z pamięci, niż z dysku. Chyba, że tablica jest naprawdę olbrzymia, wtedy już raczej nie ma wyboru.
    Pozdrawiam.
  • #28
    markus_katowice
    Level 13  
    Mam następujący problem:
    może ktoś pomoże?
    Sorki że tyle tego, ale można sobie to skopiować i skompilować. Problem pojawia się przy kończeniu aplikacji, po kasowaniu tablicy, jak i czasem przy podawaniu dziwnych rozmiarów tablicy - np. dla tablic kwadratowych nie ma problemu (2,2 ; 4,4 ; 5,5). Problem pojawia sie przy tablicach prostokątnych ( 2,3 ; 4,6) albo po modyfikacji programu odwrotnie, czyli (3,2 ; 6,4). Powiem szczerze że nie mam dziś głowy do myślenia, a walcze z tym już od 2 dni.

    Aha, taka ciekawostka- zastosowałem funkcje RANDOM do ustawiania tablicy. Odpal program i porób screeny i porównaj dane. Dane się nie zmieniają. Zmiejszenie tablicy powoduje "obcięcie" poprzednich wylosowanych liczb. wynika to z adresowania? czy jak?

    Potrzebuje coś dynamicznego do zastosowania do gry w życie.

    P.S. w funkcjach erase(x,y) i create(x,y) zmieniałem z "x" na "x-1" itp. Tak do prób. Chciałem to dokładnie zbadać. Także kompilator może się w tym miejscu wysypać.


    Code:
    //---------------------------------------------------------------------------
    

    #include <vcl.h>
    #pragma hdrstop
    #include <iostream.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>

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

    #pragma argsused
    int **tablica;

    void create(int x, int y);
    void erase(int x,int y);
    void showing(int x, int y);
    void input(int x, int y);

    void main()
    {
    int x,y,x1,y1;
    cout<<"TABLICA DYNAMICZNA\n\n\n\n";

    cout<<"Podaj rozmiar tablicy [x,y]\nX:";
    cin>>x;
    cout<<"Y:";
    cin>>y;
    create(x,y);
    cout<<"\nPRESS ANY KEY\n\nTable is created\n";
    getch();

    showing(x,y);
    getch();

    cout<<"\nUstawianie pamięci\n";
    getch();

    input(x,y);
    showing(x,y);

    getch();
    cout<<"\nPodaj wspolrzedne elementu ktory chcialbys zobaczyc\n";
    cout<<"X:";
    cin>>x1;
    cout<<"Y:";
    cin>>y1;
    cout<<"Element tej tablicy to: "<<tablica[x1-1][y1-1];
    cout<<"\n\nA teraz kasowanie pamieci\n";
    getch();


    erase(x,y);
    cout<<"Kasowanie\n";
    getch();
    cout<<"PRESS ANY KEY\n\nTable is deleted";

    }

    void create(int x, int y)
    {
    tablica = new int *[y-1];
    for (int i=0; i<x;i++)
        tablica[i]= new int [x-1];

    }

    void erase(int x,int y)
    {

    //tablica = new int *[y-1];
    for (int i=0; i<x;i++)
                 delete [] tablica[i];
     delete [] tablica;
     //free(tablica);
    }

    void showing(int x, int y)
    {
    for (int i=0;i<y;i++)
            {
            cout<<"\n"<<i<<". ";
            for (int k=0;k<x;k++)
            cout<<tablica[k][i]<<" ";
            }

    }

    void input (int x, int y)
    {
    for (int i=0;i<y;i++)
            for (int k=0;k<x;k++)
            {
            tablica[k][i]=random(5);
            }


    }