【问题标题】:how to replace a value of a variable inside code from user input?如何从用户输入中替换代码中的变量值?
【发布时间】:2019-05-15 16:32:05
【问题描述】:

我正在尝试在我的程序中添加开发者模式。由于汽车的关税每个月都会推迟,我想允许我的用户更改我程序中的每一个变量,比如关税 lccost yen2taka shipping

#include <iostream>

using namespace std;

class A
{
public:
    int carbid,duty;

    void Input()
    {
        cout<<"please insert the car price you want to bid for(in yen): ";
        cin>>carbid;

        cout<<"duty of the car: ";
        cin>>duty;
    }

    int Exportcost()
    {
        int exportcost;
        int servicechrg=10;
        int freight=20;
        exportcost=servicechrg+freight+carbid;
        return exportcost;
    }

    int Yen2taka()
    {
        int yen2taka;
        int taka2dollarrate=10;
        int dollar2yen=1;

        yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;

        return yen2taka;
    }

    int Importcost()
    {
        int importcost;
        int lccost=10;
        int cnfcost=20;

        importcost=lccost+cnfcost;

        return importcost;
    }

    int Totalcosting()
    {
        int total;
        int myprofit=10; //80000

        total=myprofit+Importcost()+Yen2taka();

        cout<<total;

        return total;

    }

    void summary()
    {
        cout<<

    }


};

int main()
{
    x:
    A ob;
    ob.Input();
    ob.Exportcost();
    ob.Yen2taka();
    ob.Importcost();
    ob.Totalcosting();

    int ch;
    cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
    cin>>ch;
    switch(ch)
    {
       case 1:
          ob.summary();
          break;
       case 2:
          goto x;
    }
}

【问题讨论】:

  • 旁注:您应该将所有代码缩进四个空格;这会引发适当的格式设置(固定宽度字体、语法突出显示等)。为此目的有一个“代码”按钮 ({})。

标签: c++


【解决方案1】:

首先,您应该将这些参数收集在一个单独的类中:

class Configuration // maybe you find a better name...
{
    int m_servicechrg = 10; // default
    int m_freight = 20;
    // ...
public:
    int servicechrg() { return m_servicechrg; }
    void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
    int freight() { return m_freight; }
    void freight(int value); { /* check some limits? */ m_freight = value; }
    // ...
};

// will allow you to do:
// C c; std::cout << c;
ostream& operator<<(ostream& s, Configuration const& c)
{
    // which ever formatting is appropriate...
    s << c.servicechrg() << ' ' << c.freight();

    return s;
}

setter 也可以返回 bool 来指示无效值。

现在你可以在 main 中使用这个类了:

Configuration c;
A a;

int cost = a.exportCost(c); // you'd have to adjust signatures...

int value;
switch(ch)
{
case 4:
    if(stc::cin >> freight) // catches invalid user input!
                            // one ALWAYS should do, otherwise you might end up in
                            // your program not working any more
    {
        c.freight(value);
        // or, if you have:
        if(!c.freight(value))
        {
            // some appropriate error message
            // (it's better not to output in the setter, you are more flexible this
            // way – maybe you want different messages at different occasions?)
        }
    }
    else
    {
        // appropriate error handling
    }
    break;
default:
    // handling invalid user input
    // again, you always should; but stream state is not in error state,
    // so you just can print appropriate error message
    break;
}

请参阅this answer,了解如何正确处理流错误。

如果您想知道错误处理的差异:如果用户输入非数字输入,例如ss,则满足第一种情况,如果输入数字,则满足第二种情况,但无效范围 (77)。

现在,如果您不想一直将配置作为参数传递,您可以从创建一个全局变量(但要小心,全局变量存在一些危险,尽可能少用)或实现 @ 987654322@.

旁注:goto 可以有时是一个很好的工具,但它是一个危险的工具(而且标签的名称 x 不是一个好名称,更喜欢一个清楚显示的名称意图,例如REENTRY_POINTLOOP_START,...)。如果您可以不费吹灰之力地相处,那么更喜欢这样的变体:

bool isRunning = true;
do
{
    // ...
    case 2:
        isRunning = false;
        break;
}
while(isRunning);

当然,一个额外的变量,一个额外的检查;不幸的是,您不能使用break 退出(伪)无限循环(for(;;))(但不要将此模式应用于嵌套循环,然后它会变得越来越难以阅读——而且效率低下:bool isExit = false; for(int i = 0; !isExit &amp;&amp; i &lt; n; ++i) { for(j = 0; j &lt; n; ++j) { isExit = true; break; } }——见我的意思是说?)。变体可能是:

for(;;)
{
    switch(ch)
    case 1:
        // ...
        //break; <- replace
        continue;
    case 2:
        //
        break;
    } // end of switch
    break; // break the surrounding for(;;) loop
}

但这也不是很好。

一个非常好的变体允许在给定的情况下退出循环,因为之后没有任何事情要做:

for(;;)
{
    switch(ch)
    {
    case 2:
        // maybe yet some cleaning up here
        return 0;
    default:
        // ...
        break;
    }
}

缺点:函数的退出点可能深深嵌套在代码中。

还有其他技巧可以实现这种模式,例如将代码的子部分打包到内部有一个 return 的 lambda 中,然后直接调用它。但这现在真的开始超出范围......

最后,如果你坚持goto,我的变种宁愿是:

for(;;)
{
    switch(ch)
    {
    case 2:
        // ...
        goto LOOP_EXIT;
    default:
        // ...
        break;
    }
}
LOOP_EXIT:
return 0; // e. g. main
(void)0;  // if there isn't anything to do in the function any more
          // (labels require an instruction afterwards!)

现在不会有隐藏循环,而且您实际在做什么更加明显。目前,这不是一个真正的问题,但如果您的代码增长,隐藏循环将变得越来越难以发现。

在这种情况下,我清楚地标记了gotos,以便其他编码人员可以立即发现关键代码点:

///////////////////////////////////////////////////
// possibly some comment why applying this pattern
goto SOME_LABEL;
///////////////////////////////////////////////////

对深度嵌套的函数退出点 (return) 也可以这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-30
    • 2014-04-18
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多