鱼C论坛

 找回密码
 立即注册
查看: 1539|回复: 1

[已解决]求救!!!!谢谢大家

[复制链接]
发表于 2022-5-23 22:16:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
设计一个python程序,它可以在用户输入数学表达式后自动将其转换为二叉树。具体来说,表达式必须与上面的格式相同,一个有效的表达式可以递归定义如下:
          它必须是(X?Y)的形式,其中X和Y要么是数字,要么是有效表达式,并且?表示操作符(*,/,+,-)
最佳答案
2022-6-3 14:46:20
来晚了,前段时间有点忙

看不懂你那个图片是怎么表示二叉树的
下面这个代码创建出了这颗树,你想要怎么输出就自己写代码吧
#!/usr/bin/env python
#coding=utf-8

from ctypes import cdll
from ctypes.util import find_library
from ctypes import c_void_p, c_int, byref
import sys

libc = cdll.LoadLibrary(find_library('c'))
stdin = c_void_p.in_dll(libc, 'stdin')

def fgetc(stream):
    return libc.fgetc(stream)

def ungetc(ch, stream):
    return libc.ungetc(ch, stream)

# token
# [[symbol, value], lchild, rchild]
last_token = None

ERROR = 256
NUM = 257
EOF = -1

def error(value):
    return [[ERROR, value], None, None]

def isdigit(ch):
    return ch >= ord('0') and ch <= ord('9')

def get_token():
    global last_token
    if last_token:
        result = last_token
        last_token = None
        return result
    ch = fgetc(stdin)
    if ch in [ord(i) for i in [' ', '\t', '\v', '\f']]:
        return get_token()
    if isdigit(ch):
        ungetc(ch, stdin)
        num = c_int()
        libc.fscanf(stdin, b'%d', byref(num))
        return [[NUM, num.value], None, None]
    return [[ch, None], None, None]

def unget_token(token):
    global last_token
    last_token = token

def factor():
    token = get_token()
    if token[0][0] == NUM: return token
    if token[0][0] == ord('-'):
        token[1] = factor()
        if token[1][0][0] == ERROR: return token[1]
        return token
    if token[0][0] != ord('('): return error(token[0][1])
    token = expression()
    if token[0][0] == ERROR: return token
    temp = token
    token = get_token()
    if token[0][0] != ord(')'): return error(token[0][1])
    return temp

def term():
    token = factor()
    if token[0][0] == ERROR: return token
    a = token
    token = get_token()
    if token[0][0] != ord('*') and token[0][0] != ord('/'):
        unget_token(token)
        return a
    op = token
    token = term()
    if token[0][0] == ERROR: return token
    b = token
    op[1] = a
    op[2] = b
    return op

def expression():
    token = term()
    if token[0][0] == ERROR: return token
    a = token
    token = get_token()
    if token[0][0] != ord('+') and token[0][0] != ord('-'):
        unget_token(token)
        return a
    op = token
    token = expression()
    if token[0][0] == ERROR: return token
    b = token
    op[1] = a
    op[2] = b
    return op

def do_error():
    print('错误的表达式!', file = sys.stderr)
    while True:
        token = get_token()
        if token[0][0] == ord('\n'): break

def val(tree):
    if tree[0][0] == NUM: return tree[0][1]
    if tree[0][0] == ord('+'): return val(tree[1]) + val(tree[2])
    if tree[0][0] == ord('*'): return val(tree[1]) * val(tree[2])
    if tree[0][0] == ord('/'): return val(tree[1]) / val(tree[2])
    if tree[0][0] == ord('-'):
        return -val(tree[1]) if tree[2] == None else val(tree[1]) - val(tree[2])
    raise "未知的运算符!"

def line():
    token = get_token()
    if token[0][0] == ord('\n'): return
    unget_token(token)
    token = expression()
    if token[0][0] == ERROR:
        do_error()
        return
    result = token
    token = get_token()
    if token[0][0] == ord('\n'):
        #print(result)
        print('>>> ' + str(val(result)))
        return
    do_error()

def lines():
    token = get_token()
    unget_token(token)
    if token[0][0] == EOF:
        return
    line()
    lines()
    return

def start():
    lines()
    token = get_token()
    if token[0][0] == EOF: return True
    return False

print(start())

下面说一下这个代码的思路
1. 先写出这个语言(表达式)的文法
start: lines (EOF);

lines: (EMPTY)
     | line lines
     ;

line: expression '\n' {print(expression);}
    | '\n'
    | (ERROR) {printf("错误的表达式!\n");}
    ;

expression: term
          | expression '+' term {$$ = $1 + $3;}
          | expression '-' term {$$ = $1 - $3;}
          ;

term: factor
    | term '*' factor {$$ = $1 * $3;}
    | term '/' factor {$$ = $1 / $3;}
    ;

