944,111 Members | Top Members by Rank

Ad:
  • C# Code Snippet
  • Views: 9286
  • C# RSS
1

Console calculator Part 1 : The Scanner

by on Nov 17th, 2008
This is a series of 3 code snippets which together form a completly working "calculator".
I used a console application in VS C# 2008, but 2005 should cause no problems.
To start with : here you have the code for a scanner class.
A scanner reads the inputline and tries to get some meaningfull words(sometimes called tokens) from it. It then passes that information to a parser.
C# Code Snippet (Toggle Plain Text)
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace ConsoleCalculator
  7. {
  8. class Scanner
  9. {
  10. /// <summary>
  11. /// Scanner class, main routine here is get_token.
  12. /// get_token returns the next token_value to the parser,
  13. /// and sets some variables. It is up to the parser to decide
  14. /// what to do next.
  15. /// </summary>
  16.  
  17. public enum token_value
  18. {
  19. NAME, NUMBER, END, LIST, HELP, SQRT,
  20. PLUS = '+', MINUS = '-',
  21. MUL = '*', DIV = '/',
  22. PRINT = ';', ASSIGN = '=',
  23. LPAREN = '(', RPAREN = ')',
  24. };
  25.  
  26. public token_value curr_tok; //current token value found
  27. public double number_value; //if the token was a number the value is held here
  28. public string name_string; //if the token was a variable name, the name can be found here
  29.  
  30. private char[] StringToParse; //the "inputstream"
  31. private int charpos = 0; //position of the next character to read from the inputstream
  32. private StringBuilder numberSB = new StringBuilder();
  33. private StringBuilder nameSB = new StringBuilder();
  34.  
  35.  
  36. /// <summary>
  37. /// Two generic Dictionary's that use hashing to store string keys and values for
  38. /// variables, commands and reserved words.
  39. /// SymbolTable is public, the parser likes this table too
  40. /// </summary>
  41. public Dictionary<string, double> SymbolTable = new Dictionary<string, double>();
  42. private Dictionary<string, token_value> ReservedWords = new Dictionary<string, token_value>();
  43.  
  44. /// <summary>
  45. /// Scanner default custom constructor, defines a small set of reseved words,
  46. /// used to give special commands to the calculator.
  47. /// </summary>
  48. public Scanner()
  49. {
  50. ReservedWords.Add("END", token_value.END); //Quit the application.
  51. ReservedWords.Add("LIST", token_value.LIST);//Show a list of all variables in the calculator.
  52. ReservedWords.Add("?", token_value.HELP); //Display help info
  53. ReservedWords.Add("SQRT", token_value.SQRT); //Function to take the square root
  54. }
  55.  
  56. //property to pass the inputline to the scanner
  57. //---------------------------------------------
  58. public string InputLine
  59. {
  60. set
  61. {
  62. string line = value + "\n";
  63. StringToParse = line.ToCharArray();
  64. }
  65. }
  66.  
  67. //for functions we must first find a left parentesis
  68. //--------------------------------------------------
  69. public bool FindLeftParentesis()
  70. {
  71. char ch;
  72. try
  73. {
  74. do
  75. {
  76. ch = GetChar();
  77. }
  78. while (!ch.Equals('('));
  79. return true;
  80. }
  81. catch
  82. {
  83. Error("( expected"); return false;
  84. }
  85. }
  86.  
  87. //find a character in the "inputstream"
  88. //-------------------------------------
  89. private char GetChar()
  90. {
  91. char ch = StringToParse[charpos];
  92. charpos++;
  93. return ch;
  94. }
  95.  
  96. public void PutBackChar()
  97. {
  98. charpos--;
  99. }
  100.  
  101. public void InitScan()
  102. {
  103. charpos = 0;
  104. number_value = 0.0;
  105. name_string = "";
  106. }
  107.  
  108. public void Error(string message)
  109. {
  110. //minor error handling, but sufficient for the moment
  111. Console.ForegroundColor = ConsoleColor.Black;
  112. Console.BackgroundColor = ConsoleColor.Cyan;
  113. Console.WriteLine(message);
  114. Console.ResetColor();
  115. }
  116.  
  117. /// <summary>
  118. /// Main function of the scanner returns the current token and
  119. /// sets the variables name_string and number_value when appropriate.
  120. /// </summary>
  121. /// <returns></returns>
  122. public token_value get_token()
  123. {
  124. char ch;
  125.  
  126. do //skip whitespace except '\n'
  127. {
  128. ch = GetChar();
  129. }
  130. while (ch != '\n' && char.IsWhiteSpace(ch));
  131. switch (ch)
  132. {
  133. case ';': case '\n':
  134. curr_tok = token_value.PRINT;
  135. return curr_tok;
  136. case '*':
  137. case '/':
  138. case '+':
  139. case '-':
  140. case '(':
  141. case ')':
  142. case '=':
  143. curr_tok = (token_value)(ch);
  144. return curr_tok;
  145. case '0':
  146. case '1':
  147. case '2':
  148. case '3':
  149. case '4':
  150. case '5':
  151. case '6':
  152. case '7':
  153. case '8':
  154. case '9':
  155. case '.':
  156. case ',':
  157. if (ch == '.') ch = ',';
  158. numberSB.Append(ch);
  159. ch = GetChar();
  160. if (ch == '.') ch = ',';
  161. while (char.IsDigit(ch) || ch == ',')
  162. {
  163. numberSB.Append(ch);
  164. ch = GetChar();
  165. }
  166. PutBackChar();
  167. try
  168. {
  169. number_value = Convert.ToDouble(numberSB.ToString());
  170. numberSB.Remove(0, numberSB.Length);
  171. }
  172. catch
  173. {
  174. Error("Fout in formaat van getal.");
  175. }
  176. return token_value.NUMBER;
  177. default:
  178. if (char.IsLetter(ch) | ch.Equals('?'))
  179. {
  180. nameSB.Append(ch);
  181. ch = GetChar();
  182. while (char.IsLetterOrDigit(ch))
  183. {
  184. nameSB.Append(ch);
  185. ch = GetChar();
  186. }
  187. PutBackChar();
  188. name_string = nameSB.ToString();
  189. nameSB.Remove(0, nameSB.Length);
  190. if (ReservedWords.TryGetValue(name_string.ToUpper(), out curr_tok)) return curr_tok;
  191. return token_value.NAME;
  192. }
  193.  
  194. Error("Bad token.");
  195. return token_value.PRINT;
  196. }
  197. } //end get_token
  198.  
  199. //print a list of all the variables defined in the symboltable
  200. //------------------------------------------------------------
  201. public void ListVars()
  202. {
  203. Console.WriteLine("+-------------------------------------------+");
  204. Console.WriteLine("| List of variables : |");
  205. Console.WriteLine("+-------------------------------------------+");
  206. Console.WriteLine();
  207. foreach (KeyValuePair<string, double> kvp in SymbolTable)
  208. {
  209. Console.WriteLine("Var = {0} \t = {1}", kvp.Key, kvp.Value);
  210. } //yeah, generics is something to get used to
  211. Console.WriteLine("+-------------------------------------------+");
  212. }
  213. }
  214. }
