6
\$\begingroup\$

I am new to C++ and with my basic knowledge of the language, I have attempted to create a simple console application filled with lots of useful functions involving math related stuff.

The following is the only version of it that I have created thus far: (also available here).

#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;

string cmd;
bool moduleRun = true;

//Decorations
void finline(string appName){cout<<"Quiting "<<appName<<" ... ";}
void h(string title, char type){
    int l = title.length();
    for(int i = 0; i < 2*(l + 1); i++){
        cout<< type;
        if( i == l /*|| i == 2 * l + 1*/ ){ cout << "\n"; }
        if( i == l ){ cout << " " << title << "\n"; }
    }
}
//End of Decorations

//Modules

//Basic 2 number Calculator Module
void calculator(){
    char op;
    double n1,n2;
    h("Calculator", '-');
    cout<< "\n Perform an operation on 2 numbers using basic operators.\n  eg: 2+2, 4*3, 5%4, 6/7 etc \t\t[ Type '0x 0' to exit ]\n\n";
    while(moduleRun){
        cin>> n1 >> op >> n2;
        switch(op){
            //case '%' :
            case '+' : cout<<n1 + n2 ; break;
            case '-' : cout<< n1 - n2 ; break;
            case 'x' : if(n1 == 0 && n2 == 0){ finline("c4lql80r"); moduleRun = false;}
            case '*' : cout<< n1 * n2 ; break;
            case '/' : cout<< n1/n2; break;
            case '^' : cout<< pow(n1,n2); break;
            case '<' : (n1<n2)?cout<<"True":cout<<"False"; break;
            case '>' : (n1>n2)?cout<<"True":cout<<"False"; break;
            case '=' : (n1==n2)?cout<<"True":cout<<"False"; break;
            default :
                if(op == '%'){int N1 = floor(n1); int N2 = floor(n2); cout << N1 % N2;}
                else{cout<< "That operation is not available";}
        }
        if(moduleRun)cout<< "\n\n";
    }
}

//Functions Module
bool isPrime(long int n) {
    if (n == 2) { return true; }
    if (n < 2 || !(n&1)) { return false; }
    long double l = floor(pow(n, 0.5));
    for (long int i = 3; i <= l; i += 2) { if (n % i == 0) {return false;}}
    return true;
}

long double sum(int n){
    int arr[n];
    long double total = 0;
    for(int i = 0; i<n; i++){
        cout<<i + 1;
        (i==0)?cout<<"st":(i==1)?cout<<"nd":(i==2)?cout<<"rd":cout<<"th";
        cout<<">> ";
        cin>>arr[i];
        total+=arr[i];
    }
    return total;
}

long double mean(int n){ return ( sum(n) / n ); }

long double prod(int n){
    int arr[n];
    long double product = 1;
    for(int i = 0; i<n; i++){
        cout<<i + 1;
        (i==0)?cout<<"st":(i==1)?cout<<"nd":(i==2)?cout<<"rd":cout<<"th";
        cout<<">> ";
        cin>>arr[i];
        product*=arr[i];
    }
    cout<<"Product = ";
    return product;
}

long double factorial(int n){ //max is 16!
    int fact = 1;
    for(int i = 1; i<=n; i++){fact*=i;}
    return fact;
}
//Sequence&Series functions

long int fibterm(int n) { long int term = (n < 2) ? n : fibterm(n - 1) + fibterm(n - 2); return term;};
void fib(int n){ for(int i = 0; i<=n ; i++) cout<<fibterm(i)<<" "; }
long int fibsum(int n){
    long int total = 0;
    for(int i = 0; i<=n; i++){total+=fibterm(i);} //Please find a formula to reduce processing
    return total;
}

long int lucasterm(int n){ long int term = (n == 1)? 2: (n == 2)? 1: lucasterm(n - 1) + lucasterm(n - 2); return term; }
void lucas( int n ){ for( int i = 0; i<=n ; i++ ) cout << lucasterm(i)<<" "; }
long int lucassum(double n){
    long int total = 0;
    for(int i = 1; i<=n; i++){total+=lucasterm(i);} //Please find a formula to reduce processing
    return total;
}

