Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

odwracajaca kolejnosc el w tablicy, zwalnianie pamieci

Ostatnio zmodyfikowano 2017-05-19 11:23
Autor Wiadomość
Chowan
Temat założony przez niniejszego użytkownika
odwracajaca kolejnosc el w tablicy, zwalnianie pamieci
» 2017-05-18 21:51:24
zadanie z książki, wypełnianie tablicy (do wielkości tablicy lub podania nie liczbowej wartości), wypisanie, odwrócenie elementów i znów wypisanie.
Czy da się funkcje odwracającą łatwiej rozpisać, i czy to zwolnienie pamięci delete[]t; jest w dobrym miejscu. chciałem użyć zwykłej tablicy ale wyrzuca błąd "address of local variable 't' returned [-Wreturn-loccal-addr] czyli z tego co się domyślam, że po zakończeniu funkcji pamięć jest zwalniania?? i to wywołuje błąd bo nie ma do czego się odwołać funkcja void show()??

C/C++
#include <iostream>
const int rozm = 10;
int fill_array( double * tab, int n );
void show( const double * tab, int n );
double * odw( double * tab, int n );
int main()
{
    using namespace std;
    double tab[ rozm ];
    int a = fill_array( tab, 10 );
    show( tab, a );
    show( odw( tab, a ), a );
    return 0;
   
}
int fill_array( double * tab, int n ) // wypelnia tablice o rozmiarze n liczbami typu double, funkcja zwraca wskaznik na tablice
{
    double a;
    int ile;
    std::cout << "Podaj liczby, które zostana wpisane do tablicy" << std::endl;
    for( int i = 0; i < n; i++ )
    {
        if( std::cin >> a )
        { tab[ i ] = a;
            ile++;
            if( ile > n ) break; }
        else break;
       
    }
    return ile;
}
void show( const double * tab, int n ) //wypisuje tablice
{
    std::cout << "tablica zawiera liczby: ";
    for( int i = 0; i < n; i++ )
    {
        std::cout << tab[ i ] << ", ";
    }
    std::cout << std::endl;
}
double * odw( double * tab, int n ) //odwraca tablice
{
    int a = n;
    double * t = new double[ a ];
    for( int i = 0; i < n; i++, a-- )
    {
       
        t[ a - 1 ] = tab[ i ];
    }
    return t;
    delete[] t;
}
P-161268
karambaHZP
» 2017-05-18 22:06:21
C/C++
return t;
delete[] t;
Zwalnianie pamięci nigdy nie nastąpi, ponieważ wyjście z funkcji jest o linię wcześniej.
Zwalnianie powinno znajdować się w miejscu, do którego zwraca się wskaźnik na
alokowaną pamięć, gdy już można ją zwolnić.

Swoją droga, nie wiem czy dobrze zrozumiałem problem.
Chcesz zamienić kolejność elementów w tablicy? (1 2 3 na 3 2 1)?
Jeśli tak, nie ma potrzeby alokować nowej pamięci na tablicę.
Wystarczy zmienić miejscami elementy.

Jeszcze lepiej użyć gotowych narzędzi C++ tj. std::vector i std::reverse z <algorithm>.
P-161269
Chowan
Temat założony przez niniejszego użytkownika
» 2017-05-18 22:19:00
Dokładnie z 1 2 3 na 3 2 1. A jak to zamienić? Co do Vector i algorithm to nie było tego w książce do tej pory. vector był przedstawiony w sensie co to jest trochę. Co do zwalniania po użyciu to tak chciałem w funkcji main zrobić ale wyskakiwał błąd że to nie jest zadeklarowane in this scope.

C/C++
double * odw( double tab[], int n ) //odwraca tablice
{
    int a = n;
    double t[ a ];
    for( int i = 0; i < n; i++, a-- )
    {
        t[ a - 1 ] = tab[ i ];
    }
    for( int i = 0; i < n; i++, a-- )
    {
        tab[ i ] = t[ i ];
    }
    return tab;
}

tak się da, ale to mało elegancko wygląda.
P-161272
karambaHZP
» 2017-05-18 23:07:51
o do zwalniania po użyciu to tak chciałem w funkcji main zrobić ale wyskakiwał błąd że to nie jest zadeklarowane in this scope.
C/C++
#include <iostream>

