পুনরুক্তি ব্যবহার করে কোনও ভেক্টর দিয়ে কীভাবে নেভিগেট করবেন? (C ++) গুলির


105

লক্ষ্যটি হ'ল [] অপারেটর বা "এট" পদ্ধতির পরিবর্তে স্ট্রিংয়ের ভেক্টরের "এনথ" উপাদানটি অ্যাক্সেস করা। আমি যা বুঝি সেগুলি থেকে পুনরাবৃত্তকারীদের পাত্রে নেভিগেট করতে ব্যবহার করা যেতে পারে, তবে আমি এর আগে কখনও পুনরাবৃত্তকারী ব্যবহার করি নি এবং আমি যা পড়ছি তা বিভ্রান্তিকর।

কেউ যদি এটি অর্জন করতে পারে সে সম্পর্কে আমাকে কিছু তথ্য দিতে পারলে আমি এটির প্রশংসা করব। ধন্যবাদ.


ভেক্টর কি সি ++ এর এসটিএলে একচেটিয়া নয়? আমি নির্বিশেষে এটি সম্পাদনা করব
কেভিন

কেভিন: ভেক্টর একটি জেনেরিক শব্দ যা কোনও ভাষা, বিশেষত গণিত সম্পর্কিত ম্যাথমেটিকা ​​বা মতলব দ্বারা ব্যবহৃত হতে পারে।
গাবে

@ মাইকেল, হ্যাঁ হা হা আমি গ্যাবের মন্তব্যের পরে এটি সম্পাদনা করেছি।
কেভিন

উত্তর:


112

আপনাকে ক্লাসের beginএবং endপদ্ধতিটি ব্যবহার করতে হবে vector, যা যথাক্রমে প্রথম এবং শেষ উপাদানটি উল্লেখ করে পুনরাবৃত্তকারীকে ফেরত দেয়।

using namespace std;  

vector<string> myvector;  // a vector of stings.


// push some strings in the vector.
myvector.push_back("a");
myvector.push_back("b");
myvector.push_back("c");
myvector.push_back("d");


vector<string>::iterator it;  // declare an iterator to a vector of strings
int n = 3;  // nth element to be found.
int i = 0;  // counter.

// now start at from the beginning
// and keep iterating over the element till you find
// nth element...or reach the end of vector.
for(it = myvector.begin(); it != myvector.end(); it++,i++ )    {
    // found nth element..print and break.
    if(i == n) {
        cout<< *it << endl;  // prints d.
        break;
    }
}

// other easier ways of doing the same.
// using operator[]
cout<<myvector[n]<<endl;  // prints d.

// using the at method
cout << myvector.at(n) << endl;  // prints d.

5
বাস্তবে দেখা যায় যে ব্যার্থ std::vectorরেণ্ডম এক্সেস iterators হয়েছে।
এসবিআই

24
আপনি জানেন যে এটারেটর টাইপটি এলোমেলো-অ্যাক্সেস কিনা বা না, একটি পুনরাবৃত্তকারীকে n স্পেসে এগিয়ে নিয়ে যাওয়ার "সেরা" উপায়টি আপনার নিজের লুপটি নয়, কল করা std::advance(it, n)। এটি আপনি যা চান ঠিক তা করার জন্য এটি সংজ্ঞায়িত হয়েছে এবং এটির it + nপুনরুক্তি-অ্যাক্সেস হিসাবে ট্যাগ করা থাকলে এটি স্বয়ংক্রিয়ভাবে ব্যবহৃত হবে বা যদি এটি করতে হয় তবে লুপটি করে।
স্টিভ জেসোপ

61

সাধারণত, আয়ররেটরগুলি রৈখিক ফ্যাশনে ধারকগুলির উপাদানগুলি অ্যাক্সেস করতে ব্যবহৃত হয়; তবে, "এলোমেলো অ্যাক্সেস পুনরায়" দিয়ে, একই ফ্যাশনে যে কোনও উপাদান অ্যাক্সেস করা সম্ভব operator[]

করার একটি ভেক্টর অ্যাক্সেস নির্বিচারে উপাদান vec , আপনি নিম্নলিখিত ব্যবহার করতে পারেন:

vec.begin()                  // 1st
vec.begin()+1                // 2nd
// ...
vec.begin()+(i-1)            // ith
// ...
vec.begin()+(vec.size()-1)   // last

