2010-04-26 9 views
61

मैं दो बिंदुओं के बीच की दूरी की गणना करने की कोशिश कर रहा हूं। सी ++ में वेक्टर में संग्रहीत दो बिंदु: (0,0) और (1,1)।एक पुनरावर्तक का उपयोग कैसे करें?

मैं के रूप में

0 
1.4 
1.4 
0 

परिणाम प्राप्त करने की अपेक्षा की कर रहा हूँ लेकिन वास्तविक नतीजा यह है कि मुझे मिल गया

0 
1 
-1 
0 

मुझे लगता है कि वहाँ कुछ तरह से मैं वेक्टर में इटरेटर का उपयोग के साथ गलत है। मैं इस समस्या को कैसे ठीक कर सकता हूं?

मैंने नीचे दिए गए कोड को पोस्ट किया है।

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; 
} 

उत्तर

158

अपने कोड सब पर संकलित यही कारण है कि शायद इसलिए है क्योंकि आप एक using namespace std कहीं है। (अन्यथा vectorstd::vector होना चाहिए।) That's something I would advise against और आपने अभी एक अच्छा मामला प्रदान किया है:
दुर्घटना से, आपकी कॉल std::distance() उठाती है, जो दो इटरेटर लेती है और उनके बीच की दूरी की गणना करती है। उपयोग निर्देश को हटाएं और std:: के साथ सभी मानक लाइब्रेरी प्रकारों को उपसर्ग करें और संकलक आपको बताएगा कि आपने vector <point>::iterator पास करने का प्रयास किया है जहां point* आवश्यक था।

ऑब्जेक्टर को इंगित करने वाले ऑब्जेक्ट को पॉइंटर प्राप्त करने के लिए, आपको इटरेटर को अव्यवस्थित करना होगा - जो ऑब्जेक्ट का संदर्भ देता है - और परिणाम का पता लेना: &*ii
(ध्यान दें कि एक सूचक पूरी तरह से std::vector इटरेटर के लिए सभी आवश्यकताओं को पूरा करेगा और मानक पुस्तकालय के कुछ पहले कार्यान्वयन वास्तव में इसके लिए पॉइंटर्स का उपयोग करेगा, जिसने आपको std::vector इटरेटर को पॉइंटर्स के रूप में इलाज करने की अनुमति दी है। लेकिन आधुनिक कार्यान्वयन उस के लिए एक विशेष इटरेटर वर्ग का उपयोग करते हैं । मैं std::vector iterators के रूप में संकेत का उपयोग कर लगता है कारण यह है कि एक वर्ग का उपयोग कर संकेत दिए गए और iterators के लिए कार्य भार अनुमति देता है। इसके अलावा, प्रोत्साहित संकेत और iterators, जो कोड पाएगा मिश्रण संकलित करने के लिए जब आप अपने कंटेनर बदल जाते हैं।)

लेकिन ऐसा करने के बजाए, मेरा सुझाव है कि आप अपना फ़ंक्शन बदल दें ताकि इसके बजाय संदर्भ ले सकें (this answer देखें कि यह एक अच्छा विचार क्यों है।):

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)); 
} 

ध्यान दें कि अंक const संदर्भों द्वारा लिया गया है। यह कॉलर को इंगित करता है कि फ़ंक्शन पारित अंकों को नहीं बदलेगा।

फिर आप इसे इस तरह से कॉल कर सकते हैं: distance(*ii,*jj)


एक तरफ ध्यान दें पर, यह

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

एक सी वाद C++ अनावश्यक है। बस इसे

struct point { 
    float x; 
    float y; 
}; 

कि समस्याओं की तरह होगा अगर यह struct परिभाषा कभी (कोड, तो struct point का उल्लेख करना होगा बस point नहीं) एक सी संकलक से पार्स करने के लिए था, लेकिन मैं std::vector लगता है और होगा वर्तनी वैसे भी एक सी संकलक के लिए एक चुनौती के अधिक हो।

+10

यह उत्तर गलत है। std :: दूरी को एडीएल द्वारा std :: iterator पर उठाया जा सकता है, इसलिए यह 'std' का उपयोग किया जाता है या नहीं, इस पर ध्यान दिए बिना उम्मीदवार सेट का हिस्सा बन सकता है। – Puppy

+2

@Puppy: यह वास्तव में सच है (और 2.5 वर्षों के लिए कोई भी ध्यान नहीं दिया), लेकिन यह मेरा पूरा जवाब नहीं है। 'कॉन्स्ट पॉइंट और पी 1 'प्रति अंक पास करने से भी इस समस्या का समाधान होगा। – sbi

+3

@ एसबीआई: नहीं, यह समस्या का समाधान नहीं करेगा। गलती से 'दूरी (ii, jj)' लिखना और 'std :: distance' प्राप्त करना संभव होगा। –

17

संयोग से, आप वास्तव में a built-in STL function "distance", जो iterators के बीच की दूरी की गणना करता है का उपयोग कर रहे, के बजाय अपने खुद के सुदूर क्रिया बुला। निहित वस्तु प्राप्त करने के लिए आपको अपने इटरेटर को "अव्यवस्था" करने की आवश्यकता है।

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

आप ऊपर वाक्य रचना से देख सकते हैं, एक "इटरेटर" एक सामान्यीकृत "सूचक" की तरह काफी एक बहुत कुछ है। इटरेटर को "आपके" ऑब्जेक्ट प्रकार के रूप में सीधे इस्तेमाल नहीं किया जा सकता है। असल में इटेटरेटर पॉइंटर्स के समान होते हैं कि इटरेटर्स पर चलने वाले कई मानक एल्गोरिदम पॉइंटर्स पर भी ठीक काम करते हैं।

जैसा कि एसबीआई ने नोट किया: आपकी दूरी समारोह पॉइंटर्स लेता है। इसके बजाय इसे कॉन्स्ट रेफरेंस लेने के रूप में बेहतर ढंग से लिखा जाएगा, जो फ़ंक्शन को "कैनोलिक" सी ++ बना देगा, और इटरेटर डिटेरेंस सिंटैक्स को कम दर्दनाक बना देगा।

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

आप चीजों की एक जोड़ी कर सकते हैं:

  1. distance() समारोह point वस्तुओं के लिए संदर्भ लेना सुनिश्चित करें। यह वास्तव में है सिर्फ बातें अधिक पठनीय जब distance() फ़ंक्शन को कॉल करने के लिए:

    distance(*ii, *jj) 
    

आप हैं:

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)); 
} 
  • अपने iterators भिन्नता जब distance() ताकि आप गुजर रहे हैं point वस्तुओं बुला distance() फ़ंक्शन के इंटरफ़ेस को न बदलें, आपको उपयुक्त पॉइंटर्स प्राप्त करने के लिए निम्न जैसे कुछ का उपयोग करके इसे कॉल करना पड़ सकता है:

    distance(&*ii, &*jj) 
    
  • संबंधित मुद्दे