Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions CalculatorApp/CalculatorApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CalculatorLibrary\CalculatorLibrary.csproj" />
</ItemGroup>

</Project>
4 changes: 4 additions & 0 deletions CalculatorApp/CalculatorApp.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<Solution>
<Project Path="../CalculatorLibrary/CalculatorLibrary.csproj" />
<Project Path="CalculatorApp.csproj" />
</Solution>
223 changes: 223 additions & 0 deletions CalculatorApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using CalculatorLibrary;

class Program
{
static void Main(string[] args)
{
bool endApp = false;
int count = 0;
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");

Calculator calculator = new Calculator();

while (!endApp)
{
// Declare variables and set to empty.
// Use Nullable types (with ?) to match type of System.Console.ReadLine
string? numInput1 = "";
string? numInput2 = "";
double result = 0;

endApp = ShowMenu();
if (endApp == true)
{ break; }

// Ask the user to type the first number.
Console.WriteLine("Collecting your first number...");
numInput1 = GetNumInput();

double cleanNum1 = 0;
while (!double.TryParse(numInput1, out cleanNum1))
{
Console.Write("This is not valid input. Please enter a numeric value: ");
numInput1 = Console.ReadLine();
}

// Ask the user to type the second number.
Console.WriteLine("Collecting your second number...");
numInput2 = GetNumInput();

double cleanNum2 = 0;
while (!double.TryParse(numInput2, out cleanNum2))
{
Console.Write("This is not valid input. Please enter a numeric value: ");
numInput2 = Console.ReadLine();
}

string? op = GetOperand();
// Validate input is not null, and matches the pattern
while (op == null || op == "exit")
{
if (op == "exit")
{
Console.WriteLine("You've chosen to close the app, press any key to close.");
Console.ReadKey();
return;
}
Console.WriteLine("Error: Unrecognized input. Try Again or type 'exit' to exit.");
op = GetOperand();


}
try
{
result = calculator.DoOperation(cleanNum1, cleanNum2, op);
if (double.IsNaN(result))
{
Console.WriteLine("This operation will result in a mathematical error.\n");
}
else
{

Console.WriteLine("Your result: {0:0.##}\n", result);
count++;
Console.WriteLine($"You have used the calculator {count} times.");
}
}
catch (Exception e)
{
Console.WriteLine("Oh no! An exception occurred trying to do the math.\n - Details: " + e.Message);
}
Console.WriteLine("------------------------\n");

// Wait for the user to respond before closing.
Console.Write("Press 'n' and Enter to close the app, or press any other key and Enter to continue: ");
if (Console.ReadLine() == "n") endApp = true;

Console.WriteLine("\n"); // Friendly linespacing.
}
calculator.Finish();
return;

string GetOperand()
{

// Ask the user to choose an operator.
Console.WriteLine("Choose an operator from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");

string? input = Console.ReadLine()?.Trim()?.ToLower() switch
{
"a" or "add" => "a",
"s" or "subtract" => "s",
"m" or "multiply" => "m",
"d" or "divide" => "d",
"exit" => "exit",
_ => null
};
return input;
}


string GetNumInput()
{
if (calculator.History.Count > 0)
{
Console.WriteLine("Do you want to use a previous result as your number? Y/N");
bool? decision;
do
{
decision = Console.ReadLine()?.ToLower()?.Trim() switch
{
"y" => true,
"n" => false,
_ => null
};
} while (decision == null);

if (decision == true)
{
calculator.RecallMemory();
int choice;
while (true)
{
Console.Write($"Pick an entry (from 1 to {calculator.History.Count}) or 'c' to cancel: ");
string? input = Console.ReadLine()?.Trim().ToLower();

if (input == "c")
{
Console.WriteLine("Cancelled.");
Console.Write("Type a number, and then press Enter: ");
return Console.ReadLine();
}

if (int.TryParse(input, out choice) && choice >= 1 && choice <= calculator.History.Count)
{
return calculator.RecallResult(choice - 1).ToString();
}

Console.WriteLine("Invalid input, try again.");
}

}
else
{
Console.Write("Type a number, and then press Enter: ");
return Console.ReadLine();
}
}
else
{
Console.Write("Type a number, and then press Enter: ");
return Console.ReadLine();
}
}

bool ShowMenu()
{
while (true)
{
Console.Clear();
Console.WriteLine("What would you like to do?");
Console.WriteLine("1. Perform Calculation");
Console.WriteLine("2. Display Number of calculations performed");
Console.WriteLine("3. Display History");
Console.WriteLine("4. Clear History");
Console.WriteLine("5. Exit");
Console.Write("Enter the # for your choice: ");

switch (Console.ReadLine()?.Trim())
{
case "1":
return false;
case "2":
Console.WriteLine($"Calculations performed: {count}");
break;
case "3":
if (calculator.History.Count > 0)
calculator.RecallMemory();
else
Console.WriteLine("No history to display.");
break;
case "4":
if (calculator.History.Count > 0)
{
calculator.History.Clear();
Console.WriteLine("History has been cleared.");
}
else
{
Console.WriteLine("No history to clear.");
}
break;
case "5":
return true;
default:
Console.WriteLine("Invalid choice, please try again.");
break;
}

Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
}
}
105 changes: 105 additions & 0 deletions CalculatorLibrary/CalculatorLibrary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.Diagnostics;
using Newtonsoft.Json;
namespace CalculatorLibrary
{
public class Calculator
{
JsonWriter writer;
StreamWriter logFile;

public record Calculation(double Num1, double Num2, string Op, double Result)
{
public string Symbol => Op switch
{
"a" => "+",
"s" => "-",
"m" => "*",
"d" => "/",
_ => Op
};
}
public List<Calculation> History { get; private set; } = new();
public Calculator()
{
StartLog();
}
public double DoOperation(double num1, double num2, string op)
{
double result = double.NaN; // Default value is "not-a-number" if an operation, such as division, could result in an error.
writer.WriteStartObject();
writer.WritePropertyName("Operand1");
writer.WriteValue(num1);
writer.WritePropertyName("Operand2");
writer.WriteValue(num2);
writer.WritePropertyName("Operation");
// Use a switch statement to do the math.
switch (op)
{
case "a":
result = num1 + num2;
writer.WriteValue("Add");
break;
case "s":
result = num1 - num2;
writer.WriteValue("Subtract");
break;
case "m":
result = num1 * num2;
writer.WriteValue("Multiply");
break;
case "d":
// Ask the user to enter a non-zero divisor.
if (num2 != 0)
{
result = num1 / num2;
writer.WriteValue("Divide");
}
break;
// Return text for an incorrect option entry.
default:
break;
}
writer.WritePropertyName("Result");
writer.WriteValue(result);
writer.WriteEndObject();
History.Add(new Calculation(num1, num2, op, result));

return result;
}
public void Finish()
{
writer.WriteEndArray();
writer.WriteEndObject();
writer.Close();
}

public void ClearMemory()
{
History.Clear();
}

public void RecallMemory()
{
for (int i = 0; i < History.Count; i++)
{
Calculation calc = History[i];
Console.WriteLine($"{i + 1}. {calc.Num1} {calc.Symbol} {calc.Num2} = {calc.Result}");
}
}

public double RecallResult(int resultNum)
{
return History[resultNum].Result;
}
private void StartLog()
{
logFile = File.CreateText("calculatorlog.json");
logFile.AutoFlush = true;
writer = new JsonTextWriter(logFile);
writer.Formatting = Formatting.Indented;
writer.WriteStartObject();
writer.WritePropertyName("Operations");
writer.WriteStartArray();
}
}
}
13 changes: 13 additions & 0 deletions CalculatorLibrary/CalculatorLibrary.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

</Project>
Loading