一、简介

扫描C语言文件中第一个结构体,生成结构体初始化和打印结构体出来。

二、使用方法

运行即可

'''
作者:黄宏哲
struct\s+[_a-zA-Z0-9\*]+\s+\{[\s\S]+?\};

# 匹配到第一个括号
struct\s+[_a-zA-Z0-9\*]+\s+\{

# 匹配中间内容
(\s+(char|unsigned char|float|double|long double|signed char|int|unsigned int|short|unsigned short|long|unsigned long)\s+[_a-zA-Z0-9\[\]]+;)+

# 匹配最后一个括号
\s+}\s.*?;

'''
import re
import os
import pyperclip
reference = {"char": "%s",
             "float": "%f",
             "unsigned int": "%u",
             "double": "%lf ",
             "int": "%d",
             }
# path = input("请输入:")
path = "first.c"

if os.path.isfile(path):
    with open(path, encoding="utf-8")as file:
        data = u'%s' % file.read()

pattern = re.compile('''struct\s+([_a-zA-Z0-9\*]+)\s+\{[\s\S]+?\}''')
result = pattern.search(data).group(0)
result = result.strip().replace("\n", "")
struct_name = pattern.search(data).group(1)
left = result.index("{")
right = result.index("}")
args_list = result[left+1:right].split()


def get_struct_print_code() -> str:
    global struct_name
    struct_name_ = struct_name.lower()
    left_, right_ = '', ''
    for index, arg in enumerate(args_list):
        if reference.__contains__(arg):
            left_ += ' %s' % (reference[arg])
            right_ += "," + struct_name_+"." + \
                args_list[index+1].replace("*",
                                           "").replace(";", "").replace("[]", "")
            right_ = re.sub("\[.*?\]", "", right_)

    return 'printf("{0}"{1});'.format(left_, right_)


def define_struct():
    global struct_name
    one = "struct %s %s;\n" % (struct_name, struct_name.lower())

    for index, arg in enumerate(args_list):
        if reference.__contains__(arg):
            right_ = struct_name+"." + \
                args_list[index+1].replace("*",
                                           "").replace(";", "").replace("[]", "")
            right_ = re.sub("\[.*?\]", "", right_)

            if "char" in args_list[index]:
                one += 'strcpy( {}, NULL);\n'.format(right_.lower()+"\n")

            elif "float" in args_list[index]:
                one += right_.lower()+" = 1.0f;\n"

            else:
                one += right_.lower()+" = NULL;\n"
    return one

if __name__=="__main__":
    msg = define_struct()+'\n'+get_struct_print_code()
    pyperclip.copy(msg)
    print("成功复制至剪切板!")
    os.system("pause")

更新,优化版

#  Copyright (c) 2022 黄宏哲 All rights reserved.
#  Email: hongzhe2022@163.com

import re
from os import getcwd
from os import path as Path
from os import walk
from typing import List
from typing import Tuple

import pyperclip


class CodeString:
    def __str__(self) -> str:
        """
        :return: struct_name
        """
        return self.struct_name

    def __init__(self, declaration_struct_variable: str, declaration_struct_member_variable_string: str,
                 print_member_variable_message: str, total_message: str, struct_name: str, struct_variables: List[str],
                 struct_instance: str) -> None:
        """
        :param declaration_struct_variable:                 声明结构体变量语句
        :param declaration_struct_member_variable_string:   声明结构体成员变量语句
        :param print_member_variable_message:               打印结构体成员变量语句
        :param total_message:                               全部代码模板
        :param struct_name:                                 结构体名称
        :param struct_variables:                            结构体变量成员列表
        :param struct_instance:                             结构体初始化变量
        """

        self.declaration_struct_variable, self.declaration_struct_member_variable_string, self. \
            print_member_variable_message, self.total_message, self.struct_name, self.struct_variables, \
        self.struct_instance = declaration_struct_variable, declaration_struct_member_variable_string, \
                               print_member_variable_message, total_message, struct_name, struct_variables, struct_instance

    declaration_struct_variable = str()
    print_member_variable_message = str()
    declaration_struct_member_variable = list()
    total_message = str()

    struct_name = str()
    struct_variables = str()
    struct_instance = str()


