- Prison Code Breaker Diary -

=> aka: Nhật Kí Code Tù

Categories

Original Topic Discussion => [Cviet]

Relax #1 [ by me ]

Given 3 functions:

int add( int _a, int _b ) { return _a + _b; }
int sub( int _a, int _b ) { return _a - _b; }
int mul( int _a, int _b ) { return _a * _b; }

Implement the following program:
+ Prompt user to input 1 of 4 strings: "add", "sub", "mul" or "end"; otherwise, start program again; "end" to exit.
+ Then, prompt user to input 2 numbers
+ Output result in this form

A [operator] B = [result]

Operator must be one of the following '+', '-' and '*', according to its own function, which means string "add" match add() function ....

Requirement
+ Must use function pointer
+ Call function according to its name, call add() if user prompt "add"....so on.
+ Language to use: C, C++

Demo output

> type 'add', 'sub', 'mul' or 'end': add
 a = 1
 b = 2
 1 + 2 = 3
> type 'add', 'sub', 'mul' or 'end': sub
 a = 6
 b = 4
 6 - 4 = 2
> type 'add', 'sub', 'mul' or 'end': mul
 a = 12
 b = 1
 12 * 1 = 12
> type 'add', 'sub', 'mul' or 'end': end

PROGRAM ENDED ! 


Solution #1 [ by me ]


Code in C as following:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE    1024

//
// #struct JFUNC
//
struct JFUNC {
    char *name;                 // function name
    int (*func)(int, int);      // pointer to function
    char sign;                  // sign of function, '+', '-', '*'
};

//
// #function        say()
// #purpose         format output with given params
//
void say( int (*func)(int,int), int _a, int _b, char _ )
{
    printf(" %d %c %d = %d\n", _a, _, _b, func( _a, _b ) );
}

//
// #function        input()
// #purpose         get input from user
//
void input( int *a, int *b ) {
    printf(" a = "); scanf("%d%*c", a);
    printf(" b = "); scanf("%d%*c", b);
}

//
// #function        add(),sub(),mul()
// #purpose         provide regular calculation
//
int add( int _a, int _b ) { return _a + _b; }
int sub( int _a, int _b ) { return _a - _b; }
int mul( int _a, int _b ) { return _a * _b; }
//int div( int _a, int _b ) { return _a / _b; }

/* ENTRY POINT */
int main( )
{
    // init array of 3 structs
    struct JFUNC calc[3] = {
        { "add", add, '+' },
        { "sub", sub, '-' },
        { "mul", mul, '*' }
    };
    int a, b; // input from user
    int idx; // index of struct JFUNC array
    char *key = (char *)malloc( MAX_SIZE * sizeof(char) ); // string to get from user
    do {
   
        printf("> type 'add', 'sub', 'mul' or 'end': " );
        // get input, exactly 4 bytes
        fgets( key, MAX_SIZE, stdin );     

        // iterate through array to get correct function
        for( idx = 0; idx < 3; ++idx ) {
            // if function name is matched
            if( strcmp(calc[idx].name, key) == 0 ) {
                // get input
                input( &a, &b );
                // output
                say( calc[idx].func, a, b, calc[idx].sign );
            }
        }
    // end program if "end" prompted
    } while ( strcmp(key, "end") != 0 );
   
    // free memory
    free( key );
   
    printf(" PROGRAM ENDED!\n");
    // program return
    return 0;
}

Code in C++ as following

#include <iostream>

using namespace std;

//
// #struct JFUNC
//
struct JFUNC {
    string name;                    // function name
    int (*func)(int, int);      // pointer to function
    char sign;                  // sign of function, '+', '-', '*'
};

//
// #function        say()
// #purpose         format output with given params
//
void say( int (*func)(int,int), int _a, int _b, char _ )
{
    cout << " " << _a << " " << _ << " " << _b << " = " << func( _a, _b ) << "\n";
}

//
// #function        input()
// #purpose         get input from user
//
void input( int *a, int *b ) {
    cout << " a = "; cin >> *a;
    cout << " b = "; cin >> *b;
}

//
// #function        add(),sub(),mul()
// #purpose         provide regular calculation
//
int add( int _a, int _b ) { return _a + _b; }
int sub( int _a, int _b ) { return _a - _b; }
int mul( int _a, int _b ) { return _a * _b; }
//int div( int _a, int _b ) { return _a / _b; }

/* ENTRY POINT */
int main( )
{
    // init array of 3 structs
    struct JFUNC calc[3] = {
        { "add", add, '+' },
        { "sub", sub, '-' },
        { "mul", mul, '*' }
    };
    int a, b; // input from user
    int idx; // index of struct JFUNC array
    string key; // string to get from user
    do {
   
        cout << "> type 'add', 'sub', 'mul' or 'end': ";
        // get input, exactly 4 bytes
        cin >> key;

        // iterate through array to get correct function
        for( idx = 0; idx < 3; ++idx ) {
            // if function name is matched
            if( calc[idx].name == key ) {
                // get input
                input( &a, &b );
                // output
                say( calc[idx].func, a, b, calc[idx].sign );
            }
        }
    // end program if "end" prompted
    } while ( key != "end" );
   

    cout << " PROGRAM ENDED!\n";
    // program return
    return 0;
}

