লুপের জন্য আমি কীভাবে একটি সি ++ তে দুটি বর্ধন বিবরণী রাখি?


93

আমি একটি forপরিবর্তে একটি লুপ অবস্থায় দুটি ভেরিয়েবল বৃদ্ধি করতে চাই ।

সুতরাং যেমন কিছু:

for (int i = 0; i != 5; ++i and ++j) 
    do_something(i, j);

এর সিনট্যাক্স কী?

উত্তর:


155

একটি প্রচলিত প্রজ্ঞা হ'ল কমা অপারেটরটি ব্যবহার করা যা উভয় অপারেন্ডকে মূল্যায়ন করে এবং দ্বিতীয় অপারেন্ডকে ফিরিয়ে দেয়। এইভাবে:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

তবে এটি কি আসলেই কমা অপারেটর?

এখন এটি লিখেছেন, একজন মন্তব্যকারী পরামর্শ দিয়েছিলেন যে এটি আসলে বিবৃতি দেওয়ার জন্য কিছু বিশেষ সিনট্যাকটিক চিনি ছিল, এবং কোনও কমা অপারেটর নয়। আমি জিসিসিতে এটি নীচে পরীক্ষা করেছি:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

আমি এক্স এর মূল মান বাছাই করার প্রত্যাশা করছিলাম, সুতরাং এটি এক্স এর জন্য 5,6,7 .. প্রদর্শিত হবে। যা পেলাম তা এই ছিল

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

যাইহোক, আমি যদি পার্সারটিকে সত্যিকার অর্থে কমা অপারেটরকে দেখে জোর করার জন্য অভিব্যক্তিটি বন্ধন করেছিলাম তবে আমি এটি পেয়েছি

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

প্রাথমিকভাবে আমি ভেবেছিলাম যে এটি দেখায় এটি একেবারে কমা অপারেটর হিসাবে আচরণ করছে না, তবে যেমনটি দেখা যাচ্ছে যে কমা অপারেটরের সম্ভাব্যতমতম নজির রয়েছে , তাই এক্স = আই ++, একটি ++ কার্যকরভাবে কার্যকর (x = i ++), a ++ হিসাবে পার্স করা হয়েছে

সমস্ত মন্তব্যের জন্য ধন্যবাদ, এটি একটি আকর্ষণীয় শেখার অভিজ্ঞতা ছিল, এবং আমি সি ব্যবহার করছি বহু বছর ধরে!


4
আমি বহুবার পড়েছি যে লুপ জন্য একটি প্রথম বা তৃতীয় অংশে কমা হয় না কমা অপারেটর, কিন্তু একটি কমা বিভাজক। (তবে, আমি এটির জন্য একটি সরকারী উত্স খুঁজে পেতে ব্যর্থ, যেহেতু আমি বিশেষত সি ++ ভাষার মানকে পার্স করার ক্ষেত্রে বিশেষভাবে খারাপ))
ড্যানিয়েল দারানাস

আমি প্রথমে ভেবেছিলাম আপনি ভুল, কিন্তু আমি কিছু পরীক্ষার কোড লিখেছি এবং আপনি সঠিক - এটি কমা অপারেটরের মতো আচরণ করে না। আমার উত্তর সংশোধন করবে!
পল ডিকসন

19
এটা তোলে হয় যে প্রেক্ষাপটে একটি কমা অপারেটর। আপনি যেটি প্রত্যাশা করছেন তা পাচ্ছেন না কারণ হ'ল কমান্ড অপারেটরের অ্যাসাইনমেন্ট অপারেটরের চেয়ে কম অগ্রাধিকার রয়েছে, সুতরাং প্যারান্থিস ছাড়াই এটি (x = i ++), j ++ হিসাবে পার্স করে।
ক্যাফে

