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