int * create_array( std::size_t size )
{
    int * arr_ptr = new int[ size ];
    return arr_ptr; // zwrócenie wskaźnika na alokowaną pamięć
}

void fill_array( int * arr, std::size_t size )
{
    for( std::size_t i { 0 }; i < size; ++i ) {
        arr[ i ] = static_cast < int >( i );
    }
}

int main()
{
    std::size_t size;
    std::cin >> size;
    int * arr_ptr_in_main = create_array( size ); // tutaj wskaźnik odbiera adres, ale wskaźnik ma już inną nazwę
    // i to nią się już tutaj posługujemy (arr_ptr nie jest znany w tym scopie)
    fill_array( arr_ptr_in_main, size );
    // tutaj operacje
    delete[] arr_ptr_in_main; // zwalniamy pamięć, do której mamy dostęp poprzez nowy wskaźnik (z tego scopu).
}

https://dsp.krzaq.cc/post/176​/ucze-sie-cxx-kiedy-uzywac-new-​i-delete​/

Jeśli nadal jest potrzeba na
new
 i
delete
 to zerknij:
C/C++
#include <iostream>
#include <utility>

//void my_swap(int& lhs, int& rhs)
//{
// int tmp = lhs;
// lhs = rhs;
// rhs = tmp;
//}

void fill_array( int arr[], std::size_t size )
{
    // wypełniamy tablicę kolejnymi liczbami od 0 do (size - 1)
    for( std::size_t i { 0 }; i < size; ++i ) {
        arr[ i ] = static_cast < int >( i );
    }
}

void reverese_array( int arr[], std::size_t size )
{
    std::size_t first { 0 };
    std::size_t last { size - 1 };
    while( first < last ) {
        std::swap( arr[ first ], arr[ last ] ); // tutaj można napisać własną funkcję swap,
        // jeśli nie chcesz korzysać z bibliotecznej
        ++first;
        --last;
    }
}

void print_array( int arr[], std::size_t size )
{
    for( std::size_t i { 0 }; i < size; ++i ) {
        std::cout << arr[ i ] << ' ';
    }
    std::cout << std::endl;
}

int main()
{
    std::size_t size_arr;
    std::cin >> size_arr;
    int * arr_ptr = new int[ size_arr ];
    fill_array( arr_ptr, size_arr );
    print_array( arr_ptr, size_arr );
    reverese_array( arr_ptr, size_arr );
    print_array( arr_ptr, size_arr );
    delete[] arr_ptr;
}

edit: wersja uproszczona
C/C++
#include <iostream>
#include <algorithm>
#include <vector>

int main()
{
    std::size_t size;
    std::cin >> size;
    std::vector < int > v( size );
    int n { 0 };
    std::generate( v.begin(), v.end(),[ & ]() { return n++; } );
    std::for_each( v.cbegin(), v.cend(),[]( auto const & el ) { std::cout << el << ' '; } );
    std::cout << std::endl;
    std::reverse( v.begin(), v.end() );
    std::for_each( v.cbegin(), v.cend(),[]( auto const & el ) { std::cout << el << ' '; } );
}
P-161277
Chowan
Temat założony przez niniejszego użytkownika
» 2017-05-19 11:23:32
tablica dynamicznie alokowana była mi potrzebna, bo nie widziałem jak inaczej zamienić kolejność, więc chciałem stworzyć nową tablice w środku funkcji i wpisać tam dane w odwrotnej kolejności i wskaźnik do tej nowej tablicy zwrócić. Nie mogłem jej wyrzucić jak była to zwykła tablica a przy dynamicznie alokowanej nie wiedziałem jak usunąć pamieć jak tablica była już nie potrzebna. Bo Twoje przykłady odnoszą się do tablicy "głownej" z która nie było problemu. Natomiast z Twoimi przykładami funkcji swap nie potrzebne mi to(new i delete), zwłaszcza że w tym artykule piszą, że to zły nawyk. W książce Prata to jest często używane (dynamiczna alokacja), natomiast vectory były tylko wspomniane, ale nie używane przynajmniej do tego etapu gdzie jestem, ale poszukam trochę informacji i postaram się używać tych vectorow zamiast new i delete.

Dzięki za prace, którą włożyłeś w wytłumaczenie mi tego.
P-161287
« 1 »
  Strona 1 z 1