mirror of
https://github.com/markjprice/cs11dotnet7.git
synced 2026-01-01 22:09:57 +01:00
Initial commit
This commit is contained in:
parent
c0d4d11b54
commit
0e89590d92
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
24
vs4win/Chapter08/Ch08Ex02RegularExpressions/Program.cs
Normal file
24
vs4win/Chapter08/Ch08Ex02RegularExpressions/Program.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
WriteLine("The default regular expression checks for at least one digit.");
|
||||
|
||||
do
|
||||
{
|
||||
Write("Enter a regular expression (or press ENTER to use the default): ");
|
||||
string? regexp = ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(regexp))
|
||||
{
|
||||
regexp = @"^\d+$";
|
||||
}
|
||||
|
||||
Write("Enter some input: ");
|
||||
string input = ReadLine()!; // will never be null
|
||||
|
||||
Regex r = new(regexp);
|
||||
|
||||
WriteLine($"{input} matches {regexp}: {r.IsMatch(input)}");
|
||||
|
||||
WriteLine("Press ESC to end or any key to try again.");
|
||||
}
|
||||
while (ReadKey(intercept: true).Key != ConsoleKey.Escape);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ch08Ex03NumbersAsWordsLib\Ch08Ex03NumbersAsWordsLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
16
vs4win/Chapter08/Ch08Ex03NumbersAsWordsApp/Program.cs
Normal file
16
vs4win/Chapter08/Ch08Ex03NumbersAsWordsApp/Program.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using Packt.Shared; // ToWords extension method
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
Write("Enter a number up to twenty one digits long: ");
|
||||
string? input = ReadLine();
|
||||
if (input is null) return;
|
||||
|
||||
if (input.Length > 21)
|
||||
{
|
||||
WriteLine("I cannot handle more than twenty one digits!");
|
||||
return;
|
||||
}
|
||||
|
||||
BigInteger number = BigInteger.Parse(input);
|
||||
|
||||
WriteLine($"{number:N0} in words is {number.ToWords()}.");
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
220
vs4win/Chapter08/Ch08Ex03NumbersAsWordsLib/NumbersToWords.cs
Normal file
220
vs4win/Chapter08/Ch08Ex03NumbersAsWordsLib/NumbersToWords.cs
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
using System.Diagnostics; // Trace
|
||||
using System.IO; // File
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
namespace Packt.Shared
|
||||
{
|
||||
public static class NumbersToWords
|
||||
{
|
||||
// Single-digit and small number names
|
||||
private static string[] smallNumbers = new string[]
|
||||
{
|
||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
|
||||
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
|
||||
"sixteen", "seventeen", "eighteen", "nineteen"
|
||||
};
|
||||
|
||||
// Tens number names from twenty upwards
|
||||
private static string[] tens = new string[]
|
||||
{
|
||||
"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
|
||||
"eighty", "ninety"
|
||||
};
|
||||
|
||||
// Scale number names for use during recombination
|
||||
private static string[] scaleNumbers = new string[]
|
||||
{
|
||||
"", "thousand", "million", "billion", "trillion",
|
||||
"quadrillion", "quintillion"
|
||||
};
|
||||
|
||||
private static int groups = 7; // i.e. up to quintillion
|
||||
|
||||
public static string ToWords(this int number)
|
||||
{
|
||||
return ToWords((BigInteger)number);
|
||||
}
|
||||
|
||||
public static string ToWords(this long number)
|
||||
{
|
||||
return ToWords((BigInteger)number);
|
||||
}
|
||||
|
||||
public static string ToWords(this BigInteger number)
|
||||
{
|
||||
/*
|
||||
Convert A Number into Words
|
||||
by Richard Carr, published at http://www.blackwasp.co.uk/numbertowords.aspx
|
||||
*/
|
||||
|
||||
/*
|
||||
Zero Rule.
|
||||
If the value is 0 then the number in words is 'zero' and no other rules apply.
|
||||
*/
|
||||
if (number == 0)
|
||||
{
|
||||
return "zero";
|
||||
}
|
||||
|
||||
/*
|
||||
Three Digit Rule.
|
||||
The integer value is split into groups of three digits starting from the
|
||||
right-hand side. Each set of three digits is then processed individually
|
||||
as a number of hundreds, tens and units. Once converted to text, the
|
||||
three-digit groups are recombined with the addition of the relevant scale
|
||||
number (thousand, million, billion).
|
||||
*/
|
||||
|
||||
// Array to hold the specified number of three-digit groups
|
||||
int[] digitGroups = new int[groups];
|
||||
|
||||
// Ensure a positive number to extract from
|
||||
var positive = BigInteger.Abs(number);
|
||||
|
||||
// Extract the three-digit groups
|
||||
for (int i = 0; i < groups; i++)
|
||||
{
|
||||
digitGroups[i] = (int)(positive % 1000);
|
||||
positive /= 1000;
|
||||
}
|
||||
|
||||
// write to a text file in the project folder
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(
|
||||
File.AppendText("log.txt")));
|
||||
|
||||
// text writer is buffered, so this option calls
|
||||
// Flush() on all listeners after writing
|
||||
Trace.AutoFlush = true;
|
||||
|
||||
// log array of group numbers
|
||||
for (int x = 0; x < digitGroups.Length; x++)
|
||||
{
|
||||
Trace.WriteLine(string.Format(
|
||||
format: "digitGroups[{0}] = {1}",
|
||||
arg0: x,
|
||||
arg1: digitGroups[x]));
|
||||
}
|
||||
|
||||
// Convert each three-digit group to words
|
||||
string[] groupTexts = new string[groups];
|
||||
|
||||
for (int i = 0; i < groups; i++)
|
||||
{
|
||||
// call a local function (see below)
|
||||
groupTexts[i] = ThreeDigitGroupToWords(digitGroups[i]);
|
||||
}
|
||||
|
||||
// log array of group texts
|
||||
for (int x = 0; x < groupTexts.Length; x++)
|
||||
{
|
||||
Trace.WriteLine(string.Format(
|
||||
format: "groupTexts[{0}] = {1}",
|
||||
arg0: x,
|
||||
arg1: groupTexts[x]));
|
||||
}
|
||||
|
||||
/*
|
||||
Recombination Rules.
|
||||
When recombining the translated three-digit groups, each group except the
|
||||
last is followed by a large number name and a comma, unless the group is
|
||||
blank and therefore not included at all. One exception is when the final
|
||||
group does not include any hundreds and there is more than one non-blank
|
||||
group. In this case, the final comma is replaced with 'and'. eg.
|
||||
'one billion, one million and twelve'.
|
||||
*/
|
||||
|
||||
// Recombine the three-digit groups
|
||||
string combined = groupTexts[0];
|
||||
bool appendAnd;
|
||||
|
||||
// Determine whether an 'and' is needed
|
||||
appendAnd = (digitGroups[0] > 0) && (digitGroups[0] < 100);
|
||||
|
||||
// Process the remaining groups in turn, smallest to largest
|
||||
for (int i = 1; i < groups; i++)
|
||||
{
|
||||
// Only add non-zero items
|
||||
if (digitGroups[i] != 0)
|
||||
{
|
||||
// Build the string to add as a prefix
|
||||
string prefix = groupTexts[i] + " " + scaleNumbers[i];
|
||||
|
||||
if (combined.Length != 0)
|
||||
{
|
||||
prefix += appendAnd ? " and " : ", ";
|
||||
}
|
||||
|
||||
// Opportunity to add 'and' is ended
|
||||
appendAnd = false;
|
||||
|
||||
// Add the three-digit group to the combined string
|
||||
combined = prefix + combined;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a three-digit group into English words
|
||||
string ThreeDigitGroupToWords(int threeDigits)
|
||||
{
|
||||
// Initialise the return text
|
||||
string groupText = "";
|
||||
|
||||
// Determine the hundreds and the remainder
|
||||
int hundreds = threeDigits / 100;
|
||||
int tensUnits = threeDigits % 100;
|
||||
|
||||
/*
|
||||
Hundreds Rules.
|
||||
If the hundreds portion of a three-digit group is not zero, the number of
|
||||
hundreds is added as a word. If the three-digit group is exactly divisible
|
||||
by one hundred, the text 'hundred' is appended. If not, the text
|
||||
"hundred and" is appended. eg. 'two hundred' or 'one hundred and twelve'
|
||||
*/
|
||||
|
||||
if (hundreds != 0)
|
||||
{
|
||||
groupText += smallNumbers[hundreds] + " hundred";
|
||||
|
||||
if (tensUnits != 0)
|
||||
{
|
||||
groupText += " and ";
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the tens and units
|
||||
int tens = tensUnits / 10;
|
||||
int units = tensUnits % 10;
|
||||
|
||||
/* Tens Rules.
|
||||
If the tens section of a three-digit group is two or higher, the appropriate
|
||||
'-ty' word (twenty, thirty, etc.) is added to the text and followed by the
|
||||
name of the third digit (unless the third digit is a zero, which is ignored).
|
||||
If the tens and the units are both zero, no text is added. For any other value,
|
||||
the name of the one or two-digit number is added as a special case.
|
||||
*/
|
||||
|
||||
if (tens >= 2)
|
||||
{
|
||||
groupText += NumbersToWords.tens[tens];
|
||||
if (units != 0)
|
||||
{
|
||||
groupText += " " + smallNumbers[units];
|
||||
}
|
||||
}
|
||||
else if (tensUnits != 0)
|
||||
groupText += smallNumbers[tensUnits];
|
||||
|
||||
return groupText;
|
||||
}
|
||||
|
||||
/* Negative Rule.
|
||||
Negative numbers are always preceded by the text 'negative'.
|
||||
*/
|
||||
if (number < 0)
|
||||
{
|
||||
combined = "negative " + combined;
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ch08Ex03NumbersAsWordsLib\Ch08Ex03NumbersAsWordsLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using Packt.Shared; // ToWords extension method
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
namespace Ch08Ex03NumbersAsWordsTests
|
||||
{
|
||||
public class NumbersToWordsUnitTests
|
||||
{
|
||||
[Fact]
|
||||
public void Test_Int32_0()
|
||||
{
|
||||
// arrange
|
||||
int number = 0;
|
||||
string expected = "zero";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_Int32_1234()
|
||||
{
|
||||
// arrange
|
||||
int number = 1234;
|
||||
string expected = "one thousand, two hundred and thirty four";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_BigInteger_18456002032011000007()
|
||||
{
|
||||
// arrange
|
||||
BigInteger number = BigInteger.Parse("18456002032011000007");
|
||||
string expected = "eighteen quintillion, four hundred and fifty six quadrillion, two trillion, thirty two billion, eleven million and seven";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_Int32_minus_13()
|
||||
{
|
||||
// arrange
|
||||
int number = -13;
|
||||
string expected = "negative thirteen";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
vs4win/Chapter08/Ch08Ex03NumbersAsWordsTests/Usings.cs
Normal file
1
vs4win/Chapter08/Ch08Ex03NumbersAsWordsTests/Usings.cs
Normal file
|
|
@ -0,0 +1 @@
|
|||
global using Xunit;
|
||||
79
vs4win/Chapter08/Chapter08.sln
Normal file
79
vs4win/Chapter08/Chapter08.sln
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32210.308
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithNumbers", "WorkingWithNumbers\WorkingWithNumbers.csproj", "{EF42A2EE-FB4A-4BE4-A331-2B3D6CC1A1C5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithText", "WorkingWithText\WorkingWithText.csproj", "{BD0568D2-A0C9-4FB5-AD3A-A685E794A29E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithRegularExpressions", "WorkingWithRegularExpressions\WorkingWithRegularExpressions.csproj", "{221EF67C-EB18-417F-811F-2836BBC4B9ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithCollections", "WorkingWithCollections\WorkingWithCollections.csproj", "{678CA866-8E00-48EB-A8F5-1D587BFB311A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithRanges", "WorkingWithRanges\WorkingWithRanges.csproj", "{D93AB524-D62D-422B-895A-B1F0ACD3E137}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkingWithNetworkResources", "WorkingWithNetworkResources\WorkingWithNetworkResources.csproj", "{5A9BBCB8-F680-45DA-BBAD-DC20F3FBEE4E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch08Ex02RegularExpressions", "Ch08Ex02RegularExpressions\Ch08Ex02RegularExpressions.csproj", "{BDCF7297-FA66-437C-A428-AF1B32C520DD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch08Ex03NumbersAsWordsLib", "Ch08Ex03NumbersAsWordsLib\Ch08Ex03NumbersAsWordsLib.csproj", "{42F893F1-B861-4B4B-A14B-4F278E11F87F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch08Ex03NumbersAsWordsApp", "Ch08Ex03NumbersAsWordsApp\Ch08Ex03NumbersAsWordsApp.csproj", "{25385931-197B-4713-82B9-74764DBD76A3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ch08Ex03NumbersAsWordsTests", "Ch08Ex03NumbersAsWordsTests\Ch08Ex03NumbersAsWordsTests.csproj", "{793E6479-9AE4-4802-B5BF-BC4CED5E72F0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EF42A2EE-FB4A-4BE4-A331-2B3D6CC1A1C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EF42A2EE-FB4A-4BE4-A331-2B3D6CC1A1C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EF42A2EE-FB4A-4BE4-A331-2B3D6CC1A1C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EF42A2EE-FB4A-4BE4-A331-2B3D6CC1A1C5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BD0568D2-A0C9-4FB5-AD3A-A685E794A29E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BD0568D2-A0C9-4FB5-AD3A-A685E794A29E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BD0568D2-A0C9-4FB5-AD3A-A685E794A29E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BD0568D2-A0C9-4FB5-AD3A-A685E794A29E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{221EF67C-EB18-417F-811F-2836BBC4B9ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{221EF67C-EB18-417F-811F-2836BBC4B9ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{221EF67C-EB18-417F-811F-2836BBC4B9ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{221EF67C-EB18-417F-811F-2836BBC4B9ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{678CA866-8E00-48EB-A8F5-1D587BFB311A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{678CA866-8E00-48EB-A8F5-1D587BFB311A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{678CA866-8E00-48EB-A8F5-1D587BFB311A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{678CA866-8E00-48EB-A8F5-1D587BFB311A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D93AB524-D62D-422B-895A-B1F0ACD3E137}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D93AB524-D62D-422B-895A-B1F0ACD3E137}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D93AB524-D62D-422B-895A-B1F0ACD3E137}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D93AB524-D62D-422B-895A-B1F0ACD3E137}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5A9BBCB8-F680-45DA-BBAD-DC20F3FBEE4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5A9BBCB8-F680-45DA-BBAD-DC20F3FBEE4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5A9BBCB8-F680-45DA-BBAD-DC20F3FBEE4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5A9BBCB8-F680-45DA-BBAD-DC20F3FBEE4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDCF7297-FA66-437C-A428-AF1B32C520DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDCF7297-FA66-437C-A428-AF1B32C520DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDCF7297-FA66-437C-A428-AF1B32C520DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDCF7297-FA66-437C-A428-AF1B32C520DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42F893F1-B861-4B4B-A14B-4F278E11F87F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42F893F1-B861-4B4B-A14B-4F278E11F87F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42F893F1-B861-4B4B-A14B-4F278E11F87F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42F893F1-B861-4B4B-A14B-4F278E11F87F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{25385931-197B-4713-82B9-74764DBD76A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{25385931-197B-4713-82B9-74764DBD76A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{25385931-197B-4713-82B9-74764DBD76A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{25385931-197B-4713-82B9-74764DBD76A3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{793E6479-9AE4-4802-B5BF-BC4CED5E72F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{793E6479-9AE4-4802-B5BF-BC4CED5E72F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{793E6479-9AE4-4802-B5BF-BC4CED5E72F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{793E6479-9AE4-4802-B5BF-BC4CED5E72F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {BD4295A9-D6CF-470E-8220-CDA9A1FEA2C6}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
21
vs4win/Chapter08/WorkingWithCollections/Program.Helpers.cs
Normal file
21
vs4win/Chapter08/WorkingWithCollections/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
partial class Program
|
||||
{
|
||||
static void Output(string title, IEnumerable<string> collection)
|
||||
{
|
||||
WriteLine(title);
|
||||
foreach (string item in collection)
|
||||
{
|
||||
WriteLine($" {item}");
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputPQ<TElement, TPriority>(string title,
|
||||
IEnumerable<(TElement Element, TPriority Priority)> collection)
|
||||
{
|
||||
WriteLine(title);
|
||||
foreach ((TElement, TPriority) item in collection)
|
||||
{
|
||||
WriteLine($" {item.Item1}: {item.Item2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
129
vs4win/Chapter08/WorkingWithCollections/Program.cs
Normal file
129
vs4win/Chapter08/WorkingWithCollections/Program.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
using System.Collections.Immutable;
|
||||
|
||||
// Working with lists
|
||||
|
||||
// Simple syntax for creating a list and adding three items
|
||||
List<string> cities = new();
|
||||
cities.Add("London");
|
||||
cities.Add("Paris");
|
||||
cities.Add("Milan");
|
||||
|
||||
/* Alternative syntax that is converted by the compiler into
|
||||
the three Add method calls above
|
||||
List<string> cities = new()
|
||||
{ "London", "Paris", "Milan" }; */
|
||||
|
||||
/* Alternative syntax that passes an
|
||||
array of string values to AddRange method
|
||||
List<string> cities = new();
|
||||
cities.AddRange(new[] { "London", "Paris", "Milan" }); */
|
||||
|
||||
Output("Initial list", cities);
|
||||
WriteLine($"The first city is {cities[0]}.");
|
||||
WriteLine($"The last city is {cities[cities.Count - 1]}.");
|
||||
|
||||
cities.Insert(0, "Sydney");
|
||||
Output("After inserting Sydney at index 0", cities);
|
||||
|
||||
cities.RemoveAt(1);
|
||||
cities.Remove("Milan");
|
||||
Output("After removing two cities", cities);
|
||||
|
||||
// Working with dictionaries
|
||||
|
||||
Dictionary<string, string> keywords = new();
|
||||
|
||||
// add using named parameters
|
||||
keywords.Add(key: "int", value: "32-bit integer data type");
|
||||
|
||||
// add using positional parameters
|
||||
keywords.Add("long", "64-bit integer data type");
|
||||
keywords.Add("float", "Single precision floating point number");
|
||||
|
||||
/* Alternative syntax; compiler converts this to calls to Add method
|
||||
Dictionary<string, string> keywords = new()
|
||||
{
|
||||
{ "int", "32-bit integer data type" },
|
||||
{ "long", "64-bit integer data type" },
|
||||
{ "float", "Single precision floating point number" },
|
||||
}; */
|
||||
|
||||
/* Alternative syntax; compiler converts this to calls to Add method
|
||||
Dictionary<string, string> keywords = new()
|
||||
{
|
||||
["int"] = "32-bit integer data type",
|
||||
["long"] = "64-bit integer data type",
|
||||
["float"] = "Single precision floating point number", // last comma is optional
|
||||
}; */
|
||||
|
||||
Output("Dictionary keys:", keywords.Keys);
|
||||
Output("Dictionary values:", keywords.Values);
|
||||
|
||||
WriteLine("Keywords and their definitions");
|
||||
foreach (KeyValuePair<string, string> item in keywords)
|
||||
{
|
||||
WriteLine($" {item.Key}: {item.Value}");
|
||||
}
|
||||
|
||||
// lookup a value using a key
|
||||
string key = "long";
|
||||
WriteLine($"The definition of {key} is {keywords[key]}");
|
||||
|
||||
// Working with queues
|
||||
|
||||
Queue<string> coffee = new();
|
||||
|
||||
coffee.Enqueue("Damir"); // front of queue
|
||||
coffee.Enqueue("Andrea");
|
||||
coffee.Enqueue("Ronald");
|
||||
coffee.Enqueue("Amin");
|
||||
coffee.Enqueue("Irina"); // back of queue
|
||||
|
||||
Output("Initial queue from front to back", coffee);
|
||||
|
||||
// server handles next person in queue
|
||||
string served = coffee.Dequeue();
|
||||
WriteLine($"Served: {served}.");
|
||||
|
||||
// server handles next person in queue
|
||||
served = coffee.Dequeue();
|
||||
WriteLine($"Served: {served}.");
|
||||
Output("Current queue from front to back", coffee);
|
||||
|
||||
WriteLine($"{coffee.Peek()} is next in line.");
|
||||
Output("Current queue from front to back", coffee);
|
||||
|
||||
// Working with priority queues
|
||||
|
||||
PriorityQueue<string, int> vaccine = new();
|
||||
|
||||
// add some people
|
||||
// 1 = high priority people in their 70s or poor health
|
||||
// 2 = medium priority e.g. middle aged
|
||||
// 3 = low priority e.g. teens and twenties
|
||||
|
||||
vaccine.Enqueue("Pamela", 1); // my mum (70s)
|
||||
vaccine.Enqueue("Rebecca", 3); // my niece (teens)
|
||||
vaccine.Enqueue("Juliet", 2); // my sister (40s)
|
||||
vaccine.Enqueue("Ian", 1); // my dad (70s)
|
||||
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
|
||||
WriteLine("Adding Mark to queue with priority 2");
|
||||
vaccine.Enqueue("Mark", 2); // me (50s)
|
||||
|
||||
WriteLine($"{vaccine.Peek()} will be next to be vaccinated.");
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
// Working with immutable collections
|
||||
|
||||
ImmutableList<string> immutableCities = cities.ToImmutableList();
|
||||
ImmutableList<string> newList = immutableCities.Add("Rio");
|
||||
Output("Immutable list of cities:", immutableCities);
|
||||
Output("New list of cities:", newList);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
50
vs4win/Chapter08/WorkingWithNetworkResources/Program.cs
Normal file
50
vs4win/Chapter08/WorkingWithNetworkResources/Program.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System.Net; // IPHostEntry, Dns, IPAddress
|
||||
using System.Net.NetworkInformation; // Ping, PingReply, IPStatus
|
||||
|
||||
// Working with URIs, DNS, and IP addresses
|
||||
|
||||
Write("Enter a valid web address (or press Enter): ");
|
||||
string? url = ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(url)) // if they enter nothing...
|
||||
{
|
||||
// ... set a default URL
|
||||
url = "https://stackoverflow.com/search?q=securestring";
|
||||
}
|
||||
|
||||
Uri uri = new(url);
|
||||
WriteLine($"URL: {url}");
|
||||
WriteLine($"Scheme: {uri.Scheme}");
|
||||
WriteLine($"Port: {uri.Port}");
|
||||
WriteLine($"Host: {uri.Host}");
|
||||
WriteLine($"Path: {uri.AbsolutePath}");
|
||||
WriteLine($"Query: {uri.Query}");
|
||||
|
||||
IPHostEntry entry = Dns.GetHostEntry(uri.Host);
|
||||
WriteLine($"{entry.HostName} has the following IP addresses:");
|
||||
foreach (IPAddress address in entry.AddressList)
|
||||
{
|
||||
WriteLine($" {address} ({address.AddressFamily})");
|
||||
}
|
||||
|
||||
// Pinging a server
|
||||
|
||||
try
|
||||
{
|
||||
Ping ping = new();
|
||||
|
||||
WriteLine("Pinging server. Please wait...");
|
||||
PingReply reply = ping.Send(uri.Host);
|
||||
WriteLine($"{uri.Host} was pinged and replied: {reply.Status}.");
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
{
|
||||
WriteLine("Reply from {0} took {1:N0}ms",
|
||||
arg0: reply.Address,
|
||||
arg1: reply.RoundtripTime);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteLine($"{ex.GetType().ToString()} says {ex.Message}");
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
27
vs4win/Chapter08/WorkingWithNumbers/Program.cs
Normal file
27
vs4win/Chapter08/WorkingWithNumbers/Program.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.Numerics;
|
||||
|
||||
WriteLine("Working with large integers:");
|
||||
WriteLine("-----------------------------------");
|
||||
|
||||
ulong big = ulong.MaxValue;
|
||||
WriteLine($"{big,40:N0}");
|
||||
|
||||
BigInteger bigger =
|
||||
BigInteger.Parse("123456789012345678901234567890");
|
||||
WriteLine($"{bigger,40:N0}");
|
||||
|
||||
WriteLine("Working with complex numbers:");
|
||||
|
||||
Complex c1 = new(real: 4, imaginary: 2);
|
||||
Complex c2 = new(real: 3, imaginary: 7);
|
||||
Complex c3 = c1 + c2;
|
||||
|
||||
// output using default ToString implementation
|
||||
WriteLine($"{c1} added to {c2} is {c3}");
|
||||
|
||||
// output using custom format
|
||||
WriteLine("{0} + {1}i added to {2} + {3}i is {4} + {5}i",
|
||||
c1.Real, c1.Imaginary,
|
||||
c2.Real, c2.Imaginary,
|
||||
c3.Real, c3.Imaginary);
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
28
vs4win/Chapter08/WorkingWithRanges/Program.cs
Normal file
28
vs4win/Chapter08/WorkingWithRanges/Program.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
string name = "Samantha Jones";
|
||||
|
||||
// getting the lengths of the first and last names
|
||||
|
||||
int lengthOfFirst = name.IndexOf(' ');
|
||||
int lengthOfLast = name.Length - lengthOfFirst - 1;
|
||||
|
||||
// Using Substring
|
||||
|
||||
string firstName = name.Substring(
|
||||
startIndex: 0,
|
||||
length: lengthOfFirst);
|
||||
|
||||
string lastName = name.Substring(
|
||||
startIndex: name.Length - lengthOfLast,
|
||||
length: lengthOfLast);
|
||||
|
||||
WriteLine($"First name: {firstName}, Last name: {lastName}");
|
||||
|
||||
// Using spans
|
||||
|
||||
ReadOnlySpan<char> nameAsSpan = name.AsSpan();
|
||||
ReadOnlySpan<char> firstNameSpan = nameAsSpan[0..lengthOfFirst];
|
||||
ReadOnlySpan<char> lastNameSpan = nameAsSpan[^lengthOfLast..^0];
|
||||
|
||||
WriteLine("First name: {0}, Last name: {1}",
|
||||
arg0: firstNameSpan.ToString(),
|
||||
arg1: lastNameSpan.ToString());
|
||||
14
vs4win/Chapter08/WorkingWithRanges/WorkingWithRanges.csproj
Normal file
14
vs4win/Chapter08/WorkingWithRanges/WorkingWithRanges.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
38
vs4win/Chapter08/WorkingWithRegularExpressions/Program.cs
Normal file
38
vs4win/Chapter08/WorkingWithRegularExpressions/Program.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System.Text.RegularExpressions; // Regex
|
||||
|
||||
Write("Enter your age: ");
|
||||
string input = ReadLine()!; // null-forgiving
|
||||
|
||||
Regex ageChecker = new(@"^\d+$");
|
||||
|
||||
if (ageChecker.IsMatch(input))
|
||||
{
|
||||
WriteLine("Thank you!");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine($"This is not a valid age: {input}");
|
||||
}
|
||||
|
||||
string films = "\"Monsters, Inc.\",\"I, Tonya\",\"Lock, Stock and Two Smoking Barrels\"";
|
||||
|
||||
WriteLine($"Films to split: {films}");
|
||||
|
||||
string[] filmsDumb = films.Split(',');
|
||||
|
||||
WriteLine("Splitting with string.Split method:");
|
||||
foreach (string film in filmsDumb)
|
||||
{
|
||||
WriteLine(film);
|
||||
}
|
||||
|
||||
Regex csv = new(
|
||||
"(?:^|,)(?=[^\"]|(\")?)\"?((?(1)[^\"]*|[^,\"]*))\"?(?=,|$)");
|
||||
|
||||
MatchCollection filmsSmart = csv.Matches(films);
|
||||
|
||||
WriteLine("Splitting with regular expression:");
|
||||
foreach (Match film in filmsSmart)
|
||||
{
|
||||
WriteLine(film.Groups[2].Value);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
45
vs4win/Chapter08/WorkingWithText/Program.cs
Normal file
45
vs4win/Chapter08/WorkingWithText/Program.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
string city = "London";
|
||||
WriteLine($"{city} is {city.Length} characters long.");
|
||||
|
||||
WriteLine($"First char is {city[0]} and third is {city[2]}.");
|
||||
|
||||
string cities = "Paris,Tehran,Chennai,Sydney,New York,Medellín";
|
||||
|
||||
string[] citiesArray = cities.Split(',');
|
||||
|
||||
WriteLine($"There are {citiesArray.Length} items in the array.");
|
||||
|
||||
foreach (string item in citiesArray)
|
||||
{
|
||||
WriteLine(item);
|
||||
}
|
||||
|
||||
string fullName = "Alan Jones";
|
||||
|
||||
int indexOfTheSpace = fullName.IndexOf(' ');
|
||||
|
||||
string firstName = fullName.Substring(
|
||||
startIndex: 0, length: indexOfTheSpace);
|
||||
|
||||
string lastName = fullName.Substring(
|
||||
startIndex: indexOfTheSpace + 1);
|
||||
|
||||
WriteLine($"Original: {fullName}");
|
||||
WriteLine($"Swapped: {lastName}, {firstName}");
|
||||
|
||||
string company = "Microsoft";
|
||||
bool startsWithM = company.StartsWith("M");
|
||||
bool containsN = company.Contains("N");
|
||||
WriteLine($"Text: {company}");
|
||||
WriteLine($"Starts with M: {startsWithM}, contains an N: {containsN}");
|
||||
|
||||
string recombined = string.Join(" => ", citiesArray);
|
||||
WriteLine(recombined);
|
||||
|
||||
string fruit = "Apples";
|
||||
decimal price = 0.39M;
|
||||
DateTime when = DateTime.Today;
|
||||
|
||||
WriteLine($"Interpolated: {fruit} cost {price:C} on {when:dddd}.");
|
||||
WriteLine(string.Format("string.Format: {0} cost {1:C} on {2:dddd}.",
|
||||
arg0: fruit, arg1: price, arg2: when));
|
||||
14
vs4win/Chapter08/WorkingWithText/WorkingWithText.csproj
Normal file
14
vs4win/Chapter08/WorkingWithText/WorkingWithText.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
24
vscode/Chapter08/Ch08Ex02RegularExpressions/Program.cs
Normal file
24
vscode/Chapter08/Ch08Ex02RegularExpressions/Program.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.Text.RegularExpressions;
|
||||
|
||||
WriteLine("The default regular expression checks for at least one digit.");
|
||||
|
||||
do
|
||||
{
|
||||
Write("Enter a regular expression (or press ENTER to use the default): ");
|
||||
string? regexp = ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(regexp))
|
||||
{
|
||||
regexp = @"^\d+$";
|
||||
}
|
||||
|
||||
Write("Enter some input: ");
|
||||
string input = ReadLine()!; // will never be null
|
||||
|
||||
Regex r = new(regexp);
|
||||
|
||||
WriteLine($"{input} matches {regexp}: {r.IsMatch(input)}");
|
||||
|
||||
WriteLine("Press ESC to end or any key to try again.");
|
||||
}
|
||||
while (ReadKey(intercept: true).Key != ConsoleKey.Escape);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ch08Ex03NumbersAsWordsLib\Ch08Ex03NumbersAsWordsLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
16
vscode/Chapter08/Ch08Ex03NumbersAsWordsApp/Program.cs
Normal file
16
vscode/Chapter08/Ch08Ex03NumbersAsWordsApp/Program.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using Packt.Shared; // ToWords extension method
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
Write("Enter a number up to twenty one digits long: ");
|
||||
string? input = ReadLine();
|
||||
if (input is null) return;
|
||||
|
||||
if (input.Length > 21)
|
||||
{
|
||||
WriteLine("I cannot handle more than twenty one digits!");
|
||||
return;
|
||||
}
|
||||
|
||||
BigInteger number = BigInteger.Parse(input);
|
||||
|
||||
WriteLine($"{number:N0} in words is {number.ToWords()}.");
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
220
vscode/Chapter08/Ch08Ex03NumbersAsWordsLib/NumbersToWords.cs
Normal file
220
vscode/Chapter08/Ch08Ex03NumbersAsWordsLib/NumbersToWords.cs
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
using System.Diagnostics; // Trace
|
||||
using System.IO; // File
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
namespace Packt.Shared
|
||||
{
|
||||
public static class NumbersToWords
|
||||
{
|
||||
// Single-digit and small number names
|
||||
private static string[] smallNumbers = new string[]
|
||||
{
|
||||
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
|
||||
"nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen",
|
||||
"sixteen", "seventeen", "eighteen", "nineteen"
|
||||
};
|
||||
|
||||
// Tens number names from twenty upwards
|
||||
private static string[] tens = new string[]
|
||||
{
|
||||
"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
|
||||
"eighty", "ninety"
|
||||
};
|
||||
|
||||
// Scale number names for use during recombination
|
||||
private static string[] scaleNumbers = new string[]
|
||||
{
|
||||
"", "thousand", "million", "billion", "trillion",
|
||||
"quadrillion", "quintillion"
|
||||
};
|
||||
|
||||
private static int groups = 7; // i.e. up to quintillion
|
||||
|
||||
public static string ToWords(this int number)
|
||||
{
|
||||
return ToWords((BigInteger)number);
|
||||
}
|
||||
|
||||
public static string ToWords(this long number)
|
||||
{
|
||||
return ToWords((BigInteger)number);
|
||||
}
|
||||
|
||||
public static string ToWords(this BigInteger number)
|
||||
{
|
||||
/*
|
||||
Convert A Number into Words
|
||||
by Richard Carr, published at http://www.blackwasp.co.uk/numbertowords.aspx
|
||||
*/
|
||||
|
||||
/*
|
||||
Zero Rule.
|
||||
If the value is 0 then the number in words is 'zero' and no other rules apply.
|
||||
*/
|
||||
if (number == 0)
|
||||
{
|
||||
return "zero";
|
||||
}
|
||||
|
||||
/*
|
||||
Three Digit Rule.
|
||||
The integer value is split into groups of three digits starting from the
|
||||
right-hand side. Each set of three digits is then processed individually
|
||||
as a number of hundreds, tens and units. Once converted to text, the
|
||||
three-digit groups are recombined with the addition of the relevant scale
|
||||
number (thousand, million, billion).
|
||||
*/
|
||||
|
||||
// Array to hold the specified number of three-digit groups
|
||||
int[] digitGroups = new int[groups];
|
||||
|
||||
// Ensure a positive number to extract from
|
||||
var positive = BigInteger.Abs(number);
|
||||
|
||||
// Extract the three-digit groups
|
||||
for (int i = 0; i < groups; i++)
|
||||
{
|
||||
digitGroups[i] = (int)(positive % 1000);
|
||||
positive /= 1000;
|
||||
}
|
||||
|
||||
// write to a text file in the project folder
|
||||
Trace.Listeners.Add(new TextWriterTraceListener(
|
||||
File.AppendText("log.txt")));
|
||||
|
||||
// text writer is buffered, so this option calls
|
||||
// Flush() on all listeners after writing
|
||||
Trace.AutoFlush = true;
|
||||
|
||||
// log array of group numbers
|
||||
for (int x = 0; x < digitGroups.Length; x++)
|
||||
{
|
||||
Trace.WriteLine(string.Format(
|
||||
format: "digitGroups[{0}] = {1}",
|
||||
arg0: x,
|
||||
arg1: digitGroups[x]));
|
||||
}
|
||||
|
||||
// Convert each three-digit group to words
|
||||
string[] groupTexts = new string[groups];
|
||||
|
||||
for (int i = 0; i < groups; i++)
|
||||
{
|
||||
// call a local function (see below)
|
||||
groupTexts[i] = ThreeDigitGroupToWords(digitGroups[i]);
|
||||
}
|
||||
|
||||
// log array of group texts
|
||||
for (int x = 0; x < groupTexts.Length; x++)
|
||||
{
|
||||
Trace.WriteLine(string.Format(
|
||||
format: "groupTexts[{0}] = {1}",
|
||||
arg0: x,
|
||||
arg1: groupTexts[x]));
|
||||
}
|
||||
|
||||
/*
|
||||
Recombination Rules.
|
||||
When recombining the translated three-digit groups, each group except the
|
||||
last is followed by a large number name and a comma, unless the group is
|
||||
blank and therefore not included at all. One exception is when the final
|
||||
group does not include any hundreds and there is more than one non-blank
|
||||
group. In this case, the final comma is replaced with 'and'. eg.
|
||||
'one billion, one million and twelve'.
|
||||
*/
|
||||
|
||||
// Recombine the three-digit groups
|
||||
string combined = groupTexts[0];
|
||||
bool appendAnd;
|
||||
|
||||
// Determine whether an 'and' is needed
|
||||
appendAnd = (digitGroups[0] > 0) && (digitGroups[0] < 100);
|
||||
|
||||
// Process the remaining groups in turn, smallest to largest
|
||||
for (int i = 1; i < groups; i++)
|
||||
{
|
||||
// Only add non-zero items
|
||||
if (digitGroups[i] != 0)
|
||||
{
|
||||
// Build the string to add as a prefix
|
||||
string prefix = groupTexts[i] + " " + scaleNumbers[i];
|
||||
|
||||
if (combined.Length != 0)
|
||||
{
|
||||
prefix += appendAnd ? " and " : ", ";
|
||||
}
|
||||
|
||||
// Opportunity to add 'and' is ended
|
||||
appendAnd = false;
|
||||
|
||||
// Add the three-digit group to the combined string
|
||||
combined = prefix + combined;
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a three-digit group into English words
|
||||
string ThreeDigitGroupToWords(int threeDigits)
|
||||
{
|
||||
// Initialise the return text
|
||||
string groupText = "";
|
||||
|
||||
// Determine the hundreds and the remainder
|
||||
int hundreds = threeDigits / 100;
|
||||
int tensUnits = threeDigits % 100;
|
||||
|
||||
/*
|
||||
Hundreds Rules.
|
||||
If the hundreds portion of a three-digit group is not zero, the number of
|
||||
hundreds is added as a word. If the three-digit group is exactly divisible
|
||||
by one hundred, the text 'hundred' is appended. If not, the text
|
||||
"hundred and" is appended. eg. 'two hundred' or 'one hundred and twelve'
|
||||
*/
|
||||
|
||||
if (hundreds != 0)
|
||||
{
|
||||
groupText += smallNumbers[hundreds] + " hundred";
|
||||
|
||||
if (tensUnits != 0)
|
||||
{
|
||||
groupText += " and ";
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the tens and units
|
||||
int tens = tensUnits / 10;
|
||||
int units = tensUnits % 10;
|
||||
|
||||
/* Tens Rules.
|
||||
If the tens section of a three-digit group is two or higher, the appropriate
|
||||
'-ty' word (twenty, thirty, etc.) is added to the text and followed by the
|
||||
name of the third digit (unless the third digit is a zero, which is ignored).
|
||||
If the tens and the units are both zero, no text is added. For any other value,
|
||||
the name of the one or two-digit number is added as a special case.
|
||||
*/
|
||||
|
||||
if (tens >= 2)
|
||||
{
|
||||
groupText += NumbersToWords.tens[tens];
|
||||
if (units != 0)
|
||||
{
|
||||
groupText += " " + smallNumbers[units];
|
||||
}
|
||||
}
|
||||
else if (tensUnits != 0)
|
||||
groupText += smallNumbers[tensUnits];
|
||||
|
||||
return groupText;
|
||||
}
|
||||
|
||||
/* Negative Rule.
|
||||
Negative numbers are always preceded by the text 'negative'.
|
||||
*/
|
||||
if (number < 0)
|
||||
{
|
||||
combined = "negative " + combined;
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Ch08Ex03NumbersAsWordsLib\Ch08Ex03NumbersAsWordsLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
using Packt.Shared; // ToWords extension method
|
||||
using System.Numerics; // BigInteger
|
||||
|
||||
namespace Ch08Ex03NumbersAsWordsTests
|
||||
{
|
||||
public class NumbersToWordsUnitTests
|
||||
{
|
||||
[Fact]
|
||||
public void Test_Int32_0()
|
||||
{
|
||||
// arrange
|
||||
int number = 0;
|
||||
string expected = "zero";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_Int32_1234()
|
||||
{
|
||||
// arrange
|
||||
int number = 1234;
|
||||
string expected = "one thousand, two hundred and thirty four";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_BigInteger_18456002032011000007()
|
||||
{
|
||||
// arrange
|
||||
BigInteger number = BigInteger.Parse("18456002032011000007");
|
||||
string expected = "eighteen quintillion, four hundred and fifty six quadrillion, two trillion, thirty two billion, eleven million and seven";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_Int32_minus_13()
|
||||
{
|
||||
// arrange
|
||||
int number = -13;
|
||||
string expected = "negative thirteen";
|
||||
|
||||
// act
|
||||
string actual = number.ToWords();
|
||||
|
||||
// assert
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
vscode/Chapter08/Ch08Ex03NumbersAsWordsTests/Usings.cs
Normal file
1
vscode/Chapter08/Ch08Ex03NumbersAsWordsTests/Usings.cs
Normal file
|
|
@ -0,0 +1 @@
|
|||
global using Xunit;
|
||||
34
vscode/Chapter08/Chapter08.code-workspace
Normal file
34
vscode/Chapter08/Chapter08.code-workspace
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "WorkingWithNumbers"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithText"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithRegularExpressions"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithCollections"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithRanges"
|
||||
},
|
||||
{
|
||||
"path": "WorkingWithNetworkResources"
|
||||
},
|
||||
{
|
||||
"path": "Ch08Ex02RegularExpressions"
|
||||
},
|
||||
{
|
||||
"path": "Ch08Ex03NumbersAsWordsLib"
|
||||
},
|
||||
{
|
||||
"path": "Ch08Ex03NumbersAsWordsApp"
|
||||
},
|
||||
{
|
||||
"path": "Ch08Ex03NumbersAsWordsTests"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
vscode/Chapter08/WorkingWithCollections/Program.Helpers.cs
Normal file
21
vscode/Chapter08/WorkingWithCollections/Program.Helpers.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
partial class Program
|
||||
{
|
||||
static void Output(string title, IEnumerable<string> collection)
|
||||
{
|
||||
WriteLine(title);
|
||||
foreach (string item in collection)
|
||||
{
|
||||
WriteLine($" {item}");
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputPQ<TElement, TPriority>(string title,
|
||||
IEnumerable<(TElement Element, TPriority Priority)> collection)
|
||||
{
|
||||
WriteLine(title);
|
||||
foreach ((TElement, TPriority) item in collection)
|
||||
{
|
||||
WriteLine($" {item.Item1}: {item.Item2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
129
vscode/Chapter08/WorkingWithCollections/Program.cs
Normal file
129
vscode/Chapter08/WorkingWithCollections/Program.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
using System.Collections.Immutable;
|
||||
|
||||
// Working with lists
|
||||
|
||||
// Simple syntax for creating a list and adding three items
|
||||
List<string> cities = new();
|
||||
cities.Add("London");
|
||||
cities.Add("Paris");
|
||||
cities.Add("Milan");
|
||||
|
||||
/* Alternative syntax that is converted by the compiler into
|
||||
the three Add method calls above
|
||||
List<string> cities = new()
|
||||
{ "London", "Paris", "Milan" }; */
|
||||
|
||||
/* Alternative syntax that passes an
|
||||
array of string values to AddRange method
|
||||
List<string> cities = new();
|
||||
cities.AddRange(new[] { "London", "Paris", "Milan" }); */
|
||||
|
||||
Output("Initial list", cities);
|
||||
WriteLine($"The first city is {cities[0]}.");
|
||||
WriteLine($"The last city is {cities[cities.Count - 1]}.");
|
||||
|
||||
cities.Insert(0, "Sydney");
|
||||
Output("After inserting Sydney at index 0", cities);
|
||||
|
||||
cities.RemoveAt(1);
|
||||
cities.Remove("Milan");
|
||||
Output("After removing two cities", cities);
|
||||
|
||||
// Working with dictionaries
|
||||
|
||||
Dictionary<string, string> keywords = new();
|
||||
|
||||
// add using named parameters
|
||||
keywords.Add(key: "int", value: "32-bit integer data type");
|
||||
|
||||
// add using positional parameters
|
||||
keywords.Add("long", "64-bit integer data type");
|
||||
keywords.Add("float", "Single precision floating point number");
|
||||
|
||||
/* Alternative syntax; compiler converts this to calls to Add method
|
||||
Dictionary<string, string> keywords = new()
|
||||
{
|
||||
{ "int", "32-bit integer data type" },
|
||||
{ "long", "64-bit integer data type" },
|
||||
{ "float", "Single precision floating point number" },
|
||||
}; */
|
||||
|
||||
/* Alternative syntax; compiler converts this to calls to Add method
|
||||
Dictionary<string, string> keywords = new()
|
||||
{
|
||||
["int"] = "32-bit integer data type",
|
||||
["long"] = "64-bit integer data type",
|
||||
["float"] = "Single precision floating point number", // last comma is optional
|
||||
}; */
|
||||
|
||||
Output("Dictionary keys:", keywords.Keys);
|
||||
Output("Dictionary values:", keywords.Values);
|
||||
|
||||
WriteLine("Keywords and their definitions");
|
||||
foreach (KeyValuePair<string, string> item in keywords)
|
||||
{
|
||||
WriteLine($" {item.Key}: {item.Value}");
|
||||
}
|
||||
|
||||
// lookup a value using a key
|
||||
string key = "long";
|
||||
WriteLine($"The definition of {key} is {keywords[key]}");
|
||||
|
||||
// Working with queues
|
||||
|
||||
Queue<string> coffee = new();
|
||||
|
||||
coffee.Enqueue("Damir"); // front of queue
|
||||
coffee.Enqueue("Andrea");
|
||||
coffee.Enqueue("Ronald");
|
||||
coffee.Enqueue("Amin");
|
||||
coffee.Enqueue("Irina"); // back of queue
|
||||
|
||||
Output("Initial queue from front to back", coffee);
|
||||
|
||||
// server handles next person in queue
|
||||
string served = coffee.Dequeue();
|
||||
WriteLine($"Served: {served}.");
|
||||
|
||||
// server handles next person in queue
|
||||
served = coffee.Dequeue();
|
||||
WriteLine($"Served: {served}.");
|
||||
Output("Current queue from front to back", coffee);
|
||||
|
||||
WriteLine($"{coffee.Peek()} is next in line.");
|
||||
Output("Current queue from front to back", coffee);
|
||||
|
||||
// Working with priority queues
|
||||
|
||||
PriorityQueue<string, int> vaccine = new();
|
||||
|
||||
// add some people
|
||||
// 1 = high priority people in their 70s or poor health
|
||||
// 2 = medium priority e.g. middle aged
|
||||
// 3 = low priority e.g. teens and twenties
|
||||
|
||||
vaccine.Enqueue("Pamela", 1); // my mum (70s)
|
||||
vaccine.Enqueue("Rebecca", 3); // my niece (teens)
|
||||
vaccine.Enqueue("Juliet", 2); // my sister (40s)
|
||||
vaccine.Enqueue("Ian", 1); // my dad (70s)
|
||||
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
WriteLine($"{vaccine.Dequeue()} has been vaccinated.");
|
||||
|
||||
WriteLine("Adding Mark to queue with priority 2");
|
||||
vaccine.Enqueue("Mark", 2); // me (50s)
|
||||
|
||||
WriteLine($"{vaccine.Peek()} will be next to be vaccinated.");
|
||||
OutputPQ("Current queue for vaccination:", vaccine.UnorderedItems);
|
||||
|
||||
// Working with immutable collections
|
||||
|
||||
ImmutableList<string> immutableCities = cities.ToImmutableList();
|
||||
ImmutableList<string> newList = immutableCities.Add("Rio");
|
||||
Output("Immutable list of cities:", immutableCities);
|
||||
Output("New list of cities:", newList);
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
50
vscode/Chapter08/WorkingWithNetworkResources/Program.cs
Normal file
50
vscode/Chapter08/WorkingWithNetworkResources/Program.cs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
using System.Net; // IPHostEntry, Dns, IPAddress
|
||||
using System.Net.NetworkInformation; // Ping, PingReply, IPStatus
|
||||
|
||||
// Working with URIs, DNS, and IP addresses
|
||||
|
||||
Write("Enter a valid web address (or press Enter): ");
|
||||
string? url = ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(url)) // if they enter nothing...
|
||||
{
|
||||
// ... set a default URL
|
||||
url = "https://stackoverflow.com/search?q=securestring";
|
||||
}
|
||||
|
||||
Uri uri = new(url);
|
||||
WriteLine($"URL: {url}");
|
||||
WriteLine($"Scheme: {uri.Scheme}");
|
||||
WriteLine($"Port: {uri.Port}");
|
||||
WriteLine($"Host: {uri.Host}");
|
||||
WriteLine($"Path: {uri.AbsolutePath}");
|
||||
WriteLine($"Query: {uri.Query}");
|
||||
|
||||
IPHostEntry entry = Dns.GetHostEntry(uri.Host);
|
||||
WriteLine($"{entry.HostName} has the following IP addresses:");
|
||||
foreach (IPAddress address in entry.AddressList)
|
||||
{
|
||||
WriteLine($" {address} ({address.AddressFamily})");
|
||||
}
|
||||
|
||||
// Pinging a server
|
||||
|
||||
try
|
||||
{
|
||||
Ping ping = new();
|
||||
|
||||
WriteLine("Pinging server. Please wait...");
|
||||
PingReply reply = ping.Send(uri.Host);
|
||||
WriteLine($"{uri.Host} was pinged and replied: {reply.Status}.");
|
||||
|
||||
if (reply.Status == IPStatus.Success)
|
||||
{
|
||||
WriteLine("Reply from {0} took {1:N0}ms",
|
||||
arg0: reply.Address,
|
||||
arg1: reply.RoundtripTime);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteLine($"{ex.GetType().ToString()} says {ex.Message}");
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
27
vscode/Chapter08/WorkingWithNumbers/Program.cs
Normal file
27
vscode/Chapter08/WorkingWithNumbers/Program.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using System.Numerics;
|
||||
|
||||
WriteLine("Working with large integers:");
|
||||
WriteLine("-----------------------------------");
|
||||
|
||||
ulong big = ulong.MaxValue;
|
||||
WriteLine($"{big,40:N0}");
|
||||
|
||||
BigInteger bigger =
|
||||
BigInteger.Parse("123456789012345678901234567890");
|
||||
WriteLine($"{bigger,40:N0}");
|
||||
|
||||
WriteLine("Working with complex numbers:");
|
||||
|
||||
Complex c1 = new(real: 4, imaginary: 2);
|
||||
Complex c2 = new(real: 3, imaginary: 7);
|
||||
Complex c3 = c1 + c2;
|
||||
|
||||
// output using default ToString implementation
|
||||
WriteLine($"{c1} added to {c2} is {c3}");
|
||||
|
||||
// output using custom format
|
||||
WriteLine("{0} + {1}i added to {2} + {3}i is {4} + {5}i",
|
||||
c1.Real, c1.Imaginary,
|
||||
c2.Real, c2.Imaginary,
|
||||
c3.Real, c3.Imaginary);
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
28
vscode/Chapter08/WorkingWithRanges/Program.cs
Normal file
28
vscode/Chapter08/WorkingWithRanges/Program.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
string name = "Samantha Jones";
|
||||
|
||||
// getting the lengths of the first and last names
|
||||
|
||||
int lengthOfFirst = name.IndexOf(' ');
|
||||
int lengthOfLast = name.Length - lengthOfFirst - 1;
|
||||
|
||||
// Using Substring
|
||||
|
||||
string firstName = name.Substring(
|
||||
startIndex: 0,
|
||||
length: lengthOfFirst);
|
||||
|
||||
string lastName = name.Substring(
|
||||
startIndex: name.Length - lengthOfLast,
|
||||
length: lengthOfLast);
|
||||
|
||||
WriteLine($"First name: {firstName}, Last name: {lastName}");
|
||||
|
||||
// Using spans
|
||||
|
||||
ReadOnlySpan<char> nameAsSpan = name.AsSpan();
|
||||
ReadOnlySpan<char> firstNameSpan = nameAsSpan[0..lengthOfFirst];
|
||||
ReadOnlySpan<char> lastNameSpan = nameAsSpan[^lengthOfLast..^0];
|
||||
|
||||
WriteLine("First name: {0}, Last name: {1}",
|
||||
arg0: firstNameSpan.ToString(),
|
||||
arg1: lastNameSpan.ToString());
|
||||
14
vscode/Chapter08/WorkingWithRanges/WorkingWithRanges.csproj
Normal file
14
vscode/Chapter08/WorkingWithRanges/WorkingWithRanges.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
38
vscode/Chapter08/WorkingWithRegularExpressions/Program.cs
Normal file
38
vscode/Chapter08/WorkingWithRegularExpressions/Program.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System.Text.RegularExpressions; // Regex
|
||||
|
||||
Write("Enter your age: ");
|
||||
string input = ReadLine()!; // null-forgiving
|
||||
|
||||
Regex ageChecker = new(@"^\d+$");
|
||||
|
||||
if (ageChecker.IsMatch(input))
|
||||
{
|
||||
WriteLine("Thank you!");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteLine($"This is not a valid age: {input}");
|
||||
}
|
||||
|
||||
string films = "\"Monsters, Inc.\",\"I, Tonya\",\"Lock, Stock and Two Smoking Barrels\"";
|
||||
|
||||
WriteLine($"Films to split: {films}");
|
||||
|
||||
string[] filmsDumb = films.Split(',');
|
||||
|
||||
WriteLine("Splitting with string.Split method:");
|
||||
foreach (string film in filmsDumb)
|
||||
{
|
||||
WriteLine(film);
|
||||
}
|
||||
|
||||
Regex csv = new(
|
||||
"(?:^|,)(?=[^\"]|(\")?)\"?((?(1)[^\"]*|[^,\"]*))\"?(?=,|$)");
|
||||
|
||||
MatchCollection filmsSmart = csv.Matches(films);
|
||||
|
||||
WriteLine("Splitting with regular expression:");
|
||||
foreach (Match film in filmsSmart)
|
||||
{
|
||||
WriteLine(film.Groups[2].Value);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
45
vscode/Chapter08/WorkingWithText/Program.cs
Normal file
45
vscode/Chapter08/WorkingWithText/Program.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
string city = "London";
|
||||
WriteLine($"{city} is {city.Length} characters long.");
|
||||
|
||||
WriteLine($"First char is {city[0]} and third is {city[2]}.");
|
||||
|
||||
string cities = "Paris,Tehran,Chennai,Sydney,New York,Medellín";
|
||||
|
||||
string[] citiesArray = cities.Split(',');
|
||||
|
||||
WriteLine($"There are {citiesArray.Length} items in the array.");
|
||||
|
||||
foreach (string item in citiesArray)
|
||||
{
|
||||
WriteLine(item);
|
||||
}
|
||||
|
||||
string fullName = "Alan Jones";
|
||||
|
||||
int indexOfTheSpace = fullName.IndexOf(' ');
|
||||
|
||||
string firstName = fullName.Substring(
|
||||
startIndex: 0, length: indexOfTheSpace);
|
||||
|
||||
string lastName = fullName.Substring(
|
||||
startIndex: indexOfTheSpace + 1);
|
||||
|
||||
WriteLine($"Original: {fullName}");
|
||||
WriteLine($"Swapped: {lastName}, {firstName}");
|
||||
|
||||
string company = "Microsoft";
|
||||
bool startsWithM = company.StartsWith("M");
|
||||
bool containsN = company.Contains("N");
|
||||
WriteLine($"Text: {company}");
|
||||
WriteLine($"Starts with M: {startsWithM}, contains an N: {containsN}");
|
||||
|
||||
string recombined = string.Join(" => ", citiesArray);
|
||||
WriteLine(recombined);
|
||||
|
||||
string fruit = "Apples";
|
||||
decimal price = 0.39M;
|
||||
DateTime when = DateTime.Today;
|
||||
|
||||
WriteLine($"Interpolated: {fruit} cost {price:C} on {when:dddd}.");
|
||||
WriteLine(string.Format("string.Format: {0} cost {1:C} on {2:dddd}.",
|
||||
arg0: fruit, arg1: price, arg2: when));
|
||||
14
vscode/Chapter08/WorkingWithText/WorkingWithText.csproj
Normal file
14
vscode/Chapter08/WorkingWithText/WorkingWithText.csproj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net7.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="System.Console" Static="true" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in a new issue