الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

حساب قيمة معادلة بالتكست بوكس مثلا

بدأه محمد جمال شريقي في 15 أغسطس 2013 · 0 رد · 412 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1

بسم الله الرحمن الرحيم

كنت قد كتبت هذه الدروس الاربعة السابقة

هياكل البيانات Data Structures الصف Queue : الجزء الاول

هياكل البيانات Data Structures المكدس Stack: الجزء الثاني

التعريف بـ PostFix و PreFix و InFix ومجالات استخدامهم : الجزء الثالث

التحويل من Infix الى postfix و prefix : الجزء الرابع

 

وهذه الدروس فقط للتفصيل اكثر

لنفترض ان لدينا تكست بوكس ونريد ان يدخل المستخدم صيغة رياضية وتريد ان يحسب البرنامج قيمة الصيغة مثلا اذا كتب المستخدم

5+6

يجب ان يرد البرنامج
11

او اذا كتب

5*(2+3)

يجب ان يرد البرنامج 25

او اذا كتب

5^(1+3)/25*(2+1)

يجب ان يرد البرنامج 75

او حتى باستخدام الرفع للقوة او الجذر من المرتبة N او لوغاريتم او اي شيء اخر
يجب ان يقوم البرنامج بحساب الناتج

لنرى كيف يتم ذلك

الخطوة الاولى :

يجب كتابة الصيغة باحدى الطريقتين postfix او prefix
وهذا مكتوب بالتفصيل في الدرس الرابع

وهاهو التابع المسؤول عن ذلك ولكني قمت ببعض التعديلات عليه من اجل ان يعيد القيمة داخل صف queue (راجع الدرس الاول)
وليس داخل متغير نصي String

وايضا قمت بتعديل آخر هام جداً وهو من اجل الارقام التي تتكون من اكثر من خانة مثلا 11 او 1648
حيث يتكون من احاد وعشرات و .... الخ

وهاهو كود التابع بطريقة postfix
InfixToPostfix

 

  Private Function InfixToPostfix(ByVal infix As String) As Queue(Of String)
        Dim RESULT As New Queue(Of String), S As New Stack(Of String), multnum As String = ""
        For i = 1 To infix.Length
            Dim Temp As String = Mid(infix, i, 1)
            If IsOpr(Temp) = False Then
                multnum &= Temp
                If i < infix.Length Then
                    Dim NextTemp As String = ""
                    NextTemp = Mid(infix, i + 1, 1)
                    If IsOpr(NextTemp) Then
                        RESULT.Enqueue(multnum)
                        multnum = ""
                    End If
                Else
                    RESULT.Enqueue(multnum)
                End If
            Else
                If Temp = ")" Then
                    Do Until S.Peek = "("
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Pop()
                ElseIf Temp = "(" Then
                    S.Push(Temp)
                Else
                    Do While S.Count > 0 AndAlso Prio(S.Peek) >= Prio(Temp) AndAlso S.Peek <> "("
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Push(Temp)
                End If
            End If
        Next

        Do While S.Count > 0
            RESULT.Enqueue(S.Pop)
        Loop

        Return RESULT
    End Function

لاحظ الكود جديد هذا

               multnum &= Temp
                If i < infix.Length Then
                    Dim NextTemp As String = ""
                    NextTemp = Mid(infix, i + 1, 1)
                    If IsOpr(NextTemp) Then
                        RESULT.Enqueue(multnum)
                        multnum = ""
                    End If
                Else
                    RESULT.Enqueue(multnum)
                End If

ومهمته التأكد من الرمز اللاحق فإذا كان معامل يكون الرقم يتكون من اكثر من خانة ويقوم بالمطلوب