long int oddterm(int n){ return 2*(n-1);}
void odd(int n){ for( int i = 0; i<=n ; i++ ) cout << oddterm(i)<<" "; }
long int oddsum(int n){return pow(n,2);}

void prime(int n){ //prints n primes
    int p = 0, i = 1;
    while(p<=n){
        if(isPrime(i)){
            cout<<i<<" ";
            p++;
        }
        i++;
    }
}

//End of Sequence and series functions
void functions(){
    string &func = cmd;
    double param;
    h("Scientific Functions", '-');
    cout<<"\n eg: log 20, sin 60, cosh 40, atan 80, etc \n [ Type 'func 101' for a list of all available functions & '0x 0' to exit]\n";
    while(moduleRun){
        cin>> func >> param;
        //Trigo
        if(func == "sin") cout<< sin(param);
        else if(func == "cos") cout<< cos(param);
        else if(func == "tan") cout<< tan(param);
        else if(func == "sinh") cout<< sinh(param);
        else if(func == "cosh") cout<< cosh(param);
        else if(func == "tanh") cout<< tanh(param);
        else if(func == "asin") cout<< asin(param);
        else if(func == "acos") cout<< acos(param);
        else if(func == "atan") cout<< atan(param);
        //Scientific
        else if(func == "exp") cout<< exp(param);
        else if(func == "log") cout<< log10(param);
        else if(func == "ln") cout<< log(param);
        //Sequence&Series fuAnctions
        else if(func == "fib") fib(param);
        else if(func == "fib.term") cout<< fibterm(param);
        else if(func == "fib.sum") cout << fibsum(param);
        else if(func == "lucas") lucas(param);
        else if(func == "lucas.term") cout<< lucasterm(param);
        else if(func == "lucas.sum") cout << lucassum(param);
        else if(func == "odd")odd(param);
        else if(func == "odd.term")oddterm(param);
        else if(func == "odd.sum")oddsum(param);
        //Other
        else if(func == "sum"){cout<<"Total = "<<sum(param);}
        else if(func == "prod" || func == "product" || func == "multiply"){cout<< prod(param);}
        else if(func == "mean" || func == "average" || func == "avg"){cout << "Arithmetic Mean = "<<mean(param);}
        else if(func == "fact" || func == "factorial"){cout<< factorial(param);}
        else if(func == "isprime") (isPrime(param))? cout<<"Yes, it is prime":cout<<"No, it's not prime";
    //ModuleSupport
        else if(func == "function" || func == "functions" || func == "func"){
            cout<< "\nTrig Functions:\n sin,cos,tan,sinh,cosh,tanh,asin,acos,atan\n\nScientific Functions:\nexp,log,ln\n";
        }
        else if(func == "exit" || func == "0x" || func == "0 x"){
            moduleRun = false;
            finline("Sc13nt1fic funct10n5");
        }
        else {
            cout<< "function not available.\n";
        }
        cout<<"\n\n";
    }
}
//End of Functions Module

