C 语言 四 目 运算 请 帮 我 解答
仅 供 参考 ： / * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 函数 型 计算器 ( VC + + 6 . 0 , Win32 Console ) 程序 由 yu _ hua 于 2007 - 07 - 27 设计 完成 功能 ： 目前 提供 了 10 多 个 常用 数学 函数 : ⑴ 正 弦 sin ⑵ 余 弦 cos ⑶ 正 切 tan ⑷ 开 平方 sqrt ⑸ 反 正 弦 arcsin ⑹ 反 余 弦 arccos ⑺ 反正 切 arctan ⑻ 常用 对数 lg ⑼ 自然 对数 ln ⑽ｅ 指数 exp ⑾ 乘 幂 函数 ∧ 用法 ： 如果 要求 2 的 32 次 幂 ， 可以 打入 2 ^ 32 < 回车 > 如果 要求 30 度 角 的 正 切 可 键入 tan ( Pi / 6 ) < 回车 > 注意 不 能 打入 ： tan ( 30 ) < Enter > 如果 要求 1 . 23 弧度 的 正 弦 ， 有 几 种 方法 都 有效 ： sin ( 1 . 23 ) < Enter > sin 1 . 23 < Enter > sin1 . 23 < Enter > 如果 验证 正 余 弦 的 平方 和 公式 , 可 打入 sin ( 1 . 23 ) ^ 2 + cos ( 1 . 23 ) ^ 2 < Enter > 或 sin1 . 23 ^ 2 + cos1 . 23 ^ 2 < Enter > 此外 两 函数 表达式 连 在 一起 , 自动 理解 为 相乘 如 ： sin1 . 23cos 0 . 77 + cos1 . 23 sin0 . 77 就 等价 于 sin ( 1 . 23 ) * cos ( 0 . 77 ) + cos ( 1 . 23 ) * si n ( 0 . 77 ) 当 然 你 还 可 以依 据 三角 变 换 ，再用sin (1 . 23 +0.77 ) 也 即 si n2 验 证 一下 。 本 计算器 充分 考虑 了 运算 符 的 优先 级 因此 诸如 ： 2 + 3 * 4 ^ 2 实际上 相当于 ： 2 + ( 3 * ( 4 * 4 ) ) 另外 函数 名 前面 如果 是 数字 , 那么 自动 认为 二者 相乘 . 同理 ， 如果 某 数 的 右侧 是 左 括号 ， 则 自动 认为 该 数 与 括弧 项 之间 隐含 一 乘号 。 如 ： 3sin1.2 ^ 2 + 5cos2.1 ^ 2 相当于 3 * sin2 ( 1.2 ) + 5 * cos2 ( 2.1 ) 又 如 ： 4 ( 3 - 2 ( sqrt5 - 1 ) + ln2 ) + lg5 相当于 4 * ( 3 - 2 * ( √5 - 1 ) + loge ( 2 ) ) + log10 ( 5 ) 此外 ， 本 计算器 提供 了 圆周 率 Pi 键入 字母 时 不 区分 大小 写 , 以 方便 使用 。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * / # include < iostream > # include < iomanip > # include < cstd lib > # include < cstring > # include < cctype > # include < cmath > # include < stdio . h > # include < string . h > # include < windows . h > using namespace std ; const char Tab = 0x9 ; const int DIGIT = 1 ; const int MAXLEN = 16384 ; char s [ MAXLEN ] , * endss ; int pcs = 15 ; double fun ( double x , char op [ ] , int * iop ) { while ( op [ * iop - 1 ] < 32 ) / / 本 行 使得 函数 嵌 套 调用 时 不必 加 括号 , 如 arc sin ( sin ( 1 . 234 ) ) 只 需 键入 arc sin sin 1 . 234 < Enter > switch ( op [ * iop - 1 ] ) { case 7 : x = si n ( x ) ; ( * iop ) - - ; break ; case 8 : x = cos ( x ) ; ( * iop ) - - ; break ; case 9 : x = tan ( x ) ; ( * iop ) - - ; break ; case 10 : x = s qrt ( x ) ; ( * iop ) - - ; break ; case 11 : x = as in ( x ) ; ( * iop ) - - ; break ; case 12 : x = ac os ( x ) ; ( * iop ) - - ; break ; case 13 : x = atan ( x ) ; ( * iop ) - - ; break ; case 14 : x = log10 ( x ) ; ( * iop ) - - ; break ; case 15 : x = log ( x ) ; ( * iop ) - - ; break ; case 16 : x = exp ( x ) ; ( * iop ) - - ; break ; } return x ; } double calc ( char * expr , char * * addr ) { static int deep ; / / 递 归 深度 static char * fname [ ] = { " sin " , " cos " , " tan " , " sqrt " , " arcs in " , " arccos " , " arctan " , " lg " , " ln " , " exp " , NULL } ; double ST [ 10 ] = { 0 . 0 } ; / / 数字 栈 char op [ 10 ] = { ' + ' } ; / / 运算 符 栈 char c , * rexp , * pp , * pf ; int ist = 1 , iop = 1 , last , i ; if ( ! deep ) { pp = pf = expr ; do { c = * pp + + ; if ( c ! = ' ' & & c ! = Tab ) * pf + + = c ; } while ( c ! = ' \ 0 ' ) ; } pp = expr ; if ( ( c = * pp ) = = ' - ' | | c = = ' + ' ) { op [ 0 ] = c ; pp + + ; } last = ! DIGIT ; w hile ( ( c = * pp ) ! = ' \ 0 ' ) { if ( c = = ' ( ' ) { / / 左 圆括 弧 deep + + ; ST [ ist + + ] = calc ( + + pp , addr ) ; deep - - ; ST [ ist - 1 ] = fun ( ST [ ist - 1 ] , op , & iop ) ; pp = * addr ; last = DIGIT ; if ( * pp = = ' ( ' | | isalpha ( * pp ) & & strnicmp ( pp , " Pi " , 2 ) ) { / / 目的 是 ： 当 右 圆括 弧 的 右 恻 为 左 圆 括弧 或 函数 名字 时 ， 默认 其 为 乘法 op [ iop + + ] = ' * ' ; last = ! DIGIT ; c = op [ - - iop ] ; goto operate ; } } else if ( c = = ' ) ' ) { / / 右 圆 括 弧 pp + + ; break ; } else if ( isalpha ( c ) ) { if ( ! strnicmp ( pp , " Pi " , 2 ) ) { if ( last = = DIGIT ) { cout < < " π 左侧 遇 ） " < < endl ; exit ( 1 ) ; } ST [ ist + + ] = 3 . 14159265358979323846264338328 ; ST [ ist - 1 ] = fun ( ST [ ist - 1 ] , op , & iop ) ; pp + = 2 ; last = DIGIT ; if ( ! strnicmp ( pp , " Pi " , 2 ) ) { cout < < " 两 个 π 相连 " < < endl ; exit ( 2 ) ; } if ( * pp = = ' ( ' ) { cout < < " π 右侧 遇 （ " < < endl ; exit ( 3 ) ; } } else { for ( i = 0 ; ( pf = fname [ i ] ) ! = NULL ; i + + ) if ( ! strnic mp ( pp , pf , strlen ( pf ) ) ) break ; if ( pf ! = NULL ) { op [ iop + + ] = 07 + i ; pp + = strlen ( pf ) ; } else { cout < < " 陌生 函数 名 " < < endl ; exit ( 4 ) ; } } } else if ( c = = ' + ' | | c = = ' - ' | | c = = ' * ' | | c = = ' / ' | | c = = ' ^ ' ) { char cc ; if ( last ! = DIGIT ) { cout < < " 运算 符 粘连 " < < endl ; exit ( 5 ) ; } pp + + ; if ( c = = ' + ' | | c = = ' - ' ) { do { cc = op [ - - iop ] ; - - ist ; switch ( cc ) { case ' + ' : ST [ ist - 1 ] + = ST [ ist ] ; break ; case ' - ' : ST [ ist - 1 ] - = ST [ ist ] ; break ; case ' * ' : ST [ ist - 1 ] * = ST [ ist ] ; break ; case ' / ' : ST [ ist - 1 ] / = ST [ ist ] ; break ; case ' ^ ' : ST [ ist - 1 ] = po w ( ST [ ist - 1 ] , ST [ ist ] ) ; break ; } } w hile ( iop ) ; op [ iop + + ] = c ; } else if ( c = = ' * ' | | c = = ' / ' ) { opera te : cc = op [ iop - 1 ] ; if ( cc = = ' + ' | | cc = = ' - ' ) { op [ iop + + ] = c ; } else { - - ist ; op [ iop - 1 ] = c ; switch ( cc ) { case ' * ' : ST [ ist - 1 ] * = ST [ ist ] ; break ; case ' / ' : ST [ ist - 1 ] / = ST [ ist ] ; break ; case ' ^ ' : ST [ ist - 1 ] = pow ( ST [ ist - 1 ] , ST [ ist ] ) ; break ; } } } else { cc = op [ iop - 1 ] ; if ( cc = = ' ^ ' ) { cout < < " 乘 幂 符 连 用 " < < endl ; exit ( 6 ) ; } op [ iop + + ] = c ; } last = ! DI GIT ; } else { if ( last = = DIGIT ) { cout < < " 两 数字 粘 连 " < < endl ; exit ( 7 ) ; } ST [ ist + + ] = strtod ( pp , & rexp ) ; ST [ ist - 1 ] = fun ( ST [ ist - 1 ] , op , & iop ) ; if ( pp = = rexp ) { cout < < " 非法 字 符 " < < endl ; exit ( 8 ) ; } pp = rexp ; last = DIGIT ; if ( * pp = = ' ( ' | | isalpha ( * pp ) ) { op [ iop + + ] = ' * ' ; last = ! DIGIT ; c = op [ - - iop ] ; goto operate ; } } } * addr = pp ; if ( iop > = ist ) { cout < < " 表达式 有 误 " < < endl ; exit ( 9 ) ; } while ( iop ) { - - ist ; switch ( op [ - - iop ] ) { case ' + ' : ST [ ist - 1 ] + = ST [ ist ] ; break ; case ' - ' : ST [ ist - 1 ] - = ST [ ist ] ; break ; case ' * ' : ST [ ist - 1 ] * = ST [ ist ] ; break ; case ' / ' : ST [ ist - 1 ] / = ST [ ist ] ; break ; case ' ^ ' : ST [ ist - 1 ] = pow ( ST [ ist - 1 ] , ST [ ist ] ) ; break ; } } return ST [ 0 ] ; } int main ( int argc , char * * argv ) { int a ; if ( argc < 2 ) { if ( Get ConsoleOutputCP ( ) ! = 936 ) system ( " chcp 936 > NUL " ) ; / / 中文 代码 页 cout < < " 计算 函数 表达式 的 值 。 " < < endl < < " 支持 ( ) , + , - , * , / , ^ , Pi , sin , cos , tan , sqrt , arcsin , arccos , arctan , lg , ln , exp " < < endl ; while ( 1 ) { cout < < " 请 输入 表达式 ： " ; gets ( s ) ; if ( s [ 0 ] = = 0 ) break ; / / cout < < s < < " = " ; cout < < setprecision ( 15 ) < < calc ( s , & endss ) < < endl ; } } else if ( argc = = 2 & & 0 = = strcmp ( argv [ 1 ] , " / ? " ) ) { if ( GetConsoleOutputCP ( ) ! = 936 ) system ( " chcp 936 > NUL " ) ; / / 中文 代码 页 cout < < " 计算 由 ≥1 个 命令行 参数 给出 的 函数 表达式 的 值 。 最后 一 个 参数 是 . 0 ～ . 15 表示 将 计算 结果 保留 小数 0 ～ 15 位 " < < endl < < " 支持 ( ) , + , - , * , / , ^ ^ , Pi , sin , cos , tan , sqrt , arcsin , arccos , arctan , lg , ln , exp " < < endl ; } else { strncpy ( s , argv [ 1 ] , MAXLEN-1 ) ; s [ MAXLEN-1 ] = 0 ; if ( argc > 2 ) { for ( a = 2 ; a < argc-1 ; a + + ) strncat ( s , argv [ a ] , MAXLEN-1 ) ; / / 将 空格 间隔 的 各 参数 连接 到 s if ( 1 = = sscanf ( argv [ a ] , " . % d " , & pcs ) & & 0 < = pcs & & pcs < = 15 ) { / / 最后 一 个 参数 是 . 0 ～ . 15 表示 将 计算 结果 保留 小数 0 ～ 15 位 printf ( " % . * lf \ n " , pcs , calc ( s , & endss ) ) ; } else { strncat ( s , argv [ a ] , MAXLEN - 1 ) ; printf ( " % . 15lg \ n " , calc ( s , & endss ) ) ; } } else { printf ( " % . 15lg \ n " , calc ( s , & endss ) ) ; } } return 0 ; }