وهنا الطريقة الثانية prefix
InfixToPrefix

    Private Function InfixToPrefix(ByVal infix As String) As Queue(Of String)
        Dim RESULT As New Queue(Of String), S As New Stack(Of String), multnum As String = ""
        Dim TT As String = infix
        infix = ""
        For i = TT.Length To 1 Step -1
            infix &= Mid(TT, i, 1)
        Next
        ' reverse the infix expr

        For i = 1 To infix.Length
            Dim Temp As String = Mid(infix, i, 1)
            If IsOpr(Temp) = False Then
                multnum = Temp & multnum
                If i < infix.Length Then
                    Dim NextTemp As String = ""
                    NextTemp = Mid(infix, i + 1, 1)
                    If IsOpr(NextTemp) Then
                        RESULT.Enqueue(multnum)
                        multnum = ""
                    End If
                Else
                    RESULT.Enqueue(multnum)
                End If
            Else
                If Temp = "(" Then
                    Do Until S.Peek = ")"
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Pop()
                ElseIf Temp = ")" Then
                    S.Push(Temp)
                Else
                    Do While S.Count > 0 AndAlso Prio(S.Peek) > Prio(Temp) AndAlso S.Peek <> ")"
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Push(Temp)
                End If
            End If
        Next

        Do While S.Count > 0
            RESULT.Enqueue(S.Pop)
        Loop

        Return RESULT
    End Function

هنا نكون انتهينا من كود التحويل من infix الى postfix او prefix

الخطوة الثانية :
حتى نستطيع معرفة الناتج نتبع التالي
في صيغة postfix
نقوم بفحص القيم واحد تلو الاخر بواسطة التابع isopr الموجود في الدرس الرابع
وهاهو للتذكير فقط

Private Function IsOpr(ByVal OPR As String) As Boolean
        Select Case OPR
            Case "+", "-", "*", "/", ")", "(", "^", "%"
                Return True
            Case Else
                Return False
        End Select

اذا كان الخرج هو عدد (معامل operand)
ندخل العدد الى مكدس (راجع الدرس الثاني)
اما اذا كان الخرج هو عامل Operator
نسحب اخر قيمتين من المكدس بواسطة pop طبعا (راجع الدرس الثاني)
ثم نممررهم مع العامل الى الدالة calculat لتقوم بحساب الناتج وتعيده ونقوم بوضع الناتج بالمكدس push

وهنا جسم الدالة calculat

    Private Function CalCulat(ByVal A As Long, ByVal opr As String, ByVal B As Long) As Double
        Select Case opr
            Case "^"
                Return A ^ B
            Case "%"
                Return A ^ (1 / B)
            Case "*"
                Return A * B
            Case "/"
                Return A / B
            Case "+"
                Return A + B
            Case "-"
                Return A - B
            Case Else
                Return 0
        End Select
    End Function

وهي واضحة ليست بحاجة للشرح على ما اعتقد
وبعد المرور على جميع المدخلات
سيظهر لنا الناتج بقمة المكدس
نقوم باستخراجه pop وعرضه للمستخدم

وهذا كود التابع السابق ذكره
 

   Private Function postfixresult(ByRef post As Queue(Of String)) As Double
        On Error Resume Next
        Dim S As New Stack(Of String)
        Do While post.Count > 0
            Dim Temp As String = post.Dequeue
            If IsOpr(Temp) = False Then
                S.Push(Temp)
            Else
                Dim B As Long = S.Pop
                Dim A As Long = S.Pop
                S.Push(CalCulat(A, Temp, B))
            End If
        Loop
        Return S.Pop

اما بالنسبة للصيغة المكتوبة بالـ prefix
فهي نفس الخطوات ولكن بتبديل الترتيب الـ operands

    Private Function prefixresult(ByRef post As Queue(Of String)) As Double
        On Error Resume Next
        Dim S As New Stack(Of String)
        Do While post.Count > 0
            Dim Temp As String = post.Dequeue
            If IsOpr(Temp) = False Then
                S.Push(Temp)
            Else
                Dim A As Long = S.Pop
                Dim B As Long = S.Pop
                S.Push(CalCulat(A, Temp, B))
            End If
        Loop
        Return S.Pop
    End Function

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

