سؤال

ومؤخرا لفئة البرمجة، لقد أعطيت المهمة لكتابة البرنامج في أي لغة، نظرا <م> ن ، وسوف تنتج كل خللا المحتملة لمجموعة <م> ص من حجم <م> ن بحيث <م> ص [أنا] = ط عن كل ما: 0 <= ط yield.

مثال: ن = 3، [0، 1، 2] ليس التشويش، ولكن [2، 0، 1] هو كذلك [1، 2، 0]

.

وجئت إلى حل شبة الكود من شأنها أن تعمل، ولكن المشكلة أنه يحتاج إلى حلقات السلطة (أي، <م> ن حلقات متداخلة حيث <م> ن ومن المعروف فقط في وقت التشغيل). للقيام بذلك، وأنا ولدت <م> ن حلقات متداخلة في التعليمات البرمجية روبي في سلسلة، ثم eval إد السلسلة. بلدي الحل عملت، ولكن يعتقد أستاذي أن استخدام عدد قليل gotos كان يمكن أن يكون أفضل حل (أسهل للقراءة، على الأقل) من رمز جيل ديناميكي.

وكنت تحت انطباع بأن goto كان دائما خيارا سيئا. لماذا قد وقت تقييم الشفرة التي تم إنشاؤها ديناميكيا يكون خيارا أسوأ من goto؟ الشفرة التي تم إنشاؤها نظيفة وبسيطة، ويبدو فعالة إلى حد ما لمشكلة معينة. إدخال المستخدم الوحيد الذي يتوقف عليه الجيل متاحة <م> ن ، والتي يتم التحقق لضمان انها قيمة عددية مسبقا. ومن yields خللا الفريدة فقط، كما يجب.

وأنا لا يسأل عن حل لاحالة البرمجة بلدي، وأنا فقط أريد أن أعرف الأسباب الكامنة وراء استخدام goto على تقييم دينامية رمز، أو العكس بالعكس.

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

هل كانت مفيدة؟

المحلول

وهذا سؤال مثير للاهتمام حقا - أنا لست متأكدا من أن هناك إجابة محددة

والمشكلة مع غوتو هو استخدامه بطريقة غير منظم - وغوتو هو "قفزة عشوائية ضخمة" حتى في المقام العام، بعد القفزة، كنت لا تعرف المكان الذي جئت منه والذي يسبب كل أنواع القضايا على حد سواء من حيث التصحيح والصيانة و- بمعنى أكثر رسمية مع إثبات "صحة" من التعليمات البرمجية. بالطبع هناك لغات (لقد حول بعض الوقت) حيث لم يكن لديك خيار النقطة التي فرض هيكل على التعليمات البرمجية. خلاصة القول هي أن ليس لها أن GOTO سيئة بقدر ما هو الطريقة التي يستخدم غوتو (وسوء المعاملة) ما هو سيء وهذا يجعل لها لبناء خطير أن يكون المتاحة.

<ع> استخدام الجيل رمز وثم تقييم النتيجة هي ذكية :) ومع ذلك "ذكية" ليست دائما شيئا جيدا، وأظن أنه في إطار هذه القضية مع استخدام هذا كحل غير أنه ليس لها في الواقع معالجة المشكلة على النحو المنشود. قد يكون ذلك "الغش" إن صح التعبير - حتى الآن على الأقل ما يتعلق أستاذك - لا يفسد الحل ولكن قد يجعله "غير مصقول". تنشأ القضايا وتصحيح الأخطاء والصيانة أيضا فيما يتعلق التعليمات البرمجية.

وهناك حل العودية - وخاصة ما أتذكر غامضة يجري تدريسها (قبل نحو 25 عاما) التي يمكن للمرء أن عادة الاسترخاء العودية في الحلقات - ربما يكون الأكثر أناقة

.

وبالتأكيد مسألة مثيرة للاهتمام!

نصائح أخرى

وكلا GOTO وتوليد كود حلول ائقة لهذه المشكلة IMO. هناك خوارزمية العودية ربما كان هذا هو الحق الإجابة هنا.

ودون رؤية الشفرة، وأنا أميل إلى جنب مع أ. اذا كان الاختيار بين الانتقال إلى ورمز الحيوية، وأود أن تميل السابق. الانتقال إلى ليسوا <م> دائما خيارا سيئا.

ويمكنك حل المشاكل كلها تقريبا دون استخدام GoTos. على وجه التحديد مع الحلقات يمكنك استخدام في الشوط الثاني ومواصلة تصريحات لgotos استخدام implitly بينما لا تزال تحتفظ مستوى التعليمات البرمجية.

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

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

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

في واحدة من assignement لي في الكلية، وكان لي مرة واحدة أن تفعل شيئا كانت مشابهة نسبيا كان لي حل لاستخدام وظيفة متكررة، ويمر على مجموعة، وحجم المصفوفة ومستوى التداخل كما حجة. وظيفة ثم استدعاء نفسها مع مستوى التداخل +1، حتى مستوى التداخل يساوي حجم المصفوفة. لا جوتو، أي تقييم المدونة، فقط متاحة نظيفة!

مثال

function computeDerangement(yourArray, loopLevel, arraySize)
{
    //We check to see if the loop level is the same as the array size
    //if true, then we have executed exactly n loop
    if (loopLevel == arraySize) {
         display(yourArray); //Display being some kind of function that show the array,
                             //you get the idea
    } else {
        while(something) {
            //Here you put the logic that you execute at one level of the loop

            //Then you call yourself with one more level of nesting
            computeDerangement(yourArray, loopLevel + 1, arraySize);
        }
    }
}

