可以在C++中循环遍历数组结构

Possible to loop through an array structure in C++

本文关键字:遍历 数组 结构 循环 C++      更新时间:2023-10-16

如果之前已经回答过,请提前道歉。没有找到任何内容(或者没有使用正确的搜索词)。无论如何,我想知道我的代码中有一个特定的部分是否可以通过循环来完成。我继续添加了下面的代码。我认为可能需要清理的两个部分是请求用户输入在各种预算类别上花费的金额。我曾计划使用for循环,但不知道如何将值分配给MonthlyBudget结构"currentMonthlyBBudget"的各个元素(即currentMonthlyBudget.housing、currentMonthleBudget.utilities等)。这对expenseCategories[]来说是有效的,但我可以找到如何(或者是否可能)为结构做这件事。如有任何协助,我们将不胜感激。提前谢谢。

/* Exercise_10.cpp Monthly Budget Calculation*/
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
using namespace std;
struct MonthlyBudget
{
    double housing;             //Housing
    double utilities;           //Utilities
    double householdExpense;    //Household Expense
    double transportation;      //Transportation
    double food;                //Food
    double medical;             //Medical
    double insurance;           //Insurance
    double entertainment;       //Entertainment
    double clothing;            //Clothing
    double misc;                //Miscellaneous
};
int main()
{
    //Array of Monthly Budget Values
    double defaultMonthlyBudget[10] = { 500.00, 150.00, 65.00,
                                        50.00, 250.00, 30.00,
                                        100.00, 150.00, 75.00,
                                        50.00 };
    //Array of Expense Categories
    string expenseCategories[10] = { "Housing Accomodations", "Utilities", "Household Expenses",
                                     "Transporation", "Food", "Medical Expenses", "Insurance",
                                     "Entertainment", "Clothing", "Miscellaneous Expenses" };
    //Array to hold the over budget and under budget values
    double actualBudget[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    //Accumulator for actual budget
    double sum = 0.00;
    //Loop counter
    int index;
    //Final Total Budget
    double calculatedTotalBudget = 0.00;
    //Structure
    MonthlyBudget currentMonthlyBudget;
    cout << "Greetings. This program will determine if you are meeting your agreed upon budget." << endl;
    cout << "I will ask you questions about your spending habits, and return a report to see hown";
    cout << "you did this month. Lets get started!nnn";
    cout << "nPlease type in how much was spent this month for " << expenseCategories[0] << ": ";
    cin >> currentMonthlyBudget.housing;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[1] << ": ";
    cin >> currentMonthlyBudget.utilities;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[2] << ": ";
    cin >> currentMonthlyBudget.householdExpense;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[3] << ": ";
    cin >> currentMonthlyBudget.transportation;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[4] << ": ";
    cin >> currentMonthlyBudget.food;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[5] << ": ";
    cin >> currentMonthlyBudget.medical;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[6] << ": ";
    cin >> currentMonthlyBudget.insurance;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[7] << ": ";
    cin >> currentMonthlyBudget.entertainment;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[8] << ": ";
    cin >> currentMonthlyBudget.clothing;
    cout << "nPlease type in how much was spent this month for " << expenseCategories[9] << ": ";
    cin >> currentMonthlyBudget.misc;
    cout << "nnn";
    //Compare inputted values to those of the predetermine budget
    actualBudget[0] = (defaultMonthlyBudget[0] - currentMonthlyBudget.housing);
    actualBudget[1] = (defaultMonthlyBudget[1] - currentMonthlyBudget.utilities);
    actualBudget[2] = (defaultMonthlyBudget[2] - currentMonthlyBudget.householdExpense);
    actualBudget[3] = (defaultMonthlyBudget[3] - currentMonthlyBudget.transportation);
    actualBudget[4] = (defaultMonthlyBudget[4] - currentMonthlyBudget.food);
    actualBudget[5] = (defaultMonthlyBudget[5] - currentMonthlyBudget.medical);
    actualBudget[6] = (defaultMonthlyBudget[6] - currentMonthlyBudget.insurance);
    actualBudget[7] = (defaultMonthlyBudget[7] - currentMonthlyBudget.entertainment);
    actualBudget[8] = (defaultMonthlyBudget[8] - currentMonthlyBudget.clothing);
    actualBudget[9] = (defaultMonthlyBudget[9] - currentMonthlyBudget.misc);

    //TEST
    /*for (index = 0; index < 10; index++)
    {
        cout << actualBudget[index] << "n";
    }*/

    //Add up actualBudget
    for (index = 0; index < 10; index++)
    {
        sum += actualBudget[index];
    }
    //Assign value to Calculated Total Budget
    calculatedTotalBudget = (1420.00 - sum);
    //Loop to display what categories we went over, under, & met our budget
    for (index = 0; index < 10; index++)
    {
        if (actualBudget[index] < 0.00)
        {
            cout << "For the category of " << expenseCategories[index] << ", you went over your budget by $" << abs(actualBudget[index]) << ".n";
        }
        else if (actualBudget[index] > 0.00)
        {
            cout << "For the category of " << expenseCategories[index] << ", you came in under your budget by $" << abs(actualBudget[index]) << ".n";
        }
        else
        {
            cout << "For the category of " << expenseCategories[index] << ", you met your budget exactly.n";
        }
    }

    //Provide information to the user if the grand total went over, under, or met our total budget
    if (calculatedTotalBudget > 1420.00)
    {
        cout << "This month's total expenditure was $" << calculatedTotalBudget << ". You were over budget by $" << (calculatedTotalBudget - 1420.00) << ".n";
    }
    else if (calculatedTotalBudget < 1420.00)
    {
        cout << "This month's total expenditure was $" << calculatedTotalBudget << ". You were under budget by $" << abs(1420.00 - calculatedTotalBudget) << ".n";
    }
    else
    {
        cout << "This month's total expenditure was $" << calculatedTotalBudget << ". You met your budget exactly.n";
    }
}

一个干净的解决方案可能只是保存一个类别向量和它们映射到的值的引用

  //Array of Expense Categories
  std::vector<std::pair<string, double&>> expenseCategories = {
    { "Housing Accomodations", currentMonthlyBudget.housing },
    { "Utilities", currentMonthlyBudget.utilities },
    { "Household Expenses", currentMonthlyBudget.householdExpense },
    { "Transporation", currentMonthlyBudget.transportation },
    { "Food", currentMonthlyBudget.food },
    { "Medical Expenses", currentMonthlyBudget.medical },
    { "Insurance", currentMonthlyBudget.insurance },
    { "Entertainment", currentMonthlyBudget.entertainment },
    { "Clothing", currentMonthlyBudget.clothing },
    { "Miscellaneous Expenses", currentMonthlyBudget.misc } 
  };

任何循环都将只使用类别描述或映射到的值

for (auto& category : expenseCategories) {
  cout << "nPlease type in how much was spent this month for " << category.first << ": ";
  cin >> category.second;
}

实时示例

上面的解决方案的优点是,您可以根据需要重新组织字段,只需更新所涉及的引用。

对于像您所拥有的这样的简单数据结构,您还可以像在简单数组中一样引用它的字段(即,通过获取指向第一个元素的指针,然后迭代这些字段)。

如果您真的想从MonthlyBudget输入中生成for循环,可以通过创建一个简单结构的数组来实现:

struct BudgetInputInfo {
  std::string message;
  double& targetValue;
}

只需创建一个这样的静态数组,就可以基于该数组编写for循环。

您甚至可以向该结构添加一个方法,用于显示消息并设置targetValue。

稍后,当您有double以外的其他成员时,可以将其更改为template

但我认为这不会产生最可读的代码,你不会从for循环中获得真正的好处,除非你想改变它基于运行时的列表。

如果您的列表像示例中那样是固定的,那么创建一个打印出消息并读取输入的函数将更具可读性:

void readInput(std::string targetName, double& target) {
  cout << "Please type in how much was spent this month for " << targetName << ": ";
  cin >> target;
  cout << endl;
}

这样,您就只能进行几个相对较短的readInput调用。

您甚至可以创建一个函数,读取MonhtlyBudget:的每个成员

void readMonhtlyBudget(MonthlyBudget& m) {
  readInput("Housing Accomodations", m.housing);
  // ...
}

此外,我会将您的10个元素数组更改为MonthlyBudgets的实例。这更清楚,如果您使用C++11:,您甚至可以保留当前的初始值设定项语法

MonthlyBudget defaultBudget =     { 500.00, 150.00, 65.00,
                                    50.00, 250.00, 30.00,
                                    100.00, 150.00, 75.00,
                                    50.00 };

并将差异计算代码移动到一个单独的方法中,首选operator-:

MonthlyBudget operator-(MonthlyBudget const& a, MonthlyBudget const& b) {
  MonthlyBudget result;
  result.housing = a.housing - b.housing;
  // ...
  return result;
}

有了这些变化,你只需写:

actualBudget = defaultBudget - currentMonthlyBudget;