Tablice dynamiczne i funkcje

0

Hej, mam mały prozaiczny problem. Uczę się tablic i wskaźników. Zadeklarowałem dwa wskaźniki w funkcji main():

int **XX; 
int **YY;  

Następnie napisałem funkcję:

int funkcja(int **XX, int **YY)
{
    int rozmiar; 

    cout << endl;
    cout << " Podaj ilosc elementow obu tablic: ";
    cin >> rozmiar;
    XX = new int[rozmiar]; 
    YY = new int[rozmiar];
    
    for (int i = 0; i < rozmiar; i++)
    {
        XX[i] = rand() % 25 + 5;
        cout << " Liczba x " << i + 1 << ": " << XX[i] << endl;
        YY[i] = rand() % 25 + 5;
        cout << " Liczba y " << i + 1 << ": " << YY[i] << endl;
    }
    return(0);
} 

Chciałbym ją wywołać w main-ie ale nie wiem dla jakich argumentów powinna zostać wywołana.

 case '5':

                funkcja();   
                break;

Prówowałem kilku sposobów ale widocznie nie dość dobrze rozumiem wskaźniki. Za wszelkie sugestię i pomoc z góry dziękuję :)

screenshot-20210512090119.png1.png2.png3.png

0

Jeśli chodzi o odpowiedź wprost, jak to zawołać to możesz zrobić w ten sposób, ale generalnie jest parę innych błędów w tym kodzie, min. wyciek pamięci i użycie globalnych zmiennych.

#include <iostream>
using namespace std;
int *XX; 
int *YY;  
int funkcja(int *XX, int *YY)
{
    int rozmiar; 

    cout << endl;
    cout << " Podaj ilosc elementow obu tablic: ";
    cin >> rozmiar;
    XX = new int[rozmiar]; 
    YY = new int[rozmiar];

    for (int i = 0; i < rozmiar; i++)
    {
        XX[i] = rand() % 25 + 5;
        cout << " Liczba x " << i + 1 << ": " << XX[i] << endl;
        YY[i] = rand() % 25 + 5;
        cout << " Liczba y " << i + 1 << ": " << YY[i] << endl;
    }
    return(0);
} 

int main()
{
    funkcja(XX, YY);
}
0

@Trisolaris: No właśnie to nie jest takie proste bo w przypadku prób wywołania funkcji "funkcja(XX, YY);" wyświetla błąd "użycie niezainicjowanej zmiennej lokalne" a samo zadanie nad którym teraz siedzę wymaga deklarowania wszystkich tablic w funkcji main() ...

1

Ucząc się wskaźników warto dobierać sobie jakieś sensowne przykłady. Funkcja w której tworzy się dwie dynamiczne tablice, wyciek pamięci i zawsze zwraca zero jest takim antyprzykładem.
Wiem że dla uczącego najważniejsze jest zrozumienie działania wskaźników, ale złe przykłady mogą dużo namieszać w ogólnym zrozumieniu tworzenia prawidłowego kodu.

Jeżeli chcesz mieć funkcję tworząca dynamiczną tablicę, to zwracaj ją aby nie mieć wycieków pamięci i wymyśl jakieś sensowne nazewnictwo do tego.

[[nodiscard]] int* make_dynamic_table( int size )
{
    int* table = new int[size];
    for( int i {0} ; i<size ; ++i ) table[i] = rand() % 25 + 5;
    return table;
}
0

Tutaj masz wskaźnik na wskaźnik:

int** XX

Czyli coś co wskazuje na fragment pamięci, który wskazuje na inny fragment pamięci.

XX = new int[rozmiar];

Próbujesz zaalakować pamięć, na ten wskaźnik na wskaźnik, czyli nie jest to prawidłowe.

*XX = new int[rozmiar];

Mógłbyś wyciągnąć wartość tego wskaźnika na wskaźnik, czyli wskaźnik, który może wskazywać na konkretną pamięć, ale w tym momencie wyłuskujesz wartość, z czegoś co jeszcze na nic nie wskazuj (niezainicjalizowałeś tego).

Jeśli to ma być ćwiczenie, które pokazuje jak działać na tego typu wskaźnikach, to możesz to zrobić tak:

int **XX; 
int **YY;  

