একটি 'for' লুপের ভিতরে 'for' লুপ একই কাউন্টের ভেরিয়েবল নামটি ব্যবহার করতে পারে?


107

আমি কি forলুপের ভিতরে লুপের জন্য একই পাল্টা ভেরিয়েবলটি ব্যবহার করতে পারি for?

বা ভেরিয়েবলগুলি একে অপরকে প্রভাবিত করবে? নীচের কোডটি কি দ্বিতীয় লুপের জন্য আলাদা ভেরিয়েবল ব্যবহার করা উচিত j, যেমন , বা iঠিক আছে?

for(int i = 0; i < 10; i++)
{
  for(int i = 0; i < 10; i++)
  {
  }
}

72
এটি বিভ্রান্তিকর - কোনও কোড পর্যালোচনায় এটি আমার অতীত হবে না। তবে এটি বৈধ। দুটি iস্কোপ সহ দুটি পৃথক ভেরিয়েবল রয়েছে । -Wshadowএই জাতীয় সমস্যাগুলি স্বয়ংক্রিয়ভাবে প্রতিবেদন করতে জিসিসির সাথে ব্যবহার করুন ।
জোনাথন লেফলার

15
আমি অবাক হই যে -Wshadowএতে অন্তর্ভুক্ত নেই -Wall
27:58

5
@ লেফটারাউন্ডাউউট -Wshadowবিশ্বব্যাপী ভেরিয়েবলের ছায়া নেওয়ার বিষয়েও সতর্ক করে, যা বড় প্রকল্পগুলিতে সহজেই বিরক্তিকর হয়ে উঠতে পারে।
কিউবিক

9
@ বামদিক থেকে আরও অবাক করেও, এমনকি -Wextraএতে অন্তর্ভুক্ত হয় না -Wshadow। আমি অনুমান করি যে এটি কিছু প্রকল্পে যথেষ্ট সাধারণ, বা কিছু জিসিসি বিকাশকারী ছায়া কাটা একটি কোডিং শৈলী হিসাবে পছন্দ করে, যাতে এইভাবে ছেড়ে দেওয়া যায় না warrant
হাইড

5
কিউবিক যা বলেছিল তা বোধ করে @ বামফ্রন্টাউন্ডে -Wshadowভয়াবহ মিথ্যা পজিটিভ রেট রয়েছে, একে পুরোপুরি অকেজো করে দিয়েছে। ব্যাপ্তি একটি কারণে উপস্থিত রয়েছে এবং ছায়া কাটা সমস্যাযুক্ত নয় এমন একটি অগ্রাধিকার । এখন -Wshadow-local(দ্রষ্টব্য: নয় -Wshadow=local ) খুব আলাদা। তবে দুর্ভাগ্যক্রমে জিসিসি এখনও পর্যন্ত এটিকে ট্রাঙ্কে অন্তর্ভুক্ত করতে অস্বীকার করেছে (যদিও এতে জিসিসির কাঁটাচামচ রয়েছে যা এতে অন্তর্ভুক্ত রয়েছে)।
কনরাড রুডল্ফ

উত্তর:


140

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

এটি সাধারণত খারাপ শৈলী, বিভ্রান্তির ঝুঁকিপূর্ণ এবং এড়ানো উচিত।

যদি int iআপনি দেখিয়েছেন তেমন অভ্যন্তরটি পৃথকভাবে সংজ্ঞায়িত করা হয় তবে অবজেক্টগুলি আলাদা । কোনও নতুন অবজেক্টকে সংজ্ঞায়িত না করে যদি একই নাম ব্যবহার করা হয় তবে লুপগুলি একই বস্তুটি ব্যবহার করবে এবং একে অপরের সাথে হস্তক্ষেপ করবে।


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

3
@ ব্লাডগেইন: "অবজেক্ট" একটি প্রযুক্তিগত শব্দ যা সি স্ট্যান্ডার্ডে ব্যবহৃত হয়। আমি এটি এখানে ইচ্ছাকৃতভাবে ব্যবহার করেছি।
এরিক পোস্টপিসিল