class TemplateBase:
    ONE_LINE = '''([a-zA-Z\[\]0-9\(\)\s,\.\=_\"\'\%]+;)'''

    def __init__(self) -> None:
        pass

    def clean(self, string: str) -> str:
        """
        :param string: 输入字符串
        :return: string 字符串
        """
        string = string.strip().replace("\n", "").replace(";", "")
        string = re.sub("\[\d+\]", "", string)
        return string

    def scan(self) -> List[str]:
        """
        :return: 字符串列表
        """
        res = []

        def get_string(path):
            with open(path, encoding='utf-8') as file:
                data = file.read()
            return data

        for root, dirs, files in walk(getcwd(), topdown=False):
            for name in files:
                file_path = Path.join(root, name)
                if "mingw" in file_path:
                    continue
                if name.endswith(".c"):
                    print(file_path)
                    res.append(get_string(file_path))

        return res

    def parser(self, *args) -> any:
        """
        解析器
        """
        raise NotImplementedError

    def string_concat(self, *args) -> CodeString:
        """
        处理字符串
        """

        raise NotImplementedError

    def engine(self) -> CodeString:
        """
        :return: CodeString
        """

        results: List[CodeString] = []
        for s in self.scan():
            string_concat_response = self.string_concat(*self.parser(s))
            results.append(string_concat_response)

        for index, i in enumerate(results):
            print("结构体:[%s] \t%d" % (i, index))

        num = int(input("请输入序号:"))
        pyperclip.copy(results[num].total_message)
        print(results[num].total_message)
        print("\nSuccessful replication!")
        return results[num]


class Generate_c_struct_template(TemplateBase):

    def __init__(self) -> None:
        super().__init__()
        self.reference = {"char": "%s",
                          "float": "%f",
                          "unsigned int": "%u",
                          "double": "%lf ",
                          "int": "%d",
                          }

    def parser(self, struct_string) -> Tuple[str, List[List[str]], str]:
        """

        :param struct_string: 结构体字符串
        :return: 1.struct_name
                 2.struct_variables[struct_variable_type,struct_variable_name]
                 3.struct_instance
        """

        struct_instance = str()
        struct_variables = []
        pattern = re.compile(r'struct\s*?([_a-zA-Z0-9\*]+)\s*?\{[\s\S]+?\}')
        match_result = pattern.search(struct_string)
        if match_result:
            match_result = match_result.group(0)
        else:
            print(struct_string)
            raise ValueError("结构体不存在!:", match_result)
        match_result = match_result.strip().replace("\n", "")
        struct_name = pattern.search(struct_string).group(1)
        left = match_result.index("{")
        right = match_result.index("}")
        args = match_result[left + 1:right].split()

        for index, arg in enumerate(args):
            if self.reference.__contains__(arg):
                struct_variable_type, struct_variable_name = arg, self.clean(args[index + 1])
                struct_variables.append(
                    [struct_variable_type, struct_variable_name])

                struct_instance = struct_name.lower()  # 未完成

        return struct_name, struct_variables, struct_instance

    def string_concat(self, struct_name: str, struct_variables: List[str], struct_instance: str) -> CodeString:
        """
        :param struct_name:
        :param struct_variables:
        :param struct_instance:
        :return: declaration_struct_variable
        :return: declaration_struct_member_variable
        :return: print_member_variable_message
        """

        def clean(string: str):
            string = string.strip().replace("\n", "").replace(";", "")
            string = re.sub("\[\d+\]", "", string)
            return string

        print_variable_list = []
        format_string_list = []
        declaration_struct_member_variable_list = []
        declaration_struct_variable = "struct {0} {1};".format(
            struct_name, struct_instance)
        for struct_variable in struct_variables:
            struct_variable_type, struct_variable_name = struct_variable[0], struct_variable[1]
            struct_variable_type = clean(struct_variable_type)
            struct_variable_name = clean(struct_variable_name)

            if self.reference.__contains__(struct_variable_type):

                format_string = self.reference[struct_variable_type]
                format_string_list.append(format_string)

                if "char" in struct_variable_type:
                    declaration_struct_member_variable = "strcpy({0}.{1}, NULL);".format(
                        struct_instance, struct_variable_name)
                elif "float" in struct_variable_type:
                    declaration_struct_member_variable = "{0}.{1} = 1.0f;".format(
                        struct_instance, struct_variable_name)
                else:
                    declaration_struct_member_variable = "{0}.{1} = NULL;".format(
                        struct_instance, struct_variable_name)
                declaration_struct_member_variable_list.append(
                    declaration_struct_member_variable)

                print_variable_name = "{0}.{1}".format(
                    struct_instance, struct_variable_name)
                print_variable_list.append(print_variable_name)

        print_str_mid = ' "{0}",{1}'.format(
            " ".join(format_string_list), ",".join(print_variable_list))
        print_member_variable_message = "printf(%s);" % print_str_mid

        declaration_struct_member_variable_string = "\n".join(
            declaration_struct_member_variable_list)
        total_message = declaration_struct_variable + "\n" + \
                        declaration_struct_member_variable_string + "\n" + print_member_variable_message
        code_string = CodeString(declaration_struct_variable, declaration_struct_member_variable_string,
                                 print_member_variable_message, total_message, struct_name, struct_variables,
                                 struct_instance)

        return code_string


if __name__ == "__main__":
    Generate_c_struct_template().engine()