c++ 如何让用户通过用户输入替换代码中的变量值?

bxgwgixi  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(125)

我正在尝试将开发者模式融入到我的程序中。考虑到汽车的责任每个月都在变化,我的目标是让用户能够修改程序中的各个变量,如关税,lccost,yen2taka和运费。

  1. #include <iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6. int carbid,duty;
  7. void Input()
  8. {
  9. cout<<"please insert the car price you want to bid for(in yen): ";
  10. cin>>carbid;
  11. cout<<"duty of the car: ";
  12. cin>>duty;
  13. }
  14. int Exportcost()
  15. {
  16. int exportcost;
  17. int servicechrg=10;
  18. int freight=20;
  19. exportcost=servicechrg+freight+carbid;
  20. return exportcost;
  21. }
  22. int Yen2taka()
  23. {
  24. int yen2taka;
  25. int taka2dollarrate=10;
  26. int dollar2yen=1;
  27. yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;
  28. return yen2taka;
  29. }
  30. int Importcost()
  31. {
  32. int importcost;
  33. int lccost=10;
  34. int cnfcost=20;
  35. importcost=lccost+cnfcost;
  36. return importcost;
  37. }
  38. int Totalcosting()
  39. {
  40. int total;
  41. int myprofit=10; //80000
  42. total=myprofit+Importcost()+Yen2taka();
  43. cout<<total;
  44. return total;
  45. }
  46. void summary()
  47. {
  48. cout<<
  49. }
  50. };

字符串
下面的主要功能创建了一个交互式循环,用户可以在其中重复输入汽车详细信息,计算成本,并选择查看摘要或重新启动成本计算过程。

  1. int main()
  2. {
  3. x:
  4. A ob;
  5. ob.Input();
  6. ob.Exportcost();
  7. ob.Yen2taka();
  8. ob.Importcost();
  9. ob.Totalcosting();
  10. int ch;
  11. cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
  12. cin>>ch;
  13. switch(ch)
  14. {
  15. case 1:
  16. ob.summary();
  17. break;
  18. case 2:
  19. goto x;
  20. }
  21. }

bpsygsoo

bpsygsoo1#

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

  1. class Configuration // maybe you find a better name...
  2. {
  3. int m_servicechrg = 10; // default
  4. int m_freight = 20;
  5. // ...
  6. public:
  7. int servicechrg() { return m_servicechrg; }
  8. void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
  9. int freight() { return m_freight; }
  10. void freight(int value); { /* check some limits? */ m_freight = value; }
  11. // ...
  12. };
  13. // will allow you to do:
  14. // C c; std::cout << c;
  15. ostream& operator<<(ostream& s, Configuration const& c)
  16. {
  17. // which ever formatting is appropriate...
  18. s << c.servicechrg() << ' ' << c.freight();
  19. return s;
  20. }

字符串
setter也可以返回bool来指示无效值。
现在你可以在main中使用这个类:

  1. Configuration c;
  2. A a;
  3. int cost = a.exportCost(c); // you'd have to adjust signatures...
  4. int value;
  5. switch(ch)
  6. {
  7. case 4:
  8. if(stc::cin >> freight) // catches invalid user input!
  9. // one ALWAYS should do, otherwise you might end up in
  10. // your program not working any more
  11. {
  12. c.freight(value);
  13. // or, if you have:
  14. if(!c.freight(value))
  15. {
  16. // some appropriate error message
  17. // (it's better not to output in the setter, you are more flexible this
  18. // way – maybe you want different messages at different occasions?)
  19. }
  20. }
  21. else
  22. {
  23. // appropriate error handling
  24. }
  25. break;
  26. default:
  27. // handling invalid user input
  28. // again, you always should; but stream state is not in error state,
  29. // so you just can print appropriate error message
  30. break;
  31. }


请参阅this answer了解如何正确处理流错误。
如果你想知道错误处理的差异:第一种情况是,如果用户输入非数字输入,如ss,第二种情况是,如果输入 * 是 * 数字,但超出有效范围(77)。
现在,如果你不想一直将配置作为参数传递,你可以从(但要小心,全局变量有一些危险,尽可能少地使用它们)或实现singleton pattern
旁注:goto * 有时候是一个很好的工具,但它是一个危险的工具(标签的名字x不是一个好的,更喜欢一个明确表明意图的名字,如REENTRY_POINTLOOP_START,.)。如果你可以沿着而不需要不合理的努力,更喜欢这样的变体:

  1. bool isRunning = true;
  2. do
  3. {
  4. // ...
  5. case 2:
  6. isRunning = false;
  7. break;
  8. }
  9. while(isRunning);


当然,一个额外的变量,一个额外的检查;不幸的是,你不能使用break退出(伪)无限循环(for(;;))(但不要将这种模式应用于嵌套循环,那么它会变得越来越不可读和低效:bool isExit = false; for(int i = 0; !isExit && i < n; ++i) { for(j = 0; j < n; ++j) { isExit = true; break; } }-明白我的意思吗?)。一个变体可能是:

  1. for(;;)
  2. {
  3. switch(ch)
  4. case 1:
  5. // ...
  6. //break; <- replace
  7. continue;
  8. case 2:
  9. //
  10. break;
  11. } // end of switch
  12. break; // break the surrounding for(;;) loop
  13. }


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

  1. for(;;)
  2. {
  3. switch(ch)
  4. {
  5. case 2:
  6. // maybe yet some cleaning up here
  7. return 0;
  8. default:
  9. // ...
  10. break;
  11. }
  12. }


缺点:函数的退出点可能深深地嵌套在代码中。
还有其他的技巧来允许这种模式,比如将代码的子部分打包在一个lambda中,并在其中返回,然后直接调用它。
最后,如果你坚持goto,我的变体更倾向于:

  1. for(;;)
  2. {
  3. switch(ch)
  4. {
  5. case 2:
  6. // ...
  7. goto LOOP_EXIT;
  8. default:
  9. // ...
  10. break;
  11. }
  12. }
  13. LOOP_EXIT:
  14. return 0; // e. g. main
  15. (void)0; // if there isn't anything to do in the function any more
  16. // (labels require an instruction afterwards!)


现在不会有隐藏循环了,你实际上在做什么变得更加明显。目前,这不是一个真正的问题,但如果你的代码增长,隐藏循环会变得越来越难以发现。
在这种情况下,我清楚地标记goto s,以便另一个编码器可以立即发现关键代码点:

  1. ///////////////////////////////////////////////////
  2. // possibly some comment why applying this pattern
  3. goto SOME_LABEL;
  4. ///////////////////////////////////////////////////


可以对深度嵌套的函数出口点(return)做同样的事情。

展开查看全部

相关问题