void converter(){
    double n, pi = 3.141592653589793;
    string u1, u2;
    h("Converter",'-');
    cout<<"\n eg: 2m to km, 92cm to km, 34 deg to rad, etc \nWARNING: HIGHLY EXPERIMENTAL\n\n";
    while(moduleRun){
        cin>>n>>u1;
        cout<<"to ";
        cin>>u2;
        if(u1 == u2){cout<< n;}
        //Length
        else if(u1 == "mm" || u1 == "millimetre"){
            if(u2 == "cm" || u1 == "centimetre" ) cout << ( n * pow(10,-1) );
            else if( u2 == "dm" || u1 == "decimetre" ) cout << ( n * pow(10,-2) );
            else if( u2 == "m" || u1 == "metre") cout << ( n * pow(10,-3) );
            else if( u2 == "dam"  || u1 == "decametre") cout << ( n * pow(10,-4) );
            else if(u2 == "hm" || u1 == "hectometre") cout << (n * pow(10,-5));
            else if(u2 == "km" || u1 == "kilometre") cout << (n * pow(10,-6));
        }
        else if( u1 == "cm" ){
            if(u2 == "mm" || u1 == "millimetre") cout << (n * 10);
            else if(u2 == "dm" || u1 == "decimetre" ) cout << (n * pow(10,-1));
            else if(u2 == "m") cout<< (n * pow(10,-2));
            else if(u2 == "dam") cout<< (n * pow(10,-3));
            else if(u2 == "hm") cout<< (n * pow(10,-4));
        else if(u2 == "km") cout<< (n * pow(10,-5));
        }
        else if( u1 == "dm" ){
            if(u2 == "mm") cout << (n * pow(10,2));
            else if(u2 == "cm") cout << (n * 10);
            else if(u2 == "m") cout << (n * pow(10,-1));
            else if(u2 == "dam") cout << (n * pow(10,-2));
            else if(u2 == "hm") cout << (n * pow(10,-3));
            else if(u2 == "km") cout << (n * pow(10,-4));
        }
        else if( u1 == "dm" ){
            if(u2 == "mm") cout << (n * pow(10,2));
            else if(u2 == "cm") cout << (n * 10);
            else if(u2 == "m") cout << (n * pow(10,-1));
            else if(u2 == "dam") cout << (n * pow(10,-2));
            else if(u2 == "hm") cout << (n * pow(10,-3));
            else if(u2 == "km") cout << (n * pow(10,-4));
        }
        else if( u1 == "m"){
            if(u2 == "mm") cout << (n * pow(10,3));
            else if(u2 == "cm") cout << (n * pow(10,2));
            else if(u2 == "dm") cout << (n * 10);
            else if(u2 == "dam") cout << (n * pow(10,-1));
            else if(u2 == "hm") cout << (n * pow(10,-2));
            else if(u2 == "km") cout << (n * pow(10,-3));
        }
        else if( u1 == "dam"){
            if(u2 == "mm") cout << (n * pow(10,4));
            else if(u2 == "cm") cout << (n * pow(10,3));
            else if(u2 == "dm") cout << (n * pow(10,2));
            else if(u2 == "m") cout << (n * 10);
            else if(u2 == "hm") cout << (n * pow(10,-1));
            else if(u2 == "km") cout << (n * pow(10,-2));
        }
        else if( u1 == "hm"){
            if(u2 == "mm") cout << (n * pow(10,5));
            else if(u2 == "cm") cout << (n * pow(10,4));
            else if(u2 == "dm") cout << (n * pow(10,3));
            else if(u2 == "m") cout << (n * pow(10,2));
            else if(u2 == "da") cout << (n * 10);
            else if(u2 == "km") cout << (n * pow(10,-1));
        }
        else if( u1 == "km"){
            if(u2 == "mm") cout << (n * pow(10,6));
            else if(u2 == "cm") cout << (n * pow(10,5));
            else if(u2 == "dm") cout << (n * pow(10,4));
            else if(u2 == "m") cout << (n * pow(10,3));
            else if(u2 == "da") cout << (n * pow(10,2));
            else if(u2 == "hm") cout << (n * 10);
        }
        //Mass
        else if( u1 == "mg"){
            if(u2 == "cg") cout << (n * pow(10,-1));
            else if( u2 == "dg") cout << (n * pow(10,-2));
            else if( u2 == "g") cout << (n * pow(10,-3));
            else if( u2 == "dag") cout << (n * pow(10,-4));
            else if( u2 == "hg") cout << (n * pow(10,-5));
            else if( u2 == "kg") cout << (n * pow(10,-6));
        }
        else if( u1 == "cg" ){
            if(u2 == "mg") cout << (n * 10);
            else if( u2 == "dg") cout << (n * pow(10,-1));
            else if( u2 == "g") cout << (n * pow(10,-2));
            else if( u2 == "dag") cout << (n * pow(10,-3));
            else if( u2 == "hg") cout << (n * pow(10,-4));
            else if( u2 == "kg") cout << (n * pow(10,-5));
        }
        else if( u1 == "dg" ){
            if(u2 == "mg") cout << (n * pow(10,2));
            else if( u2 == "cg") cout << (n * 10);
            else if( u2 == "g") cout << (n * pow(10,-1));
            else if( u2 == "dag") cout << (n * pow(10,-2));
            else if( u2 == "hg") cout << (n * pow(10,-3));
            else if( u2 == "kg") cout << (n * pow(10,-4));
        }
        else if( u1 == "dg" ){
            if(u2 == "mg") cout << (n * pow(10,2));
            else if( u2 == "cg") cout << (n * 10);
            else if( u2 == "g") cout << (n * pow(10,-1));
            else if( u2 == "dag") cout << (n * pow(10,-2));
            else if( u2 == "hg") cout << (n * pow(10,-3));
            else if( u2 == "kg") cout << (n * pow(10,-4));
        }
        else if( u1 == "g"){
            if(u2 == "mg") cout << (n * pow(10,3));
            else if( u2 == "cg") cout << (n * pow(10,2));
            else if( u2 == "dg") cout << (n * 10);
            else if( u2 == "dag") cout << (n * pow(10,-1));
            else if( u2 == "hg") cout << (n * pow(10,-2));
            else if( u2 == "kg") cout << (n * pow(10,-3));
        }
        else if( u1 == "dag"){
            if(u2 == "mg") cout << (n * pow(10,4));
            else if( u2 == "cg") cout << (n * pow(10,3));
            else if( u2 == "dg") cout << (n * pow(10,2));
            else if( u2 == "g") cout << (n * 10);
            else if(u2 == "hg") cout << (n * pow(10,-1));
            else if(u2 == "kg") cout << (n * pow(10,-2));
        }
        else if( u1 == "hg"){
            if(u2 == "mg") cout << (n * pow(10,5));
            else if(u2 == "cg") cout << (n * pow(10,4));
            else if(u2 == "dg") cout << (n * pow(10,3));
            else if(u2 == "g") cout << (n * pow(10,2));
            else if(u2 == "dg") cout << (n * 10);
            else if(u2 == "kg") cout << (n * pow(10,-1));
        }
        else if( u1 == "kg" ){
            if(u2 == "mg") cout << (n * pow(10,6));
            else if(u2 == "cg") cout << (n * pow(10,5));
            else if(u2 == "dg") cout << (n * pow(10,4));
            else if(u2 == "g") cout << (n * pow(10,3));
            else if(u2 == "dg") cout << (n * pow(10,2));
            else if(u2 == "hg") cout << (n * 10);
        }
        //Angular measure
        else if ( u1 == "deg" || u1 == "degrees"){ if( u2 == "radians" || u2 == "rad") cout << (n*pi/180);}
        else if ( u1 == "radians" || u1 == "rad"){ if(u2 == "deg" || u2 == "degrees") cout << (n*180/pi);}
        else{
            cout <<"\n conversion not available from "<< u1 << " to";
            moduleRun = false;
        }
        cout<<" "<<u2<<"\n\n";
        if(!moduleRun){finline("c0nv3rt3r");}
    }
}
void quad(){
    int a,b,c;
    h("Quadratic Solver", '-');
    cout<<"\n Solves the value for x in a quadratic of the form ax^2 + bx + c = 0\n";
    cout<<"\nEnter the coefficient of x^2 >> ";
    cin>>a;
    cout<<"\nEnter the coefficient of x >> ";
    cin>>b;
    cout<<"\nEnter the numerical value >> ";
    cin>>c;
    double d = pow(b,2) - (4*a*c);
    if( d < 0 ){ cout<<"\nThere are no real roots possible"; }
    else if(d == 0){ cout<<"\nThe root is "<<(-1*b)/(2*a);}
    else{ cout<<"\nThe roots are "<< (sqrt(d) - b) / (2 * a) << " & " << (-1*( sqrt(d) + b )) / ( 2 * a ); }
}