factor: NUM
      | '-' factor {$$ = -$2;}
      | '(' expression ')' {$$ = $2;}
      ;
2. 用递归下降分析,照着这个文法写代码
3. 调试,其实应该是边写代码边调试,写一点调试一点
微信图片_20220523221327.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-6-3 14:46:20 | 显示全部楼层    本楼为最佳答案   
来晚了,前段时间有点忙

看不懂你那个图片是怎么表示二叉树的
下面这个代码创建出了这颗树,你想要怎么输出就自己写代码吧
#!/usr/bin/env python
#coding=utf-8

from ctypes import cdll
from ctypes.util import find_library
from ctypes import c_void_p, c_int, byref
import sys

libc = cdll.LoadLibrary(find_library('c'))
stdin = c_void_p.in_dll(libc, 'stdin')

def fgetc(stream):
    return libc.fgetc(stream)

def ungetc(ch, stream):
    return libc.ungetc(ch, stream)

# token
# [[symbol, value], lchild, rchild]
last_token = None

ERROR = 256
NUM = 257
EOF = -1

def error(value):
    return [[ERROR, value], None, None]

def isdigit(ch):
    return ch >= ord('0') and ch <= ord('9')

def get_token():
    global last_token
    if last_token:
        result = last_token
        last_token = None
        return result
    ch = fgetc(stdin)
    if ch in [ord(i) for i in [' ', '\t', '\v', '\f']]:
        return get_token()
    if isdigit(ch):
        ungetc(ch, stdin)
        num = c_int()
        libc.fscanf(stdin, b'%d', byref(num))
        return [[NUM, num.value], None, None]
    return [[ch, None], None, None]

def unget_token(token):
    global last_token
    last_token = token

def factor():
    token = get_token()
    if token[0][0] == NUM: return token
    if token[0][0] == ord('-'):
        token[1] = factor()
        if token[1][0][0] == ERROR: return token[1]
        return token
    if token[0][0] != ord('('): return error(token[0][1])
    token = expression()
    if token[0][0] == ERROR: return token
    temp = token
    token = get_token()
    if token[0][0] != ord(')'): return error(token[0][1])
    return temp

def term():
    token = factor()
    if token[0][0] == ERROR: return token
    a = token
    token = get_token()
    if token[0][0] != ord('*') and token[0][0] != ord('/'):
        unget_token(token)
        return a
    op = token
    token = term()
    if token[0][0] == ERROR: return token
    b = token
    op[1] = a
    op[2] = b
    return op

def expression():
    token = term()
    if token[0][0] == ERROR: return token
    a = token
    token = get_token()
    if token[0][0] != ord('+') and token[0][0] != ord('-'):
        unget_token(token)
        return a
    op = token
    token = expression()
    if token[0][0] == ERROR: return token
    b = token
    op[1] = a
    op[2] = b
    return op

def do_error():
    print('错误的表达式!', file = sys.stderr)
    while True:
        token = get_token()
        if token[0][0] == ord('\n'): break

def val(tree):
    if tree[0][0] == NUM: return tree[0][1]
    if tree[0][0] == ord('+'): return val(tree[1]) + val(tree[2])
    if tree[0][0] == ord('*'): return val(tree[1]) * val(tree[2])
    if tree[0][0] == ord('/'): return val(tree[1]) / val(tree[2])
    if tree[0][0] == ord('-'):
        return -val(tree[1]) if tree[2] == None else val(tree[1]) - val(tree[2])
    raise "未知的运算符!"

def line():
    token = get_token()
    if token[0][0] == ord('\n'): return
    unget_token(token)
    token = expression()
    if token[0][0] == ERROR:
        do_error()
        return
    result = token
    token = get_token()
    if token[0][0] == ord('\n'):
        #print(result)
        print('>>> ' + str(val(result)))
        return
    do_error()

def lines():
    token = get_token()
    unget_token(token)
    if token[0][0] == EOF:
        return
    line()
    lines()
    return

def start():
    lines()
    token = get_token()
    if token[0][0] == EOF: return True
    return False

print(start())

下面说一下这个代码的思路
1. 先写出这个语言(表达式)的文法
start: lines (EOF);

lines: (EMPTY)
     | line lines
     ;

line: expression '\n' {print(expression);}
    | '\n'
    | (ERROR) {printf("错误的表达式!\n");}
    ;

expression: term
          | expression '+' term {$$ = $1 + $3;}
          | expression '-' term {$$ = $1 - $3;}
          ;

term: factor
    | term '*' factor {$$ = $1 * $3;}
    | term '/' factor {$$ = $1 / $3;}
    ;

factor: NUM
      | '-' factor {$$ = -$2;}
      | '(' expression ')' {$$ = $2;}
      ;
2. 用递归下降分析,照着这个文法写代码
3. 调试,其实应该是边写代码边调试,写一点调试一点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-27 09:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表