تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
حساب قيمة معادلة(اقصد صيغة دون مجاهيل) مكتوبة بالتكست - الدرس الخامس والاخير
#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 او لوغاريتم او اي شيء اخر
يجب ان يقوم البرنامج بحساب الناتج

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

[SIZE=5]الخطوة الاولى :


يجب كتابة الصيغة باحدى الطريقتين 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
واي سؤال انا جاهز بإذن الله
وسامحوني على الاطالة والسلام عليكم
[/SIZE]
}}}}
تم الشكر بواسطة:


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  درس: كيفية حساب عدد الأسطر في نص المبرمج الطموح vb6 4 1,620 04-08-15, 12:45 AM
آخر رد: العواد الصغير
  حساب قيمة معادلة(اقصد صيغة دون مجاهيل) مكتوبة بالتكست : الجزء الخامس والاخير محمد شريقي 3 906 28-05-13, 01:06 PM
آخر رد: Sajad
  كود- حساب مواقيت الصلاة Prayer Times في الدوت نت 2008 و 2005 RaggiTech 0 1,467 05-10-12, 01:48 PM
آخر رد: RaggiTech
  دورة الفيجوال بيسك و اللينيكس - الدرس الثاني RaggiTech 0 539 03-10-12, 03:01 PM
آخر رد: RaggiTech
  دورة الفيجوال بيسك و اللينيكس - الدرس الاول RaggiTech 0 620 03-10-12, 03:00 PM
آخر رد: RaggiTech
  حساب مواقيت الصلاة الشرعية لأى مكان بالعالم RaggiTech 0 952 03-10-12, 12:34 PM
آخر رد: RaggiTech
  حساب الاسبوع والشهر الحالي والسابق RaggiTech 0 287 03-10-12, 12:31 PM
آخر رد: RaggiTech
  تطوير الكونترول Rendering Control الجزء الخامس RaggiTech 1 325 03-10-12, 09:18 AM
آخر رد: RaggiTech
  الدرس السادس -تابع المتغيرات ( امكانية الوصول) RaggiTech 0 424 02-10-12, 06:19 PM
آخر رد: RaggiTech
  الدرس السادس - المتغيرات RaggiTech 0 394 02-10-12, 06:17 PM
آخر رد: RaggiTech

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم