2 while循环vs if else语句在1 while循环中

时间:2013-04-27 10:26:23

标签: c++ performance

首先介绍一下:

我是一名新手C ++程序员(我是编程新手)编写一个实用程序的小乘法表。该项目最初是一个小程序,用于自学编程的基础知识,随着我对编程的了解越来越多,我不断添加新功能。起初它只是有一些基础知识,比如要求输入,循环和if-else语句。但现在它使用向量,读取和写入文件,创建目录等。

您可以在此处查看代码:Project on Bitbucket

我的程序现在将有两种模式:练习单个乘法表,用户可以自己选择或练习混合的所有乘法表。现在两种模式在内部完全不同。我将混合模式作为一个单独的程序开发,为了简化开发,我可以专注于编写代码本身,而不是打扰如何将它集成到现有代码中。

在当前单独的混合模式程序的代码下面:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <time.h> 

using namespace std;
using std::string;

int newquestion(vector<int> remaining_multiplication_tables, vector<int> multiplication_tables, int table_selecter){
  cout << remaining_multiplication_tables[table_selecter] << " * " << multiplication_tables[remaining_multiplication_tables[table_selecter]-1]<< " =" << "\n";
  return remaining_multiplication_tables[table_selecter] * multiplication_tables[remaining_multiplication_tables[table_selecter]-1];
}

int main(){
  int usersanswer_int;
  int cpu_answer;
  int table_selecter;
  string usersanswer;
  vector<int> remaining_multiplication_tables = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  vector<int> multiplication_tables(10, 1);//fill vector with 10 elements that contain the value '1'. This vector will store the "progress" of each multiplication_table.
  srand(time(0));

  table_selecter = rand() % remaining_multiplication_tables.size();
  cpu_answer = newquestion(remaining_multiplication_tables, multiplication_tables, table_selecter);
  while(remaining_multiplication_tables.size() != 0){
    getline(cin, usersanswer);
    stringstream usersanswer_stream(usersanswer);
    usersanswer_stream >> usersanswer_int;
    if(usersanswer_int == cpu_answer){
      cout << "Your answer is correct! :)" << "\n";
      if(multiplication_tables[remaining_multiplication_tables[table_selecter]-1] == 10){
       remaining_multiplication_tables.erase(remaining_multiplication_tables.begin() + table_selecter);
      }
      else{
    multiplication_tables[remaining_multiplication_tables[table_selecter]-1] +=1;
      }
      if (remaining_multiplication_tables.size() != 0){
    table_selecter = rand() % remaining_multiplication_tables.size();
    cpu_answer = newquestion(remaining_multiplication_tables, multiplication_tables, table_selecter);
      }
    }
    else{
      cout << "Unfortunately your answer isn't correct! :(" << "\n";
    } 
  }
  return 0;
}

正如您所看到的,混合模式的newquestion函数是完全不同的。 while循环还包括其他混合模式特定代码。

现在,如果我想将混合乘法表模式集成到现有的主程序中,我有两个选择: -I可以使用if-else语句来混乱while循环,以便每次循环运行时检查mode == 10(单乘法表模式)或mode == 100(混合乘法表模式)。并在newquestion()函数中放置一个if-else语句来检查mode == 10或mode == 100 - 我可以让程序在启动时检查用户是选择单个乘法表还是混合乘法表模式并创建2个while循环和2个newquestion()函数。这看起来像这样:

int newquestion_mixed(){
 //newquestion function for mixed mode
}
int newquestion_single(){
 //newquestion function for single mode
}

//initialization
if mode == 10
 //create necessary variables for single mode
 while(){
  //single mode loop
 }
else{
 //create necessary variables for mixed mode
 while(){
  //mixed mode loop
 }
}

现在为什么我要打扰创建2个单独的循环和函数?如果程序每次循环运行时检查(每次向用户询问一个新问题,例如:'5 * 3 ='),用户选择的模式是不是效率低?我担心这个选项的性能。现在我听到你的想法:但是为什么你会为这样一个简单的,非常小的非性能关键应用程序以及当今极其强大的处理器和大量的RAM而烦恼?好吧,正如我之前所说,这个程序主要是教自己一个好的编码风格和学习如何编程等等。所以我想从一开始就教会自己良好的习惯。

2 while循环和函数选项更有效率将使用更少的CPU,但更多的空间,并包括重复的代码。我不知道这也不错。

所以基本上我问专家什么是处理这类事情的最佳风格/方式。此外,如果你发现我的代码/坏风格的坏事请告诉我,我很乐意反馈,因为我还是一个新手。 ;)

2 个答案:

答案 0 :(得分:5)

首先,编程的基本规则是“不要过早地优化代码” - 也就是说,在代码正常工作之前不要弄乱细节,并编写表达你的代码希望尽可能清楚地完成。这是很好的编码风格。想要了解“哪个更快”(在一个花费大部分时间等待用户输入某个数字的循环中)的细节并不是很好的编码风格。

一旦它正确地工作,分析(使用例如分析器工具)代码花费它的时间(假设性能是首要的主要因素)。一旦找到主要的“热点”,然后尝试以某种方式改善它 - 你如何去做,这在很大程度上取决于特定热点代码的作用。

哪个性能最佳将高度依赖于代码和编译器的详细信息(以及选择的编译器优化)。很可能在while循环中使用if会运行得更慢,但是现代编译器非常聪明,而且我确实看到过编译器在循环中提出这样一个选择的情况,如果条件没有更改。有两个while循环对于编译器来说更难“变得更好”,因为它很可能不会看到你在两个循环中都做同样的事情[因为编译器从解析树的底部开始工作,并且它将首先优化while循环的内部,然后转到if-else侧,并且在那时它“丢失了”每个循环内部发生的事情。

更清楚的是,如果有一个while循环,if有一个if,或者if有两个while循环,这是另一个好问题。

当然,面向对象的解决方案是有两个类 - 一个用于混合,另一个用于单个 - 并且只运行一个循环,它调用基于if-else语句创建的对象的相关(虚拟)成员函数在循环之前。

答案 1 :(得分:1)

现代CPU分支预测器非常好,如果在循环期间条件永远不会改变,它可能与在每个分支中有两个while循环一样快。