wskaźnik a pętla(wywala bład)

Odpowiedz Nowy wątek
2015-01-05 18:53
0

Witajcie,
mam problem taki, że chce wypełnić tablicę losowymi wartościami, ale nie chce robić tego za pomocą tab[i] tylko za pomocą wskaźników. Zrobiłem to tak jak na dole i wpisywanie w funkcji main szwankuje. Pogrubiłem to co jest nie tak. Jak zaprintuje linijkę //tablica++; wpisuje się wartość zgodnie z oczekiwaniami, jak chce żeby przeskoczył do następnego adresu i tam wrzucił wartość to wywala błąd i podkreśla mi delete [] tablica; Ma ktoś jakiś pomysł co jest nie halo?

 #include <cmath>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
 
using namespace std;
 
void wypisz(float *tab, int ile)
{
    for ( int i = 0; i < ile; i++)
    {
        cout << *tab << endl;
        tab++;
    }
}
 
float srednia(float *tab, int ile)
{
    float suma = 0;
    for (int i = 0; i < ile; i++)
 
        suma+= *tab;
        tab++;
 
    return suma / ile;
}
 
int main()
{
    srand((unsigned)time(NULL));
    int ile;
    ile = 0;
    cerr << "Podaj z ilu liczb chcesz obliczyć średnią" << endl;
    cin >> ile;
 
    float *tablica;
    tablica = new float[ile];
 
    for (int i = 0; i < ile; i++)
    {
        *tablica = 1 + rand() % 6;
        tablica++; // tu nie przesuwa
    }
 
    wypisz(tablica, ile);
    cout << "srednia wynosi = " << srednia(tablica, ile) << endl;
   delete [] tablica; // tutaj wywala
 
    return 0;
}

Apple MacBook Pro 15" Retina, i7 2,2Ghz/256 GB SSD/Ram 16 GB
Kompilator: XCode, Visual Studio 2013 Ultimate
edytowany 1x, ostatnio: Berike, 2015-01-05 18:54

Pozostało 580 znaków

2015-01-05 18:56
0

Ech chłopie, myśl trochę. W chwili alokacji wskaźnik tablica wskazuje na POCZĄTEK zaalokowanego bloku. Każde wykonanie ++ na tym wskaźniku PRZESUWA go, co zrozumiałe, bo przecież próbujesz wpisywać dane do kolejnych elementów. Ale potem wesoło wywołujesz funkcje która oczukuje na argument będący znów POCZĄTKIEM tablicy, a przecież twój wskaźnik po tych wszystkich ++ wskazuje na KONIEC tablicy. delete[] także oczekuje adresu POCZĄTKU zaalokowanego bloku pamięci.


Na PW przyjmuje tylko (ciekawe!) zlecenia. Masz problem? Pisz na forum, nie do mnie.

Pozostało 580 znaków

2015-01-05 18:56
0
    for (float *i=tablica;i<tablica+ile;++i) *i=1+rand()%6;

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Pokaż pozostałe 3 komentarze
Wyjaśnienie masz jeden post wyżej. - _13th_Dragon 2015-01-05 19:08
od to zadam pewnie dla Was dość pytanie z trywialną odpowiedzią. To w takim razie jak mam ustawić po tych wszystkich ++, aby wskaźnik pokazywał znów na początek tablicy i żeby funkcja wypisująca zadziałała? - Berike 2015-01-05 19:12
Na to jest dwa sposoby: pierwszy pokazany w tym poście, drugi jest bezsensowny więc nie będę go nawet omawiać. - _13th_Dragon 2015-01-05 19:14
a czy jest jakaś szansa na wytłumaczenie dlaczego tak? - Berike 2015-01-05 19:17
Podejrzewam że na pytanie: - "Dlaczego tak?" - jest tylko jedna odpowiedź: - "Bo 42". Zadaj konkretne pytanie i nie w komentarzach. - _13th_Dragon 2015-01-05 19:20

Pozostało 580 znaków

2015-01-05 19:26
0
_13th_Dragon napisał(a):
for (float *i=tablica;i<tablica+ile;++i) *i=1+rand()%6;

czy mogę prosić o wytłumaczenie dlaczego pętla for i później podawanie kolejnych wartości wygląda w ten sposób? nie rozumiem dlaczego znalazł się

 *i = tablica

oraz i < tablica + ile


Apple MacBook Pro 15" Retina, i7 2,2Ghz/256 GB SSD/Ram 16 GB
Kompilator: XCode, Visual Studio 2013 Ultimate

Pozostało 580 znaków

2015-01-05 19:35
0

A czy w: for (int i = 0; i < ile; i++)
Rozumiesz dlaczego znalazł się: i = 0
oraz: i < ile
?


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Pozostało 580 znaków

2015-01-05 19:36
1

Ech. Idea którą zaproponował @_13th_Dragon jest prosta: tworzysz lokalną kopię wskaźnika i bawisz się już tylko nią, a oryginalny wskaźnik tablica pozostaje nieruszony.

Mam wrażenie że nie do końca rozumiesz co to jest wskaźnik. Wyjaśnijmy więc to: wskaźnik to jest po prostu adres w pamięci komputera gdzie cośtam się znajduje. Pamięć komputera ma ponumerowane komórki a wskaźnik przechowuje numer komórki, nic więcej.

Po twojej alokacji wskaźnik tablica może mieć wartość 0, gdyby akurat przypadkiem zaalokowało ci pamięć na samym początku puli adresowej (to nie jest możliwe, ale to tylko przykład!). Więc zaalokowałeś komórki od 0 do X. Jak sobie wypiszesz WARTOŚĆ wskaźnika to będzie ona wynosiła 0, a jak wypiszesz wartość wskazywaną *tablica to dostaniesz wartość pod zerowym numerem komórki pamięci komputera. Wywołanie ++ powoduje zwyczajnie zwiększenie wartości, więc gdyby tablica była wskaźnikiem na 1-bajtowe zmienne to ++ sprawiłoby że wartość przeskoczyłaby z 0 na 1.
Jak więc rozwiązać problem? Utworzyć drugą zmienną i wpisać do niej tą samą wartość którą ma tablica, czyli mamy drugą zmienną np. tablica2 która też ma wartość 0 i to na niej sobie pracujemy. Efekt jest taki, że tablica cały czas ma wartość 0, czyli pokazuje na początek bloku.


Na PW przyjmuje tylko (ciekawe!) zlecenia. Masz problem? Pisz na forum, nie do mnie.
edytowany 1x, ostatnio: Shalom, 2015-01-05 19:41
wielkie dzięki za wytłumaczenie! - Berike 2015-01-05 19:47

Pozostało 580 znaków

2015-01-05 19:40
0
_13th_Dragon napisał(a):

A czy w: for (int i = 0; i < ile; i++)
Rozumiesz dlaczego znalazł się: i = 0
oraz: i < ile
?

rozumiem


Apple MacBook Pro 15" Retina, i7 2,2Ghz/256 GB SSD/Ram 16 GB
Kompilator: XCode, Visual Studio 2013 Ultimate

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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