নিম্নলিখিতটি একটি অ্যাক্সেস প্যাটার্নের একটি উদাহরণ (সি ++ এর পূর্ববর্তী সংস্করণ):

int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
    sum += *it;
}

পুনরুক্তিকারী ব্যবহারের সুবিধা হ'ল আপনি অন্যান্য পাত্রে একই প্যাটার্ন প্রয়োগ করতে পারেন :

sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
    sum += *it;
}

এই কারণে, টেম্পলেট কোড তৈরি করা সত্যই সহজ যা ধারক প্রকার নির্বিশেষে একই কাজ করবে । পুনরাবৃত্তির আরেকটি সুবিধা হ'ল এটি ধরে নেই যে ডেটা মেমরির বাসিন্দা; উদাহরণস্বরূপ, কেউ একটি ফরোয়ার্ড ইটারেটর তৈরি করতে পারে যা কোনও ইনপুট স্ট্রিম থেকে ডেটা পড়তে পারে, বা এটি ফ্লাইতে ডেটা উত্পন্ন করে (যেমন একটি পরিসর বা এলোমেলো সংখ্যা জেনারেটর)।

std::for_eachল্যাম্বডাস ব্যবহার করে আর একটি বিকল্প :

sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });

যেহেতু সি ++ 11 আপনি autoপূর্বে দেখানো (বা আরও জটিল) এর পুনরাবৃত্তির খুব দীর্ঘ, জটিল ধরণের নাম নির্দিষ্ট করে এড়াতে ব্যবহার করতে পারেন :

sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
    sum += *it;
}

এবং, উপরন্তু, প্রতিটি বৈকল্পিক জন্য একটি সহজ আছে:

sum = 0;
for (auto value : vec) {
    sum += value;
}

এবং অবশেষে এমনও রয়েছে std::accumulateযেখানে আপনাকে পূর্ণসংখ্যা বা ভাসমান পয়েন্ট সংখ্যা যুক্ত করা হচ্ছে কিনা সে বিষয়ে আপনাকে সতর্কতা অবলম্বন করতে হবে।


53

সি ++ - 11 এ আপনি করতে পারেন:

std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (auto i : v)
{
   // access by value, the type of i is int
   std::cout << i << ' ';
}
std::cout << '\n';

বিভিন্নতার জন্য এখানে দেখুন: https://en.cppreferences.com/w/cpp/language/range- for


4
কেন এই জিরো পছন্দ হয় ?! <3
jperl

3
@ jperl 8 বছর দেরী পোস্ট করেছেন। পর্যাপ্ত পরিমাণে আপলোড পেতে পরবর্তী 8 বছর সময় লাগবে :)
লাশগার

@ জ্যাপারেল, ভাল উত্তরটি অফ-টপিক। যদিও এই লুপটির বৈশিষ্ট্যটি দুর্দান্ত, এটি আপনাকে কখন নবম এলিমেন্টে রয়েছেন তা জানতে সহায়তা করে না, যা ওপি'র প্রশ্ন। এছাড়াও, এই উত্তরটির মতো ও (এন) সময়ের জটিলতার যে কোনও উত্তর খুব খারাপ। কোনও ভেক্টরের নবম উপাদান অ্যাক্সেস করা সর্বদা ও (1) হওয়া উচিত।
এলিয়ট

@ ল্যাশগর আমি অ্যারে দিয়ে চেষ্টা করেছিলাম কিন্তু ব্যর্থ হয়েছি। এটি অ্যারের জন্য কাজ করে?
যুগ s'q

@ ইরাস'উ, 7.5.0উবুন্টু ১৮.০৪-তে জিসিসি দিয়ে চেষ্টা করে এবং অ্যারেতে একইভাবে কাজ করে।
লশগার

17

ভেক্টরের পুনরুক্তিগুলি এলোমেলোভাবে প্রবেশের পুনরাবৃত্তি যার অর্থ তারা সরল পয়েন্টারগুলির মতো দেখতে এবং অনুভব করে।

আপনি ধারকটির begin()পদ্ধতি থেকে ফিরে আসা পুনরুক্তিতে এন যোগ করে নবম উপাদানটি অ্যাক্সেস করতে পারেন বা আপনি অপারেটরটি ব্যবহার করতে পারেন []

std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();

int sixth = *(it + 5);
int third = *(2 + it);
int second = it[1];