1
@ এরিকপোস্টপিসিল: আহা, আমি দেখছি, হ্যাঁ আমি স্ট্যান্ডার্ডে সেই সংজ্ঞাটি সম্পর্কে অবগত ছিলাম না, এবং ভয় পেয়েছিলাম যে এটি নতুন প্রোগ্রামারদের জন্য বিভ্রান্তিকর হবে (এটি এটি খুব স্পষ্টভাবে একটি প্রাথমিক প্রশ্ন), যেহেতু সি এর সাধারণ অর্থে আমরা এই শব্দটি ব্যবহার করি না সে অর্থে "অবজেক্ট" নেই। আমি এটি সি 11 স্ট্যান্ডার্ডে দেখছি, এবং এখন আমি কৌতূহলী যদি এটি সি 11 এর আগে এভাবে সংজ্ঞায়িত করা হত।
ব্লাডগেইন

1
ইহা ছিল. এটি C15 স্ট্যান্ডার্ডে 3.15 এর পরিবর্তে 3.14। সুতরাং আমার পক্ষ থেকে কোন অজুহাত। এটি আমাকে আপনাকে প্রশ্ন করতে শেখাবে <: - |
রক্তদান

1
আরও সাধারণভাবে: আপনাকে কোনও নেস্টেড স্কোপে ভেরিয়েবল নামটি পুনরায় ব্যবহার করা থেকে বিরত করার মতো কিছুই নেই। অবশ্যই, বিভ্রান্তিকর কোড লেখার জন্য Punশ্বরের শাস্তির ভয়।
আইজাক রবিনোভিচ 23

56

প্রথমত, এটি একেবারেই আইনী: কোডটি সঙ্কলিত এবং চলবে, নেস্টেড লুপের 10 × 10 = 100 বার বার করে body iনেস্টেড লুপের অভ্যন্তরে লুপের কাউন্টারটি বাইরের লুপের কাউন্টারকে আড়াল করবে , সুতরাং দুটি কাউন্টার পৃথকভাবে একে অপরের থেকে বর্ধিত হবে।

যেহেতু বাহ্যিকটি iলুকানো রয়েছে তাই নেস্টেড লুপের দেহের অভ্যন্তরের কোডটিতে কেবল বাইরের লুপ থেকে iনয় নেস্টেড লুপের মান অ্যাক্সেস থাকবে i। এমন পরিস্থিতিতে যখন নেস্টেড লুপের বাইরের iযেমন কোডটিতে অ্যাক্সেসের প্রয়োজন হয় না তা পুরোপুরি ন্যায়সঙ্গত হতে পারে। তবে এটি সম্ভবত এটির পাঠকদের আরও বিভ্রান্তি তৈরি করতে পারে, তাই "রক্ষণাবেক্ষণের দায়বদ্ধতা" এড়ানোর জন্য এই জাতীয় কোডটি এড়ানো এড়ানো ভাল ধারণা।

দ্রষ্টব্য: যদিও উভয় লুপের কাউন্টার ভেরিয়েবলগুলির একই শনাক্তকরণ রয়েছেi থাকা সত্ত্বেও তারা দুটি স্বতন্ত্র ভেরিয়েবল রয়ে গেছে, আপনি উভয় লুপগুলিতে একই ভেরিয়েবল ব্যবহার করছেন না । উভয় লুপগুলিতে একই ভেরিয়েবল ব্যবহার করাও সম্ভব তবে কোডটি পড়া খুব কঠিন। এখানে একটি উদাহরণ:

for (int i = 1 ; i < 100 ; i++) {
    for ( ; i % 10 != 0 ; i++) {
        printf("%02d ", i);
    }
    printf("%d\n", i);
}

