ما هي نصائحك لتتبع وتجنب الأخطاء في الحلقات؟

StackOverflow https://stackoverflow.com/questions/1011712

  •  06-07-2019
  •  | 
  •  

سؤال

لقد وجدت ...مرة أخرى ...خطأ هدر في الوقت الحقيقي على النحو التالي

for (int i = 0; i < length; i++)
{ //...Lots of code 
    for (int j = 0; i < length; j++)
    {
        //...Lots of code 
    }
}

هل لاحظت مباشرة الجزء الداخلي i الذي يجب أن يكون j ؟ولا أنا.لذلك من الآن فصاعدا سأستخدم:

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

ما هي نصائحك للحلقات الداخلية والخارجية والحلقات؟

يحرر:شكرا على الردود القيمة.وفيما يلي ملخص قصير للنصائح المقترحة:

  • استخدم أسماء متغيرات ذات معنى لمتغيرات الفهرس (بدلاً من ذلك أستخدم SomeObjCollectionLength)
  • ضع محتويات الحلقة الداخلية في طريقة منفصلة واستدعاء هذه الطريقة من الحلقة الخارجية
  • يعد عدم وجود عدد يمكن التحكم فيه من أسطر التعليمات البرمجية بين الحلقة الخارجية والداخلية إشارة قوية لرائحة التعليمات البرمجية
  • تجنب النسخ واللصق والتسرع، واكتب الفهرس vars بعناية

قد ترغب في التحقق من الملخص عن طريق لبوشكين ل التالي

  • استخدم foreach والتكرارات كلما أمكن ذلك
  • تهيئة المتغيرات قبل الدخول إلى الحلقات مباشرة
  • اجعل كل حلقة تؤدي وظيفة واحدة فقط.تجنب خلط المسؤوليات في حلقة واحدة
  • عندما يكون ذلك ممكنًا، اجعل حلقاتك قصيرة بما يكفي لعرضها كلها مرة واحدة
هل كانت مفيدة؟

المحلول

لا تستخدم i & j (أو أي متغير آخر يتكون من حرف واحد) كأسماء فهرس.استخدم الأسماء الصحيحة ولن تدخل في هذا النوع من المشاكل.

نصائح أخرى

أحد أبسط وأنظف الحلول هو وضع محتويات الحلقة الداخلية في طريقة بحيث تصبح:

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

private void DoSomething(int outerValue)
{
    for (int i = 0; i < length; i++)
    {
        // Do something else
    }

}

بالنسبة لي، "رائحة الكود" هنا هي "الكثير من الكود".

إذا كانت كمية التعليمات البرمجية في الحلقات كبيرة بشكل خاص، فإن المسافة بين الحلقات الداخلية والخارجية تعني أنه من غير المحتمل مقارنتها ببعضها البعض للتأكد من صحتها.

من المسلم به أن النظر إلى بداية الحلقة الداخلية بشكل منفصل يجب أن يلفت انتباهك إلى المشكلة، ولكن وجود البنية الرئيسية في قسم صغير قدر الإمكان من التعليمات البرمجية يمنح عقلك قدرًا أقل من الهضم.

قد يكون من الممكن استخراج أقسام "الكثير من التعليمات البرمجية" في وظائف/طرق منفصلة، ​​من أجل تقليل حجم البنية الرئيسية - ولكن هذا قد لا يكون عمليًا دائمًا.

أيضًا، أود أن أقول إن "i1" ليس اختيارًا جيدًا بشكل خاص لاسم المتغير، لأن ذلك يميل إلى تشجيع "i2" و"i3" وما إلى ذلك، وهو ما لا يؤدي حقًا إلى تعليمات برمجية مفهومة.ربما يؤدي استبدال جميع متغيرات الحلقة بشيء أكثر أهمية إلى المساعدة في وضوح الكود وتقليل فرص حدوث الخطأ الأصلي.

أهم نصيحتي (بدون ترتيب معين) لكتابة كود حلقة أفضل (معظم هذا مأخوذ من الكتاب الممتاز اكتمال الكود):

  1. تجنب نقاط الخروج المتعددة للحلقات.
  2. استخدم الاستمرار/الاستراحة باعتدال.
  3. قم بإعادة بناء الحلقات المتداخلة في إجراءات منفصلة، ​​عندما يكون ذلك ممكنًا.
  4. استخدم أسماء متغيرات ذات معنى لجعل الحلقات المتداخلة قابلة للقراءة.
  5. استخدم حلقات foreach() عندما يكون ذلك ممكنًا، بدلاً من حلقات for(i=...).
  6. أدخل الحلقة من مكان واحد فقط.لا تقفز إلى حلقة مع goto.أبدًا.
  7. ضع رمز التهيئة مباشرة قبل الحلقة.
  8. احتفظ ببيانات تهيئة الحلقة مع الحلقة المرتبطة بها.
  9. تجنب إعادة استخدام المتغيرات بين الحلقات غير المتداخلة.10. حدد نطاق متغيرات فهرس الحلقة بالحلقة نفسها.
  10. استخدم while(true) للحلقات اللانهائية، بدلاً من for(;;)
  11. في اللغات التي توفر بنيات الكتلة (على سبيل المثال.'{' و '}') استخدمهما بدلاً من المسافة البادئة لإحاطة عبارات الحلقة.نعم، حتى بالنسبة للحلقات ذات السطر الواحد.
  12. تجنب الحلقات الفارغة.
  13. تجنب وضع أعمال التدبير المنزلي في منتصف الحلقة، وضعها في البداية و/أو النهاية بدلاً من ذلك.
  14. اجعل كل حلقة تؤدي وظيفة واحدة فقط.تجنب خلط المسؤوليات في حلقة واحدة.
  15. اجعل شروط إنهاء الحلقة واضحة.
  16. لا تستخدم متغير فهرس الحلقة الخاص بحلقة for() لإنهائها.
  17. تجنب التعليمات البرمجية التي تعتمد على القيمة النهائية لمفهرس الحلقة.
  18. فكر في استخدام عدادات الأمان في الحلقات المعقدة - يمكن التحقق منها للتأكد من عدم تنفيذ الحلقة مرات كثيرة جدًا أو قليلة جدًا.
  19. استخدم عبارات الاستراحة، عندما يكون ذلك ممكنًا، لإنهاء الحلقات.
  20. عندما يكون ذلك ممكنًا، اجعل حلقاتك قصيرة بما يكفي لعرضها كلها مرة واحدة.

