2010-04-26 36 views
61

İki nokta arasındaki mesafeyi hesaplamaya çalışıyorum. C++ 'da bir vektörde sakladığım iki nokta: (0,0) ve (1,1).Yineleyici nasıl kullanılır?

Ben

0 
1.4 
1.4 
0 

olarak sonuç almak mı gerekiyor Ama got gerçek sonuç ben vektöründe tekrarlayıcı kullanmak yolu ile yanlış bir şey olduğunu düşünüyorum

0 
1 
-1 
0 

olduğunu. Bu sorunu nasıl düzeltebilirim?

Aşağıdaki kodu yolladım. Tesadüf

typedef struct point { 
    float x; 
    float y; 
} point; 

float distance(point *p1, point *p2) 
{ 
    return sqrt((p1->x - p2->x)*(p1->x - p2->x) + 
       (p1->y - p2->y)*(p1->y - p2->y)); 
} 

int main() 
{ 
    vector <point> po; 
    point p1; p1.x = 0; p1.y = 0; 
    point p2; p2.x = 1; p2.y = 1; 
    po.push_back(p1); 
    po.push_back(p2); 

    vector <point>::iterator ii; 
    vector <point>::iterator jj; 
    for (ii = po.begin(); ii != po.end(); ii++) 
    { 
     for (jj = po.begin(); jj != po.end(); jj++) 
     { 
      cout << distance(ii,jj) << " "; 
     } 
    } 
    return 0; 
} 

cevap

158

olasılıkla gerçek değildir. (Aksi takdirde vectorstd::vector olması gerekir.) That's something I would advise against ve neden iyi bir durum sağladıysanız:
Kaza sonucu, aramanız iki yineleyici alır ve aralarındaki mesafeyi hesaplar std::distance() alır. std:: ile tüm standart kitaplık türlerini kullanma yönergesini ve önekini kaldırın ve derleyici size vector <point>::iterator'u point*'un gerekli olduğu yerlerde iletmeye çalıştığınızı söyleyecektir.

Yineleyicinin işaret ettiği bir nesneye bir işaretçi almak için, yineleyicinin - nesneye bir başvuruda bulunarak - ve sonucun adresini almanız gerekir: &*ii.
(Bir işaretçinin bir std::vector yineleyici için tüm gereksinimleri ve standart kitaplık için gerçekten kullanılan işaretçilerin bazı önceki uygulamalarını mükemmel bir şekilde yerine getireceğini unutmayın; bu, std::vector yineleyicilerini işaretçi olarak kullanmanıza olanak tanır. Ancak, modern uygulamalar, bunun için özel bir yineleme sınıfı kullanır. Bunun nedeni, bir sınıf kullanmanın, işaretçiler ve yineleyiciler için aşırı yükleme işlevlerine izin verdiğidir.Ayrıca, std::vector yineleyicileri olarak işaretçileri kullanarak, kapsayıcınızı değiştirdiğinizde kodun derlenmesini engelleyen karıştırma işaretleyicilerini ve yineleyicileri de teşvik eder.)

Ancak Bunu yapmak yerine, işlevinizi değiştirmenizi öneririm, böylece bunun yerine referanslar alır (neden bu iyi bir fikir olduğunu görmek için this answer'a bakın.): ​​

float distance(const point& p1, const point& p2) 
{ 
    return sqrt((p1.x - p2.x)*(p1.x - p2.x) + 
       (p1.y - p2.y)*(p1.y - p2.y)); 
} 

Bu noktaların const referans alınarak alındığını unutmayın. Bu, arayan kişiye işlevin geçirilen noktaları değiştirmeyeceğini gösterir.

Ardından bunu şu şekilde arayabilirsiniz: distance(*ii,*jj). Yan not


bu

typedef struct point { 
    float x; 
    float y; 
} point; 

C++ gereksiz bir Cı-izm. Sadece

struct point { 
    float x; 
    float y; 
}; 
bu struct tanım şimdiye (kod, daha sonra struct point başvurmak zorunda kalacak değil sadece point) bir C derleyicisinden ayrıştırmak olsaydı sorunları yapmak ama std::vector tahmin ve benzeri ediyorum

olur büyü Zaten bir C derleyicisine daha fazla meydan okuma.

+10

Bu yanıt yanlış. std :: mesafe bir std :: yineleyici üzerinde ADL tarafından alınabilir, bu yüzden std' kullanılıp kullanılmadığına bakılmaksızın aday kümesinin bir parçasını oluşturabilir. – Puppy

+2

@Puppy: Bu gerçekten doğrudur (ve 2.5 yıldır kimse farketmez), fakat bu benim cevabımın hepsi değil. Const point & p1' başına düşen puanlar da bu sorunu çözecektir. – sbi

+3

@sbi: Hayır, sorunu çözmeyecek. Mesafe (ii, jj) 'yi yanlışlıkla yazıp,' std :: distance' yazısını almak mümkün olacaktır. –

17

, aslında yineleyiciler arasındaki mesafeyi hesaplar a built-in STL function "distance" kullanılarak yerine kendi mesafe işlevini diyorlar. İçerilen nesneyi almak için yineleyicilerinizi "dereference" yapmanız gerekir. Yukarıdaki sözdizimi görebileceğiniz gibi

cout << distance(&(*ii), &(*jj)) << " "; 

, bir "yineleyici" oldukça çok genelleştirilmiş bir "pointer" gibidir. Yineleyici doğrudan "sizin" nesne tipi olarak kullanılamaz. Aslında yineleyiciler, yineleyiciler üzerinde çalışan birçok standart algoritmanın işaretçiler üzerinde de iyi çalıştığını gösteren göstericilere çok benzer.

Sbi'nin belirttiği gibi: mesafe fonksiyonunuz işaretçiler alır. Bunun yerine const başvuruları almak daha iyi olurdu, bu da fonksiyonu daha "canonical" C++ yapar ve yineleyici dereference sözdizimini daha az ağrılı hale getirir. Bir yerde bir using namespace std çünkü kodunuzu hiç derler Yani

float distance(const point& i_p1, const point& i_p2) 
{ 
    return sqrt((p1.x - p2.x)*(p1.x - p2.x) + 
       (p1.y - p2.y)*(p1.y - p2.y)); 
} 

cout << distance(*ii, *jj) << " "; 
6

Sen birkaç şey yapabilir:

  1. distance() fonksiyon point nesnelere başvurular almaya olun.

    distance(*ii, *jj) 
    

Eğer: distance() böylece geçiyoruz point nesneleri telefonla ararken Yineleyicilerin KQUEUE

float distance(point const& p1, point const& p2) 
{ 
    return sqrt((p1.x - p2.x)*(p1.x - p2.x) + 
       (p1.y - p2.y)*(p1.y - p2.y)); 
} 
  • : Bu distance() işlevi çağrılırken sadece işleri daha okunabilir hale getirmek için gerçekten distance() işlevinin arabirimini değiştirmeyin, uygun işaretçiler almak için aşağıdaki gibi bir şey kullanmanız gerekebilir:

    distance(&*ii, &*jj)