এখন উভয় লুপ একই ভেরিয়েবল ব্যবহার করে। তবে, কোডটি ( ডেমো ) সংকলন না করে এই কোডটি কী করে তা নির্ধারণের জন্য কিছুটা সময় নেয় ;


4
যেহেতু প্রশ্নটি "একই পাল্টা ভেরিয়েবল ব্যবহার করে" হিসাবে চিহ্নিত করা হয়েছে আমি এগুলিও উল্লেখ করতে চাই যে ছায়ামুখ কেবল তখনই ঘটে যখন পুনরায় সংজ্ঞাটি ঘটে। intলুপের জন্য অভ্যন্তরীণ অংশটি ছেড়ে দেওয়া , অর্থাৎ প্রকৃতপক্ষে একই কাউন্টার ভেরিয়েবলটি ব্যবহার করা হলে বাইরের লুপটি কেবল একবার চালিত হবে, কারণ অভ্যন্তরীণ লুপটি চলে যাবে i == 10। এটি তুচ্ছ, তবে ভেবেছিল কীভাবে প্রশ্নটি বর্ণিত হয়েছে তা প্রদত্ত স্পষ্টতা প্রদান করেছে
ইস্টন বোর্নিমেয়ার

@ ইস্টনবর্নমিয়ার আপনি ঠিক বলেছেন, আমি অনুভব করেছি যে উত্তরটির শরীরে আমার "একই পরিবর্তনশীল" ইস্যুটি সমাধান করা উচিত। ধন্যবাদ!
dasblinkenlight

@ এরিকপোস্টপিসিল "ভেরিয়েবল শেডাউনিং" একটি সরকারী শব্দ, যা উইকিপিডিয়ায় নিজস্ব পৃষ্ঠা দিয়ে সম্পূর্ণ । যদিও আমি উত্তরটির সাথে মানটির শব্দের সাথে সামঞ্জস্য রাখতে আপডেট করেছি। ধন্যবাদ!
dasblinkenlight

2
@ ড্যাসব্লিংকনলাইট: আসলে, দিক সম্পর্কে আমার মস্তিষ্কের স্প্যাম ছিল এবং অভ্যন্তরীণ নামটি বাইরের নামকে ছায়া দেয় shadow আমার আগের মন্তব্যটি সে ক্ষেত্রে ভুল ছিল। আমার ক্ষমা। (তবে এটি ইংরেজী অর্থে, সরকারী অর্থে নয় — উইকিপিডিয়া সাধারণভাবে সি বা প্রোগ্রামিংয়ের জন্য কোনও আনুষ্ঠানিক প্রকাশনা নয় এবং আমি কোনও অফিস বা অনুমোদনকারী সংস্থা যা এই শব্দটি সংজ্ঞায়িত করে তা সম্পর্কে অবগত নই।) সি স্ট্যান্ডার্ড ব্যবহার করে "আড়াল করুন", যাতে এটি পছন্দনীয়।
এরিক পোস্টপিসিল

দুর্দান্ত, বিশেষত "একই পরিবর্তনশীল" উদাহরণ সহ with তবে আমি মনে করি " কোডটি সঙ্কলিত এবং প্রত্যাশার মতো চলবে " আরও ভাল হবে "কোডটি এমন কেউ হিসাবে সংকলন করে চালিত হবে যিনি মনোযোগ সহকারে এটি পড়েছেন এবং প্রত্যাশিত সমস্ত পদক্ষেপগুলি বোঝেন " ... আপনি যেমন বলেছেন, কোড এর মতো " সম্ভবত " এটির পাঠকদের মধ্যে আরও বিভ্রান্তি তৈরি হতে পারে " এবং সমস্যাটি হ'ল বিভ্রান্ত পাঠক এটি থেকে ব্যতীত অন্য কিছু আশা করতে পারে।
ট্রিপহাউন্ড

26

আপনি পারেন। তবে আপনার এর স্কোপ সম্পর্কে সচেতন হওয়া উচিত i। যদি আমরা বাইরের কল iসঙ্গে i_1এবং ভেতরের iসঙ্গে i_2, সুযোগ is হিসেবে অনুসরণ করে হল:

