operator de selectie indirecta ->

Intrebari despre limbajul C++, standardul C++, STL, OOP in C++ sau alte subiecte nelegate de VisualC++
Post Reply
vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

operator de selectie indirecta ->

Post by vili_c++ » 11 Feb 2014, 23:52

Salutare !
Am facut urmatorul cod ce realizeaza afisarea unei matrici cu ajutorul structurilor, folosind pointerii si alocarea dinamica.

Code: Select all

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

struct matrice
{
    int A;
    int n;
    int m;
}q, **p;

int main()
{
    cout <<"\n Numarul de linii : ";
    cin >>q.n;
    cout <<"\n Numarul de coloane : ";
    cin >>q.m;
    p = (matrice**)malloc(q.n*sizeof(matrice));
    for (int i=0; i<q.n; i++)
        p[i] = (matrice*)malloc(q.m*sizeof(matrice));
    for (int i=0; i<q.n; i++)
    {
        for (int j=0; j<q.m; j++)
        {
            cout <<"\n A["<<i<<"]["<<j<<"] = ";
            cin >>(*(*(p+i)+j)).A;
        }
    }
    cout <<"\n";
    for (int i=0; i<q.n; i++)
    {
        for (int j=0; j<q.m; j++)
            cout <<"\t\t"<<(*(*(p+i)+j)).A;
        cout <<"\n";
    }
    for (int i=0; i<q.n; i++)
        free (p);
    free (p);
    return 0;
}
As vrea sa fac acest cod cu operatorul de selectie indirecta -> la fel cum am facut urmatoarele coduri ce afiseaza un vector de n elemente

cod facut cu operatorul de adresare indirecta *

Code: Select all

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

struct vector
{
    int A;
    int n;
}q, *p;

int main()
{
    int n;
    cout <<"\n Dati dimensiunea vectorului : ";
    cin >>q.n;
    cout <<"\n Introduceti elementele vectorului : "<<endl;
    p = (vector*)malloc(q.n*sizeof(vector));
    for (int i=0; i<q.n; ++i)
    {
        cout <<"\n A["<<i<<"] = ";
        cin >>(*(p+i)).A;
    }
    cout <<"\n Elementele vectorului sunt : ";
    for (int i=0; i<q.n; ++i)
        cout <<" "<<(*(p+i)).A;
    cout <<endl;
    free(p);
    return 0;
}
cod facut cu operatorul de selectie indirecta ->

Code: Select all

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

struct vector
{
    int A;
    int n;
}q, *p;

int main()
{
    int n;
    cout <<"\n Dati dimensiunea vectorului : ";
    cin >>q.n;
    cout <<"\n Introduceti elementele vectorului : "<<endl;
    p = (vector*)malloc(q.n*sizeof(vector));
    for (int i=0; i<q.n; ++i)
    {
        cout <<"\n A["<<i<<"] = ";
        cin >>(p+i)->A;
    }
    cout <<"\n Elementele vectorului sunt : ";
    for (int i=0; i<q.n; ++i)
        cout <<" "<<(p+i)->A;
    cout <<endl;
    free(p);
    return 0;
}
Astept cu interes sugestii.
Last edited by Marius Bancila on 12 Feb 2014, 09:34, edited 1 time in total.
Reason: code tags



User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

Re: operator de selectie indirecta ->

Post by Marius Bancila » 12 Feb 2014, 09:37

Aici ai o gresala:

Code: Select all

    for (int i=0; i<q.n; i++)
        free (p);
    free (p);
In for-ul ala trebuie sa faci free(p);

Parerea mea ca din exemplele 2 si 3 ar trebui sa-ti dai seama singur care e diferenta intre a folosi . si respectiv ->

Code: Select all

cin >>(*(p+i)).A;

Code: Select all

cin >>(p+i)->A;
Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: operator de selectie indirecta ->

Post by Ovidiu Cucu » 12 Feb 2014, 13:02

Code: Select all

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

