This commit is contained in:
ipvg 2024-08-04 14:06:59 -04:00
parent 3a032a08b1
commit 39a1140397
9 changed files with 1419 additions and 2 deletions

View File

@ -0,0 +1,704 @@
# Guided project
## Work with variable data in C#
Demonstrate your ability to develop a console app that implements data
formatting and using arrays to deliver a search feature.
### Learning objectives
- Apply iteration statements to gather data input.
- Use data processing.
- Format data output.
- Choose the correct data types and safely convert data types.
- Manipulate number, string and character arrays, as well as add, remove, and
sort data.
- Modify and build complex strings from multiple data sources, and format data
for display across regions.
## Introduction
Suppose you're a developer who likes to support the local community. You and
some of your friends started a business that helps find new homes for stray or
abandoned cats and dogs. Your business started off small, with just a couple of
animals, but it's starting to grow. Your friends have an initial application
developed that enables the entry and display of the animals available for
adoption. They ask you to investigate adding features to the app that could
help to match the animals in your care with people who are looking for a new
family pet.
In completing this coding project, you apply your C# data knowledge and skills
in:
- Choosing the correct data types and safely converting data types.
- Create two dimensional arrays of numbers and strings.
- Search data in arrays to display or update data.
- Modifying and building complex strings from multiple data sources, and
formatting data for display across regions.
Your team has found that it's important to search the pet data to identify
animals with possible matches based on characteristics provided by potential
owners. Further, the team wants to include a fundraising feature to include
suggested donation data and to present the pet data with fewer lines of output.
You begin with a starting application that adds a predefined sample data to the
pets array. The application has two menu items. The first item displays all the
pet data, and the code is complete. The second is menu item, "Display all dogs
with a specified characteristic", is "work in progress" that you complete.
You also make updates to existing code to add `suggestedDonation` data and
display all data in a shortened format.
By the end of this module, you're able to develop code that combines iteration
statements with data input, data processing, string indexing, and data output.
---
### Prepare for guided project
Develop a version of a C# console application. The application comes with the
basic features that create sample data on pets available for adoption and is
able to display the pet's information. The main feature to add is searching
available dogs using a single search term. The secondary tasks include adding
and displaying suggestedDonation data.
### The design specification
For the new features of the Contoso Pets application, the design specification
provides details for the dog search and suggested donation features:
- Dog attribute search
- Gather input for the pet characteristic search term
- Loop through the animals array and identify "dogs"
- For each dog, combine the physical and personality descriptions to search
- Search the combined description for the input term match
- Output the dogs that have a term match
- Suggested donation data
- Define `suggestedDonation` string
- Expand the `ourAnimals` array to contain `suggestedDonation` and populate
sample data for `suggestedDonation`
- Ensure all usage of `ourAnimals` array accounts for the added
`suggestedDonation` data
- Output `suggestedDonation` with regional currency symbol ($, €, ¥,... )
#### Starter code overview
Initial starter code development is complete.
The Starter project for this guided project module includes a Program.cs file
that provides the following code features:
- the code declares variables used to collect and process pet data and menu
item selections
- the code declares the ourAnimals array
- the code uses a for loop around an `if`-`else if`-`else` construct to
populate the ourAnimals array with a sample dataset
- the code displays the following main menu options for user selection:
```txt
1. List all of our current pet information
2. Display all dogs with a specified characteristic
Enter menu item selection or type "Exit" to exit the program
```
- the code reads the user's menu item selection and displays a message
echoing their selection
- only selection "1. List all of our current pet information" functions using
the starter code
Your goal is to update the existing code to develop app features described
previously. The key features:
- Add dog attribute search
- Include suggested donation data
Use your development environment, and you test your application at each stage
of your development process.
#### Setup
Download the zip file containing the code folders for the guided
[project](https://github.com/MicrosoftLearning/Guided-project-Work-with-variable-data-in-CSharp/archive/refs/heads/main.zip)
and then extract.
- [Contoso](../019_branching_and_looping_structures/ChallengeProject/Own/Program.cs)
You're now ready to begin the Guided project exercises. Good luck!
---
## Exercise
### Review starter code
In this first step of the development process, you review the code provided in
the Starter project folder.
#### Review the contents of the Program.cs file
The Program.cs file contains a preliminary version of the application that you
're working on. The code includes features to generate and display the sample
data for the application, and it displays a list of menu options that define
the main features of the application.
Take a few minutes to review the initial variable declarations at the top of
the Program.cs file.
```cs
// #1 the ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
// #2 variables that support data entry
int maxPets = 8;
string? readResult;
string menuSelection = "";
// #3 array used to store runtime data, there is no persisted data
string[,] ourAnimals = new string[maxPets, 6];
```
First, you see a comment (comment #1) followed by a list of variables. These
variables, `animalSpecies` through `animalNickname`, used to hold the values of
the pet characteristics within a multidimensional string array named
`ourAnimals`, and initialized to contain a zero length string `""`. The
`ourAnimals` array declaration is a little further down in the code.
The next group of variables (under comment #2) are a mix of `string` and `int`
variables used to help generate sample data, read user input, and establish
exit criteria for the main program loop. Notice the code line
`string? readResult;`. You use the `?` character to transform a normally
non-nullable variable type (int, string, bool,...) with support for the
nullable type.
> Note
> When reading user entered values with the `Console.ReadLine()` method, it's
best to enable a nullable type string using string? to avoid the code compiler
generating a warning when you build the project.
The final variable (under comment #3) is the two-dimensional string array named
`ourAnimals`. You initialized the number of rows, defined by maxPets, to 8. The
number of characteristics that you're storing initially is six. The six
characteristics match the number of string variables that you examined in the
sample code, but the number of characteristics needs to expand to add a field
for `suggestedDonation`.
Scroll down the Program.cs file to examine the `for` loop that contains a
`switch` selection construct within its code block.
The code sample is a shortened version to save space.
```cs
// #4 create sample data ourAnimals array entries
for (int i = 0; i < maxPets; i++) {
switch (i) {
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
break;
case 1:
animalSpecies = "dog";
animalID = "d2";
animalAge = "9";
animalPhysicalDescription = "large reddish-brown male golden retriever weighing about 85 pounds. housebroken.";
animalPersonalityDescription = "loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.";
animalNickname = "gus";
break;
// case 2: deleted for brevity
// case 3: deleted for brevity
default:
animalSpecies = "";
animalID = "";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "";
break;
}
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
}
```
Notice that the `for` loop uses the `maxPets` variable to establish an upper
bound on the number of iterations following comment # 4.
Also notice that the `switch` construct selectively branches the code so that
you can define different pet characteristics for the pets in the sample data
set.
You use a `switch` statement to define different values for the first four
iterations of the `for` loop. After the sample data processing, all
characteristics are empty, or zero-length, string.
The values of the animal characteristic variables are assigned to the
`ourAnimals` array at the bottom of the for loop.
Scroll to the bottom of the code file. Examine the code used to display the
menu options and capture the input of the user's selection.
You should observe the following code:
```cs
// #5 display the top-level menu options
do {
// NOTE: the Console.Clear method is throwing an exception in debug sessions
Console.Clear();
Console.WriteLine("Welcome to the Contoso PetFriends app. Your main menu options are:");
Console.WriteLine(" 1. List all of our current pet information");
Console.WriteLine(" 2. Display all dogs with a specified characteristic");
Console.WriteLine();
Console.WriteLine("Enter your selection number (or type Exit to exit the program)");
readResult = Console.ReadLine();
if (readResult != null) {
menuSelection = readResult.ToLower();
}
// use switch-case to process the selected menu option
switch (menuSelection) {
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 0] != "ID #: ") {
Console.WriteLine();
for (int j = 0; j < 6; j++) {
Console.WriteLine(ourAnimals[i, j]);
}
}
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
case "2":
// Display all dogs with a specified characteristic");
Console.WriteLine("\nUNDER CONSTRUCTION - please check back next month to see progress.");
Console.WriteLine("Press the Enter key to continue.");
readResult = Console.ReadLine();
break;
default:
break;
}
} while (menuSelection != "exit");
```
Take a minute to review the two `case` statements.
There are only two menu options working with a limited version of the
application. The starter application provides only the capabilities needed for
running and testing features prototype.
Notice the line of code is `readResult = Console.ReadLine();` is followed by a
check for a null value.
The code using the `Console.ReadLine()` method, has the value set to the
nullable string `readResult` to avoid the code compiler generating a warning
when you build the project.
#### Check your work
Test the starter code console app, at the TERMINAL command prompt build & run
your project code with one command by entering: `dotnet run`.
When the code runs, two menu items are displayed.
- Enter "`1`" to test the "List all of our current pet information" output
- Enter "`2`" to test the placeholder message "under construction" message
Enter 1 followed by pressing the Enter key to "display all pets".
Check that all of the pet information displays.
As you observe the data on all pets, the last pet displayed should match the
following output:
```txt
ID #: c4
Species: cat
Age: 3
Nickname: Lion
Physical description: Medium sized, long hair, yellow, female, about 10 pounds. Uses litter box.
Personality: A people loving cat that likes to sit on your lap.
Press the Enter key to continue
```
Press the Enter key to continue and return to the menu.
At the menu prompt, enter `2` followed by pressing the Enter key.
This choice is a place holder for "Display all dogs with a specified
characteristic" functionality.
Check that the "UNDER CONSTRUCTION" message displays for "Display all dogs with
a specified characteristic" selection.
You should observe the following output:
```txt
UNDER CONSTRUCTION - please check back next month to see progress.
Press the Enter key to continue.
```
Type `exit`, at the app menu, to end the program and then close the terminal
panel.
The program should exit.
Now you're ready to start developing the new features.
---
## Exercise
### Add suggested donation data
In this step of the development process, you update the code provided in the
starter project folder, adding features for "suggested donation" to the
application.
#### Create the "Suggested Donation" features
The added donation features require you to create `suggestedDonation` variable,
and to expand the `ourAnimals` array accommodate the new donation data. Also,
you need to add the suggested donation amounts for each animal, and implement a
default amount when there suggested donation information is missing.
##### Add support for suggested donation data
You need to create a new variable to hold suggested donations and expand the
`ourAnimals` array to hold the new data.
Notice the code under comment #1 that declares variables used for populating
the `ourAnimals` array for each animal.
You need to declare another string for the suggested donation data.
```cs
// #1 the ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
```
Create the `suggestedDonation` variable below the declaration for
`animalNickname`.
The declaration for the `suggestedDonation` is added with the following
code:
```cs
string suggestedDonation = "";
```
Locate the code to create the `ourAnimals` array following comment # 3.
The following line of code creates the array:
```cs
string[,] ourAnimals = new string[maxPets, 6];
```
The sizes defining the two dimensions of the array are the maximum number of
pets `maxPets` and the number `6` for the six strings originally defined, but
without room for the new `suggestedDonation` data.
Update `ourAnimals` array to hold `7` "columns" of data for each animal instead
of `6`.
The following line shows the updated code:
```cs
string[,] ourAnimals = new string[maxPets, 7];
```
You've expanded the `ourAnimals` array to support the added `suggestedDonation`
data.
#### Add suggestedDonation amounts to the sample data
Take a minute to review `case 0:` inside the switch statement following comment
#4.
The following code that defines sample data for the first pet before the
`suggestedDonation` data is created. It would fit nicely below the
`animalNickname`!
```cs
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
break;
```
Insert a `suggestedDonation` value above the `break` statement for `case 0;`
through `default:` with the following values:
- Case 0: `suggestedDonation = "85.00";`
- Case 1: `suggestedDonation = "49.99";`
- Case 2: `suggestedDonation = "40.00";`
- Case 3: `suggestedDonation = "";`
- default: `suggestedDonation = "";`
The following code shows `case 0:` code with the addition of
'suggestedDonation':
```cs
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
suggestedDonation = "85.00";
break;
```
In your project.cs file, locate the following array populated with the pet data
from case statements (it's just before comment # 5):
```cs
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
```
Notice that `suggestedDonation` data isn't included as part of the sample data
starter code for populating the array.
It makes sense to populate the array with a statement like:
```cs
ourAnimals[i, 6] = "Suggested Donation: " + suggestedDonation;
```
But, you won't add that code. In the next section you'll use another approach.
#### Data validation with `TryParse()`
The variable `suggestedDonation` is intended to be a numeric value, but is
collected and stored as a `string`. In the future you may have to validate
`suggestedDonation` represents a decimal, and that you can convert it to a
decimal so it's available to use for billing calculations. To avoid an error
trying to use an entry like `twenty` you need to use `TryParse` validation.
> Note
> The code samples in this exercise are designed based on en-US culture setting
s, and use a period (`.`) as the decimal separator. Building and running the
code with a culture setting that uses a different decimal separators (such as a
comma `,`) may give unexpected results or errors. To fix this issue, replace the
period decimal separators in the code samples with your local decimal separator
(such as `,`). Alternatively, to run a program using the en-US culture setting,
add the following code to the top of your program: `using System.Globalization;`
and after any other `using` statements add
`CultureInfo.CurrentCulture = new CultureInfo("en-US");`.
Before comment #5, inside the end of the code block, add the code to validate
that `suggestedDonation` can be cast as a decimal.
You add the following:
```cs
if (!decimal.TryParse(suggestedDonation, out decimalDonation)) {
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
````
If the `suggestedDonation` variable can't be cast as a `decimal` the code
assigns a default value `decimalDonation = 45.00m;`. If the cast is successful,
the `TryParse` populates `decimalDonation`. Either way, `decimalDonation`
represents a proper decimal.
Ensure that your validation code is in the right place!
The two lines you added should appear in the code as the top two lines of the
following code:
```cs
if (!decimal.TryParse(suggestedDonation, out decimalDonation)){
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
}
// #5 display the top-level menu options
```
Note, validation still doesn't work. You can't forget, the need to declare
`decimalDonation` to use it in the code.
Following the comment #2, declare `decimalDonation`, after
`string menuSelection = "";`:
```cs
decimal decimalDonation = 0.00m;
```
Finally you're ready to populate `suggestedDonation` data for each pet.
Above comment #5, immediately after the `TryParse` closing bracket `}` you
completed, add the following code:
```cs
ourAnimals[i, 6] = $"Suggested Donation: {decimalDonation:C2}";
```
You used the `decimalDonation` version of the suggested donation data. You also
used string interpolation and currency formatting in the output.
Take a minute to review how the suggested donation data finally makes it into
the `ourAnimals` array.
The following code populates the `decimalAnimals` in context of the
`TryParse()`:
```cs
if (!decimal.TryParse(suggestedDonation, out decimalDonation)) {
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
ourAnimals[i, 6] = $"Suggested Donation: {decimalDonation:C2}";
}
// #5 display the top-level menu options
```
Notice that by using the code `{decimalDonation:C2}` the suggested donation,
from `decimalDonation`, will display with the local currency symbol and two
decimal places as directed by the currency formatting `:C2`.
#### Review and update where ourAnimals array should be used
The addition of the `suggestedDonation` data created need for further updates.
The menu option `"1. List all of our current pet information"` is missing the
added data.
Notice the code under comment #5, for the menu loop within `case 1`.
The inner loop "`for (int j = 0; j < 6; j++)`" that prints the pet attributes
needs to account for `suggestedDonation` data added.
Update the inner loop code exit condition. Increased the exit condition by "1",
so it becomes `j <7`. Check that your code matches the following:
```cs
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 0] != "ID #: ") {
Console.WriteLine();
for (int j = 0; j < 7; j++) { // increased exit condition
Console.WriteLine(ourAnimals[i, j]);
}
}
}
```
#### Testing Overview
With several code additions in place, you need to confirm your code works as
expected. The two significant test areas are:
The code complies without errors.
Selecting menu option 1 all pet information displays:
- Output includes all of sample pet information, including: ID, species, age,
nickname, physical description, and personality description.
- For each pet, the suggested donation displays with a currency symbol and with
two decimal places of precision.
#### Check your work
Build and run to test the code.
At the TERMINAL command prompt, to build your project code, enter the following
command: `dotnet build`
After a couple seconds, you should see a message telling you that your build
succeeded, and that you have 0 Warning(s) and 0 Error(s).
The solution code may look considerably different than the Program.cs code that
you've developed at this point in the Guided project. However, you can try
examining the Program.cs code in Final to help you isolate and fix an issue in
your code if you need to.
Try not to limit your use the solution code. Remember that you learn from
mistakes and that every developer spends time finding and fixing errors.
Test the updated console app, at the TERMINAL command prompt build & run your
project code with one command by entering: `dotnet run`. When the code runs two
menu items display.
- Enter "1" to test the "display all pets" output
- Enter "2" to test the placeholder message "under construction" message
The output for menu item #1 should closely match the following sample:
```txt
ID #: d1
Species: dog
Age: 2
Nickname: lola
Physical description: medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.
Personality: loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.
Suggested Donation: $85.00
ID #: d2
Species: dog
Age: 9
Nickname: gus
Physical description: large reddish-brown male golden retriever weighing about 85 pounds. housebroken.
Personality: loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.
Suggested Donation: $49.99
ID #: c3
Species: cat
Age: 1
Nickname: snow
Physical description: small white female weighing about 8 pounds. litter box trained.
Personality: friendly
Suggested Donation: $40.00
ID #: c4
Species: cat
Age:
Nickname: lion
Physical description:
Personality:
Suggested Donation: $45.00
```
If everything worked as expected, congratulations! Otherwise, look for the
error by checking code instruction steps involved. If needed, start over with a
new starter Project.cs file and if you still have issues check the solution
folder code for this exercise.
Type exit, at the app menu, to end the program and then close the terminal
panel.

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,189 @@
// using System;
// #1 the ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
string suggestedDonation = "";
// #2 variables that support data entry
int maxPets = 8;
string? readResult;
string menuSelection = "";
decimal decimalDonation = 0.00m;
// #3 array used to store runtime data, there is no persisted data
string[,] ourAnimals = new string[maxPets, 7];
// #4 create sample data ourAnimals array entries
for (int i = 0; i < maxPets; i++)
{
switch (i)
{
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
suggestedDonation = "85.00";
break;
case 1:
animalSpecies = "dog";
animalID = "d2";
animalAge = "9";
animalPhysicalDescription = "large reddish-brown male golden retriever weighing about 85 pounds. housebroken.";
animalPersonalityDescription = "loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.";
animalNickname = "gus";
suggestedDonation = "49.99";
break;
case 2:
animalSpecies = "cat";
animalID = "c3";
animalAge = "1";
animalPhysicalDescription = "small white female weighing about 8 pounds. litter box trained.";
animalPersonalityDescription = "friendly";
animalNickname = "snow";
suggestedDonation = "40.00";
break;
case 3:
animalSpecies = "cat";
animalID = "c4";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "lion";
suggestedDonation = "";
break;
default:
animalSpecies = "";
animalID = "";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "";
suggestedDonation = "";
break;
}
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
if (!decimal.TryParse(suggestedDonation, out decimalDonation)){
decimalDonation = 45.00m; // if suggestedDonation NOT a number, default to 45.00
}
ourAnimals[i, 6] = $"Suggested Donation: {decimalDonation:C2}";
}
// #5 display the top-level menu options
do
{
// NOTE: the Console.Clear method is throwing an exception in debug sessions
Console.Clear();
Console.WriteLine("Welcome to the Contoso PetFriends app. Your main menu options are:");
Console.WriteLine(" 1. List all of our current pet information");
Console.WriteLine(" 2. Display all dogs with a specified characteristic");
Console.WriteLine();
Console.WriteLine("Enter your selection number (or type Exit to exit the program)");
readResult = Console.ReadLine();
if (readResult != null)
{
menuSelection = readResult.ToLower();
}
// use switch-case to process the selected menu option
switch (menuSelection)
{
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++)
{
if (ourAnimals[i, 0] != "ID #: ")
{
Console.WriteLine();
for (int j = 0; j < 7; j++)
{
Console.WriteLine(ourAnimals[i, j].ToString());
}
}
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
case "2":
// Display all dogs with a specified characteristic");
string dogCharacteristic = "";
while (dogCharacteristic == "")
{
// have the user enter physical characteristics to search for
Console.WriteLine($"\nEnter one desired dog characteristics to search for");
readResult = Console.ReadLine();
if (readResult != null)
{
dogCharacteristic = readResult.ToLower().Trim();
}
}
bool noMatchesDog = true;
string dogDescription = "";
// #6 loop through the ourAnimals array to search for matching animals
for (int i = 0; i < maxPets; i++)
{
bool dogMatch = true;
if (ourAnimals[i, 1].Contains("dog"))
{
if (dogMatch == true)
{
// #7 Search combined descriptions and report results
dogDescription = ourAnimals[i, 4] + "\n" + ourAnimals[i, 5];
if (dogDescription.Contains(dogCharacteristic))
{
Console.WriteLine($"\nOur dog {ourAnimals[i, 3]} is a match!");
Console.WriteLine(dogDescription);
noMatchesDog = false;
}
}
}
}
if (noMatchesDog)
{
Console.WriteLine("None of our dogs are a match found for: " + dogCharacteristic);
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
default:
break;
}
} while (menuSelection != "exit");

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Microsoft Learning
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,363 @@
int max_pets = 8;
bool exit = false;
string? selection;
const string WIP = "Under Construction - please check " +
"back next month to see progress.";
const string separator = "+-------------------------------------" +
"----------------------------------------+";
const string main_menu = @"
1. List all of our current pet information.
2. Assign values to the ourAnimals array fields.
3. Ensure animal ages and physical descriptions are complete.
4. Ensure animal nicknames and personality descriptions are complete.
5. Edit an animal's age.
6. Edit an animal's personality description.
7. Display all cats with a specified characteristic.
8. Display all dogs with a specified characteristic.
Enter menu item selection or type 'Exit' to exit the program
";
string[] description = {
"big sized female golden colored weighing 20 pounds. housebroken.",
"large dark-brown male siver back weighing 15 pounds. housebroken.",
"small white female weighing about 8 pounds. translucid.",
"medium size male. fluorescent at night.",
"medium size weighing 4 punds, orange with black lines.",
};
string[] personality = {
"friendly",
"loves to have his ears rubbed at any time! loves to lean-in.",
"loves to have her belly rubbed. gives lots of kisses.",
"sauvage and lovelly.",
"mad but cute",
"loves to play with a rope",
};
string[] options = { "1", "2", "3", "4", "5", "6", "7", "8", "exit" };
string[] nickname = { "lola", "loki", "fuzz", "boby", "gogo", "besti" };
string[] species = { "cat", "dog", "bee", "pig", "fly", "rat", "bat" };
string[] abcd = { "a", "b", "c", "d" };
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8 };
string[,] our_animals = new string[max_pets, 6];
Random rand = new Random();
var clear = Console.Clear;
void print(string text, bool new_line = true) {
if (new_line) {
Console.WriteLine(text);
} else {
Console.Write(text);
}
}
string rand_str(string[] choices) {
int indx = rand.Next(choices.Length);
return choices[indx];
}
int rand_int(int[] choices) {
int indx = rand.Next(choices.Length);
return choices[indx];
}
string get_uniq_id(string[,] animals) {
for (int i = 0; i < max_pets - 4; i++) {
bool uniq_id = false;
while (!uniq_id) {
bool check = true;
string id = $"{rand_str(abcd)}{rand_int(nums)}";
for (int j = 0; j < max_pets - 4; j++) {
if (!string.IsNullOrEmpty(animals[j, 1]) && animals[j, 1] == id) {
uniq_id = false;
check = false;
break;
}
}
if (check) {
uniq_id = true;
return id;
}
}
}
return "?";
}
void populate_animals_array() {
for (int i = 0; i < max_pets - 4; i++) {
our_animals[i, 0] = rand_str(species);
our_animals[i, 1] = get_uniq_id(our_animals);
our_animals[i, 2] = rand_str(description);
our_animals[i, 3] = $"{rand_int(nums)}";
our_animals[i, 4] = rand_str(personality);
our_animals[i, 5] = rand_str(nickname);
}
}
void press_enter(string msg = "\n\tPress 'Enter' to continue") {
print(msg, false);
Console.ReadLine();
}
void print_pets(string[,] animals) {
clear();
print(separator);
for (int j = 0; j < animals.GetLength(0); j++) {
string[] animal = new string[6];
for (int k = 0; k < animals.GetLength(1); k++) {
animal[k] = animals[j, k];
}
print_pet(animal);
}
press_enter();
}
void print_pet(string[] pet) {
if (!string.IsNullOrEmpty(pet[1])) {
string id = pet[1];
string name = pet[5];
string specie = pet[0];
int age = Int32.Parse(pet[3].ToString());
string year_word = age > 1 ? "years" : "year";
string desc = pet[2];
string perso = pet[4];
print($@" ID: {id} SPECIE: {specie}
NAME: {name} AGE: {age} {year_word}
DESCRIPTION: {desc}
PERSONALITY: {perso}
{separator}");
}
}
int availability(string[,] animals) {
int pet_count = 0;
for (int j = 0; j < animals.GetLength(0); j++) {
if (!string.IsNullOrEmpty(animals[j, 1])) {
pet_count++;
}
}
int slots = max_pets - pet_count;
return slots;
}
string get_input(string text = "Please enter your text: ",
bool integer = false,
string[]? opts = null) {
bool invalid = true;
while (invalid) {
print(text, false);
string? usr_in = Console.ReadLine();
if (!string.IsNullOrEmpty(usr_in) && usr_in.Trim() != "") {
string resp = usr_in.Trim();
if (integer) {
int temp_int;
if (int.TryParse(resp, out temp_int)) {
return resp;
}
} else if (opts != null) {
resp = resp.ToLower();
if (opts.Contains(resp)) {
return resp;
} else {
print($"Please enter a valid option (", false);
foreach (string opt in opts) {
print($" {opt} ", false);
}
print(")");
}
} else {
return resp;
}
}
}
return "?";
}
void add_new_pet(string[,] animals, int slots) {
int at_indx = max_pets - slots;
string id = $"{rand_str(abcd)}{rand_int(nums)}";
string specie = get_input("Enter pet specie: ", false, species);
string name = get_input("Enter the pet name (? if unknown): ");
int age = Int32.Parse(get_input("Enter pet age (-1 if unknown): ", true));
string desc = get_input("Enter the physical description (? if unknown): ");
string perso = get_input("Enter pet personality (? if unknown): ");
animals[at_indx, 0] = specie;
animals[at_indx, 1] = id;
animals[at_indx, 2] = desc;
animals[at_indx, 3] = age.ToString();
animals[at_indx, 4] = perso;
animals[at_indx, 5] = name;
}
void ask_new_pet() {
clear();
print("Assign values to the ourAnimals array fields");
print(separator);
int slots = availability(our_animals);
print($"\nWe currently have {max_pets - slots} pets that need homes.");
print($"We can manage {slots} more.");
if (slots > 0) {
bool another = false;
do {
string resp = get_input(
"Do you want to enter info for another pet?: "
);
bool invalid = true;
if (resp != "") {
while (invalid) {
switch (resp) {
case "y" or "yes":
add_new_pet(our_animals, slots);
resp = "";
invalid = false;
another = true;
break;
case "n" or "no":
invalid = false;
another = false;
break;
default:
resp = get_input("Please enter [Y]es or [N]o: ");
break;
}
}
}
slots = availability(our_animals);
} while (another && slots > 0);
if (slots == 0) {
print("We have reached our limit on the number of pets that we can manage.");
}
}
press_enter();
}
void check_age_and_desc(string[,] animals) {
clear();
print("\nEnsure animal ages and physical descriptions are complete");
int pet_count = max_pets - (availability(animals));
for (int j = 0; j < pet_count; j++) {
if (animals[j, 3] == "-1") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
int age = Int32.Parse(
get_input(
$"Enter an age for ID: {animals[j, 1]}" +
" (-1 if unknown): ", true
)
);
animals[j, 3] = age.ToString();
}
if (animals[j, 2] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string desc = get_input(
$"Enter a physical description for ID: {animals[j, 1]}" +
" (? if unknown): "
);
animals[j, 2] = desc;
}
}
press_enter();
}
void check_nick_and_perso(string[,] animals) {
clear();
print("Ensure animal nicknames and personality descriptions are complete");
print(separator);
int pet_count = max_pets - (availability(animals));
for (int j = 0; j < pet_count; j++) {
if (animals[j, 5] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string nick = get_input(
$"Enter a nickname for ID: {animals[j, 1]}" +
"(? if unknown): "
);
animals[j, 5] = nick;
}
if (animals[j, 4] == "?") {
print("\n" + separator);
string[] animal = {
animals[j,0], animals[j,1], animals[j,2],
animals[j,3], animals[j,4], animals[j,5]
};
print_pet(animal);
string perso = get_input(
$"Enter a personality description for ID: {animals[j, 1]}" +
"(? if unknown): "
);
animals[j, 4] = perso;
}
}
press_enter();
}
populate_animals_array();
while (!exit) {
clear();
print(main_menu);
selection = Console.ReadLine();
if (selection != null && options.Contains(selection.ToLower())) {
selection = selection.ToLower();
switch (selection) {
case "1":
print_pets(our_animals);
break;
case "2":
ask_new_pet();
break;
case "3":
check_age_and_desc(our_animals);
break;
case "4":
check_nick_and_perso(our_animals);
break;
case "5":
clear();
print(WIP);
press_enter();
break;
case "6":
clear();
print(WIP);
press_enter();
break;
case "7":
clear();
print(WIP);
press_enter();
break;
case "8":
clear();
print(WIP);
press_enter();
break;
case "exit":
print("\n\tTerminating application\n");
exit = !exit;
break;
default:
print("\n\tPlease read the instructions");
press_enter();
break;
}
} else {
print("\n\tPlease read the instructions");
press_enter();
}
}
Environment.Exit(0);

View File

@ -0,0 +1,109 @@
// #1 the ourAnimals array will store the following:
string animalSpecies = "";
string animalID = "";
string animalAge = "";
string animalPhysicalDescription = "";
string animalPersonalityDescription = "";
string animalNickname = "";
// #2 variables that support data entry
int maxPets = 8;
string? readResult;
string menuSelection = "";
// #3 array used to store runtime data, there is no persisted data
string[,] ourAnimals = new string[maxPets, 6];
// #4 create sample data ourAnimals array entries
for (int i = 0; i < maxPets; i++) {
switch (i) {
case 0:
animalSpecies = "dog";
animalID = "d1";
animalAge = "2";
animalPhysicalDescription = "medium sized cream colored female golden retriever weighing about 45 pounds. housebroken.";
animalPersonalityDescription = "loves to have her belly rubbed and likes to chase her tail. gives lots of kisses.";
animalNickname = "lola";
break;
case 1:
animalSpecies = "dog";
animalID = "d2";
animalAge = "9";
animalPhysicalDescription = "large reddish-brown male golden retriever weighing about 85 pounds. housebroken.";
animalPersonalityDescription = "loves to have his ears rubbed when he greets you at the door, or at any time! loves to lean-in and give doggy hugs.";
animalNickname = "gus";
break;
case 2:
animalSpecies = "cat";
animalID = "c3";
animalAge = "1";
animalPhysicalDescription = "small white female weighing about 8 pounds. litter box trained.";
animalPersonalityDescription = "friendly";
animalNickname = "snow";
break;
case 3:
animalSpecies = "cat";
animalID = "c4";
animalAge = "3";
animalPhysicalDescription = "Medium sized, long hair, yellow, female, about 10 pounds. Uses litter box.";
animalPersonalityDescription = "A people loving cat that likes to sit on your lap.";
animalNickname = "Lion";
break;
default:
animalSpecies = "";
animalID = "";
animalAge = "";
animalPhysicalDescription = "";
animalPersonalityDescription = "";
animalNickname = "";
break;
}
ourAnimals[i, 0] = "ID #: " + animalID;
ourAnimals[i, 1] = "Species: " + animalSpecies;
ourAnimals[i, 2] = "Age: " + animalAge;
ourAnimals[i, 3] = "Nickname: " + animalNickname;
ourAnimals[i, 4] = "Physical description: " + animalPhysicalDescription;
ourAnimals[i, 5] = "Personality: " + animalPersonalityDescription;
}
// #5 display the top-level menu options
do {
// NOTE: the Console.Clear method is throwing an exception in debug sessions
Console.Clear();
Console.WriteLine("Welcome to the Contoso PetFriends app. Your main menu options are:");
Console.WriteLine(" 1. List all of our current pet information");
Console.WriteLine(" 2. Display all dogs with a specified characteristic");
Console.WriteLine();
Console.WriteLine("Enter your selection number (or type Exit to exit the program)");
readResult = Console.ReadLine();
if (readResult != null) {
menuSelection = readResult.ToLower();
}
// use switch-case to process the selected menu option
switch (menuSelection) {
case "1":
// list all pet info
for (int i = 0; i < maxPets; i++) {
if (ourAnimals[i, 0] != "ID #: ") {
Console.WriteLine();
for (int j = 0; j < 6; j++) {
Console.WriteLine(ourAnimals[i, j]);
}
}
}
Console.WriteLine("\n\rPress the Enter key to continue");
readResult = Console.ReadLine();
break;
case "2":
// Display all dogs with a specified characteristic
Console.WriteLine("\nUNDER CONSTRUCTION - please check back next month to see progress.");
Console.WriteLine("Press the Enter key to continue.");
readResult = Console.ReadLine();
break;
default:
break;
}
} while (menuSelection != "exit");

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@ -27,5 +27,6 @@ Following
20. [Choose the correct data type](./020_data_types/020_csharp.md)
21. [Convert data types](./021_Casting_and_conversion_techniques/021_csharp.md)
22. [Array Operations](./022_array_operations/022_csharp.md)
23. [Format alphanumeric data](/023_alphanumeric_data_format/023_csharp.md)
24. [String data type methods](/024_String_data_type_methods/024_csharp.md)
23. [Format alphanumeric data](./023_alphanumeric_data_format/023_csharp.md)
24. [String data type methods](./024_String_data_type_methods/024_csharp.md)
25. [Work with variable data](./025_Work_with_variable_data/025_csharp.md)