Solution #2 [ by tauit_dnmd ]

/*
  UITs:UITstudent.com
  Coder:tauit_dnmd.
*/
#include<iostream>
#include<string>
using namespace std;
typedef int (*MyType)(int,int);

int  add( int _a, int _b ) { return _a + _b; }
int sub( int _a, int _b ) { return _a - _b; }
int mul( int _a, int _b ) { return _a * _b; }

int (*GetFunctionVerSion1(string s,char &oper))(int,int) 
{
        if(s=="add"){oper='+'; return &add;}
        if(s=="sub"){oper='-';return ⊂}
        if(s=="mul"){oper='*'; return &mul;}
}

MyType GetFunctionVerSion2(string s,char &oper)
{
        if(s=="add"){oper='+'; return &add;}
        if(s=="sub"){oper='-';return ⊂}
        if(s=="mul"){oper='*'; return &mul;}
}

int main()
{
    int (*uitstudent)(int,int)=NULL;//define 
    int a,b;
    string myoperator;//operator
    char UITs;
    do
    {
        do
        {
            cout<<"type 'add' 'sub' 'mul' or 'end':"; 
            cin>>myoperator;
            if(myoperator=="add"||myoperator=="sub"||myoperator=="mul"||myoperator=="end") break;
        }while(1);
        if(myoperator!="end")
        {
            uitstudent=GetFunctionVerSion1(myoperator,UITs);//Or uitstudent=GetFunctionVerSion2(myoperator,UITs);
            cout<<"a= ";cin>>a;
            cout<<"b= ";cin>>b;
            cout<<"a "<<UITs<<" b = "<<(*uitstudent)(a,b)<<endl;
        }
    }while(myoperator!="end");
    cout<<"UITs:PROGRAM END!"<<endl;
    return 0;
}  


Solution #3 [ by QuangHoang ]

#include <iostream>
#include <string>
#include <map>
using namespace std;

typedef int (*func)( int, int );

int add( int _a, int _b ) { return _a + _b; }
int sub( int _a, int _b ) { return _a - _b; }
int mul( int _a, int _b ) { return _a * _b; }

map <string, func> fmap;
map <string, func>::iterator it;

void initMap()
{
    fmap["add"] = add;
    fmap["sub"] = sub;
    fmap["mul"] = mul;
}

bool result(string oper)
{
    bool ok = false;
    for ( it=fmap.begin() ; it != fmap.end(); it++ )
        if ( oper == (*it).first ) ok = true;

    if ( !ok ) return false;
   

    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;

    cout << a << " " << oper << " " << b << " = " << fmap[oper]( a,b ) << endl;
   
    cin.ignore();
    return true;
}

string label()
{
    string lbl;

    for ( it=fmap.begin() ; it != fmap.end(); it++ )
        lbl += "'" + (*it).first + "', ";

    return lbl;
}

int main()
{
    initMap();
    string oper;

    cout << "> type " << label() << "or 'end': ";
    do
    {
        getline(cin,oper);
        if (oper == "end") break;  

        if (!result(oper))
            cout << "> retype " << label() << "or 'end': ";
        else cout << "> type " << label() << "or 'end': ";

    } while (true);

    cout << "\nPROGRAM ENDED !";
    return 0;
}


Solution #4 [ by rox_rook ]

#include <iostream>
#include <map>
#include <string>


int add( int a, int b ) { return a + b; }
int sub( int a, int b ) { return a - b; }
int mul( int a, int b ) { return a * b; }
int end( int a, int b ) { return 0;     } // dummy func

typedef int( *FUNC )( int , int );

int main()
{
    std::map< std::string, std::pair< char, FUNC > > _func;

    _func[ "add" ] = std::make_pair< char, FUNC >( '+', add );
    _func[ "sub" ] = std::make_pair< char, FUNC >( '-', sub );
    _func[ "mul" ] = std::make_pair< char, FUNC >( '*', mul );
    _func[ "end" ] = std::make_pair< char, FUNC >( ' ', end );

    std::string user_repl;
    int a, b;

    do {
        std::cout << "> type 'add', 'sub', 'mul' or 'end' : ";
        std::cin >> user_repl;
        if( user_repl == "end" )
            break;
        std::cout << "> 'a' 'b' : ";
        std::cin >> a >> b;
        std::cout << a << _func[ user_repl ].first << b << "=" << _func[ user_repl ].second( a, b ) << "\n";
    }
    while( 1 );

    return 0;
}


Evaluation

- Solution #1: My approach follows the traditions of C, calling function by name through a structure, which is mentioned in C-faq under section 20.6 ( Read C-Faq 20.6 )
- Solution #2: It's kinda handy in matching strings.
- Solution #3: mapping, but not really satisfy requirements.
- Solution #4: mapping using value of pair template, it's short, clear and understandable. I think it's the best solution under C++.

0 comments

Post a Comment