for(int i = 0; i < 10; i++)
{
     // i means i_1
     for(int i = 0; i < 10; i++)
     {
        // i means i_2
     }
     // i means i_1
}

আপনার লক্ষ্য করা উচিত যে তারা একে অপরকে প্রভাবিত করে না এবং কেবল তাদের সংজ্ঞা দেওয়ার ক্ষেত্রটি আলাদা।


17

এটি সম্পূর্ণ সম্ভব তবে মনে রাখবেন, আপনি প্রথম ঘোষিত i কে সম্বোধন করতে পারবেন না

for(int i = 0; i < 10; i++)//I MEAN THE ONE HERE
{

  for(int i = 0; i < 10; i++)
    {

    }
}

দ্বিতীয় সন্তানের লুপের মধ্যে দ্বিতীয় লুপে

for(int i = 0; i < 10; i++)
{

  for(int i = 0; i < 10; i++)//the new i
    {
        // i cant see the i thats before this new i here
    }
}

যদি আপনাকে প্রথম i এর মান সামঞ্জস্য করতে বা পেতে হয় তবে দ্বিতীয় লুপে j ব্যবহার করুন

for(int i = 0; i < 10; i++)
{

  for(int j = 0; j < 10; j++)
    {

    }
}

এবং আপনার ক্রিয়েটিভ যথেষ্ট পরিমাণে যদি আপনি উভয়কে একটি লুপে করতে পারেন

for(int i ,j= 0; i < 10; (j>9) ? (i++,j=0) : 0 ,j++)
{
    printf("%d %d\n",i,j);
}

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

এটা এক লুপ এটি শুধুমাত্র এক হয়েছে, জন্য , লুপ যদি এটি 2 ছিল তার জন্য এবং যখন কীওয়ার্ড বা কীওয়ার্ড জন্য দুই দুই যখন কীওয়ার্ড বা একটি হবে
দোদোর

3
এজন্যই আমি বলেছিলাম আপনি লুপটি অবলম্বন করেছেন। আপনি এখনও লুপিং করছেন, আপনি এটিকে কম সুস্পষ্ট বাক্য গঠন দিয়ে লুকিয়ে রেখেছেন। এবং এটি এর জন্য প্রতিটি উপায়ে খারাপ।
ব্লাডগেইন

12

হ্যাঁ আপনি forবাইরের forলুপের মতো কোনও অভ্যন্তরীণ লুপের জন্য একই পাল্টা পরিবর্তনশীল নামটি ব্যবহার করতে পারেন ।

লুপের জন্য থেকে :

for ( init_clause ; cond_expression ; iteration_expression ) loop_statement
লুপ_স্টেটমেন্ট হিসাবে ব্যবহৃত এক্সপ্রেশন স্টেটমেন্টটি তার নিজস্ব ব্লক স্কোপ স্থাপন করে , init_clause এর ক্ষেত্র থেকে পৃথক

for (int i = 0; ; ) {
    long i = 1;   // valid C, invalid C++
    // ...
}  

পরিধি loop_statement হয় নেস্টেড সুযোগ মধ্যে init_clause

সি স্ট্যান্ডার্ডগুলি থেকে # 6.8.5p5 আইট্রেটেশন স্টেটমেন্ট [জোর আমার]

একটি পুনরাবৃত্তি বিবৃতি এমন একটি ব্লক যার স্কোপটি তার বদ্ধ ব্লকের সুযোগের একটি কঠোর উপসেট। লুপ বডিটিও একটি ব্লক যার স্কোপটি পুনরাবৃত্তির বিবৃতিটির স্কোপের একটি কঠোর উপসেট

সি স্ট্যান্ডার্ডগুলি থেকে # .2.২.১৪.৪ শনাক্তকারীদের স্কোপ [জোর দেওয়া আমার]