বিকল্পভাবে আপনি অগ্রিম ফাংশনটি ব্যবহার করতে পারেন যা সব ধরণের পুনরাবৃত্তির সাথে কাজ করে। (আপনি সত্যই এলোমেলো অ্যাক্সেস পুনরুদ্ধারকারীদের সাথে "র্যান্ডম অ্যাক্সেস" করতে চান কিনা তা বিবেচনা করতে হবে, কারণ এটি করা ব্যয়বহুল জিনিস হতে পারে))

std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();

std::advance(it, 5);
int sixth = *it;

1
আপনি advanceএলোমেলোভাবে অ্যাক্সেস পুনরুদ্ধারকারী বা অজানা বিভাগের পুনরাবৃত্তকারীদের জন্যও ব্যবহার করতে পারেন , যেহেতু সেই ক্ষেত্রে স্থির সময়ে চালিত হওয়ার গ্যারান্টিযুক্ত। এই কারণেই ব্যবহারকারী-সংজ্ঞায়িত পুনরাবৃত্তিগুলি সঠিকভাবে ট্যাগ করা উচিত।
স্টিভ জেসোপ

প্রকৃতপক্ষে, তবে advanceআপনি যদি এলোমেলো অ্যাক্সেস পুনরাবৃত্তিকারীদের সাথে ডিল করে থাকেন তবে আপনি ব্যবহার করতে পারা মাত্র (প্যারামিটার ব্যবহারের কারণে) বিরক্তিকর। কেবল জেনেরিক কোডে সুপারিশ করবে, এবং যদি খুব বেশি ব্যবহার না করা হয় (যদি অ্যালগোরিদম অ-র্যান্ডম-অ্যাক্সেস পুনরুদ্ধারকারীদের ভালভাবে সমর্থন করে না, তবে তা হ'ল - উদাহরণস্বরূপ, একটি বাছাই std::sort করতে পারেstd::list তবে এটি এটি হাস্যকরভাবে অক্ষম হবে কারণ )।
আঙ্কেলবেন্স

অবশ্যই, ক্লাসিক উদাহরণটি হ'ল যদি আপনার অ্যালগরিদমটি কেবলমাত্র একটি ইনপুটআইটিটার প্রয়োজন হয় তবে যে কোনও কারণেই এটি কখনও কখনও এগিয়ে যায়, তাই যদি আপনি পুনরাবৃত্তিটির এলোমেলো অ্যাক্সেস না পান তবে আপনি এটি আরও দক্ষ হতে চান। এটি ব্যবহার করে আপনার অ্যালগরিদমকে এলোমেলো অ্যাক্সেসে সীমাবদ্ধ রাখার মতো নয় operator+। তবে প্রশ্নটি স্পষ্টভাবে ভেক্টর সম্পর্কে ছিল, সুতরাং আপনার উত্তরের প্রথম অংশে কোনও ভুল নেই। আমি কেবল ভেবেছিলাম দ্বিতীয় ভাগটি "আপনি এলোমেলো অ্যাক্সেস পুনরুদ্ধারকারীদের সাথে অগ্রিম ব্যবহার করতে পারবেন না, এমনকি যদি আপনি advanceআগে কখনও দেখেননি এমন কাউকে" করতে চান তবে।
স্টিভ জেসোপ

ঠিক আছে, সেই বিটটিকে উচ্চারণ করলেন এবং ভেক্টরের সাথে উদাহরণ দিলেন।
আঙ্কেলবেন্স 14

দ্বিতীয় লাইনটি Vectorনিম্নতর হওয়া উচিত
লেই ইয়াং

0

এখানে লুপের মধ্যে একটি ব্যবহার করে এর ithসূচক অ্যাক্সেস করার একটি উদাহরণ রয়েছে যার জন্য দুটি পুনরুক্তি বৃদ্ধির প্রয়োজন হয় না।std::vectorstd::iterator

std::vector<std::string> strs = {"sigma" "alpha", "beta", "rho", "nova"};
int nth = 2;
std::vector<std::string>::iterator it;
for(it = strs.begin(); it != strs.end(); it++) {
    int ith = it - strs.begin();
    if(ith == nth) {
        printf("Iterator within  a for-loop: strs[%d] = %s\n", ith, (*it).c_str());
    }
}

একটি লুপ ছাড়া

it = strs.begin() + nth;
printf("Iterator without a for-loop: strs[%d] = %s\n", nth, (*it).c_str());

এবং atপদ্ধতি ব্যবহার :

printf("Using at position: strs[%d] = %s\n", nth, strs.at(nth).c_str());
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.