هذا خطأ نسخ ولصق، تجنب النسخ واللصق.

أما بالنسبة للحل الخاص بك، فهو ليس أفضل بكثير.لا يزال من الممكن أن ينزلق الخطأ بين الكثير من التعليمات البرمجية.أميل إلى استخدام أسماء ذات معنى حتى بالنسبة للمتغيرات المؤقتة للحلقة.

الاستفادة من IDE الخاص بك، على VS، حاول استخدام هذا: http://msdn.microsoft.com/en-us/library/z4c5cc9b(VS.80).aspx

عينة:يكتب ل, ، ثم اضغط علامة تبويب على التوالي

جئت إلى هنا لأكون ذكيًا وأقول "أنا أكتبها بشكل صحيح في المرة الأولى".ولكن بعد ذلك رأيت مثالك، حسنًا، لقد فعلت ذلك مرات عديدة بنفسي.

عندما تحتاج إلى حلقات متداخلة كهذه، فإن الحل الوحيد هو أن تكون يقظًا وتفكر عند كتابة الكود.

حيثما أمكن، يعد استخدام التكرارات ولكل حلقة أمرًا رائعًا.

وأيضًا، لا أستطيع أن أرى كيف سيكون الحل المقترح أفضل.ولا تبدو جميلة أيضًا.

بادئ ذي بدء، قم بتقليل حجم جسم الحلقة، أي.نقل الأشياء إلى وظائف منفصلة.إنها فكرة سيئة بشكل عام أن يكون لديك وظائف أطول مما يمكن أن يتناسب مع الشاشة، لذلك يجب أن تكون الحلقات أصغر.

ثانيًا، استخدم أسماء متغيرات ذات معنى في مثل هذه الحالات.سأستخدم i وj فقط في حلقات بسيطة تحتوي على بضعة أسطر من التعليمات البرمجية.على سبيل المثال، إذا كنت تمر بمصفوفة ثنائية الأبعاد، فإن "col" و"row" سيكونان أكثر منطقية، ويجعلان قراءة التعليمات البرمجية أسهل ("أيهما؟") ويسهل اكتشاف أخطاء مثل هذه.

كل ما عليك فعله هو الاهتمام بمثل هذه المشكلات، فليس هناك حل سحري ضد ذلك.حتى مع "التسمية الأفضل" التي تقترحها، ستفقد من حين لآخر ما إذا كان هذا هو المستوى N أو (N+M) من الحلقة المتداخلة وترتكب خطأ.

إذا كانت الحلقة المتداخلة ضرورية، فاكتبها بعناية.إذا كان من الممكن تجنب ذلك عن طريق استخراج جسم الحلقة الخارجية إلى وظيفة من شأنها أن تكون بمثابة حارس جيد ضد سوء استخدام المؤشرات.

أستخدم "ii" و"jj" لعدادات الحلقة العابرة إذا كنت في حاجة إليها حقًا - حيث يسهل البحث عنها أكثر من "i" و"j" كما يسهل اكتشافها في أمثلة مثل ما سبق.للمضي قدماً بشكل أفضل، يمكنك بالفعل استخدام اسم متغير حقيقي.إذا كنت تقوم بالتكرار فوق سلسلة، فيمكنك تسميتها CharacterIndex أو شيء من هذا القبيل.إنها عملية كتابة أكثر، ولكنها توثق نفسها وتوفر الوقت في تصحيح المشكلات الغامضة لاحقًا.

والأفضل من ذلك هو تجنب العدادات الرقمية واستخدام التكرارات المسماة على المجموعة.إنهم يجعلون النية أكثر وضوحًا، في رأيي.

أخيرًا، إذا كان ذلك ممكنًا، فمن الجيد التخلص من الحلقة تمامًا: تعزيز::للبحث هي إحدى طرق القيام بذلك في C++، على الرغم من أنني أفضل عمومًا استخدام لغات مثل Python التي تسمح أصلاً بالتكرار المباشر على محتويات الحاوية دون الحاجة إلى زيادة قيمة فهرس أو مكرر.

حاول استخدام بنيات حلقة تعريفية أكثر.على سبيل المثال، إذا كنت لا تحتاج حقًا إلى المؤشرات (تلك iرمل js) وبيئة البرمجة الخاصة بك تسمح بذلك، يمكنك استخدام ملف foreach إنشاء للتكرار على المجموعة.

كما هو الحال في هذا كما هو الحال في أشياء كثيرة، هناك بعض النصائح الممتازة في ستيف ماكونيل اكتمال الكود.سيكون من المفيد أن تقضي وقتك في قراءة ما سيقوله حول إنشاء كود تكراري جيد.ليس لدي نسخة من الكتاب في متناول يدي هنا ولكن الكتاب بأكمله يستحق وقتك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top