Public Class Form1

    Private Function InfixToPostfix(ByVal infix As String) As Queue(Of String)
        Dim RESULT As New Queue(Of String), S As New Stack(Of String), multnum As String = ""
        For i = 1 To infix.Length
            Dim Temp As String = Mid(infix, i, 1)
            If IsOpr(Temp) = False Then
                multnum &= Temp
                If i < infix.Length Then
                    Dim NextTemp As String = ""
                    NextTemp = Mid(infix, i + 1, 1)
                    If IsOpr(NextTemp) Then
                        RESULT.Enqueue(multnum)
                        multnum = ""
                    End If
                Else
                    RESULT.Enqueue(multnum)
                End If
            Else
                If Temp = ")" Then
                    Do Until S.Peek = "("
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Pop()
                ElseIf Temp = "(" Then
                    S.Push(Temp)
                Else
                    Do While S.Count > 0 AndAlso Prio(S.Peek) >= Prio(Temp) AndAlso S.Peek <> "("
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Push(Temp)
                End If
            End If
        Next

        Do While S.Count > 0
            RESULT.Enqueue(S.Pop)
        Loop

        Return RESULT
    End Function

    Private Function InfixToPrefix(ByVal infix As String) As Queue(Of String)
        Dim RESULT As New Queue(Of String), S As New Stack(Of String), multnum As String = ""
        Dim TT As String = infix
        infix = ""
        For i = TT.Length To 1 Step -1
            infix &= Mid(TT, i, 1)
        Next
        ' reverse the infix expr

        For i = 1 To infix.Length
            Dim Temp As String = Mid(infix, i, 1)
            If IsOpr(Temp) = False Then
                multnum = Temp & multnum
                If i < infix.Length Then
                    Dim NextTemp As String = ""
                    NextTemp = Mid(infix, i + 1, 1)
                    If IsOpr(NextTemp) Then
                        RESULT.Enqueue(multnum)
                        multnum = ""
                    End If
                Else
                    RESULT.Enqueue(multnum)
                End If
            Else
                If Temp = "(" Then
                    Do Until S.Peek = ")"
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Pop()
                ElseIf Temp = ")" Then
                    S.Push(Temp)
                Else
                    Do While S.Count > 0 AndAlso Prio(S.Peek) > Prio(Temp) AndAlso S.Peek <> ")"
                        RESULT.Enqueue(S.Pop)
                    Loop
                    S.Push(Temp)
                End If
            End If
        Next

        Do While S.Count > 0
            RESULT.Enqueue(S.Pop)
        Loop

        Return RESULT
    End Function

    Private Function IsOpr(ByVal OPR As String) As Boolean
        Select Case OPR
            Case "+", "-", "*", "/", ")", "(", "^", "%"
                Return True
            Case Else
                Return False
        End Select
    End Function

    Private Function Prio(ByVal Sym As String) As Integer
        Select Case Sym
            Case "^", "%"
                Return 4
            Case "*", "/"
                Return 2
            Case "+", "-"
                Return 1
            Case Else
                Return 0
        End Select
    End Function

    Private Function CalCulat(ByVal A As Long, ByVal opr As String, ByVal B As Long) As Double
        Select Case opr
            Case "^"
                Return A ^ B
            Case "%"
                Return A ^ (1 / B)
            Case "*"
                Return A * B
            Case "/"
                Return A / B
            Case "+"
                Return A + B
            Case "-"
                Return A - B
            Case Else
                Return 0
        End Select
    End Function

    Private Function postfixresult(ByRef post As Queue(Of String)) As Double
        On Error Resume Next
        Dim S As New Stack(Of String)
        Do While post.Count > 0
            Dim Temp As String = post.Dequeue
            If IsOpr(Temp) = False Then
                S.Push(Temp)
            Else
                Dim B As Long = S.Pop
                Dim A As Long = S.Pop
                S.Push(CalCulat(A, Temp, B))
            End If
        Loop
        Return S.Pop
    End Function

    Private Function prefixresult(ByRef post As Queue(Of String)) As Double
        On Error Resume Next
        Dim S As New Stack(Of String)
        Do While post.Count > 0
            Dim Temp As String = post.Dequeue
            If IsOpr(Temp) = False Then
                S.Push(Temp)
            Else
                Dim A As Long = S.Pop
                Dim B As Long = S.Pop
                S.Push(CalCulat(A, Temp, B))
            End If
        Loop
        Return S.Pop
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        MessageBox.Show("The Result Is : " & postfixresult(InfixToPostfix(TextBox1.Text)), "PostFix Type")
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        MessageBox.Show("The Result Is : " & prefixresult(InfixToPrefix(TextBox1.Text)), "PreFix Type")
    End Sub

    Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
        Select Case e.KeyChar
            Case "0" To "9", ControlChars.Back, "^", "%", "*", "/", "+", "-", "(", ")"
                e.Handled = False
            Case Else
                e.Handled = True
        End Select
    End Sub

End Class

وهذا البرنامج بالمرفقات

واي سؤال انا جاهز بإذن الله
وسامحوني على الاطالة والسلام عليكم

 

Real Calculator.rar

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…