CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Wskaźnik do tablicy jako argument funkcji
Strona 1 z 2

Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: poniedziałek, 16 marca 2015, 10:55
przez nvdante
Witam ponownie!
Chciałbym napisać krótki kod, który po odpaleniu main wywoła funkcję z argumentem podanym przez usera, a następnie zrobi tablicę n-elementową i do kolejnej funkcji poda wskaźnik do tablicy oraz jej rozmiar.
Napisałem sobie takie coś:
KOD cpp:     UKRYJ  
#include <iostream>
#include <windows.h>
#include <ctime>

using namespace std;
void srednia(int, int);

void funkcja(int n)
{
        int *t1=new int[n];
        srand(unsigned(time(0)));
       
        for (int i=0; i<n; i++)
                {
                        t1[i]=rand()%10;
                }
        for (int i=0; i<n; i++)
                {
                        cout<<"["<<t1[i]<<"]";
                }
        cout<<endl<<"Wskaznik do tablicy to: "<<&t1<<endl;
       
        int **wsk = &t1;
        srednia(**wsk, n);
}

void srednia(int wsk, int n)
{
        cout<< &wsk;
}

int main()
{
        cout<<"Podaj n: "<<endl;
        int n;
        cin>>n;
       
        funkcja(n);
       
        system("pause");
        return 0;
}
 

Problem jednak w tym, że:
- wsk wyświetla wartość inną niż &t1, więc nie jest to adres pamięci
- nie mogę odnaleźć drugiego elementu i kolejnych

Kompiluje na Dev-cpp i Visual Studio.
Pozdrawiam

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: poniedziałek, 16 marca 2015, 11:48
przez Mironas
Zmienna t1 jest wskaźnikiem a więc:

1. Nie musisz wyłuskiwać adresu z &t1 aby go wyświetlić.

2. Możesz ten wskaźnik (t1) przekazać do następnej funkcji jako parametr.
Nie musisz tworzyć kolejnego wskaźnika do wskaźnika (int **wsk = &t1) co zresztą źle robisz, tylko po to aby przekazać go do innej funkcji.

3. parametrem funkcji srednia powinien być wskaźnik a nie zmienną int.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: poniedziałek, 16 marca 2015, 12:47
przez nvdante
1. Ok tylko jak w takim przypadku pobrać adres np.: 1 elementu tablicy? Zapis t1[1] spowoduje pobranie wartości, a nie adresu. Czy w tej sytuacji mam wykorzystać &t1[1]? Skoro tak to &t1[0] da mi to samo co t1, prawda?
2. Czy w takim razie przekazanie powinno wyglądać tak:
KOD cpp:     UKRYJ  
typ_funkcji nazwa(typ *wskaźnik, typ zmienna)
{
}

int main()
{
     nazwa(*wskaźnik, zmienna);
}
 

Mam wrażenie, że main jest źle, ale nie wiem jak poprawić.
Czy w moim kodzie zapis: void srednia(int, int) jest dobry? Pisałeś, żeby przekazywać wskaźnik, więc nie wiem czy int, chociaż typ danych to int.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: poniedziałek, 16 marca 2015, 13:34
przez Mironas
Zapis t1[1] spowoduje pobranie wartości, a nie adresu. Czy w tej sytuacji mam wykorzystać &t1[1]? Skoro tak to &t1[0] da mi to samo co t1, prawda?

Tak, tak, tak.

Przekazanie powinno wyglądać tak:
KOD cpp:     UKRYJ  
typ_funkcji nazwa(typ *wskaźnik, typ zmienna)
{
}

int main()
{
     //nazwa(*wskaźnik, zmienna); // Źle
     nazwa(wskaźnik, zmienna); // Dobrze
}

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: poniedziałek, 16 marca 2015, 13:38
przez nvdante
Super, wielkie dzięki, dalej postaram się sam :)

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 10:41
przez nvdante
Zastanawia mnie jeszcze jedna rzecz.
Skoro takim kodem:
KOD cpp:     UKRYJ  
#include <iostream>
#include <Windows.h>
#include <ctime>

using namespace std;

void Funkcja(float x)
{
        cout<<"Zostalam wywolana "<<x<<" razy!"<<endl;
}

int main()
{
        int x=5;
        void (*Wskaznik)(float x);
        Wskaznik=&Funkcja;
        (*Wskaznik)(x);
       
        system("pause");
        return 0;
}
 

Jestem w stanie wywołać funkcję poprzez wskaźnik na nią z jednym argumentem to dlaczego w tym kodzie to nie działa:
KOD cpp:     UKRYJ  
#include <iostream>
#include <Windows.h>
#include <ctime>

using namespace std;

void zwieksz(float x, float d)
{
        cout << "Liczba " << x << " zwiekszona o " << d << " daje liczbe: " << x + d << endl;
}

void zmniejsz(float x, float d)
{
        cout << "Liczba " << x << " zmniejszona o " << d << " daje liczbe: " << x - d<<endl;
}

void dzialanie(float x, float d)
{
        int wybor;
        cout << "Wybierz dzialanie na liczbach: " << endl;
        cout << "1. Zwiekszenie wartosci" << endl;
        cout << "2. Zmniejszenie wartosci" << endl;
        cin >> wybor;
       
        void(*zwieksz)(float x, float d);
        zwieksz=&zwieksz;
        void(*zmniejsz)(float x, float d);
        zmniejsz=&zmniejsz;
        switch (wybor)
        {
                case 1:
                        (*zwieksz)(x, d);
                        break;
                case 2:
                        (*zmniejsz)(x, d);
                        break;
        }
}

