python 动态生成多个变量(例子:self.createVar = locals();)

本文介绍了一种使用Python实现多个复选框的方法,通过遍历创建12个复选框,并利用字典存储这些复选框,以便于后续获取被选择的复选框的标题。此外,还讲解了如何在用户点击提交按钮后,收集并打印所有被选中复选框的标题。
12个复选框
self.createVar = locals(); 为了生成多个变量
for i in range(12)):
    k='p' + str(i);
    这样用的:self.createVar为字典
    self.createVar[k]=QCheckBox('节点'+str(i+1), self);
    self.createVar[k].stateChanged.connect(self.stateClicked)
    self.QHBox_whole.addWidget(self.createVar[k]);
提交按钮
self.ps=[];

以下代码取被选择的复选框的标题
self.createVar为字典,第一个不知道为什么是'self'
for i,j in self.createVar.items():
    if i=='self':continue;
    lp=self.createVar[i];
    if lp.isChecked():
        self.ps.append(lp.text())

print(self.ps)
import pygame from pygame.locals import * from itertools import cycle import random import sys # 定义全局变量 SCREENWIDTH = 822 SCREENHEIGHT = 199 FPS = 30 # 初始化pygame pygame.init() FPSCLOCK = pygame.time.Clock() # 创建窗体 SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT)) pygame.display.set_caption('玛丽冒险') # 定义滚动地图类 class MyMap(): def __init__(self, x, y): self.bg = pygame.image.load("image/bg.png").convert_alpha() self.x = x self.y = y # 更新地图图像 def map_update(self): SCREEN.blit(self.bg, (self.x, self.y)) # 地图滚动逻辑 def map_rolling(self): if self.x < -790: self.x = 800 else: self.x -= 5 # 定义玛丽类 class Marie(): def __init__(self): self.rect = pygame.Rect(0, 0, 0, 0) self.jumpState = False # 跳跃状态 self.jumpHeight = 130 # 跳跃最大高度 self.lowest_y = 140 # 地面y坐标 self.jumpValue = 0 # 跳跃速度增量 self.marieIndex = 0 self.marieIndexGen = cycle([0, 1, 2]) # 加载玛丽奔跑帧 self.adventure_img = ( pygame.image.load("image/adventure1.png").convert_alpha(), pygame.image.load("image/adventure2.png").convert_alpha(), pygame.image.load("image/adventure3.png").convert_alpha(), ) # 跳跃音效 self.jump_audio = pygame.mixer.Sound("audio/jump.wav") self.rect.size = self.adventure_img[0].get_size() self.x = 50 self.y = self.lowest_y self.rect.topleft = (self.x, self.y) # 开启跳跃 def jump(self): if self.rect.y >= self.lowest_y: self.jumpState = True self.jump_audio.play() # 处理跳跃移动 def move(self): if self.jumpState: if self.rect.y >= self.lowest_y: self.jumpValue = -5 # 向上 if self.rect.y <= self.lowest_y - self.jumpHeight: self.jumpValue = 5 # 向下 self.rect.y += self.jumpValue if self.rect.y >= self.lowest_y: self.jumpState = False self.rect.y = self.lowest_y # 绘制玛丽 def draw_marie(self): marieIndex = next(self.marieIndexGen) SCREEN.blit(self.adventure_img[marieIndex], (self.x, self.rect.y)) # 定义障碍物类 class Obstacle(): score = 1 # 分数 move = 5 # 移动速度 obstacle_y = 150 def __init__(self): self.rect = pygame.Rect(0, 0, 0, 0) # 加载障碍物图像 self.missile = pygame.image.load("image/missile.png").convert_alpha() self.pipe = pygame.image.load("image/pipe.png").convert_alpha() # 加载数字图像用于计分 self.numbers = tuple(pygame.image.load(f"image/{i}.png").convert_alpha() for i in range(10)) # 加分音效 self.score_audio = pygame.mixer.Sound("audio/score.wav") r = random.randint(0, 1) if r == 0: self.image = self.missile self.move = 15 self.obstacle_y = 100 else: self.image = self.pipe self.obstacle_y = 150 self.rect.size = self.image.get_size() self.width, self.height = self.rect.size self.x = 800 self.y = self.obstacle_y self.rect.center = (self.x, self.y) # 障碍物移动 def obstacle_move(self): self.rect.x -= self.move # 绘制障碍物 def draw_obstacle(self): SCREEN.blit(self.image, (self.rect.x, self.rect.y)) # 获取分数 def getScore(self): tmp = self.score if tmp == 1: self.score_audio.play() self.score = 0 return tmp # 显示分数 def showScore(self, score): scoreDigits = [int(x) for x in str(score)] totalWidth = 0 for digit in scoreDigits: totalWidth += self.numbers[digit].get_width() Xoffset = (SCREENWIDTH - (totalWidth + 30)) for digit in scoreDigits: SCREEN.blit(self.numbers[digit], (Xoffset, SCREENHEIGHT * 0.1)) Xoffset += self.numbers[digit].get_width() # 背景音乐按钮类 class Music_Button(): is_open = True def __init__(self): self.open_img = pygame.image.load("image/btn_open.png").convert_alpha() self.close_img = pygame.image.load("image/btn_close.png").convert_alpha() self.bg_music = pygame.mixer.Sound("audio/bg_music.wav") # 判断鼠标是否在按钮范围内 def is_select(self): point_x, point_y = pygame.mouse.get_pos() w, h = self.open_img.get_size() in_x = 20 < point_x < 20 + w in_y = 20 < point_y < 20 + h return in_x and in_y # 游戏结束函数 def game_over(): bump_audio = pygame.mixer.Sound("audio/bump.wav") bump_audio.play() screen_w = pygame.display.Info().current_w screen_h = pygame.display.Info().current_h over_img = pygame.image.load("image/gameover.png").convert_alpha() SCREEN.blit(over_img, ((screen_w - over_img.get_width()) // 2, (screen_h - over_img.get_height()) // 2)) # 主游戏函数 def mainGame(): score = 0 over = False global SCREEN, FPSCLOCK # 创建地图对象 bg1 = MyMap(0, 0) bg2 = MyMap(800, 0) # 创建玛丽对象 marie = Marie() # 障碍物定时器和列表 addObstacleTimer = 0 list_obstacles = [] # 创建音乐按钮 music_button = Music_Button() btn_img = music_button.open_img music_button.bg_music.play(-1) # 循环播放 while True: # 事件处理 for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit() elif event.type == KEYDOWN and event.key == K_SPACE: if not over: marie.jump() else: # 游戏结束后按空格重启 mainGame() elif event.type == MOUSEBUTTONUP: if music_button.is_select(): if music_button.is_open: btn_img = music_button.close_img music_button.is_open = False music_button.bg_music.stop() else: btn_img = music_button.open_img music_button.is_open = True music_button.bg_music.play(-1) if not over: # 更新地图 bg1.map_update() bg1.map_rolling() bg2.map_update() bg2.map_rolling() # 玛丽移动与绘制 marie.move() marie.draw_marie() # 添加障碍物定时 addObstacleTimer += 20 if addObstacleTimer >= 1300: r = random.randint(0, 100) if r > 40: obstacle = Obstacle() list_obstacles.append(obstacle) addObstacleTimer = 0 # 遍历障碍物 for obstacle in list_obstacles: obstacle.obstacle_move() obstacle.draw_obstacle() # 碰撞检测 if pygame.sprite.collide_rect(marie, obstacle): over = True game_over() music_button.bg_music.stop() else: # 判断是否越过障碍物 if (obstacle.rect.x + obstacle.rect.width) < marie.rect.x: score += obstacle.getScore() obstacle.showScore(score) # 绘制音乐按钮 SCREEN.blit(btn_img, (20, 20)) # 更新屏幕 pygame.display.update() FPSCLOCK.tick(FPS) if __name__ == '__main__': mainGame() 跳跃不成功
09-23
我正在编辑【python】代码,遇到了 【Traceback (most recent call last): File "C:/Users/Alan/Desktop/python源码/blackjack.py", line 303, in <module> main() File "C:/Users/Alan/Desktop/python源码/blackjack.py", line 295, in main game.draw_game(screen) File "C:/Users/Alan/Desktop/python源码/blackjack.py", line 251, in draw_game self.dealer.draw(surface, is_dealer=True) File "C:/Users/Alan/Desktop/python源码/blackjack.py", line 158, in draw card.draw(surface, start_x, y_pos) File "C:/Users/Alan/Desktop/python源码/blackjack.py", line 57, in draw pygame.draw.rect(surface, BLUE, card_rect, border_radius=10) NameError: name 'BLUE' is not defined】 ,请帮我检查并改正错误点。我的原始代码如下: 【import pygame import sys import random import time # 初始化pygame pygame.init() # 颜色定义 GREEN = (0, 128, 0) BLACK = (0, 0, 0) WHITE = (255, 255, 255) RED = (255, 0, 0) GOLD = (255, 215, 0) WOOD = (210, 180, 140) # 游戏参数 WIDTH, HEIGHT = 800, 600 CARD_WIDTH, CARD_HEIGHT = 100, 140 CARD_SPACING = 30 FPS = 30 # 创建游戏窗口 screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("21点游戏 - Python IDLE版") # 时钟控制 clock = pygame.time.Clock() # 字体设置 font_large = pygame.font.SysFont('simhei', 40) font_medium = pygame.font.SysFont('simhei', 30) font_small = pygame.font.SysFont('simhei', 24) # 扑克牌类 class Card: def __init__(self, suit, value): self.suit = suit # 花色: ♠, ♥, ♦, ♣ self.value = value # 点数: A, 2-10, J, Q, K self.face_up = True def get_numeric_value(self): if self.value in ['J', 'Q', 'K']: return 10 elif self.value == 'A': return 11 # 初始值,后面会调整 else: return int(self.value) def draw(self, surface, x, y): # 绘制卡片背景 card_rect = pygame.Rect(x, y, CARD_WIDTH, CARD_HEIGHT) pygame.draw.rect(surface, WHITE, card_rect, border_radius=10) if not self.face_up: # 绘制背面 pygame.draw.rect(surface, BLUE, card_rect, border_radius=10) pygame.draw.rect(surface, GOLD, card_rect, 5, border_radius=10) return # 绘制花色和点数 suit_colors = {'♠': BLACK, '♥': RED, '♦': RED, '♣': BLACK} color = suit_colors[self.suit] # 左上角显示 value_text = font_medium.render(self.value, True, color) suit_text = font_medium.render(self.suit, True, color) surface.blit(value_text, (x + 10, y + 10)) surface.blit(suit_text, (x + 10, y + 40)) # 中央显示大花色 big_suit = font_large.render(self.suit, True, color) surface.blit(big_suit, (x + CARD_WIDTH//2 - 15, y + CARD_HEIGHT//2 - 20)) # 边框 pygame.draw.rect(surface, BLACK, card_rect, 2, border_radius=10) # 扑克牌组 class Deck: def __init__(self): self.cards = [] self.build() def build(self): suits = ['♠', '♥', '♦', '♣'] values = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'] self.cards = [Card(suit, value) for suit in suits for value in values] def shuffle(self): random.shuffle(self.cards) def deal(self): if len(self.cards) > 0: return self.cards.pop() return None # 玩家类 class Player: def __init__(self, name): self.name = name self.hand = [] self.is_dealer = False self.score = 0 self.busted = False self.stand = False def add_card(self, card): self.hand.append(card) self.calculate_score() def calculate_score(self): self.score = 0 aces = 0 # 计算基本分数 for card in self.hand: if card.value == 'A': aces += 1 self.score += card.get_numeric_value() # 调整A的分数 while self.score > 21 and aces > 0: self.score -= 10 # 把A从11变成1 aces -= 1 # 检查是否爆牌 if self.score > 21: self.busted = True def clear_hand(self): self.hand = [] self.score = 0 self.busted = False self.stand = False def draw(self, surface, is_dealer=False): # 绘制玩家名称和分数 color = RED if self.busted else WHITE text = f"{self.name}: {self.score}{' (爆牌)' if self.busted else ''}" text_surface = font_medium.render(text, True, color) if is_dealer: surface.blit(text_surface, (50, 50)) else: surface.blit(text_surface, (50, 350)) # 绘制手牌 start_x = 50 y_pos = 100 if is_dealer else 400 for i, card in enumerate(self.hand): # 庄家第一张牌背面朝上 if is_dealer and i == 0 and not self.stand: card.face_up = False else: card.face_up = True card.draw(surface, start_x, y_pos) start_x += CARD_SPACING + CARD_WIDTH # 游戏主类 class BlackjackGame: def __init__(self): self.deck = Deck() self.player = Player("玩家") self.dealer = Player("庄家") self.dealer.is_dealer = True self.game_state = "betting" # betting, player_turn, dealer_turn, game_over self.message = "按SPACE键开始新游戏" self.winner = None def start_game(self): # 重置游戏状态 self.deck = Deck() self.deck.shuffle() self.player.clear_hand() self.dealer.clear_hand() # 发牌 self.player.add_card(self.deck.deal()) self.dealer.add_card(self.deck.deal()) self.player.add_card(self.deck.deal()) self.dealer.add_card(self.deck.deal()) # 检查玩家21点 if self.player.score == 21: self.game_state = "dealer_turn" self.message = "玩家黑杰克! 庄家回合" else: self.game_state = "player_turn" self.message = "玩家回合: H-要牌, S-停牌" def player_hit(self): if self.game_state == "player_turn" and not self.player.busted and not self.player.stand: self.player.add_card(self.deck.deal()) if self.player.busted: self.message = "玩家爆牌! 按SPACE键继续" self.game_state = "game_over" self.winner = "庄家" elif self.player.score == 21: self.player_stand() def player_stand(self): if self.game_state == "player_turn": self.player.stand = True self.game_state = "dealer_turn" self.dealer_turn() def dealer_turn(self): self.message = "庄家回合..." # 翻开庄家的暗牌 if self.dealer.hand: self.dealer.hand[0].face_up = True self.dealer.calculate_score() # 庄家AI: 小于17点必须要牌 while self.dealer.score < 17: time.sleep(0.5) # 添加延迟使游戏更有节奏感 self.dealer.add_card(self.deck.deal()) self.draw_game() # 更新画面 pygame.display.flip() # 检查结果 if self.dealer.busted: self.message = "庄家爆牌! 玩家胜利" self.winner = "玩家" else: # 比较分数 if self.player.score > self.dealer.score: self.message = "玩家胜利!" self.winner = "玩家" elif self.player.score < self.dealer.score: self.message = "庄家胜利!" self.winner = "庄家" else: self.message = "平局!" self.winner = None self.game_state = "game_over" def draw_game(self, surface): # 绘制背景 surface.fill(GREEN) # 绘制标题 title = font_large.render("21点游戏", True, GOLD) surface.blit(title, (WIDTH//2 - title.get_width()//2, 10)) # 绘制玩家和庄家 self.dealer.draw(surface, is_dealer=True) self.player.draw(surface) # 绘制消息 message_text = font_medium.render(self.message, True, WHITE) surface.blit(message_text, (WIDTH//2 - message_text.get_width()//2, HEIGHT - 100)) # 绘制操作提示 if self.game_state == "player_turn": hint = font_small.render("H - 要牌(Hit) S - 停牌(Stand)", True, WHITE) surface.blit(hint, (WIDTH//2 - hint.get_width()//2, HEIGHT - 50)) elif self.game_state == "game_over": hint = font_small.render("SPACE - 新游戏 ESC - 退出", True, WHITE) surface.blit(hint, (WIDTH//2 - hint.get_width()//2, HEIGHT - 50)) # 绘制胜利信息 if self.winner: win_text = font_large.render(f"{self.winner}胜利!", True, GOLD) surface.blit(win_text, (WIDTH//2 - win_text.get_width()//2, HEIGHT//2 - 50)) # 主游戏循环 def main(): game = BlackjackGame() # 解决IDLE事件循环冲突 pygame.event.set_allowed([pygame.QUIT, pygame.KEYDOWN]) running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: running = False elif event.key == pygame.K_SPACE: if game.game_state == "game_over" or game.game_state == "betting": game.start_game() elif event.key == pygame.K_h and game.game_state == "player_turn": game.player_hit() elif event.key == pygame.K_s and game.game_state == "player_turn": game.player_stand() # 绘制游戏 game.draw_game(screen) pygame.display.flip() clock.tick(FPS) pygame.quit() sys.exit() if __name__ == "__main__": main()】
最新发布
10-15
import pygame import random import math from pygame.locals import * class Particle: def __init__(self, pos, angle, speed, color): self.pos = list(pos) self.angle = angle self.speed = speed * random.uniform(0.8, 1.2) self.color = color self.age = 0 self.lifetime = random.randint(40, 60) self.gravity = 0.5 self.alpha = 255 def update(self): self.pos[0] += math.cos(self.angle) * self.speed self.pos[1] += math.sin(self.angle) * self.speed + self.gravity self.speed *= 0.95 self.age += 1 self.alpha = max(0, 255 - (255 * self.age / self.lifetime)) def draw(self, surface): if self.alpha > 0: size = max(2, int(4 * (1 - self.age/self.lifetime))) pygame.draw.circle(surface, self.color + (self.alpha,), (int(self.pos[0]), int(self.pos[1])), size) class Firework: def __init__(self, screen_width, screen_height): self.particles = [] self.screen_width = screen_width self.screen_height = screen_height hue = random.randint(0, 360) self.color = pygame.Color(0) self.color.hsla = (hue, 100, 50, 100) # 初始发射位置 start_pos = (random.randint(100, screen_width-100), screen_height) for _ in range(200): angle = random.uniform(0, 2*math.pi) speed = random.uniform(2, 8) self.particles.append(Particle(start_pos, angle, speed, self.color)) def update(self): return [p for p in self.particles if p.age < p.lifetime] def main(): pygame.init() WIDTH, HEIGHT = 800, 600 screen = pygame.display.set_mode((WIDTH, HEIGHT)) clock = pygame.time.Clock() fireworks = [] running = True while running: screen.fill((0, 0, 0)) # 随机生成新烟花 if random.random() < 0.05: fireworks.append(Firework(WIDTH, HEIGHT)) 28行有报错,如何
03-15
import re import logging import tkinter as tk from tkinter import scrolledtext, ttk, messagebox from datetime import datetime import traceback class SimpleCLexer: def __init__(self): self.tokens = [] def tokenize(self, input_str): tokens = [] pos = 0 line = 1 column = 0 length = len(input_str) # 定义C语言的关键词和类型 keywords = { 'void', 'int', 'char', 'float', 'double', 'short', 'long', 'signed', 'unsigned', 'struct', 'union', 'enum', 'typedef', 'static', 'extern', 'auto', 'register', 'const', 'volatile', 'return', 'if', 'else', 'switch', 'case', 'default', 'for', 'while', 'do', 'break', 'continue', 'goto', 'sizeof' } # 扩展类型别名识别 types = {'U1', 'U2', 'U4', 'S1', 'S2', 'S4', 'BOOL', 'BYTE', 'WORD', 'DWORD'} while pos < length: char = input_str[pos] # 跳过空白字符 if char in ' \t': pos += 1 column += 1 continue # 处理换行 if char == '\n': line += 1 column = 0 pos += 1 continue # 处理单行注释 if pos + 1 < length and input_str[pos:pos+2] == '//': end = input_str.find('\n', pos) if end == -1: end = length pos = end continue # 处理多行注释 if pos + 1 < length and input_str[pos:pos+2] == '/*': end = input_str.find('*/', pos + 2) if end == -1: end = length else: end += 2 pos = end continue # 处理标识符 if char.isalpha() or char == '_': start = pos pos += 1 while pos < length and (input_str[pos].isalnum() or input_str[pos] == '_'): pos += 1 token_text = input_str[start:pos] token_type = 'IDENTIFIER' # 检查是否为关键字或类型 if token_text in keywords: token_type = 'KEYWORD' elif token_text in types: token_type = 'TYPE' tokens.append({ 'type': token_type, 'text': token_text, 'line': line, 'column': column }) column += (pos - start) continue # 处理数字 if char.isdigit(): start = pos pos += 1 while pos < length and (input_str[pos].isdigit() or input_str[pos] in '.xXabcdefABCDEF'): pos += 1 tokens.append({ 'type': 'NUMBER', 'text': input_str[start:pos], 'line': line, 'column': column }) column += (pos - start) continue # 处理字符串 if char == '"': start = pos pos += 1 while pos < length and input_str[pos] != '"': if input_str[pos] == '\\' and pos + 1 < length: pos += 2 else: pos += 1 if pos < length and input_str[pos] == '"': pos += 1 tokens.append({ 'type': 'STRING', 'text': input_str[start:pos], 'line': line, 'column': column }) column += (pos - start) continue # 处理字符 if char == "'": start = pos pos += 1 while pos < length and input_str[pos] != "'": if input_str[pos] == '\\' and pos + 1 < length: pos += 2 else: pos += 1 if pos < length and input_str[pos] == "'": pos += 1 tokens.append({ 'type': 'CHAR', 'text': input_str[start:pos], 'line': line, 'column': column }) column += (pos - start) continue # 处理运算符和标点符号 operators = { '(', ')', '{', '}', '[', ']', ';', ',', '.', '->', '++', '--', '&', '*', '+', '-', '~', '!', '/', '%', '<<', '>>', '<', '>', '<=', '>=', '==', '!=', '^', '|', '&&', '||', '?', ':', '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '&=', '^=', '|=', ',' } # 尝试匹配最长的运算符 matched = False for op_len in range(3, 0, -1): if pos + op_len <= length and input_str[pos:pos+op_len] in operators: tokens.append({ 'type': 'OPERATOR', 'text': input_str[pos:pos+op_len], 'line': line, 'column': column }) pos += op_len column += op_len matched = True break if matched: continue # 无法识别的字符 tokens.append({ 'type': 'UNKNOWN', 'text': char, 'line': line, 'column': column }) pos += 1 column += 1 return tokens class ImprovedFunctionAnalyzer: def __init__(self): self.function_name = "" self.parameters = [] self.global_vars = [] self.function_calls = [] self.current_function = None self.in_function_body = False self.brace_depth = 0 self.variable_declarations = {} self.macro_definitions = set() self.storage_classes = {"static", "extern", "auto", "register"} self.local_vars = [] self.struct_tags = set() self.recorded_locals = set() self.recorded_globals = set() self.recorded_params = set() self.local_scope_stack = [set()] # 作用域栈 self.basic_types = {'void', 'int', 'char', 'float', 'double', 'short', 'long', 'signed', 'unsigned'} self.type_aliases = {"U1", "U2", "U4", "S1", "S2", "S4", "BOOL", "BYTE", "WORD", "DWORD"} self.allowed_types = self.basic_types | self.type_aliases self.allowed_types.add('struct') def analyze(self, tokens): self.tokens = tokens self.pos = 0 self.current_line = 0 self.brace_depth = 0 self.local_scope_stack = [set()] self._identify_macros() # 第一步:识别函数定义 while self.pos < len(self.tokens): token = self.tokens[self.pos] self.current_line = token['line'] if token['text'] == 'struct' and self.pos + 1 < len(self.tokens): next_token = self.tokens[self.pos + 1] if next_token['type'] == 'IDENTIFIER': self.struct_tags.add(next_token['text']) self.allowed_types.add(next_token['text']) self.pos += 1 if token['text'] in self.storage_classes or token['text'] in self.allowed_types: if self._is_function_definition(): self._handle_function_definition() continue self.pos += 1 # 第二步:识别变量声明和函数调用 self.pos = 0 self.brace_depth = 0 self.in_function_body = False self.local_scope_stack = [set()] while self.pos < len(self.tokens): token = self.tokens[self.pos] self.current_line = token['line'] # 处理作用域开始 if token['text'] == '{': self.brace_depth += 1 self.local_scope_stack.append(set()) if self.current_function and self.brace_depth == 1: self.in_function_body = True # 处理作用域结束 elif token['text'] == '}': self.brace_depth -= 1 if self.brace_depth < 0: self.brace_depth = 0 if self.local_scope_stack: self.local_scope_stack.pop() if self.brace_depth == 0 and self.current_function: self.current_function = None self.in_function_body = False # 检测变量声明 if token['text'] in self.allowed_types or token['text'] in self.storage_classes: self._handle_variable_declaration() continue # 检测函数调用 if token['type'] == 'IDENTIFIER' and self.pos + 1 < len(self.tokens): next_token = self.tokens[self.pos + 1] if next_token['text'] == '(': self._handle_function_call() continue self.pos += 1 # 第三步:识别全局变量 self._identify_global_vars() return self def _identify_macros(self): for token in self.tokens: if token['type'] == 'IDENTIFIER' and token['text'].isupper(): self.macro_definitions.add(token['text']) def _identify_global_vars(self): self.pos = 0 while self.pos < len(self.tokens): token = self.tokens[self.pos] if token['type'] == 'IDENTIFIER': var_name = token['text'] skip_conditions = ( var_name in self.variable_declarations, var_name in self.macro_definitions, var_name == self.function_name, var_name in self.struct_tags ) if not any(skip_conditions): if var_name not in self.recorded_globals: self.global_vars.append({ 'name': var_name, 'line': token['line'], 'scope': 'global' }) self.recorded_globals.add(var_name) self.variable_declarations[var_name] = True self.pos += 1 def _is_function_definition(self): pos = self.pos storage_class = None # 检测存储类说明符 if self.tokens[pos]['text'] in self.storage_classes: storage_class = self.tokens[pos]['text'] pos += 1 # 检测返回类型 if pos >= len(self.tokens) or self.tokens[pos]['text'] not in self.allowed_types: return False return_type = self.tokens[pos]['text'] pos += 1 # 处理指针声明 if pos < len(self.tokens) and self.tokens[pos]['text'] == '*': return_type += '*' pos += 1 # 检测函数名 if pos < len(self.tokens) and self.tokens[pos]['type'] == 'IDENTIFIER': func_name = self.tokens[pos]['text'] pos += 1 else: return False # 检测参数列表开头的'(' if pos < len(self.tokens) and self.tokens[pos]['text'] == '(': pos += 1 else: return False # 检测函数体开头的'{' (允许最多5个token的间隔) found_brace = False for i in range(min(5, len(self.tokens) - pos)): if self.tokens[pos + i]['text'] == '{': found_brace = True break return found_brace def _handle_function_definition(self): start_pos = self.pos storage_class = None # 处理存储类说明符 if self.tokens[self.pos]['text'] in self.storage_classes: storage_class = self.tokens[self.pos]['text'] self.pos += 1 # 获取返回类型 return_type = self.tokens[self.pos]['text'] self.pos += 1 # 处理指针声明 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': return_type += '*' self.pos += 1 # 获取函数名 if self.pos < len(self.tokens) and self.tokens[self.pos]['type'] == 'IDENTIFIER': func_name = self.tokens[self.pos]['text'] self.pos += 1 else: self.pos = start_pos return # 记录函数名 self.function_name = func_name self.variable_declarations[func_name] = True # 跳过 '(' if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '(': self.pos += 1 # 提取参数 params = [] current_param = [] depth = 1 param_line = self.current_line while self.pos < len(self.tokens) and depth > 0: token = self.tokens[self.pos] if token['text'] == '(': depth += 1 elif token['text'] == ')': depth -= 1 if depth == 0: break elif token['text'] == ',' and depth == 1: # 提取参数类型和名称 param_type, param_name = self._extract_param_info(current_param) if param_type and param_name: params.append({ 'type': param_type, 'name': param_name, 'line': param_line }) self.variable_declarations[param_name] = True current_param = [] param_line = token['line'] self.pos += 1 continue current_param.append(token) self.pos += 1 # 处理最后一个参数 if current_param: param_type, param_name = self._extract_param_info(current_param) if param_type and param_name: params.append({ 'type': param_type, 'name': param_name, 'line': param_line }) self.variable_declarations[param_name] = True # 记录参数 self.parameters = params # 记录参数为参数类型 for param in params: self.recorded_params.add(param['name']) self.variable_declarations[param['name']] = True # 查找函数体开头的'{' while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] != '{': self.pos += 1 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '{': self.in_function = True self.brace_depth = 0 self.pos += 1 self.current_function = func_name return [p['name'] for p in params] if params else [] def _extract_param_info(self, tokens): """从参数token列表中提取类型和名称""" param_type = [] param_name = None for token in tokens: if token['type'] in ('KEYWORD', 'TYPE') or token['text'] in self.allowed_types: param_type.append(token['text']) elif token['type'] == 'IDENTIFIER' and not token['text'].isupper(): param_name = token['text'] return ' '.join(param_type), param_name def _handle_variable_declaration(self): start_pos = self.pos current_line = self.current_line # 获取变量类型 var_type = self.tokens[self.pos]['text'] # 处理结构体声明 is_struct = False struct_type = None if var_type == 'struct' and self.pos + 1 < len(self.tokens): is_struct = True self.pos += 1 # 跳过 'struct' # 收集结构体类型名 struct_tokens = [] while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] not in (';', '{', '='): struct_tokens.append(self.tokens[self.pos]) self.pos += 1 if struct_tokens: struct_type = ' '.join(t['text'] for t in struct_tokens) var_type = f"struct {struct_type}" else: var_type = 'struct' # 处理指针声明 while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': var_type += '*' self.pos += 1 var_names = [] # 处理变量名和声明 while self.pos < len(self.tokens): token = self.tokens[self.pos] # 结束声明 if token['text'] == ';': self.pos += 1 break # 标识符 - 变量名 if token['type'] == 'IDENTIFIER' and not token['text'].isupper(): var_name = token['text'] if var_name not in self.macro_definitions: var_names.append(var_name) self.variable_declarations[var_name] = True self.pos += 1 continue # 逗号 - 多个变量声明 elif token['text'] == ',': self.pos += 1 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '*': var_type += '*' self.pos += 1 continue # 数组声明 elif token['text'] == '[': array_dims = [] while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == '[': self.pos += 1 dim = "" while self.pos < len(self.tokens) and self.tokens[self.pos]['text'] != ']': dim += self.tokens[self.pos]['text'] self.pos += 1 if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == ']': self.pos += 1 array_dims.append(dim) for dim in array_dims: var_type += f"[{dim}]" continue # 初始化 elif token['text'] == '=': self.pos += 1 depth = 0 while self.pos < len(self.tokens): t = self.tokens[self.pos] if t['text'] in {'(', '['}: depth += 1 elif t['text'] in {')', ']'}: depth -= 1 elif t['text'] in {',', ';'} and depth == 0: break self.pos += 1 continue self.pos += 1 # 添加到变量列表 for var_name in var_names: if var_name in self.macro_definitions: continue var_info = { 'type': var_type, 'name': var_name, 'line': current_line, 'is_struct': is_struct } # 添加结构体类型信息 if is_struct and struct_type: var_info['struct_type'] = struct_type # 检查是否在参数列表中 is_param = any(param['name'] == var_name for param in self.parameters) # 在函数体内声明的变量视为局部变量 if self.in_function_body and self.brace_depth >= 1 and not is_param: var_info['scope'] = 'local' self.local_vars.append(var_info) self.recorded_locals.add(var_name) # 添加到当前作用域 if self.local_scope_stack: self.local_scope_stack[-1].add(var_name) else: # 否则视为全局变量 var_info['scope'] = 'global' self.global_vars.append(var_info) self.recorded_globals.add(var_name) def _handle_function_call(self): # 提取函数名 func_name = self.tokens[self.pos]['text'] line = self.current_line # 跳过函数名和 '(' self.pos += 2 # 提取参数 params = [] current_param = [] depth = 1 param_line = line while self.pos < len(self.tokens) and depth > 0: token = self.tokens[self.pos] if token['text'] == '(': depth += 1 elif token['text'] == ')': depth -= 1 if depth == 0: break elif token['text'] == ',' and depth == 1: # 提取参数表达式 param_text = ''.join([t['text'] for t in current_param]).strip() params.append(param_text) current_param = [] param_line = token['line'] self.pos += 1 continue current_param.append(token) self.pos += 1 if current_param: param_text = ''.join([t['text'] for t in current_param]).strip() params.append(param_text) # 跳过 ')' if self.pos < len(self.tokens) and self.tokens[self.pos]['text'] == ')': self.pos += 1 # 确定返回类型 return_type = "unknown" if func_name.startswith("vd_"): return_type = "void" elif func_name.startswith(("u1_", "u2_", "u4_", "s1_", "s2_", "s4_")): prefix = func_name.split("_")[0] return_type = prefix.upper() # 添加到函数调用列表 self.function_calls.append({ 'name': func_name, 'return_type': return_type, 'params': ", ".join(params), 'line': line }) class FunctionParserApp: def __init__(self, root): self.root = root self.root.title("C语言函数解析器") self.root.geometry("1000x800") self.root.configure(bg="#f0f0f0") self.setup_logging() # 创建样式 style = ttk.Style() style.configure("TFrame", background="#f0f0f0") style.configure("TLabelFrame", background="#f0f0f0", font=("Arial", 10, "bold")) style.configure("TButton", font=("Arial", 10), padding=5) style.configure("TProgressbar", thickness=10) # 主框架 main_frame = ttk.Frame(root) main_frame.pack(fill="both", expand=True, padx=15, pady=15) # 创建输入区域 input_frame = ttk.LabelFrame(main_frame, text="输入C语言函数体") input_frame.pack(fill="both", expand=True, padx=5, pady=5) self.input_text = scrolledtext.ScrolledText(input_frame, width=100, height=15, font=("Consolas", 11), bg="#ffffff") self.input_text.pack(fill="both", expand=True, padx=10, pady=10) # 按钮区域 btn_frame = ttk.Frame(main_frame) btn_frame.pack(fill="x", padx=5, pady=5) # 解析按钮 parse_btn = ttk.Button(btn_frame, text="解析函数", command=self.parse_function) parse_btn.pack(side="left", padx=5) # 进度条 self.progress = ttk.Progressbar(btn_frame, orient="horizontal", length=300, mode="determinate") self.progress.pack(side="left", padx=10, fill="x", expand=True) # 示例按钮 example_btn = ttk.Button(btn_frame, text="加载示例", command=self.load_example) example_btn.pack(side="right", padx=5) # 创建输出区域 output_frame = ttk.LabelFrame(main_frame, text="解析结果") output_frame.pack(fill="both", expand=True, padx=5, pady=5) self.output_text = scrolledtext.ScrolledText(output_frame, width=100, height=15, font=("Consolas", 11), bg="#ffffff") self.output_text.pack(fill="both", expand=True, padx=10, pady=10) self.output_text.config(state=tk.DISABLED) # 日志区域 log_frame = ttk.LabelFrame(main_frame, text="日志信息") log_frame.pack(fill="both", expand=True, padx=5, pady=5) self.log_text = scrolledtext.ScrolledText(log_frame, width=100, height=6, font=("Consolas", 10), bg="#f8f8f8") self.log_text.pack(fill="both", expand=True, padx=10, pady=10) self.log_text.config(state=tk.DISABLED) # 示例函数体 self.example_code = """static void Diag21_PID_C9(U1 u1_a_num) { U1 u1_t_cmplt; U1 u1_t_cnt; struct SensorData sensor; U2 u2_array[10][20]; if((U1)DIAG_CNT_ZERO == u1_t_swrstcnt) /* Determine if a software reset is in progress */ { for(u1_t_cnt = (U1)DIAG21_ZERO; u1_t_cnt < (U1)DIAG21_PIDC9_FLAG; u1_t_cnt ++) { u1_t_cmplt = u1_g_InspSoftwareVersion(u4_g_cmd, &u4_g_data, (U1)TRUE); } vd_s_Diag21_U2ToU1(u2_g_buf, u1_g_data, (U1)DIAG21_PIDC9_FLAG); } else { /* Do Nothing */ } }""" # 加载示例 self.load_example() def setup_logging(self): """配置日志系统""" self.log_filename = f"parser_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log" # 创建文件处理器 file_handler = logging.FileHandler(self.log_filename, encoding='utf-8') file_handler.setLevel(logging.INFO) file_handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) # 配置根日志器 root_logger = logging.getLogger() root_logger.setLevel(logging.INFO) root_logger.addHandler(file_handler) def log_to_gui(self, message, level="info"): """将日志信息显示在GUI中""" try: self.log_text.config(state=tk.NORMAL) timestamp = datetime.now().strftime("%H:%M:%S") self.log_text.insert(tk.END, f"[{timestamp}] {message}\n") self.log_text.see(tk.END) self.log_text.config(state=tk.DISABLED) if level == "info": logging.info(message) elif level == "warning": logging.warning(message) elif level == "error": logging.error(message) except Exception as e: logging.error(f"GUI日志错误: {str(e)}") def update_progress(self, value): """更新进度条""" self.progress['value'] = value self.root.update_idletasks() def load_example(self): """加载示例函数体""" self.input_text.delete(1.0, tk.END) self.input_text.insert(tk.END, self.example_code) self.log_to_gui("已加载示例函数体") def parse_function(self): try: code = self.input_text.get(1.0, tk.END) if not code.strip(): self.log_to_gui("错误: 没有输入函数体", "error") messagebox.showerror("错误", "请输入要解析的C语言函数体") return self.log_to_gui("开始解析函数体...") self.output_text.config(state=tk.NORMAL) self.output_text.delete(1.0, tk.END) self.update_progress(0) # 使用改进后的词法分析器 self.log_to_gui("执行词法分析...") lexer = SimpleCLexer() tokens = lexer.tokenize(code) self.update_progress(30) # 使用改进后的语法分析器 self.log_to_gui("执行语法分析...") analyzer = ImprovedFunctionAnalyzer() # 使用改进的分析器 analyzer.analyze(tokens) # 显示结果 self.log_to_gui("生成解析报告...") self.display_results( analyzer.local_vars, analyzer.global_vars, analyzer.function_calls, analyzer.function_name, analyzer.parameters ) self.update_progress(100) self.output_text.config(state=tk.DISABLED) self.log_to_gui("解析完成!") messagebox.showinfo("完成", "函数体解析成功完成!") except Exception as e: self.log_to_gui(f"解析错误: {str(e)}", "error") self.log_to_gui(f"错误详情: {traceback.format_exc()}", "error") messagebox.showerror("解析错误", f"发生错误:\n{str(e)}") self.update_progress(0) def display_results(self, local_vars, global_vars, function_calls, func_name, func_params): """增强版结果显示""" # 显示函数签名 self.output_text.insert(tk.END, "=== 函数签名 ===\n", "header") if func_name: self.output_text.insert(tk.END, f"函数名: {func_name}\n") if func_params: param_list = [] for param in func_params: param_list.append(f"{param['type']} {param['name']}") self.output_text.insert(tk.END, f"参数: {', '.join(param_list)}\n\n") else: self.output_text.insert(tk.END, "参数: 无\n\n") else: self.output_text.insert(tk.END, "警告: 无法识别函数签名\n\n") # 显示所有找到的变量 self.output_text.insert(tk.END, "=== 变量分析 ===\n", "header") self.output_text.insert(tk.END, "类型 | 名称 | 作用域 | 行号 | 类别\n", "subheader") self.output_text.insert(tk.END, "-" * 60 + "\n") # 显示参数 for param in func_params: self.output_text.insert(tk.END, f"参数 | {param['name']} | 参数 | {param['line']} | 基本类型\n") # 显示局部变量 for var in local_vars: category = "结构体" if var.get('is_struct', False) else "基本类型" struct_type = var.get('struct_type', '') if struct_type: category = f"结构体({struct_type})" self.output_text.insert(tk.END, f"变量 | {var['name']} | 局部 | {var['line']} | {category}\n") # 显示全局变量 for var in global_vars: category = "结构体" if var.get('is_struct', False) else "基本类型" struct_type = var.get('struct_type', '') if struct_type: category = f"结构体({struct_type})" self.output_text.insert(tk.END, f"变量 | {var['name']} | 全局 | {var['line']} | {category}\n") # 显示函数调用 for func in function_calls: self.output_text.insert(tk.END, f"函数调用 | {func['name']} | 调用 | {func['line']} | 函数\n") self.output_text.insert(tk.END, "\n") # 显示局部变量详情 if local_vars: self.output_text.insert(tk.END, "=== 局部变量详情 ===\n", "header") # 基本类型局部变量 basic_locals = [v for v in local_vars if not v.get('is_struct', False)] if basic_locals: self.output_text.insert(tk.END, "基本类型变量:\n") for var in basic_locals: self.output_text.insert(tk.END, f"{var['type']} {var['name']} (行号: {var['line']})\n") # 结构体局部变量 struct_locals = [v for v in local_vars if v.get('is_struct', False)] if struct_locals: self.output_text.insert(tk.END, "\n结构体变量:\n") for var in struct_locals: struct_type = var.get('struct_type', '未知结构体') self.output_text.insert(tk.END, f"{var['type']} {var['name']} (类型: {struct_type}, 行号: {var['line']})\n") else: self.output_text.insert(tk.END, "未找到局部变量\n\n") # 显示使用的全局变量 if global_vars: self.output_text.insert(tk.END, "=== 使用的全局变量 ===\n", "header") # 基本类型全局变量 basic_globals = [v for v in global_vars if not v.get('is_struct', False)] if basic_globals: self.output_text.insert(tk.END, "基本类型变量:\n") for var in basic_globals: self.output_text.insert(tk.END, f"{var['name']} (行号: {var['line']})\n") # 结构体全局变量 struct_globals = [v for v in global_vars if v.get('is_struct', False)] if struct_globals: self.output_text.insert(tk.END, "\n结构体变量:\n") for var in struct_globals: struct_type = var.get('struct_type', '未知结构体') self.output_text.insert(tk.END, f"{var['name']} (类型: {struct_type}, 行号: {var['line']})\n") self.output_text.insert(tk.END, "\n") else: self.output_text.insert(tk.END, "未使用全局变量\n\n") # 显示函数调用详情 if function_calls: self.output_text.insert(tk.END, "=== 函数调用详情 ===\n", "header") for func in function_calls: self.output_text.insert(tk.END, f"函数名: {func['name']} (行号: {func['line']})\n") self.output_text.insert(tk.END, f"返回类型: {func['return_type']}\n") self.output_text.insert(tk.END, f"参数: {func['params']}\n") self.output_text.insert(tk.END, "-" * 50 + "\n") else: self.output_text.insert(tk.END, "未调用任何函数\n\n") # 添加解析统计 self.output_text.insert(tk.END, "=== 解析统计 ===\n", "header") self.output_text.insert(tk.END, f"参数数量: {len(func_params)}\n") self.output_text.insert(tk.END, f"局部变量数量: {len(local_vars)}\n") self.output_text.insert(tk.END, f"全局变量数量: {len(global_vars)}\n") self.output_text.insert(tk.END, f"函数调用数量: {len(function_calls)}\n") # 结构体统计 struct_locals = [v for v in local_vars if v.get('is_struct', False)] struct_globals = [v for v in global_vars if v.get('is_struct', False)] self.output_text.insert(tk.END, f"结构体变量数量: {len(struct_locals) + len(struct_globals)}\n") self.output_text.insert(tk.END, f"总变量数量: {len(func_params) + len(local_vars) + len(global_vars) + len(function_calls)}\n") # 配置标签样式 self.output_text.tag_config("header", font=("Arial", 12, "bold"), foreground="#2c3e50") self.output_text.tag_config("subheader", font=("Arial", 10, "bold"), foreground="#34495e") if __name__ == "__main__": root = tk.Tk() app = FunctionParserApp(root) root.mainloop() 我希望你能够按照我的要求去解析代码: 1、对于局部变量,一般是在函数体内,找U1的变量声明,并且U1不带括号。带括号U1请不要处理。全大写的是宏定义 2、对于函数名,一般是在第一行,(前面到空格之间的就是函数名 3、对于参数,一般是在第一行的()里面的内容就是参数 4、对于全局变量,就是在函数体内使用的,但是在函数体内没有声明的,去除宏定义,结构体,数组,局部变量,参数的就是全局变量 5、对于结构体,一般是在函数体内.之前的就是结构体名称,并且在函数体内会进行声明 6、对于数组,一般会在结构体内进行声明,且固定有[]的就是数组
07-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值