Household accounts - C# Programming Exercise

This exercise in C# consists of creating a program that can store up to 10,000 costs and revenues, to create a small domestic accounting system. For each expense (or income), the following information should be allowed to be saved: • Date (8 characters: YYYYMMDD format).
• Description of the expense or income.
Category.
• Amount (if positive it's income, negative if an expense).
The program should allow the user to perform the following operations:

1 - Add a new expense (the date should "look right": day from 01 to 31, month from 01 to 12, year between 1000 and 3000). The description must not be empty. No need to validate other data.
2 - Show all expenses of a certain category (e.g., "studies") between two certain dates (e.g., between "20110101" and "20111231"). The number, date (DD/MM/YYYY format), description, category in parentheses, and amount to two decimal places should be displayed on the same line, separated by hyphens. At the end of all data, the total amount of the displayed data should be shown.
3 - Search for costs containing a certain text (in the description or category, not case-sensitive). The number, date, and description (the description will be truncated to 6 spaces if needed) will be displayed.
4 - Modify a record (prompt the user for the number, show the previous value of each field, and allow the user to press Enter to not modify any data). The user should be warned (but not asked again) if they enter a wrong record number. No need to validate any data.
5 - Delete some data, starting from the number you enter. The user should be warned (but not asked again) if they enter an incorrect number. The record to be deleted should be shown and confirmation should be asked before deletion.
6 - Sort the data alphabetically, by date, and (if dates match) by description.
7 - Normalize descriptions: remove trailing spaces, spaces, and mirror sites. If a description is all uppercase, it should be converted to lowercase (except for the first letter, which remains uppercase).
T - End the use of the application (as we store the data, it will be lost).

 Category

Arrays, Structures and Strings

 Exercise

Household Accounts

 Objective

Write a C# program in C# that can store up to 10000 costs and revenues, to create a small domestic accounting system. For each expense (or income), should be allowed to save the following information:

• Date (8 characters: YYYYMMDD format)
• Description of expenditure or revenue
• Category
• Amount (if positive income, negative if an expense)

The program should allow the user to perform the following operations:

1 - Add a new expense (the date should "look right": day 01 to 31 months from 01 to 12 years between 1000 and 3000). The description must not be empty. Needless to validate the other data.

2 - Show all expenses of a certain category (eg, "studies") between two certain dates (eg between "20110101" and "20111231"). Number is displayed, date (format DD / MM / YYYY), description, category in parentheses, and amount to two decimal places, all in the same line, separated by hyphens. At the end of all data show the total amount of data displayed.

3 - Search costs containing a certain text (in the description or category without distinguishing case sensitive). Number is displayed, the date and description (the description is displayed in the sixth truncated blank, if any spaces six or more).

4 - Modify a tab (tab number prompt the user, it will show the previous value of each field and press Enter to not be able to modify any of the data). Should be advised (but not re-order) if the user enters a wrong card number. Needless to validate any data.

5 - Delete some data, from the number that you enter. Should be advised (but not re-order) if you enter an incorrect number. It should show the card to be clear and prompt prior to deletion.

6 - Sort data alphabetically, by date and (if matched) description.

7 - Normalize descriptions: remove trailing spaces, spaces and mirror sites. If a description is all uppercase, will be converted to lowercase (except for the first letter, kept in uppercase).

T-End the use of the application (as we store the information, the data will be lost).

 Example C# Exercise

 Copy C# Code
using System;
using System.Collections.Generic;
using System.Linq;

namespace HouseholdAccounts
{
    class Program
    {
        // Create a structure to store cost/revenue information
        struct AccountEntry
        {
            public string Date;         // Date in YYYYMMDD format
            public string Description;  // Description of the expense or income
            public string Category;     // Category of the expense or income
            public decimal Amount;      // Amount (positive for income, negative for expense)
        }

        static List accountEntries = new List(); // List to store all account entries

        static void Main(string[] args)
        {
            bool running = true; // Variable to control the main loop

            while (running) // Main loop to keep the program running
            {
                Console.WriteLine("\nChoose an option:"); // Display menu options
                Console.WriteLine("1 - Add new expense");
                Console.WriteLine("2 - Show expenses by category");
                Console.WriteLine("3 - Search costs by text");
                Console.WriteLine("4 - Modify record");
                Console.WriteLine("5 - Delete data");
                Console.WriteLine("6 - Sort data");
                Console.WriteLine("7 - Normalize descriptions");
                Console.WriteLine("T - End application");

                string choice = Console.ReadLine().ToUpper(); // Read user input and convert it to uppercase

                switch (choice) // Switch based on user choice
                {
                    case "1": // Add a new entry
                        // Ask user for date, description, category, and amount
                        Console.WriteLine("Enter the date (YYYYMMDD):");
                        string date = Console.ReadLine();

                        // Validate the date format (it should be YYYYMMDD, a valid date)
                        DateTime validDate;
                        while (!DateTime.TryParseExact(date, "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out validDate))
                        {
                            Console.WriteLine("Invalid date. Please enter in the format YYYYMMDD:");
                            date = Console.ReadLine();
                        }

                        // Ask for description
                        Console.WriteLine("Enter description:");
                        string description = Console.ReadLine();
                        while (string.IsNullOrEmpty(description))
                        {
                            Console.WriteLine("Description cannot be empty. Please enter a description:");
                            description = Console.ReadLine();
                        }

                        // Ask for category
                        Console.WriteLine("Enter category:");
                        string category = Console.ReadLine();

                        // Ask for amount
                        Console.WriteLine("Enter amount (positive for income, negative for expense):");
                        decimal amount = Convert.ToDecimal(Console.ReadLine());

                        // Create a new account entry and add it to the list
                        AccountEntry entry = new AccountEntry
                        {
                            Date = date,
                            Description = description,
                            Category = category,
                            Amount = amount
                        };
                        accountEntries.Add(entry); // Add the entry to the list
                        break;

                    case "2": // Show expenses by category
                        Console.WriteLine("Enter start date (YYYYMMDD):");
                        string startDate = Console.ReadLine();

                        Console.WriteLine("Enter end date (YYYYMMDD):");
                        string endDate = Console.ReadLine();

                        // Filter the list by date range
                        var filteredEntries = accountEntries.Where(e =>
                            string.Compare(e.Date, startDate) >= 0 && string.Compare(e.Date, endDate) <= 0).ToList();

                        Console.WriteLine("Enter category:");
                        string categoryFilter = Console.ReadLine();

                        // Filter by category
                        filteredEntries = filteredEntries.Where(e => e.Category.Equals(categoryFilter, StringComparison.OrdinalIgnoreCase)).ToList();

                        // Display the filtered records
                        decimal totalAmount = 0;
                        int count = 1;
                        foreach (var entryInList in filteredEntries) // Changed variable name to avoid conflict
                        {
                            // Format and display each entry
                            Console.WriteLine($"{count} - {entryInList.Date.Substring(6, 2)}/{entryInList.Date.Substring(4, 2)}/{entryInList.Date.Substring(0, 4)} - {entryInList.Description} - ({entryInList.Category}) - {entryInList.Amount:F2}");
                            totalAmount += entryInList.Amount;
                            count++;
                        }
                        Console.WriteLine($"Total amount: {totalAmount:F2}");
                        break;

                    case "3": // Search costs by text
                        Console.WriteLine("Enter text to search:");
                        string searchText = Console.ReadLine().ToLower();

                        // Find entries that match the search text in either description or category (case insensitive)
                        var searchResults = accountEntries.Where(e =>
                            e.Description.ToLower().Contains(searchText) || e.Category.ToLower().Contains(searchText)).ToList();

                        if (searchResults.Count == 0)
                        {
                            Console.WriteLine("No records found.");
                        }
                        else
                        {
                            int searchCount = 1;
                            foreach (var entryInList in searchResults) // Changed variable name to avoid conflict
                            {
                                // Display the result with description truncated if necessary
                                string descriptionSearch = entryInList.Description.Length > 50 ? entryInList.Description.Substring(0, 50) + "..." : entryInList.Description;
                                Console.WriteLine($"{searchCount} - {entryInList.Date.Substring(6, 2)}/{entryInList.Date.Substring(4, 2)}/{entryInList.Date.Substring(0, 4)} - {descriptionSearch}");
                                searchCount++;
                            }
                        }
                        break;

                    case "4": // Modify a record
                        Console.WriteLine("Enter the record number to modify:");
                        int recordNumber = Convert.ToInt32(Console.ReadLine()) - 1;

                        if (recordNumber < 0 || recordNumber >= accountEntries.Count)
                        {
                            Console.WriteLine("Invalid record number.");
                            break;
                        }

                        // Show current values for modification
                        AccountEntry modifyEntry = accountEntries[recordNumber];
                        Console.WriteLine($"Current values: Date: {modifyEntry.Date}, Description: {modifyEntry.Description}, Category: {modifyEntry.Category}, Amount: {modifyEntry.Amount}");

                        // Modify each field
                        Console.WriteLine("Enter new date (or press Enter to keep current):");
                        string newDate = Console.ReadLine();
                        if (!string.IsNullOrEmpty(newDate)) modifyEntry.Date = newDate;

                        Console.WriteLine("Enter new description (or press Enter to keep current):");
                        string newDescription = Console.ReadLine();
                        if (!string.IsNullOrEmpty(newDescription)) modifyEntry.Description = newDescription;

                        Console.WriteLine("Enter new category (or press Enter to keep current):");
                        string newCategory = Console.ReadLine();
                        if (!string.IsNullOrEmpty(newCategory)) modifyEntry.Category = newCategory;

                        Console.WriteLine("Enter new amount (or press Enter to keep current):");
                        string newAmount = Console.ReadLine();
                        if (!string.IsNullOrEmpty(newAmount)) modifyEntry.Amount = Convert.ToDecimal(newAmount);

                        // Save the modified entry
                        accountEntries[recordNumber] = modifyEntry;
                        break;

                    case "5": // Delete data
                        Console.WriteLine("Enter start record number to delete:");
                        int startRecord = Convert.ToInt32(Console.ReadLine()) - 1;

                        Console.WriteLine("Enter end record number to delete:");
                        int endRecord = Convert.ToInt32(Console.ReadLine()) - 1;

                        if (startRecord < 0 || endRecord >= accountEntries.Count || startRecord > endRecord)
                        {
                            Console.WriteLine("Invalid record numbers.");
                            break;
                        }

                        // Confirm deletion of records
                        for (int i = startRecord; i <= endRecord; i++)
                        {
                            Console.WriteLine($"Are you sure you want to delete record {i + 1}? (Y/N)");
                            string confirmation = Console.ReadLine().ToUpper();
                            if (confirmation == "Y")
                            {
                                accountEntries.RemoveAt(i);
                                i--; // Adjust for removed entry
                            }
                        }
                        break;

                    case "6": // Sort data
                        var sortedEntries = accountEntries.OrderBy(e => e.Date).ThenBy(e => e.Description).ToList();

                        // Display sorted entries
                        int sortedCount = 1;
                        foreach (var entryInList in sortedEntries) // Changed variable name to avoid conflict
                        {
                            Console.WriteLine($"{sortedCount} - {entryInList.Date.Substring(6, 2)}/{entryInList.Date.Substring(4, 2)}/{entryInList.Date.Substring(0, 4)} - {entryInList.Description} - ({entryInList.Category}) - {entryInList.Amount:F2}");
                            sortedCount++;
                        }
                        break;

                    case "7": // Normalize descriptions
                        for (int i = 0; i < accountEntries.Count; i++) // Use a for loop to modify the list directly
                        {
                            var entryInList = accountEntries[i]; // Get the entry at index i

                            string normalizedDescription = entryInList.Description.Trim();
                            if (normalizedDescription.ToUpper() == normalizedDescription)  // If the description is all uppercase
                            {
                                normalizedDescription = char.ToUpper(normalizedDescription[0]) + normalizedDescription.Substring(1).ToLower();
                            }

                            // Update the description in the entry
                            accountEntries[i] = new AccountEntry
                            {
                                Date = entryInList.Date,
                                Description = normalizedDescription,
                                Category = entryInList.Category,
                                Amount = entryInList.Amount
                            };
                        }
                        break;

                    case "T": // End application
                        running = false;
                        break;

                    default:
                        Console.WriteLine("Invalid option."); // Handle invalid input
                        break;
                }
            }
        }
    }
}

 Output

Choose an option:
1 - Add new expense
2 - Show expenses by category
3 - Search costs by text
4 - Modify record
5 - Delete data
6 - Sort data
7 - Normalize descriptions
T - End application
1
Enter the date (YYYYMMDD):
1999/01/01
Invalid date. Please enter in the format YYYYMMDD:
19990101
Enter description:
Yogurt
Enter category:
lact
Enter amount (positive for income, negative for expense):
10

Choose an option:
1 - Add new expense
2 - Show expenses by category
3 - Search costs by text
4 - Modify record
5 - Delete data
6 - Sort data
7 - Normalize descriptions
T - End application
2
Enter start date (YYYYMMDD):
19990101
Enter end date (YYYYMMDD):
19990101
Enter category:
lact
1 - 01/01/1999 - Yogurt - (lact) - 10.00
Total amount: 10.00

Choose an option:
1 - Add new expense
2 - Show expenses by category
3 - Search costs by text
4 - Modify record
5 - Delete data
6 - Sort data
7 - Normalize descriptions
T - End application
[ConsoleInputLine_10]

 Share this C# Exercise

 More C# Programming Exercises of Arrays, Structures and Strings

Explore our set of C# programming exercises! Specifically designed for beginners, these exercises will help you develop a solid understanding of the basics of C#. From variables and data types to control structures and simple functions, each exercise is crafted to challenge you incrementally as you build confidence in coding in C#.

  •  Reverse array

    In this C# exercise, you are asked to write a program that prompts the user for 5 numbers, stores them in an array, and displays them in reverse order. ...

  •  Search in array

    In this C# exercise, you are asked to write a program that checks if a given data belongs to a previously created list. The steps to follow are:

  •  Array of even numbers

    In this C# exercise, you are asked to write a program that asks the user for 10 integer numbers and displays the even ones. This exercise w...

  •  Array of positive and negative numbers

    In this C# exercise, you are asked to write a program that asks the user for 10 real numbers and displays the average of the positive ones and the average of t...

  •  Many numbers and sum

    In this C# exercise, you are asked to write a program that asks the user for several numbers (until they enter the word "end") and then displays the sum of the...

  •  Two dimensional array

    In this C# exercise, you are asked to write a program that asks the user for marks for 20 pupils (2 groups of 10, using a two-dimensional array), and then disp...