funkcja rekurencyjna zwracajaca tablice dynamiczna

0

Witam,

Probuje napisac program ktory rekurencyjnie wczyta dane, a nastepnie stworzy z nich tablice dynamiczna.
Tablice te bede wykorzystywal po zakonczeniu fukcji.

W chwili obecnej mam cos takiego:

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

using namespace std;

void podaj_liczbe(int &rozmiar, int &licznik, double*& wsk){
    double x;
    cout << "Podaj liczbe, 0 konczy wczytywanie" << endl;
    cin >> x;
    licznik++;
    if ( x == 0) {
    rozmiar = licznik;
    wsk = new double[rozmiar];
    }
    else{
    podaj_liczbe(rozmiar, licznik, wsk);
    }
    wsk[licznik]=x;
    licznik--;


}

void drukuj_tablice(int rozmiar, double wsk[]){
    cout << "\nDrukuje zawartosc tablicy: \n" << endl;
    for (int i = 1; i <= rozmiar; i++)
    cout << " Pozycja: " << i << " \tWartosc: " << wsk[i] << endl;

}

int main()
{
double *wsk;
int rozmiar = 0;
int licznik = 0;
podaj_liczbe (rozmiar, licznik, wsk);
drukuj_tablice(rozmiar, wsk);
} 

Czy poprawnie posluguje sie wskaznikami?
Program sie kompiluje i uruchamia poprawnie, jednak probuje zastosowac ten schemat w wiekszym programie ktory takze sie kompiluje, jednak zawiesza sie po uruchomieniu w Virtualboxie (XP) a dziala poprawnie we wlasciwym systemie (tez XP).
Nie wiem gdzie tkwi blad, chce wykluczyc bledy w skladni przepuszczane przez kompilator. (Codeblocks GCC)
Prosze o pomoc.

0
  • Słabo z formatowaniem
  • Masz memlaka
  • Użyj cstdlib zamiast stdlib.h
  • W ten sposób kasujesz sobie starą tablicę i musiał byś od nowa ją zapełniać. Użyj std::vestor o ile musi to być tablica bo w tym przypadku najlepsza była by lista.
0

formatowanie - tak, wiem
memlaka - czyli? ze nie usuwam tablicy na koniec? to wiem
Użyj cstdlib - ok
musi byc tablica dynamiczna, nie lista ani nic innego. "kasuje stara tablice"? - nie rozumiem ? tablica ma powstac tylko raz w calym programie.

0

Tablice w C++ indeksowane są od zera, nie od jedynki.

0
 double*& wsk

Dawno nie programowałem w C++, ale wydaje mi się, że ta referencja('&') jest zbędna .

0

@Sarrus nie jest zbędna bo potrzebujemy zmienić wartość na jaką wskazuje wskaźnik.
@hrupek zobacz jak to idzie: http://ideone.com/QAVVs widzisz, że są inne adresy? A dodatkowo new ustawia wartość wszystkich elementów na 0 czyli w tablicy masz same 0 i ostatni element jest równy podanej wartości.

0

@winerfresh

Nie do konca rozumiem twoj przyklad. Kompiluje mi sie to w Codeblocks, ale dlaczego mozesz ponownie definiowac tab bez bledu ?
Rozne adresy poniewaz jest 9 tablic dynamicznych wskazywanych przez tab, czy to wyciek pamieci i zajmowane jest kolejne miejsce bez kasowania?

Poza tym chcialbym wrocic do mojego przykladu. Zwroc uwage na tytul/poczatek watku, moze mylnie rozumiane jest wstawienie funkcji drukuj...
Potrzebuje wczytywac rekurencyjnie nieznana ilosc danych, po otrzymaniu zera utworzyc tablice dynamiczna i cofajac sie w rekursji tablice te zapelnic.
Na koniec chce by istniala poza funkcja wczytujaca.

