diff --git a/025_Work_with_variable_data/025_csharp.md b/025_Work_with_variable_data/025_csharp.md new file mode 100644 index 0000000..06b126b --- /dev/null +++ b/025_Work_with_variable_data/025_csharp.md @@ -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. diff --git a/025_Work_with_variable_data/GuidedProject/Final/Final.csproj b/025_Work_with_variable_data/GuidedProject/Final/Final.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Final/Final.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/025_Work_with_variable_data/GuidedProject/Final/Program.cs b/025_Work_with_variable_data/GuidedProject/Final/Program.cs new file mode 100644 index 0000000..49dbc35 --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Final/Program.cs @@ -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"); diff --git a/025_Work_with_variable_data/GuidedProject/LICENSE b/025_Work_with_variable_data/GuidedProject/LICENSE new file mode 100644 index 0000000..2080d95 --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/LICENSE @@ -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. diff --git a/025_Work_with_variable_data/GuidedProject/Own/Own.csproj b/025_Work_with_variable_data/GuidedProject/Own/Own.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Own/Own.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/025_Work_with_variable_data/GuidedProject/Own/Program.cs b/025_Work_with_variable_data/GuidedProject/Own/Program.cs new file mode 100644 index 0000000..cc71f21 --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Own/Program.cs @@ -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); diff --git a/025_Work_with_variable_data/GuidedProject/Starter/Program.cs b/025_Work_with_variable_data/GuidedProject/Starter/Program.cs new file mode 100644 index 0000000..6a963bd --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Starter/Program.cs @@ -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"); diff --git a/025_Work_with_variable_data/GuidedProject/Starter/Starter.csproj b/025_Work_with_variable_data/GuidedProject/Starter/Starter.csproj new file mode 100644 index 0000000..f02677b --- /dev/null +++ b/025_Work_with_variable_data/GuidedProject/Starter/Starter.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/README.md b/README.md index 5827484..a265548 100644 --- a/README.md +++ b/README.md @@ -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)