Comments on this Code Snippet
Nov 18th, 2008
0

Re: Console calculator Part 1 : The Scanner

application in VS C# 2008, but 2005 should cause no problems.
The application makes use of generics in C# I don't know if version 2005 supports generics...
Senior Poster
ddanbe is offline Offline
3,740 posts
since Oct 2008
Sep 22nd, 2010
0

Re: Console calculator Part 1 : The Scanner

code work nicely but can you help me that how to give high priority to * (multiply) then / (division) and other operators in the input equation.
Newbie Poster
pradeep9601 is offline Offline
4 posts
since Sep 2010
Sep 23rd, 2010
0

Re: Console calculator Part 1 : The Scanner

Yes.
This scanner just does what it says, it scans the inputstring for "tokens".
These tokens are fed to a parser It is the job of the parser to find out about operator precedence.
Look also for the third snippet which will put al this together.
Succes!
Senior Poster
ddanbe is offline Offline
3,740 posts
since Oct 2008
Sep 25th, 2010
0

Re: Console calculator Part 1 : The Scanner

now i wanna add one more operator % (modulos) in the calculator so where to add codes for modulus property in this three part codes.
thanks
Newbie Poster
pradeep9601 is offline Offline
4 posts
since Sep 2010
Sep 25th, 2010
0

Re: Console calculator Part 1 : The Scanner

This should be rather straitforward. Just like adding more funcions, like SIN or EXP etc.
Give it a try! Succes!
Senior Poster
ddanbe is offline Offline
3,740 posts
since Oct 2008
Sep 27th, 2010
0

Re: Console calculator Part 1 : The Scanner

hi can anybody help me to run this calculator in cmd prompt by taking argument rather than readline. if it is possible then explain with code how to do it?
Newbie Poster
pradeep9601 is offline Offline
4 posts
since Sep 2010
Sep 27th, 2010
0

Re: Console calculator Part 1 : The Scanner

You could probably use one of the Main args strings and feed it to Parse.Input.
http://www.daniweb.com/code/snippet217187.html
Last edited by ddanbe; Sep 27th, 2010 at 9:17 am.
Senior Poster
ddanbe is offline Offline
3,740 posts
since Oct 2008
Sep 27th, 2010
0

Re: Console calculator Part 1 : The Scanner

ya but how can you explain me in this code
Newbie Poster
pradeep9601 is offline Offline
4 posts
since Sep 2010
Sep 27th, 2010
0

Re: Console calculator Part 1 : The Scanner

You could test the arguments you are passing with this code:
c# Syntax (Toggle Plain Text)
  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. for (int i = 0; i < args.Length; i++)
  6. {
  7. Console.WriteLine("Argument {0} = {1}", i, args[i]);
  8. }
  9. Console.ReadKey();
  10. }
  11. }
It is up to you which argument string to pass to Parse.InputLine(see line 59 of the above snippet in the previous post)
But I am wondering why you want to do this, because this calculator is a rather interactive console application.
Senior Poster
ddanbe is offline Offline
3,740 posts
since Oct 2008
Message:
Previous Thread in C# Forum Timeline: Setup
Next Thread in C# Forum Timeline: How do I do this in C#?





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC