2016-04-14 15 views
3

aşağıdaki varsayalım:İşaretçi, sınıf nesnelerinin bir işaretçisinin içine nasıl sürüklenir ve bunları yinelemeli olarak atayıp işaretçi döndürür? C++

  • Ben Person bir sınıf olarak adlandırılan:

    class Person { 
     
        public: 
     
        Person(); 
     
        ~Person(); 
     
        int compare(const Person & compared); //compare the names using strcmp() 
     
        void display(); 
     
        
     
        protected: 
     
        char * name; 
     
        int age; 
     
    };
    I Person nesnelerin bir listesini depolamak için bir Linked_List veri yapısını kullanmak :

class Linked_List { 
 
    public: 
 
    Linked_List(); 
 
    ~Linked_List(); 
 
    Person * retreive(Person, Node *, int &); 
 
    void insert(Person); 
 
    int remove_all(); 
 
    int display_all(); 
 
    
 
    protected: 
 
    Node * head; 
 
};

  • retrieve() işlevi bir fonksiyonu (yinelemeli) geçirilen ile aynı isme sahip Person nesneler listesi döndürmelidir.

Person * Linked_List::retreive(Person target, Node * current, int & matches) { 
 
    if (current == NULL) { 
 
     Person * persons = new Person[matches]; 
 
     return persons; 
 
    } 
 
    if (target.compare(current->getData()) == 0) { 
 
     return retreive(target, current->getNext(), ++matches); //recursive call 
 
    } 
 
    return retreive(target, current->getNext(), matches); //recursive call 
 
}

Bu fonksiyon alır üç argümanlar

1- aradığım kişi. (Listeyi diğerleriyle karşılaştırmak için)

2- Baş ibre. (Listede yinelemeli olarak geçiş yapmak için) PersonPerson hedefinin aynı adıyla listede bulunan Person nesnelerinin sayısı. teker Bu fonksiyon temelde yinelemeli Linked_List ve her zaman içinde geçtiği

bir maç Person bulunursa matches artış (listede bulunmuştur aynı isimde kişilerin dinamik dizi tahsis etmek) ve daha sonra yinelemeli çağrı yapmak Traversing tutmak için. Listenin sonuna ulaşılana kadar, Person nesnesi dizisi dinamik olarak ayrılır. Sonra problemime ulaşırım. Bu işlevi başarılı bir şekilde çalışması için bir yol düşünemedim, UNLESS persons dizisinin içinde eşleşmenin sonunda döndürülecek Person nesnesinin bir eşleşmesini (atama) yapmamı sağlayan bir yol buluyorum. özyinelemeli çağrı.Fonksiyon Person dizisi döndürür

yana, sonra ben içine yazacağım:

Peki gerçekten yapmak çalışıyorum böyle bir şey (Bu ama sadece konuya açıklık getirmek amacıyla, yanlış) 'dir ikinci koşul

return (retreive(target, current->getNext(), matches))[matches++] = current->getPerson();

Ben Person nesnelerin bir dizideki aynı ada sahip her Person depolamak istediğiniz, ama aynı zamanda özyinelemeli aramanın sonuna ulaşıncaya kadar beklemek zorunda Diziyi, eşleştirilen kişi sayısının doğru boyutuna göre başlatabilirim, YET Ayrıca bir nesneyi değil Person nesnesinin bir nesnesini (*) döndürmem gerekiyor.

+0

Kişileri saklamak için dinamik bir yineleme konteyneri kullanmayı düşündünüz mü? (“Std :: vector” veya benzer bir uygulama gibi) Sonra, ilk önce onları saymadan önce iki kez tekrar etmenize gerek kalmayacak ve bir dizi doğru kişiyi geri getireceksiniz. –

+0

@ChrisBritt Aslında iki kez geçmiyorum, bu yüzden bu biraz zor bir sorundur. Yine de teşekkürler, önerdiğin şeyi düşüneceğim. Ancak, merak uğruna, benim sorunum için bir çözüm olup olmadığını görmek için sabırsızlanıyorum VEYA belki de değil. – Bader

+0

Sadece merak, 'compare' bir eşleşme için 0 ve bir eşleşme için değil! (Ondan ek bilgi aktarıyor musunuz? Değilse, okunabilirlik amacıyla bir bool kullanmak isteyebilirsiniz.) –

cevap

3

Basit bir gerçeği farkettikten sonra cevap çok basittir. Verilen yinelemede, nmatch'lerin 0 olduğunu ve compare() iddialarının hedefle eşleştiğini gösteren bir kayıt buldunuz.

Bu, ilk eşleşen kayıt olduğu anlamına gelir. Bu, döndürülen dizide, bu eşleşmenin persons[0]'a gireceği anlamına gelir.

Eğer nmatch'ler 1 ise, bu, bu eşleşmenin persons[1]'a gireceği anlamına gelir, vb.

Bu, bu basitçe hale gelmesi anlamına gelir: bu kadar

Person * Linked_List::retreive(Person target, Node * current, int & matches) { 
    if (current == NULL) { 
     Person * persons = new Person[matches]; 
     return persons; 
    } 
    if (target.compare(current->getData()) == 0) { 
     int n=matches; 

     auto p=retreive(target, current->getNext(), ++matches); 
     p[n]=current->getData(); 
     return p; 
    } 
    return retreive(target, current->getNext(), matches); //recursive call 
} 

. Öte yandan ev ödevi, çirkin new kurtulmak ve std::vector kullanarak her şeyi yeniden yazmaktır. Modern C++ ile, nadiren manuel olarak new ve delete bir şey gerekir. Her ihtiyaç ve istek için bir konteyner var ve ekstra bir bonus olarak, kaplar düzgün kullanıldığında herhangi bir bellek sızıntısı olmayacak. Ne pazarlık!

0

Bu örnek, hem geçici bir önbellek görevi görmesi amacıyla hem de std::vector<Person*> numaralı belgeyi kullanır ve bu vektörü, işaretçi dizisine ek olarak kullanıcıya döndürür. Node :: getData() veri öğesi için bir işaretçi döndürdüğü varsayımı altında çalışıyorum. (Oldukça standart olan bu uygulama oldukça kesin.) Ayrıca, dönüş türünü geçersiz hale getirebilir ve böylece veriyi içeren std :: vektörünün geri dönüşünü aldığınız için diziye olan ihtiyacı tamamen ortadan kaldırırsınız. (new/delete ile dizileri kullanma nedeniyle STL konteynerlerin yönlülük oldukça antika.)

Sadece bir not olarak, değişken int & matches şimdi std::vector::size() içinde bulunur.

Person * Linked_List::retreive(Person target, Node * current, std::vector<Person*>& _persons) { 
    if (current == NULL) { 
     Person * persons = new Person[_persons.size()]; 
     for(int i(0); i < _persons.size(); ++i) 
     { 
      persons[i] = &_persons[i]; 
     } 
     return persons; 
    } 
    if (target.compare(current->getData()) == 0) { 
     _persons.push_back(current->getData()); 
     return retreive(target, current->getNext(), _persons); //recursive call 
    } 
    return retreive(target, current->getNext(), _persons); //recursive call 
} 
İlgili konular