Czy poprawnie posluguje sie tu wskaznikami (zakladajac ze na sam koniec skasuje tablice) ?
A moze kojarzycie jakis adres w sieci gdzie jest cos takiego opisane ? moze byc po EN, ja jakos nie moge nic znalezc :(

0

Chodzi o to, że jak chcesz mieć nową większą tablicę to musisz zrobić tak:

double* tmp = tab;
tab = new double[new_size];
memcpy(tab, tmp, oldsize*sizeof(double));
delete [] tmp;
0

ok, ale w moim przypadku tablica powstanie tylko raz.

Wiec nadal pozostaje aktualny problem z mojego poprzedniego postu.

0
winerfresh napisał(a)

@hrupek zobacz jak to idzie: http://ideone.com/QAVVs widzisz, że są inne adresy? A dodatkowo new ustawia wartość wszystkich elementów na 0 czyli w tablicy masz same 0 i ostatni element jest równy podanej wartości.

Tablica jest tworzona tylko raz, gdy x ma wartość 0, później program wraca i wykonuje kod za blokiem if..else

@hrupek bardzo niebezpieczny jest kod bo wychodzisz za tablicę. Indeksy tablicy w C++ są od 0 do rozmiar-1.
U Ciebie dla x = 0

    
    rozmiar = licznik;
    wsk = new double[rozmiar];
    wsk[licznik]=x;
    licznik--;
}

Zauważ, że

rozmiar = licznik

więc wsk[rozmiar] = x

 Piszesz za tablicą - raz program może działać, a innym razem nie. Zależy jakich jeszcze danych używasz. Powinieneś raczej używać <code class="cpp">wsk[licznik-1] = x

lub przenieść wyżej dekrementację licznika, a w funkcji drukowania tablicy for powinien wyglądać tak:

for (int i = 0; i < rozmiar; i++)

To chyba tyle
Pozdrawiam.

0

@Sarrus
Tak, oczywiscie masz racje, to jest duzy blad. Mialem do tego wrocic, ale nie zdawalem sobie sprawy, ze wychodze poza tablice.

0

Poprawienie zakresow w tablicach pomoglo choc nadal nie wiem czy do konca prawidlowo posluguje sie wskaznikami ... ;/

Pojawil sie nowy problem, w innym programie kasuje utworzona tablice dynamiczna i nadal moge jej uzywac, dlaczego ?

#include <iostream>
#include <cstdlib>

using namespace std;

void drukuj_tablice(int rozmiar, double tablica[]);
void zapelnij_tablice(int rozmiar, double tablica[]);
//****************************************************************************************
int main()
{

    int n = 10;
    double *wsk_ta = new double[n];
    cout << " \nOto zawartosc tablicy ta: " << endl;
    zapelnij_tablice (n,wsk_ta);

    drukuj_tablice (n,wsk_ta);
    delete [] wsk_ta;
    cout << " Wlasnie skasowalem tablice..." << endl;
    drukuj_tablice (n,wsk_ta);

    //system("PAUSE");
    return 0;
}


//****************************************************************************************
void drukuj_tablice(int rozmiar, double tablica[])
{
    cout << "\nDrukuje zawartosc tablicy: \n" << endl;
    for (int i = 0; i < rozmiar; i++)
    cout << " Pozycja: " << i+1 << " \tWartosc: " << tablica[i] << endl;
    cout << endl;
}
//****************************************************************************************
void zapelnij_tablice(int rozmiar, double tablica[])
{
    cout << "\nZapelniam tablice: " << endl;
        for (int i = 0; i < rozmiar; i++)
    {
        tablica[i] = 100/(i+1);
        cout << " Pozycja: " << i+1 << " \tWartosc: " << tablica[i] << endl;
    }
}
 

Wynik: http://ideone.com/2gn2a

0

Bo nikt jeszcze tego nie nadpisał, ale to nie oznacza, że nikt tego nie nadpisze.

0

Ok. Moze madre, moze nie, na pewno niebezpieczne...

0
hrupek napisał(a)

Ok. Moze madre, moze nie, na pewno niebezpieczne...

Na pewno niemądre i niebezpieczne. Zwalnianie pamięci przez delete nie blokuje danego obszaru pamięci, ani nie zeruje wskaźnika, a jedynie daje możliwość ponownego wykorzystania. Wczytywanie z tablicy zaraz po usunięciu JESZCZE działa, gdyż jej obszar nie został jeszcze zaalokowany w innym celu. Tak czy owak trzeba zapamiętać, że po delete dana zmienna/tablica/struktura/obiekt jest nie do wykorzystania. Dobrą praktyką jest zerowanie wskaźnika zaraz po usunięciu (delete).

Pozdrawiam.

0 użytkowników online, w tym zalogowanych: 0, gości: 0