//Games Module
bool play = true;
bool gameRun = true;
void solve(){
    h("Solve",'*');
    int sel, qn = 0, score = 0;
    double ans;
    char op[4];
    op[0] = '+'; op[1] = '-'; op[2] = '*'; op[3] = '/';
    while(gameRun){
        ++qn;
        double a = floor(rand()%100), b = floor(rand()%100);
        sel = rand()%4; //#Rand(0 to 3)
        if(sel == 3){a = b*(rand()%10);}
        cout<<"\n\n"<<a << op[sel] << b << '\n';
        cin>>ans;
        switch(sel){
            case 0:
                if( ans == (a + b) ){ cout<< "You are correct"; score++;}
                else{cout<<"Wrong the answer was "<< a + b;}
                break;
            case 1:
                if( ans == (a - b) ){ cout<< "Absolutely Right"; score++;}
                else{cout<<"Wrong the answer was "<< a - b;}
                break;
            case 2:
                if( ans == (a * b) ){ cout<< "You are correct"; score++;}
                else{cout<<"Wrong the answer was "<< a * b;}
                break;
            case 3:
                if( ans == (a / b) ){ cout<< "Absolutely Right"; score++;}
                else{cout<<"Wrong the answer was "<< a / b;}
                break;
            default: cout<<"\n!!An unexpected error has occured!!";
        }
        if(qn>100){
            if(score>=50){cout<<"\nGood Job, You've won";}
            else{cout<<"\nYou can do better";}
            cout<< "\nYour score is "<< score;
            cout<< "\n\n Do you wish to play again(y/n)? ";
            cin>> cmd;
            if(cmd == "n" || cmd == "no"){cout<<"\nThank you for playing."; gameRun = false;}
            else{score = 0; qn = 0;}
        }
    }
}

