如何在 void 函数中停止从重置到 0 的总运行?

How do I stop running total from resetting to 0 in void function?

提问人:Loading Screen 提问时间:11/4/2023 最后编辑:Loading Screen 更新时间:11/4/2023 访问量:103

问:

我有一个任务,我应该做一个餐厅菜单。菜单必须循环,直到用户输入 4 才能获取账单。我应该使用一个函数来显示菜单,另一个函数来计算运行总额并在用户完成订购时显示账单。

问题是,我必须在使用它之前进行初始化,并且我不知道将其放在哪里以阻止它重置为初始化。最初,我的计算函数 , , 是这样设置的:runningTotalcost()


void cost(const double ITEM_PRICE, int amtOfItemOrdered, bool isDoneOrdering) {

// initializing runningTotal and declaring other variables...
    double runningTotal = 0, tip, finalBill;

// if statement so bill only displays when order is finished...
    if (isDoneOrdering == false)

        // calculate running total...
        runningTotal += (ITEM_PRICE * amtOfItemOrdered);

    else {

        // when order finishes, calculate and display bill...
        tip = (runningTotal * 0.20);
        finalBill = (runningTotal + tip);

        cout << "\nFood total: " << runningTotal <<
                "\nTip: " << tip <<
                "\nFinal Bill: " << finalBill;
    }

我认为这会导致每次执行函数时重置为 0。当我运行程序,订购一些东西,然后按 4 查看账单时,账单中的所有内容都显示为 0。下面是输出的示例:runningTotal

Food total: 0
Tip: 0
Final Bill: 0

我认为像这样移出函数可能会有所帮助:runningTotalcost()


int main() {

// initializing runningTotal with 0 in main...
        double runningTotal = 0;

// other variables...
    const double ITEM1_PRICE = 2.50, ITEM2_PRICE = 3.50, ITEM3_PRICE = 4.50;
    int itemOrdered, amtOfItemOrdered;
    bool isDoneOrdering = false;

// loop menu choice until order is finished...
    do {
        displayMenu(ITEM1_PRICE, ITEM2_PRICE, ITEM3_PRICE);
        cout << "Enter your choice: ";
        cin >> itemOrdered;

        // don't ask "how many" when done ordering...
        if (itemOrdered != 4) {
            cout << "\nHow many? ";
            cin >> amtOfItemOrdered;
        }

        switch (itemOrdered) {
        case 1:

        // passing runningTotal to cost() so cost() can use it...
            cost(ITEM1_PRICE, amtOfItemOrdered, isDoneOrdering, runningTotal);
            break;

        case 2:
            cost(ITEM2_PRICE, amtOfItemOrdered, isDoneOrdering, runningTotal);
            break;
        case 3:
            cost(ITEM3_PRICE, amtOfItemOrdered, isDoneOrdering, runningTotal);
            break;
        case 4:
            isDoneOrdering = true;
            cost(0, 0, isDoneOrdering, runningTotal);

            // zeroes are here because cost() asks for parameters,
            // but we're done adding to running total...

            break;
        default:
            0; // empty placeholder statement...
        }
    } while (isDoneOrdering == false);
}

但这有同样的结果。我认为这里发生的事情是 in 与 in 不同,并且 中的值 0 被传递给 in ,这无论如何都会重置它?runningTotalmainrunningTotalcost()mainrunningTotalrunningTotalcost()

我考虑过为 、 和 和 做一个返回语句,并在函数之外显示账单,但我认为赋值希望我坚持使用 void 函数。runningTotaltipfinalBill

刚刚测试初始化为 1 in ,账单显示以下内容:runningTotalmain

Food total: 1
Tip: 0.2
Final Bill: 1.2

所以我确实认为初始化是这里的问题。任何帮助将不胜感激。谢谢。

C++ 函数 void cumulative-sum

评论

0赞 273K 11/4/2023
在函数中引入参数并使其返回,新的中间总计。将 main 传递给该函数,并将返回的值分配给 。double intermediateTotaldoublerunningTotalrunningTotal
0赞 Peter 11/4/2023
选项包括 (1) 通过引用(或指针)作为参数传递并在函数中更新它 [这需要调用方正确处理将传递的变量创建和初始化为零]。(2)在文件范围内创建一个具有静态存储持续时间的变量,并在多次调用之前提供另一个函数来重置它[就像静态变量的任何用法一样,这施加了一些限制]。runningTotalrunningTotalcost()
1赞 SmellyCat 11/4/2023
由于您已经更改了第二个示例中的签名,因此您应该发布更新的签名。我们很好奇您是按值还是按引用传递附加参数。它需要通过引用。costdoubledouble &
0赞 JaMiT 11/4/2023
“my calculating function” -- 函数应该只有一个用途。您有两个计算 - 计算每个选择的成本(考虑数量)和计算最终总额(包括小费)。两个计算表明您应该有两个函数。
0赞 JaMiT 11/4/2023
“我认为任务希望我坚持无效函数”——这是一个可悲的任务。(此评论与 Stack Overflow 的相关性:赞成/反对投票的标准之一是“有用”,而受不合理限制约束的问题并不是特别有用。

答:

2赞 SmellyCat 11/4/2023 #1

由于这是 C++,因此使用类是有意义的。

考虑一个类来封装成本计算,以及一个单独的类来存储菜单。

constexpr double TIP_MARGIN = 0.2;

class BillCalculator
{
    double m_RunningTotal = 0.0;
public:
    void AddCost(const double price, int count)
    {
        m_RunningTotal += price * count;
    }
   
    double CalculateTip() const
    {
        return m_RunningTotal * TIP_MARGIN;
    }

    double CalculateTotalBill() const
    {
        return GetRunningTotal() + CalculateTip();
    }

    double GetRunningTotal() const
    {
        return m_RunningTotal;
    }
};

在 中实例化两个类。拥有一个仅专注于 I/O 的函数将使代码更易于理解。main

如果需要传递所创建任一类的实例,请通过引用传递它。

-2赞 Thịnh Thông Thái 11/4/2023 #2

在函数作用域中定义和初始化的变量将保留在函数中。 在您的代码中,main() 函数中的 runningTotal 和 cost() 函数中的 runningTotal 因此在内存中具有不同的内存空间(尽管它们具有相同的名称)。

我注意到您想在 cost() 函数中访问变量 runningTotal 的值并修改变量。就像 Peter 评论的那样,您可以通过 2 种方式做到这一点:

  1. 通过参数指针将 runningTotal 传递到函数 cost() 中,也就是说,您通过标识该变量的内存空间来为函数提供变量。

例如:

按参数:

void cost(your variables..., double& runningTotal) //by parameter.

//calling the function:
cost(your variables..., runningTotal); //it's the same as calling normal function

//using the variable
//you can use its the same as normal.
//note that, any changes made in this function will affect the variable outside, so be carefull

通过指针:

void cost(your varialbe..., double* runningTotal) //by pointer.

//calling the funtion
cost(your variables...,&runningTotal);

//using the variable
//As pointer is simply the address of the variable itself
//you'll have to dereference it before using by adding a * before the variable
*runningTotal = *runningTotal +1;
//note that, changes here also affect the variable outside.
  1. 通过使用文件作用域(全局作用域)的变量:

    //the variable
    
    double runningTotal;
    
    void cost(your variable....){//your code}
    
    int main(){ //your code}
    

请注意,以这种方式进行更改仍然会影响外部变量

评论

0赞 Pepijn Kramer 11/4/2023
引用语义在较大的项目中可能会适得其反。使用 NVRO,您可以只使用返回值是running_total的地方而不会产生开销,因此重命名函数可能会有所帮助(这也使代码更具自我描述性)。只需删除带有指针的变体,不建议在 C++ 中使用原始指针,并且需要您开始测试指针的有效性(它不是 nullptr)。double cost(your variables)calculate_running_total
0赞 Pepijn Kramer 11/4/2023
最后一个带有全局变量的选项只是一个非常糟糕的举动。应不惜一切代价避免全局变量。它还在不同的代码段之间创建了一个“隐式”接口,该接口不是自记录的。想象一下,另一个函数开始“滥用”那个 globel。在少量代码中很容易避免,在大型代码库中无法监管。