6
এটি একটি কমা অপারেটর। অ্যাসাইনমেন্টটি কমা অপারেটরের চেয়ে আরও দৃ strongly়তার সাথে সম্পর্কযুক্ত, সুতরাং x = i ++, একটি ++ পার্স করা হয়েছে (x = i ++), a ++ এবং x = (i ++, a ++) নয়। সেই বৈশিষ্ট্যটি কিছু লাইব্রেরি দ্বারা অপব্যবহার করা হয় যাতে v = 1,2,3; স্বজ্ঞাত জিনিসগুলি করে তবে কেবলমাত্র v = 1 একটি প্রক্সি অবজেক্ট ফিরিয়ে দেয় যার জন্য ওভারলোডড কমা অপারেটর একটি অ্যাপেন্ড করে।
এপ্রোগ্রামার 11

4
ঠিক আছে. ওপেন -std.org/jtc1/sc22/wg21/docs/papers/2009/n2857.pdf বিভাগ থেকে 6.5.3 শেষ অংশটি একটি "এক্সপ্রেশন"। (যদিও 1.6 # 2 একটি "এক্সপ্রেশন-তালিকা "টিকে" কমা দ্বারা বিভক্ত এক্সপ্রেশনগুলির তালিকা "হিসাবে সংজ্ঞায়িত করেছে, এই নির্মাণটি 6.5.3 এ প্রদর্শিত হবে না।) এর অর্থ হ'ল আমরা যখন "++ i, ++ j" লিখি তখন এটি নিজেই একটি প্রকাশ হতে হবে এবং এইভাবে "," অবশ্যই কমা অপারেটর (5.18) হতে হবে। (এটি একটি "আরম্ভকারীদের তালিকা" বা "ফাংশনগুলির পক্ষে যুক্তিগুলির তালিকা" নয়, উদাহরণস্বরূপ যেখানে "কমা একটি বিশেষ অর্থ প্রদান করা হয়", যেমন 5.18 # 2 বলেছেন।))। যদিও আমি এটি কিছুটা বিভ্রান্তিকর মনে করি।
ড্যানিয়েল দারানাস

56

এটা চেষ্টা কর

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

18
+1 আপনি প্রথম অংশে j ঘোষণা করতে পারেন। (int i = 0, j = 0; i! = 5; ++ i, ++ j) এর জন্য {...}
ড্যানিয়েল দারানাস

4
+1 পার্শ্ব-নোট হিসাবে, এই একই বাক্য গঠনটি সি # তে কাজ করে (আমি এখানে গুগল অনুসন্ধান থেকে "লুপ ইনক্রামেন্ট 2 কাউন্টারগুলির জন্য" গুগল অনুসন্ধান থেকে পেয়েছি তাই ভেবেছিলাম আমি এটি উল্লেখ করব)।
কোডিং উইথস্পাইক

@CodingWithSpike: ওয়েল, সি # কমা হয় বিশেষ, তাই না আসলে আইনগত একটি কমা অপারেটর অভিব্যক্তি সেখানে উপস্থিত হওয়ার জন্য নয়। সি ++ তে কমা অপারেটরের আইনী ব্যবহারের উদাহরণ, তবে সি # দ্বারা প্রত্যাখ্যাত:for( ; ; ((++i), (++j)) )
বেন ভয়েগট

@ বেনভয়েগের কমা দিয়ে কিছু করার নেই। এটি হয় আইনী সি # নয়: for(int i = 0; i != 5; (++i)) {অতিরিক্ত প্যারেনসিস সংকলকটিকে ভাবতে প্ররোচিত করে যে এটি আর কোনও "ইনক্রিমেন্ট" অপারেশন নয়।
কোডিংবিথস্পাইকে

@CodingWithSpike: তা সত্য, কিন্তু প্রথম বন্ধনী এছাড়াও পরিবর্তন কিভাবে সি শার্প কমা আটকায় এবং কর্মের জন্য ভিতরে বিশেষ অর্থ সূচিত করা হবে।
বেন ভয়েগট

6

এটি না করার চেষ্টা করুন!

Http://www.research.att.com/~bs/JSF-AV-rules.pdf থেকে :

এভি বিধি 199 199
লুপের জন্য ইনক্রিমেন্ট এক্সপ্রেশন লুপের জন্য পরবর্তী মানটিতে একটি একক লুপ পরামিতি পরিবর্তন করা ছাড়া আর কোনও পদক্ষেপ করবে না।

যুক্তি: পাঠযোগ্যতা।


4
এটি সত্য, তবে ন্যায়পরায়ণভাবে আমি দৃ sure়ভাবে নিশ্চিত যে কোনও ফাইটার জেটে এম্বেড করা সফ্টওয়্যার জন্য নিয়মের মান লেখা হয়েছিল, বাগানের বিভিন্ন সি (++) প্রোগ্রাম নয়। এটি বলা হচ্ছে, সম্ভবত এটি পড়ার পক্ষে একটি ভাল অভ্যাস .োকা এবং কে জানে, সম্ভবত আপনি এফ -35 সফ্টওয়্যারটি ডিজাইন করবেন এবং এটি ভাঙার একটি কম অভ্যাস হবে।
গ্যালোইস


2

আমি এখানে নিজেকে স্মরণ করিয়ে দিতে এসেছি যে কীভাবে একটি ফর লুপের ইনক্রিমেন্ট ক্লজে দ্বিতীয় সূচকটি কোড করা যায়, যা আমি জানতাম যে এটি মূলত আমি যে কোনও প্রকল্পে অন্তর্ভুক্ত করেছি এমন একটি নমুনায় পর্যবেক্ষণ করা যা সি ++ তে লেখা ছিল।

আজ, আমি সি # তে কাজ করছি, তবে আমি নিশ্চিত হয়েছি যে এটি এই ক্ষেত্রে একই নিয়ম মানবে, যেহেতু ফর স্টেটমেন্টটি সমস্ত প্রোগ্রামিংয়ের অন্যতম প্রাচীন নিয়ন্ত্রণ কাঠামো। ধন্যবাদ, আমি সম্প্রতি আমার পুরানো একটি সি প্রোগ্রামের একটি ফর লুপের আচরণের ডকুমেন্টিং করে বেশ কয়েক দিন অতিবাহিত করেছি এবং আমি দ্রুত বুঝতে পেরেছিলাম যে সেই গবেষণাগুলি এমন পাঠগুলি ধারণ করেছিল যা আজকের সি # সমস্যার ক্ষেত্রে প্রয়োগ হয়েছিল, বিশেষত দ্বিতীয় সূচক ভেরিয়েবলের আচরণের জন্য held ।

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

  1. যখন প্রথমবারের জন্য একটি লুপ কার্যকর হয়, তখন ইনক্রিমেন্ট ক্লজ (এর তিনটির মধ্যে ২ য়) এড়িয়ে যায়। ভিজ্যুয়াল সি এবং সি ++ এ ব্লকটির মাঝখানে তিনটি মেশিনের নির্দেশনা হিসাবে বর্ধন উত্পন্ন হয় যা লুপটি প্রয়োগ করে, যাতে প্রাথমিক পাসটি একবারে আরম্ভকরণ কোডটি চালায়, তারপরে সমাপ্তি পরীক্ষাটি সম্পাদন করতে ইনক্রিমেন্ট ব্লকের উপরে লাফ দেয়। এটি এমন বৈশিষ্ট্যটি কার্যকর করে যা একটি ফর লুপ তার সূচক এবং সীমাবদ্ধ ভেরিয়েবলের অবস্থার উপর নির্ভর করে শূন্য বা আরও বেশি বার কার্যকর করে।
  2. লুপের বডি যদি কার্যকর করে, এর শেষ বিবৃতিটি প্রথম পুনরাবৃত্তি দ্বারা এড়ানো তিনটি বর্ধনের নির্দেশাবলীর প্রথমটিতে একটি লাফ। এই কার্যকর করার পরে, নিয়ন্ত্রণটি স্বাভাবিকভাবেই সীমা পরীক্ষা কোডের মধ্যে পড়ে যা মধ্যম ধারাটি প্রয়োগ করে। এই পরীক্ষার ফলাফল নির্ধারণ করে যে ফোর লুপের শরীরটি কার্যকর করে কিনা, বা নিয়ন্ত্রণ তার স্কোপের নীচে জাম্পের পরবর্তী নির্দেশে স্থানান্তরিত হয় কিনা।
  3. যেহেতু নিয়ন্ত্রণ লুপ ব্লকের নীচে থেকে ইনক্রিমেন্ট ব্লকে স্থানান্তরিত হয়, পরীক্ষার সম্পাদনের আগে সূচক ভেরিয়েবলটি বাড়ানো হয়। এই আচরণটি কেবল তা আপনাকে বোঝায় না যে আপনি নিজের সীমাবদ্ধতা অনুধাগুলি যেভাবে শিখেছিলেন সেভাবে কোড করতে হবে, তবে এটি কমা অপারেটরের মাধ্যমে আপনি যে কোনও গৌণ বর্ধনকে যুক্ত করেন তা প্রভাবিত করে কারণ এটি তৃতীয় ধারাটির অংশ হয়ে যায়। সুতরাং, এটি প্রথম পুনরাবৃত্তির পরিবর্তে পরিবর্তিত হয়নি, তবে এটি সর্বশেষ পুনরাবৃত্তির উপর রয়েছে, যা কখনই শরীরকে কার্যকর করে না।

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


1

আমি squelart সাথে একমত। দুটি ভেরিয়েবল বৃদ্ধি করা বাগ প্রবণ, বিশেষত যদি আপনি কেবল তার মধ্যে একটির জন্য পরীক্ষা করেন।

এটি করার পঠনযোগ্য উপায়:

int j = 0;
for(int i = 0; i < 5; ++i) {
    do_something(i, j);
    ++j;
}

Forলুপগুলি এমন ক্ষেত্রে বোঝানো হয় যেখানে আপনার লুপটি একটি ক্রমবর্ধমান / হ্রাসযোগ্য চলকটির উপরে চলে। অন্য কোনও ভেরিয়েবলের জন্য এটি লুপে পরিবর্তন করুন।

যদি আপনার jসাথে আবদ্ধ হওয়ার প্রয়োজন হয় i, তবে কেন মূল আসলটি যুক্ত হিসাবে যুক্ত করে যুক্ত করবেন না i?

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

যদি আপনার যুক্তি আরও জটিল হয় (উদাহরণস্বরূপ, আপনাকে আসলে একাধিক পরিবর্তনশীল নিরীক্ষণ করতে হবে), আমি একটি whileলুপ ব্যবহার করব ।


4
প্রথম উদাহরণে, j আমার চেয়ে একবারে বাড়ানো হয়েছে! এমন একটি পুনরাবৃত্তকারী সম্পর্কে কী যেখানে প্রথম এক্স পদক্ষেপের জন্য কিছু পদক্ষেপ নেওয়া দরকার? (এবং সংগ্রহটি সর্বদা যথেষ্ট দীর্ঘ) আপনি প্রতিটি পুনরাবৃত্তির চেয়ে পুনরুক্তি আরোহণের চেয়ে বেশি করতে পারেন তবে এটি বেশ পরিচ্ছন্ন ইমো।
পিটার স্মিট

0
int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

4
লুপটি তৈরি না করার iএবং aস্থানীয় করার বিষয়টি কী?
এসবিআই

4
কিছুই নেই, কেবলমাত্র উভয় বর্ধিত কীভাবে করা যায় তা দেখানো হচ্ছে, এটি কেবল সিনটেক্সের একটি উদাহরণ
আরকাইজ জিমনেজ

0

গণিত ব্যবহার করুন। দুটি অপারেশন যদি গাণিতিকভাবে লুপের পুনরাবৃত্তির উপর নির্ভর করে তবে কেন গণিত হবে না?

int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
    do_something (counter+i, counter+j);

বা আরও সুনির্দিষ্টভাবে ওপি-র উদাহরণ উল্লেখ করে:

for(int i = 0; i != 5; ++i)
    do_something(i, j+i);

বিশেষত যদি আপনি মূল্য অনুসারে কোনও ফাংশনে যাচ্ছেন তবে আপনার এমন কিছু পাওয়া উচিত যা আপনি যা চান ঠিক তেমন করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.