void guessthenumber(){
    h("Guess the number",'*');
    cout<<"\nTry to guess the super random number that the computer has chosen\n\n";
    while(gameRun){
        bool play = true;
        int number = rand(), tries = 0, guess;
        while(play){ // loop to allow repeted guessing
            cin>>guess;
            tries++;
            if(guess>number){cout<<"The number is smaller\n";}
            else if(guess<number){cout<<"The number is larger\n";}
            else if(guess==number){
                play = false;
                cout << "\nYou win, that was the number\n It only took you "<<tries<<" tries\n";
                cout << "\nDo you wish to play again?(y/n) ";
                cin>>cmd;
                if( cmd =="n" || cmd =="no"){gameRun = false;} //ends game loop
                else{ cout<<"\nGuess the new number\n"; }
            }
        }
    }
}

void games(){
    h("The Games Module", '-');
    cout<<"\nThe available games are :\n Solve - Solve a 101 little arithmatic problems\n 'GuessTheNumber' - Try to guess the number that the computer has picked.";
    while(moduleRun){
        if(!gameRun){cout<<"\nChoose a new game\n";}
        gameRun = true;
        cout<<"\ngames>";
        cin>>cmd;
        if(cmd == "guessthenumber"){ guessthenumber(); }
        else if(cmd == "solve"){ solve(); }
        else if(cmd=="exit" || cmd =="quit"){ moduleRun = false; }
        else{cout<<"!Game not Available";}
    }
}
//End of Games Module

int main(){
    bool ProgramRun = true;
    h("The Math Thingy v0.01 by Nick K.",'=');
    cout<<"\n  Type 'calc' to initialize calculator \n  & 'cmdlist' for a list of commands\n";
    while(ProgramRun){
        if(!moduleRun){cout<<"Enter new command";}
        moduleRun = true;
        cout << "\n>>";
        cin >> cmd;
        if( cmd == "cmdlist" || cmd=="commands" ){
            cout << "\n\tcalc - Starts Arithmetic Calculator\n\tconv - Convert values to different units\n\tfunc - Scientific functions including sin, cos & tan\n\tquad - Finds the roots of a Quadratic Equation of the form ax^2 + bx + c = 0\n\tgames - Activates the games module\n\n";
        }
        else if( cmd == "calc" || cmd == "calculator" ){ calculator(); }
        else if( cmd == "func" ){functions();}
        else if( cmd == "conversions" || cmd == "conv" ){ converter(); }
        else if(cmd == "quad"){ quad(); }
        else if( cmd == "games" ){ games(); }
        else if( cmd == "exit" || cmd == "quit" || cmd == "0x0"){ ProgramRun = false; }
        else{ cout<<"Invalid command\n"; }
    }
}

