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++.