int main()
{
        float x, d;
        cout << "Podaj liczbe: " << endl;
        cin >> x;
        cout << "Podaj wartosc zmiany: " << endl;
        cin >> d;

        dzialanie(x, d);

        system("pause");
        return 0;
}
 

Odpowiedź kompilatora to:

In function 'void dzialanie(float, float)':
[Error] cannot convert 'void (**)(float, float)' to 'void (*)(float, float)' in assignment
[Error] cannot convert 'void (**)(float, float)' to 'void (*)(float, float)' in assignment
recipe for target 'main.o' failed


Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 10:59
przez polymorphism
KOD cpp:     UKRYJ  
zwieksz = &zwieksz;
zmniejsz = &zmniejsz;

Nie wiem, jak żeś wpadł na pomysł nazwania wskaźników dokładnie tak samo jak funkcje, których adresy przypisujesz. Kompilator ma prawo zgłupieć.

Tak jest czytelniej:
KOD cpp:     UKRYJ  
typedef void(*fp)(float, float);

fp zwieksz_ = &zwieksz;
fp zmniejsz_ = &zmniejsz;


KOD cpp:     UKRYJ  
switch (wybor)
{
case 1:
        (*zwieksz)(x, d);
        break;
case 2:
        (*zmniejsz)(x, d);
        break;
}

Po co te wskaźniki, jeśli w tym switchu spokojnie możesz wywołać funkcje "po nazwie"? Chyba o to Ci chodziło:
KOD cpp:     UKRYJ  
fp op = nullptr;

switch (wybor)
{
case 1: op = &zwieksz; break;
case 2: op = &zmniejsz; break;
};

if(op) op(x, d);

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 11:05
przez Mironas
Dlatego, że używasz tej samej nazwy dla funkcji i dla wskaźnika do niej.
Dla przykładu polecenie:
KOD cpp:     UKRYJ  
zwieksz=&zwieksz;

dla kompilatora może oznaczać nie przypisanie adresu funkcji do wskaźnika (co było Twoim celem) a przypisanie adresu wskaźnika do wskaźnika - albo jakoś tak.

PS
Zakładam, że masz powód aby komplikować proste operacji i posługiwać się wskaźnikami do funkcji a nie wywoływać po nazwie.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 11:07
przez nvdante
Genialnie, teraz działa.
Chciałem uniknąć bałaganu, a zrobiłem jeszcze większy :)
Bardzo dziękuję!

@Mironas, niestety mam, wymagania uczelni - wykładowca karze, student musi ;)

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 11:10
przez polymorphism
p.s. przeedytowałem posta, przeczytaj.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 11:33
przez nvdante
Treść zadania jest następująca:
Zdefiniowana zostanie funkcja dzialanie() wywołująca ( za pomocą wskaźnika ) funkcję zwieksz() lub zmniejsz(). Wskaźnik do funkcji zwieksz() lub zmniejsz() ( użytkownik dokonuje wyboru działania ) jest przekazywany jako argument do funkcji dzialanie().

W związku z tym pomyślałem, żeby w switchu dać odwołanie poprzez wskaźnik do konkretnych funkcji. W sumie działa, więc raczej bym tak zostawił.
Dużo prościej można by to było zrobić właśnie po nazwie, ale chodziło o sprawdzenie zastosowania wskaźników "w akcji".

Nie bardzo tylko mam pomysł na ostatnią część, czyli na przekazanie wskaźników do funkcji działanie() jako argument. Powinienem w main() przypisać wskaźniki do funkcji i razem ze zmiennymi x i d przekazać oba do funkcji dzialanie(), a z niej do funkcji zwieksz() lub zmniejsz()? Trochę to komplikuje sprawę, bo wskaźniki są dwa, a możliwa do wykonania operacja tylko jedna.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 15:31
przez polymorphism
Dużo prościej można by to było zrobić właśnie po nazwie, ale chodziło o sprawdzenie zastosowania wskaźników "w akcji".

Nie. Po nazwie nie możesz, bo w zadaniu masz napisane, że dzialanie ma wywołać funkcję, którą dostanie w parametrze, więc ten switch robi wyjazd.

Jeśli dobrze rozumiem, chodzi o coś takiego:
KOD cpp:     UKRYJ  
void dzialanie(float x, float d, fp fn)
{
       fn(x, d);
}

/* wywołanie */
dzialanie(x, d, &zwieksz);
...

dzialanie(x, d, &zmniejsz);
 

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 17:40
przez nvdante
No, ale chyba muszę umieścić dzialanie() w switchu, bo inaczej użytkownik nie dokona wyboru tylko wykona oba działania.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 18:31
przez Mironas
Nie - to nie musi byś switch. Może być if lub jeszcze prościej:
KOD cpp:     UKRYJ  
  op = (wybor==1) ? &zwieksz : &zmniejsz
  op(x, d);
 

Tylko w tym konkretnym przypadku jeśli użytkownik wybierze błędnie, np 3 to wykona się funkcja zmniejsz.

Re: Wskaźnik do tablicy jako argument funkcji

Nowy postNapisane: wtorek, 17 marca 2015, 19:28
przez nvdante
OK, dzięki :) Potestuję.