鱼C论坛

 找回密码
 立即注册
查看: 2839|回复: 8

[已解决]问一道递归的题!告诉我思路就好!

[复制链接]
发表于 2022-6-26 11:46:46 | 显示全部楼层 |阅读模式
25鱼币
其实是一道题的两个问题,写一个递归函数
1.input一个“表达式”,计算出他的结果。
2.input一个字符串,判断他是不是“表达式”,如果是则返回0,如果不是则返回第一个错误/多余的字符的位置。
表达式的定义是:<小括号(> <数字> <加减乘(+-*)><数字><小括号)>
例子:(1+(2*2)是表达式,(((2*1)+1)-1)也是。

我想了两个小时也没什么思路555
告诉我思路就好,感激不尽!!!
最佳答案
2022-6-26 11:46:47
1. 你没有说要使用的编程语言,而且把问题发在了 新手乐园 版块
所以我不知道你要求用哪个语言写,看你的问题中出现了 input 这个单词,初步判断是用python
2. python中的这个input函数每一次都会得到一行输入,但是我需要一次得到一个字符,而且有时候还需要把这个字符退回去,用input函数就需要自己写一个字符一个字符读取和退回字符的代码,C语言中有fgetc和ungetc函数,这两个函数就是我想要的,这里就直接调用C语言的这两个函数
3. 我干脆帮你把这两个要求合并一下吧,毕竟两个要求有太多相同的地方
合并成这样
输入一个字符串,如果是“表达式”,那就计算结果然后输出,如果不是“表达式”,那就报告错误

  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from ctypes import cdll
  4. from ctypes.util import find_library
  5. from ctypes import c_void_p, c_int, byref
  6. import sys

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

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

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

  13. # token
  14. # [[symbol, value, rows, cols], lchild, rchild]
  15. last_token = None
  16. file_rows = 1
  17. file_cols = 1

  18. ERROR = 256
  19. NUM = 257
  20. EOF = -1

  21. def error(value):
  22.     return [[ERROR, value[1], value[2], value[3]], None, None]

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

  25. def get_token():
  26.     global last_token
  27.     if last_token:
  28.         result = last_token
  29.         last_token = None
  30.         return result
  31.     global file_cols, file_rows
  32.     last_position = [file_rows, file_cols]
  33.     ch = fgetc(stdin)
  34.     file_cols += 1
  35.     if ch in [ord(i) for i in [' ', '\t', '\v', '\f']]:
  36.         return get_token()
  37.     if isdigit(ch):
  38.         ungetc(ch, stdin)
  39.         file_cols -= 1
  40.         num = c_int()
  41.         libc.fscanf(stdin, b'%d', byref(num))
  42.         file_cols += len(str(num.value))
  43.         return [[NUM, num.value, *last_position], None, None]
  44.     if ch == ord('\n'):
  45.         file_rows += 1
  46.         file_cols = 1
  47.     return [[ch, ch, *last_position], None, None]

  48. def unget_token(token):
  49.     global last_token
  50.     last_token = token

  51. def factor():
  52.     token = get_token()
  53.     if token[0][0] == NUM: return token
  54.     if token[0][0] == ord('-'):
  55.         token[1] = factor()
  56.         if token[1][0][0] == ERROR: return token[1]
  57.         return token
  58.     if token[0][0] != ord('('): return error(token[0])
  59.     token = expression()
  60.     if token[0][0] == ERROR: return token
  61.     temp = token
  62.     token = get_token()
  63.     if token[0][0] != ord(')'): return error(token[0])
  64.     return temp

  65. def term():
  66.     token = factor()
  67.     if token[0][0] == ERROR: return token
  68.     a = token
  69.     token = get_token()
  70.     if token[0][0] != ord('*') and token[0][0] != ord('/'):
  71.         unget_token(token)
  72.         return a
  73.     op = token
  74.     token = term()
  75.     if token[0][0] == ERROR: return token
  76.     b = token
  77.     op[1] = a
  78.     op[2] = b
  79.     return op

  80. def expression():
  81.     token = term()
  82.     if token[0][0] == ERROR: return token
  83.     a = token
  84.     token = get_token()
  85.     if token[0][0] != ord('+') and token[0][0] != ord('-'):
  86.         unget_token(token)
  87.         return a
  88.     op = token
  89.     token = expression()
  90.     if token[0][0] == ERROR: return token
  91.     b = token
  92.     op[1] = a
  93.     op[2] = b
  94.     return op

  95. def do_error(info):
  96.     print('错误的表达式!', file = sys.stderr)
  97.     print(f'(\'{chr(info[1])}\',{info[2],info[3]})', file = sys.stderr)
  98.     while True:
  99.         token = get_token()
  100.         if token[0][0] == ord('\n'): break

  101. def val(tree):
  102.     if tree[0][0] == NUM: return tree[0][1]
  103.     if tree[0][0] == ord('+'): return val(tree[1]) + val(tree[2])
  104.     if tree[0][0] == ord('*'): return val(tree[1]) * val(tree[2])
  105.     if tree[0][0] == ord('/'): return val(tree[1]) / val(tree[2])
  106.     if tree[0][0] == ord('-'):
  107.         return -val(tree[1]) if tree[2] == None else val(tree[1]) - val(tree[2])
  108.     raise "未知的运算符!"

  109. def line():
  110.     token = get_token()
  111.     if token[0][0] == ord('\n'): return
  112.     unget_token(token)
  113.     token = expression()
  114.     if token[0][0] == ERROR:
  115.         do_error(token[0])
  116.         return
  117.     result = token
  118.     token = get_token()
  119.     if token[0][0] == ord('\n'):
  120.         #print(result)
  121.         print('>>> ' + str(val(result)))
  122.         return
  123.     do_error(token[0])

  124. def lines():
  125.     token = get_token()
  126.     unget_token(token)
  127.     if token[0][0] == EOF:
  128.         return
  129.     line()
  130.     lines()
  131.     return

  132. def start():
  133.     lines()
  134.     token = get_token()
  135.     if token[0][0] == EOF: return True
  136.     return False

  137. print(start())
复制代码


参考: https://fishc.com.cn/thread-213764-1-1.html

最佳答案

查看完整内容

1. 你没有说要使用的编程语言,而且把问题发在了 新手乐园 版块 所以我不知道你要求用哪个语言写,看你的问题中出现了 input 这个单词,初步判断是用python 2. python中的这个input函数每一次都会得到一行输入,但是我需要一次得到一个字符,而且有时候还需要把这个字符退回去,用input函数就需要自己写一个字符一个字符读取和退回字符的代码,C语言中有fgetc和ungetc函数,这两个函数就是我想要的,这里就直接调用C语言的这两个 ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 11:46:47 | 显示全部楼层    本楼为最佳答案   
1. 你没有说要使用的编程语言,而且把问题发在了 新手乐园 版块
所以我不知道你要求用哪个语言写,看你的问题中出现了 input 这个单词,初步判断是用python
2. python中的这个input函数每一次都会得到一行输入,但是我需要一次得到一个字符,而且有时候还需要把这个字符退回去,用input函数就需要自己写一个字符一个字符读取和退回字符的代码,C语言中有fgetc和ungetc函数,这两个函数就是我想要的,这里就直接调用C语言的这两个函数
3. 我干脆帮你把这两个要求合并一下吧,毕竟两个要求有太多相同的地方
合并成这样
输入一个字符串,如果是“表达式”,那就计算结果然后输出,如果不是“表达式”,那就报告错误

  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from ctypes import cdll
  4. from ctypes.util import find_library
  5. from ctypes import c_void_p, c_int, byref
  6. import sys

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

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

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

  13. # token
  14. # [[symbol, value, rows, cols], lchild, rchild]
  15. last_token = None
  16. file_rows = 1
  17. file_cols = 1

  18. ERROR = 256
  19. NUM = 257
  20. EOF = -1

  21. def error(value):
  22.     return [[ERROR, value[1], value[2], value[3]], None, None]

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

  25. def get_token():
  26.     global last_token
  27.     if last_token:
  28.         result = last_token
  29.         last_token = None
  30.         return result
  31.     global file_cols, file_rows
  32.     last_position = [file_rows, file_cols]
  33.     ch = fgetc(stdin)
  34.     file_cols += 1
  35.     if ch in [ord(i) for i in [' ', '\t', '\v', '\f']]:
  36.         return get_token()
  37.     if isdigit(ch):
  38.         ungetc(ch, stdin)
  39.         file_cols -= 1
  40.         num = c_int()
  41.         libc.fscanf(stdin, b'%d', byref(num))
  42.         file_cols += len(str(num.value))
  43.         return [[NUM, num.value, *last_position], None, None]
  44.     if ch == ord('\n'):
  45.         file_rows += 1
  46.         file_cols = 1
  47.     return [[ch, ch, *last_position], None, None]

  48. def unget_token(token):
  49.     global last_token
  50.     last_token = token

  51. def factor():
  52.     token = get_token()
  53.     if token[0][0] == NUM: return token
  54.     if token[0][0] == ord('-'):
  55.         token[1] = factor()
  56.         if token[1][0][0] == ERROR: return token[1]
  57.         return token
  58.     if token[0][0] != ord('('): return error(token[0])
  59.     token = expression()
  60.     if token[0][0] == ERROR: return token
  61.     temp = token
  62.     token = get_token()
  63.     if token[0][0] != ord(')'): return error(token[0])
  64.     return temp

  65. def term():
  66.     token = factor()
  67.     if token[0][0] == ERROR: return token
  68.     a = token
  69.     token = get_token()
  70.     if token[0][0] != ord('*') and token[0][0] != ord('/'):
  71.         unget_token(token)
  72.         return a
  73.     op = token
  74.     token = term()
  75.     if token[0][0] == ERROR: return token
  76.     b = token
  77.     op[1] = a
  78.     op[2] = b
  79.     return op

  80. def expression():
  81.     token = term()
  82.     if token[0][0] == ERROR: return token
  83.     a = token
  84.     token = get_token()
  85.     if token[0][0] != ord('+') and token[0][0] != ord('-'):
  86.         unget_token(token)
  87.         return a
  88.     op = token
  89.     token = expression()
  90.     if token[0][0] == ERROR: return token
  91.     b = token
  92.     op[1] = a
  93.     op[2] = b
  94.     return op

  95. def do_error(info):
  96.     print('错误的表达式!', file = sys.stderr)
  97.     print(f'(\'{chr(info[1])}\',{info[2],info[3]})', file = sys.stderr)
  98.     while True:
  99.         token = get_token()
  100.         if token[0][0] == ord('\n'): break

  101. def val(tree):
  102.     if tree[0][0] == NUM: return tree[0][1]
  103.     if tree[0][0] == ord('+'): return val(tree[1]) + val(tree[2])
  104.     if tree[0][0] == ord('*'): return val(tree[1]) * val(tree[2])
  105.     if tree[0][0] == ord('/'): return val(tree[1]) / val(tree[2])
  106.     if tree[0][0] == ord('-'):
  107.         return -val(tree[1]) if tree[2] == None else val(tree[1]) - val(tree[2])
  108.     raise "未知的运算符!"

  109. def line():
  110.     token = get_token()
  111.     if token[0][0] == ord('\n'): return
  112.     unget_token(token)
  113.     token = expression()
  114.     if token[0][0] == ERROR:
  115.         do_error(token[0])
  116.         return
  117.     result = token
  118.     token = get_token()
  119.     if token[0][0] == ord('\n'):
  120.         #print(result)
  121.         print('>>> ' + str(val(result)))
  122.         return
  123.     do_error(token[0])

  124. def lines():
  125.     token = get_token()
  126.     unget_token(token)
  127.     if token[0][0] == EOF:
  128.         return
  129.     line()
  130.     lines()
  131.     return

  132. def start():
  133.     lines()
  134.     token = get_token()
  135.     if token[0][0] == EOF: return True
  136.     return False

  137. print(start())
复制代码


参考: https://fishc.com.cn/thread-213764-1-1.html
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 13:06:17 From FishC Mobile | 显示全部楼层
这东西不是用栈吗
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 13:07:14 | 显示全部楼层
用栈机制来处理括号 小甲鱼有专门讲这个的视频
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 13:22:18 | 显示全部楼层
排程場演算法(或调度场算法)和逆波兰表示法
https://fishc.com.cn/thread-212875-1-1.html
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 14:40:44 | 显示全部楼层
中缀改成后缀(逆波兰)表达式,如果表达式合法再计算
用栈实现
具体见小甲鱼的数据结构和算法篇——栈和队列
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-26 15:51:01 | 显示全部楼层
改一下
  1. print(f'(\'{chr(info[1])}\',{info[2],info[3]})', file = sys.stderr)
  2. print(f'(\'{chr(info[1])}\', {info[2],info[3]})', file = sys.stderr)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-6-27 00:02:33 | 显示全部楼层
感谢楼上的各位老哥,我这就去看视频。最佳答案给帮忙写了代码的老哥啦(虽然其实我用的是c++哈哈哈,不过还是很感谢您!)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-6-27 21:23:41 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-24 04:03

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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