Things I would like addressed:

  • Ways to optimize and clean the code
  • Mistake and errors in my programming practices
  • Anything else which needs to corrected
  • The converter function is what significantly takes the most space in my program. How can I successfully decrease the amount of code for this function? I realize that I should, in some way, implement arrays fo this purpose but with my current knowledge of arrays in this language, I am not in a position to do so. I am in the process of learning more about them and in the meantime, I would appreciate the proposal of any method of optimally condensing the required code.
    (Note: I am willing conduct research into any topic on my own . All I ask for is to be pointed in the right direction)
\$\endgroup\$
2
\$\begingroup\$
  • Try not to get into the habit of using using namespace std.

  • The "decorations" don't seem that useful and only clutters the code, so I'd remove them. Don't worry about making the output look super nice (especially in a console environment). Just focus on keeping the computational implementation nice. You can, however, keep this simple by utilizing some functionality from the <iomanip> library.

  • Do not use global variables:

    string cmd;
    bool moduleRun = true;
    

    Your code is already quite lengthy, and having these global will make maintenance painful if they end up being used unknowingly. They should be used locally and passed to functions as needed.

  • It appears that you're getting the square root here:

    long double l = floor(pow(n, 0.5));
    

    Why not just use std::sqrt()?

    long double l = std::floor(std::sqrt(n));
    

    I'd also recommend renaming l to something actually accurate. Single-character variables, except as loop counters, add no context to its use, decreasing readability and maintainability (what if you completely forgot what it's for?).

  • This is hard to read:

    (i==0)?cout<<"st":(i==1)?cout<<"nd":(i==2)?cout<<"rd":cout<<"th";
    

    If you cannot shorten it, at least rearrange it in a (slightly) more readable manner:

    (i == 0)
    ? cout << "st"
    : (i == 1)
    ? cout << "nd"
    : (i == 2)
    ? cout << "rd"
    : cout << "th";
    

    But this complexity can suggest that using ternary is not preferred. Whether or not you can make this simpler, it may be beneficial to put this into its own function. This is not prod()'s primary purpose, so having a separate function will make that purpose clearer. It will also help maintain the separation of concerns design principle.

\$\endgroup\$
6
\$\begingroup\$

The command pattern is your friend.
You can then use a std::map to convert a user input string to a command during execution.

#include <map>
#include <string>
#include <functional>
#include <cmath>
#include <iostream>

int main(int argc, char* argv[])
{
    std::map<std::string, std::function<double(double)>>    commands;

    commands["sin"] = [](double d) {return std::sin(d);};
    commands["cos"] = [](double d) {return std::cos(d);};
    //... etc.

    std::string command = argv[1];
    double      value   = std::atof(argv[2]);
    std::cout << commands[command](value) << "\n";
}

Your conversions can be done by a matrix:

   Unit
              m   c   <none>   d     h     k
   mili       0   1     2      3     4     5
   cente     -1   0     1      2     3     4
   <none>    -2  -1     0      1     2     3
   deca      -3  -2    -1      0     1     2
   hecto     -4  -3    -2     -1     0     1
   kilo      -5  -4    -3     -2    -1     0

So the table above defines the power conversion from one unit to another.

   int conversion[6][6] = {{0,1,2,3,4,5}, {-1,0,1,2,3,4}, .... };
   std::map<std::string, int>  data = {{ "m", 0 }, {"c", 1}, {"", 2}, {"d", 3}, {"h", 4}, {"k", 5}};

   std::string srcType  = "d";  // src deca
   std::string dstType  = "k";  // kilo
   int   src = data[srcType];
   int   dst = data[dstType];
   int result = n * pow(10, conversion[src][dst]);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.