ونأمل أن مساعدة!

ولقد استخدمت أبدا غوتو في حياتي، لذلك أنا متأكد من أن هناك دائما وسيلة لتجنبها

والسبب الرئيسي الناس تجنب التصريحات غوتو هو أنها يمكن أن تجعل برنامجك أكثر صعوبة على الفهم.

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

وGOTO الحل - لغوتو مريحة عند محاكاة استدعاء دالة. وهنا حل غير recurisve أن مجرد يحاكي حل العودية باستخدام المكدس وتسمية غوتو ليعود إلى نقطة حيث استدعاء دالة قد حدث.

واطلع على إجراءات العودية (لقد نشرت هذا بمثابة إجابة منفصلة) للمقارنة.

والخيار صارمة على الخيار صريح في

وحدة Module1     س قاتمة كما المكدس

Private Sub printGeneratedList(ByVal generatedList As List(Of Integer))
    For Each el In generatedList
        Console.Write(el & " ")
    Next
    Console.WriteLine()
End Sub
Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _
                        ByVal generatedList As List(Of Integer))
    Dim stackI As Stack(Of Integer) = New Stack(Of Integer)
    Dim stackJ As Stack(Of Integer) = New Stack(Of Integer)


    Dim j As Integer

وStartLabel:

    j = 0

    If i >= n Then
        printGeneratedList(generatedList)
        If stackI.Count = 0 Then
            Return
        Else
            GoTo ReturnLabel
        End If
    End If

     While j < n
        If Not j = i Then
            If Not generatedList.Contains(j) Then
                generatedList.Add(j)
                stackI.Push(i)
                stackJ.Push(j)
                i = i + 1
                GoTo StartLabel

وReturnLabel:

                i = stackI.Pop()
                j = stackJ.Pop()
                generatedList.Remove(j)
            End If
        End If
        j = j + 1
    End While
    If stackI.Count = 0 Then
        Return
    Else
        GoTo ReturnLabel
    End If
End Sub

Private Sub generate(ByVal n As Integer)
    Console.WriteLine("Generating for n = " & n.ToString())
    Dim l As List(Of Integer) = New List(Of Integer)
    If n < 0 Then
        Throw New Exception("n must be >= 0")
    End If
    generateAux(0, n, l)
End Sub

Sub Main()
    generate(0)
    Console.ReadLine()
    generate(1)
    Console.ReadLine()
    generate(2)
    Console.ReadLine()
    generate(3)
    Console.ReadLine()
    generate(4)
    Console.ReadLine()
End Sub

ونهاية وحدة

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

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

تعليق : في نهاية المطاف، فإن وحدة المعالجة المركزية تنفيذ يفعل أي شيء آخر من يقفز بسيطة. فقط فقط أن لغة البرمجة / المترجم يخلق لهم. استخدام بحذر ولا تعبث معها.

وكلا الحل غوتو وتوليد دينامية رمز أفكار سيئة. يتم حل هذه بسهولة مع حل عودي كما ذكر من قبل الآخرين. كنت ببساطة متكرر تولد كل التباديل (حل العودية قياسي) وعندما الجيل اكتمال (أي في ورقة من العودية) ببساطة تخطي التباديل التي ليست خللا العودة.

وحل تكراري - هنا الحل مع التقليم المبكر. سؤالي الوحيد هو حول التعدادات: لم يريد لك لخلق العداد أن على كل مكالمة ناجحة من شأنه أن يولد العنصر التالي في القائمة؟ هذه ربما تكون أسهل تنفيذها عن طريق إنشاء نسخة امدا من هذا البرنامج - اعتدت على القيام بذلك في ثغة في كل وقت عند كتابة مولدات الاستعلام الذي من شأنه أن يولد الجواب المقبلة على سؤال عند القيام الاستفسارات أسلوب حاسوب-مترجم

والخيار صارمة على الخيار صريح في

وحدة Module1

Private Sub printGeneratedList(ByVal generatedList As List(Of Integer))
    For Each el In generatedList
        Console.Write(el & " ")
    Next
    Console.WriteLine()
End Sub

Private Sub generateAux(ByVal i As Integer, ByVal n As Integer, _
                    ByVal generatedList As List(Of Integer))
    If i >= n Then
        printGeneratedList(generatedList)
        Return
    End If
    For j As Integer = 0 To n - 1
        If Not j = i Then
            If Not generatedList.Contains(j) Then
                generatedList.Add(j)
                generateAux(i + 1, n, generatedList)
                generatedList.Remove(j)
            End If
        End If
    Next
End Sub

Private Sub generate(ByVal n As Integer)
    Console.WriteLine("Generating for n = " & n.ToString())
    Dim l As List(Of Integer) = New List(Of Integer)
    If n < 0 Then
        Throw New Exception("n must be >= 0")
    End If
    generateAux(0, n, l)
End Sub

Sub Main()
     generate(0)

    Console.ReadLine()
    generate(1)

    Console.ReadLine()
    generate(2)

    Console.ReadLine()
    generate(3)

    Console.ReadLine()
    generate(4)

    Console.ReadLine()

End Sub

ونهاية وحدة

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