int funkcja(int **XX, int **YY)
{
    int rozmiar; 

    cout << endl;
    cout << " Podaj ilosc elementow obu tablic: ";
    cin >> rozmiar;
    *XX = new int[rozmiar]; // wyłuskujesz wskaźnik, na który wskazuje wskaźnik XX i alokujesz tam pamięć
    *YY = new int[rozmiar]; // jw.

    for (int i = 0; i < rozmiar; i++)
    {
        (*XX)[i] = rand() % 25 + 5; // wyłuskujesz tablice, na którą wskazuje XX i przypisujesz wartość danemu elementowi w tablicy
        cout << " Liczba x " << i + 1 << ": " << (*XX)[i] << endl; // printujesz to co jest wyżej
        (*YY)[i] = rand() % 25 + 5;
        cout << " Liczba y " << i + 1 << ": " << (*YY)[i] << endl;
    }
    delete[] *XX; // tutaj zwalniasz zaalakowaną pamięć
    delete[] *YY;
    return(0);
} 

int main()
{
    int* x; // nowy wskaźnik na który będzie wskazywać, wskaźnik na wskaźnik XX
    int* y;

    XX = &x; // przypisanie adresu wskaźnika x, do wskaźnika na wskaźnik XX
    YY = &y;

    funkcja(XX, YY)
}
0

@Trisolaris: Aaa widzisz o taki przykład mi chodziło ! Wszystko jasne dzięki wielkie, lecę poprawiać kod na coś na co da się patrzeć :P

2

Nie znoszę mieszanki C i C++.
https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Wersja C++ (pomijając wątpliwą sensowność kodu):

using MyArray = std::vecctor<int>;


void fillRandom(MyArray *a)
{
    for (auto& x: *a) {
         x = rand() % 25 + 5;
    }
}

int printAsPairs(const MyArray& x, const MyArray& y)
{
    auto n = std::min(x.size(), y.size());
    for(size_t i =0; i < n; ++i) {
        cout << " Liczba x " << i + 1 << ": " << x[i] << '\n';
        cout << " Liczba y " << i + 1 << ": " << y[i] << '\n';
    }
}

int funkcja(MyArray *x, MyArray *y)
{
    size_t n; 
    cout << " Podaj ilosc elementow obu tablic: ";
    cin >> n;
    *x = MyArray(n); 
    *y = MyArray(n);

    fillRandom(x);
    fillRandom(u);

    printAsPairs(*x, *y);

    return(0);
} 

int main()
{
     MyArray x, y;
     funkcja(&x, &y);
}
0
Trisolaris napisał(a):
int **XX; 
int **YY;  

int funkcja(int **XX, int **YY)
{
    int rozmiar; 

    cout << endl;
    cout << " Podaj ilosc elementow obu tablic: ";
    cin >> rozmiar;
    *XX = new int[rozmiar]; // wyłuskujesz wskaźnik, na który wskazuje wskaźnik XX i alokujesz tam pamięć
    *YY = new int[rozmiar]; // jw.

    for (int i = 0; i < rozmiar; i++)
    {
        (*XX)[i] = rand() % 25 + 5; // wyłuskujesz tablice, na którą wskazuje XX i przypisujesz wartość danemu elementowi w tablicy
        cout << " Liczba x " << i + 1 << ": " << (*XX)[i] << endl; // printujesz to co jest wyżej
        (*YY)[i] = rand() % 25 + 5;
        cout << " Liczba y " << i + 1 << ": " << (*YY)[i] << endl;
    }
    delete[] *XX; // tutaj zwalniasz zaalakowaną pamięć
    delete[] *YY;
    return(0);
} 

int main()
{
    int* x; // nowy wskaźnik na który będzie wskazywać, wskaźnik na wskaźnik XX
    int* y;

    XX = &x; // przypisanie adresu wskaźnika x, do wskaźnika na wskaźnik XX
    YY = &y;

    funkcja(XX, YY)
}

Doprawdy?
Opowiadasz jak przekazać poprawnie zmienne do funkcji ay użyć parametry funkcji jako zmienne lokalne?
Naprawdę próbujesz pomóc czy może zaszkodzić?

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;

void randFill(int *tb,int size)
{
    for(int i=0;i<size;++i) tb[i]=rand()%25+5; // http://forum.4programmers.net/1101404
 }

void showTwoColumns(int *tbX,int *tbY,int size)
{
    cout<<setw(3)<<""<<setw(3)<<"X"<<setw(3)<<"Y"<<endl;
    for(int i=0;i<size;++i) cout<<setw(3)<<(i+1)<<setw(3)<<tbX[i]<<setw(3)<<tbY[i]<<endl;
}

void function()
{
    cout<<" Podaj ilosc elementow obu tablic: "; // zadanie z przydzielaniem pamięci przez `new` w C++ to anty-dydaktyczne zadanie.
    int size; 
    cin>>size;
    int *X=new int[size],*Y=new int[size];
    randFill(X,size);
    randFill(Y,size);
    showTwoColumns(X,Y,size);
    delete[] X;
    delete[] Y;
} 

int main()
{
	srand(time(0));
    function();
    return 0;
}

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