.... অভ্যন্তরীণ সুযোগের মধ্যে, শনাক্তকারীটি অন্তঃস্থলীয় স্কোপে ঘোষিত সত্তাকে মনোনীত করে; সত্তা বাইরের সুযোগ ঘোষণা লুকানো হয় (এবং দৃশ্যমান নয়) ভেতরের সুযোগ মধ্যে।


10

একটি কোড / সংকলক দৃষ্টিকোণ থেকে এটি করা একটি নিখুঁত বৈধ এবং আইনী জিনিস হবে। int iভেতরের ঘোষণা for(int i = 0; i < 10; i++)লুপ, একটি নতুন এবং ছোট সুযোগ যাতে ঘোষণা ছায়া ঘোষণা int iবাইরের লুপ (অথবা অন্যান্য শব্দের সঙ্গে: পরিবর্তনশীল ভেতরের সুযোগ ইন সব ব্যবহারের iযান int iভেতরের সুযোগ ঘোষণা ছাড়ার int iবাইরের সুযোগ অস্পৃষ্ট) এ।

এটি বলেছে যে একটি কোড মানের দৃষ্টিকোণ থেকে এটি সম্পূর্ণ ভয়ঙ্কর। এটি পড়া শক্ত, বোঝা শক্ত এবং ভুল বোঝা সহজ। এটা করবেন না।


8

হ্যাঁ, আপনি এটি ব্যবহার করতে পারেন তবে এটি বেশ বিভ্রান্তিকর। সর্বাধিক গুরুত্বপূর্ণ বিষয় হ'ল লুপের অভ্যন্তরে স্থানীয় ভেরিয়েবলের সুযোগ। যদি কোনও ফাংশনের অভ্যন্তরে যদি কোনও ভেরিয়েবল ঘোষণা করা হয় তবে সেই ভেরিয়েবলের ব্যাপ্তিটি সেই ফাংশন।

int a = 5;
// scope of a that has value 5
int func(){
    int a = 10;
   // scope of a that has value 10
}
// scope of a that has value 5

একইভাবে লুপগুলির ক্ষেত্রে, অভ্যন্তরীণ লুপের অভ্যন্তরে ঘোষিত ভেরিয়েবলের বিভিন্ন স্কোপ থাকে এবং ভেরিয়েবল ঘোষিত বহিরাগত লুপের আলাদা সুযোগ থাকে।

for(int i = 0; i < 10; i++){
    // In first iteration, value of i is 0

    for(int i = 1; i < 10; i++){
        // In first iteration, value of i is 1
    }
    // In first iteration, value of i is 0
}

অভ্যন্তরীণ এবং বাইরের লুপগুলির জন্য বিভিন্ন ভেরিয়েবল ব্যবহার করা আরও ভাল পদ্ধতির।

for(int i = 0; i < 10; i++){

    for(int j = 1; j < 10; j++){

    }

}

8

হ্যাঁ অবশ্যই আপনি একই নাম পরিবর্তনশীল ব্যবহার করতে পারেন।

সি প্রোগ্রামিং ভেরিয়েবলগুলি তিন জায়গায় ঘোষণা করা যেতে পারে:
স্থানীয় ভেরিয়েবল:-কোনও ফাংশন বা একটি ব্লকের ভিতরে।
গ্লোবাল ভেরিয়েবল: - সমস্ত ফাংশনের বাইরে।
আনুষ্ঠানিক পরামিতি: - ফাংশন পরামিতি মধ্যে।

তবে আপনার ক্ষেত্রে i scopeনীচের বিষয়গুলি মনে রাখতে হবে

for(int i = 0; i < 10; i++)
{
     // i means 1st for loop variable
     for(int i = 0; i < 10; i++)
     {
        // but here i means 2nd for loop  variable
     }
     //interesting thing here i means 1st for loop variable
}

দ্রষ্টব্য: অভ্যন্তরীণ এবং বাইরের লুপগুলির জন্য বিভিন্ন ভেরিয়েবল ব্যবহার করা ভাল অনুশীলন হবে