struct vector
{
    int A;
    int n;
}q, *p;
  1. Numai "vector" nu se poate chema ce-ai scris tu acolo. Ai pur si simplu o structura care contine doi membri de tip int. Dupa ce ai in problema i-ai putea spune cel mult "element".
  2. In plus, ai definit doua variabile globale, q si p dupa moda din C. Daca ai vrea s-o folosesti in mai multe locuri si ai muta-o intr-un header inclus in mai multe cpp-uri, o sa-ti eroare de linkeditare gen "one or more multiply defined symbols found".
    In orice caz spre deosebire de C, in care uneori n-ai incotro, in C++ e bine sa eviti variabile globale.
  3. Daca vrei vrea mai tarziu sa incluzi si headerul <vector> o sa-ti dea conflict de nume intre vector definit de tine si std::vector. Asa ca, ori redenumesti structura ta, ori stergi using namespace std si pui std:: in fata la tot ce folosesti de acolo, sau cel mai bine amandoua (am zis asta intr-un post anterior: viewtopic.php?f=13&t=2546#p16125 )
  4. Aceleasi observatii si pentru structura "matrice", mai putin cea legata de nume.
Eu zic sa pornesti de la doua structuri de genul

Code: Select all

struct vector_de_intregi
{
    int* p;
    unsigned int size; 
};

struct matrice_de_intregi
{
    vector_de_intregi* p;
    unsigned int size; 
};
Inca suntem pe teritoriul C pentru ca avem doua structuri cu membri publici pe care-i manipulam cum vrem din exterior, insa e un pic mai bine.

vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

Re: operator de selectie indirecta ->

Post by vili_c++ » 12 Feb 2014, 19:08

Raspuns pentru Marius Bancila

Am incercat sa ma inspir din exemplele pe care le-am postat domnule Bancila, dar nu am rezolvat nimic.
Astept sa ma luminati.

vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

Re: operator de selectie indirecta ->

Post by vili_c++ » 12 Feb 2014, 19:16

Raspuns pentru Ovidiu Cucu

Da stiu ca intru in conflict cu headerul <vector> din STL in cazul in care introduc headerul <vector>.
Eu vroiam doar sa aflu cum sa folosesc operatorul de selectie indirecta -> pentru structura "matrice".

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: operator de selectie indirecta ->

Post by Ovidiu Cucu » 12 Feb 2014, 22:58

vili_c++ wrote:Raspuns pentru Marius Bancila
Am incercat sa ma inspir din exemplele pe care le-am postat domnule Bancila, dar nu am rezolvat nimic.
Cum te-ai inspirit, ce ai incercat si ce nu ai rezolvat? Te rog, concret!

vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

Re: operator de selectie indirecta ->

Post by vili_c++ » 12 Feb 2014, 23:32

Pentru expresia :
cin >>(*(p+i)).A;
am folosit operatorul de selectie indirecta
cin >>(p+i)->A;
acelasi operator vreau sa-l folosesc si pentru :
cin >>(*(*(p+i)+j)).A;
dar imi dar "cu virgula"

User avatar
bu7ch3r
Membru++
Membru++
Posts: 326
Joined: 17 May 2011, 15:17
Judet: Iaşi
Location: Sofia
Contact:

Re: operator de selectie indirecta ->

Post by bu7ch3r » 13 Feb 2014, 12:41

Code: Select all

*(*(p+i)+j)).A; // devine (*(p+i)+j)->A ;
Probabil scopul tau e sa elimini in totalitate operatorul de indirectare. Problema e ca adresarea e diferita de selectie. O adresa nu poate fi "selectata".
-> inlocuieste accesarea membrului unei valori(valoare.mebru), cu accesarea membrului unei valori de la adresa(&valoare->membru).
Cu stima,
Lupu Claudiu

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: operator de selectie indirecta ->

Post by Ovidiu Cucu » 13 Feb 2014, 13:45

Marius ti-a dat deja un hint. Acuma ca-ti iese "cu virgula" si nu vrei sa ne spui si noua cum ai facut... e treaba ta.
Am intarziat putin si a venit si Claudiu cu rezolvarea. Incerc totusi sa detaliez putin.

Daca p este un pointer la o clasa (class, struct, union), iar X este un membru al acelei clase, atunci
p->X este echivalent (*p).X. In primul caz am accesat un membru printr-un pointer, in cel de-al doilea printr-un obiect (dupa ce am dereferentiat pointerul).
Tinand cont ca (p + i) unde i este un intreg, este tot un pointer, atunci
(*(p + i)).X este echivalent cu (p + i)->X

Acuma, daca avem un ceva gen tip** p, unde tip este o clasa care are un membru X, aplicand regula de mai sus
(*(*(p + i) + j)).X este echivalent cu (*(p + i) + j)->X.
Mai departe, nu mai ai ce inlocui cu -> decat poate daca faci cinestie ce giumbuslucuri si mai greu de citit.

Depasind putin topicul:

Daca vrei sa scrii mai frumos, tii cont ca *(p + i) este echivalent cu p[ i ].
Avem succesiv:

Code: Select all

(*(p + i) + j)->X  // (*(p + i) + j) este tip pointer (am dereferentiat tip** si am obtinut tip*); accesez membrul X cu -> (sageata)
(p[i] + j)->X      // (p[i] + j)     este tot tip pointer (tip*); accesez membrul X tot cu -> 
p[i][j].X          // p[i][j]        este un obiect (am dereferentiat tip* si am obtinut tip); accesez membrul X cu . (punct)  
Rezultatul este acelasi insa e mai usor de scris, mai usor de citit si scapi de pericolul de a gresi la "aritmetica", incat sa-ti dea asa cum ai spus, "cu virgula".

Si o observatie suplimentara, legata de terminologie:

Operatori . si -> se numesc operatori de acces (la membrii unei clase) (class member access operators).
Operatorul unar * se numeste operator de indirectare (indirection operator). Atunci cand se aplica unui pointer, se spune ca dereferentiaza acel pointer (dereferences the pointer). Practic, se obtine o valoare stocata la o anumita adresa din memorie, indirect, folosind o variabila (pointer) care contine acea adresa. De aceea I se spune "operator de indirectare".

Vezi si:

vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

Re: operator de selectie indirecta ->

Post by vili_c++ » 13 Feb 2014, 20:31

Da intr-adevar Claudiu scopul meu era sa elimin in totalitate operatorul de indirectare.
Pentru linia de cod *(*(p+i)+j)).A; eu incercam sa folosesc de doua ori operatorul de indirectare si de aceea si "virgula".
Va multumesc tuturor pentru ajutor !

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: operator de selectie indirecta ->

Post by Ovidiu Cucu » 13 Feb 2014, 20:42

vili_c++ wrote:[...] scopul meu era sa elimin in totalitate operatorul de indirectare.
Poti sa ne spui si noua de ce, cu ce scop si in fine... la ce bun?
vili_c++ wrote:Va multumesc tuturor pentru ajutor !
Cu placere! As fi si eu multumit daca din toata discutia asta ai inteles ceva.
Deci, chiar si din curiozitate, ce ai inteles?

vili_c++
Junior
Junior
Posts: 19
Joined: 11 Feb 2014, 23:39
Judet: Dolj

Re: operator de selectie indirecta ->

Post by vili_c++ » 13 Feb 2014, 21:26

Un singur scop: sa stiu cum se aplica acest operator de acces ->.
Daca am inteles eu asa zic.
Oricum ideea e ca daca p este un pointer la o structură, atunci p->membru_al_structurii face referire la acel membru.
Adica p->membru_al_structurii este o notatie alternativa la (*p).membru_al_structurii.
Ambele notatii fac aceeasi treaba prin accesari diferite, printr-un pointer respectiv printr-un obiect.

Post Reply