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).

 Write Your C# Exercise

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

        // Method to add a new account entry
        static void AddNewEntry()
        {
            // 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);
        }

        // Method to show all expenses of a certain category between two dates
        static void ShowExpensesByCategory()
        {
            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 and category
            var filteredEntries = accountEntries.Where(e =>
                string.Compare(e.Date, startDate) >= 0 && string.Compare(e.Date, endDate) <= 0).ToList();

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

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

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

        // Method to search for costs containing certain text in the description or category
        static void SearchCostsByText()
        {
            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 count = 1;
                foreach (var entry in searchResults)
                {
                    // Display the result with description truncated if necessary
                    string description = entry.Description.Length > 50 ? entry.Description.Substring(0, 50) + "..." : entry.Description;
                    Console.WriteLine($"{count} - {entry.Date.Substring(6, 2)}/{entry.Date.Substring(4, 2)}/{entry.Date.Substring(0, 4)} - {description}");
                    count++;
                }
            }
        }

        // Method to modify a record
        static void ModifyRecord()
        {
            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.");
                return;
            }

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

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

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

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

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

            // Save the modified entry
            accountEntries[recordNumber] = entry;
        }

        // Method to delete some data
        static void DeleteData()
        {
            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.");
                return;
            }

            // 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
                }
            }
        }

        // Method to sort the data alphabetically by date and description
        static void SortData()
        {
            var sortedEntries = accountEntries.OrderBy(e => e.Date).ThenBy(e => e.Description).ToList();

            // Display sorted entries
            int count = 1;
            foreach (var entry in sortedEntries)
            {
                Console.WriteLine($"{count} - {entry.Date.Substring(6, 2)}/{entry.Date.Substring(4, 2)}/{entry.Date.Substring(0, 4)} - {entry.Description} - ({entry.Category}) - {entry.Amount:F2}");
                count++;
            }
        }

        // Method to normalize descriptions
        static void NormalizeDescriptions()
        {
            foreach (var entry in accountEntries)
            {
                string normalizedDescription = entry.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
                entry.Description = normalizedDescription;
            }
        }

        // Main method to run the application
        static void Main(string[] args)
        {
            bool running = true;

            while (running)
            {
                Console.WriteLine("\nChoose an option:");
                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();

                switch (choice)
                {
                    case "1":
                        AddNewEntry();
                        break;
                    case "2":
                        ShowExpensesByCategory();
                        break;
                    case "3":
                        SearchCostsByText();
                        break;
                    case "4":
                        ModifyRecord();
                        break;
                    case "5":
                        DeleteData();
                        break;
                    case "6":
                        SortData();
                        break;
                    case "7":
                        NormalizeDescriptions();
                        break;
                    case "T":
                        running = false;
                        break;
                    default:
                        Console.WriteLine("Invalid option.");
                        break;
                }
            }
        }
    }
}

 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...