6

হ্যাঁ - এবং আরও মজার বিষয় আপনি প্রতিবার যখন বন্ধনীগুলির সেট খোলেন ততবার আপনি একটি পরিবর্তনশীল নামটি পুনরায় ব্যবহার করতে পারেন। ডায়গনিস্টিক কোড সন্নিবেশ করানোর সময় এটি প্রায়শই কার্যকর। ভেরিয়েবলের ঘোষণা এবং ব্যবহারের পরে একটি ওপেন ব্রেস '{' টাইপ করুন, তারপরে বন্ধনী বন্ধ করুন এবং ভেরিয়েবলগুলি চলে যাবে। এটি গ্যারান্টি দেয় যে ব্রেসগুলির বাইরে ঘোষিত কোনও চলক, শ্রেণি এবং পদ্ধতিগুলির সুবিধা বজায় রেখে আপনি মূল শরীরের কোনও কিছুর সাথে হস্তক্ষেপ করবেন না।


3

স্কোপ রুল: স্টেটমেন্টের জন্য ঘোষিত একটি পরিবর্তনশীল কেবল সেই বিবৃতিতে এবং লুপের মূল অংশে ব্যবহার করা যেতে পারে।

যদি আপনার কোডটিতে আপনি অভ্যন্তরীণ লুপগুলিতে i এর একাধিক উদাহরণ সংজ্ঞায়িত করেছেন প্রতিটি উদাহরণ তার নিজস্ব মেমরির স্থান দখল করবে। সুতরাং ফলাফলগুলি যেভাবেই হবে একই রকম হবে তা নিয়ে চিন্তার কিছু নেই।

int main(void) {

    int i = 2; //defined with file global scope outside of a function and will remain 2
    if(1)
    {       //new scope, variables created here with same name are different
        int i = 5;//will remain == 5
        for(int i = 0; i < 10; i++)
        {   //new scope for "i"

            printf("i value in first loop: %d \n", i); // Will print 0 in first iteration
            for(int i = 8; i < 15; i++) 
            {   //new scope again for "i", variable with same name is not the same
                printf("i value in nested loop: %d \n", i); // Will print 8 in first iteration
            }
        }

    }

    return 0;
}

তবে এটি একই পরিবর্তনশীল নামটি ব্যবহার করার পরামর্শ দেওয়া হয় না কারণ এটি বুঝতে অসুবিধা হয় এবং এটি পরে রক্ষণাবেক্ষণযোগ্য কোড হয়ে যায়।


1

গুরুত্বপূর্ণ অংশটি হ'ল অভ্যন্তরীণ লুপের প্যারামিটারে int i। কারণ iএইভাবে নতুন সংজ্ঞা দেওয়া হয়েছে, দুটি পরিবর্তনশীল একে অপরকে প্রভাবিত করে না; তাদের স্কোপগুলি আলাদা। এটি দেখানোর জন্য এখানে দুটি উদাহরণ দেওয়া হয়েছে:

for(int i = 0; i < 10; i++) // This code will print "Test" 100 times
{
 for(int i = 0; i < 10; i++)
 {
  puts("Test");
 }
}

নোট করুন যে উপরের কোডটি int iঅন্তঃস্থ লুপ প্যারামিটারের অন্তর্ভুক্ত রয়েছে এবং নীচের কোডটিতে কেবল অন্তর্ভুক্ত রয়েছে i

for(int i = 0; i < 10; i++) // This code will print "Test" 10 times
{
 for(i = 0; i < 10; i++)
 {
  puts("Test");
 }
}

0

ঠিক আছে, আপনি আপনার স্ক্রিপ্টগুলির কোনও সমস্যা না করেই এটি করতে পারেন তবে আপনার সেই কাঠামোটি এড়ানো উচিত। এটি সাধারণত বিভ্রান্তির দিকে পরিচালিত করে

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