linux c++头文件生成源文件 使用python脚本 配置vim快捷键

在编写c++头文件后,还需要再.cpp文件里面复制一份非常的麻烦

找过了不少方法都很难实现

提供了一个python脚本帮助你实现这个过程

python 复制代码
#!/usr/bin/env python3
import re
import sys

def process_class(content):
    """Extract and process the next class in the content, returning function definitions and remaining content."""
    # Enhanced regex to match class definitions with virtual and multiple inheritance
    class_match = re.search(r'class\s+(\w+)(?:\s*:\s*(?:virtual\s+)?(?:public\s+)?\w+(?:\s*,\s*(?:virtual\s+)?(?:public\s+)?\w+)*)?', content)
    if not class_match:
        return None, content
    class_name = class_match.group(1)
    # Find the start of the class definition, including the opening brace
    class_start = re.search(rf'class\s+{class_name}\s*(?::\s*(?:virtual\s+)?(?:public\s+)?\w+(?:\s*,\s*(?:virtual\s+)?(?:public\s+)?\w+)*)?\s*{{', content)
    if not class_start:
        print(f"Error: Could not find class definition start for {class_name}")
        return None, content
    start_pos = class_start.end() - 1  # Position right before the opening brace
    brace_count = 1
    i = start_pos + 1
    while i < len(content) and brace_count > 0:
        if content[i] == '{':
            brace_count += 1
        elif content[i] == '}':
            brace_count -= 1
        i += 1
    if brace_count != 0:
        print(f"Error: Mismatched braces in class {class_name}")
        return None, content
    class_content = content[start_pos:i]
    remaining_content = content[i:]
    # Remove access modifiers
    class_content = re.sub(r'^\s*(public|private|protected):\s*', '', class_content, flags=re.MULTILINE)
    # Find function declarations (excluding constructors and destructors)
    func_pattern = r'(friend\s+)?([\w:&<>]+\s*[\*&]?\s*)?(operator[\w<>=!+\-*]+)?\s*(\w+)?\s*\(([^)]*)\)\s*(const)?\s*(?!=)\s*;'
    functions = re.findall(func_pattern, class_content, re.MULTILINE)
    definitions = []
    for func in functions:
        friend, return_type, op_name, func_name, params, const = func
        if not func_name and not op_name:
            continue  # Skip if no function name or operator
        # Skip constructors and destructors
        if func_name == class_name or (func_name and func_name.startswith('~')):
            continue
        # Clean params: remove default values
        cleaned_params = []
        for p in params.split(','):
            p = p.strip()
            if p:
                p = re.sub(r'\s*=\s*[^,)]+', '', p)
                cleaned_params.append(p)
        params = ', '.join(cleaned_params)
        # Clean return_type
        return_type = return_type.strip() if return_type else ''
        if not friend and return_type:
            while return_type.startswith(('static ', 'virtual ', 'explicit ')):
                return_type = return_type.split(' ', 1)[1].strip()
        const = ' const' if const else ''
        if op_name:
            func_name = f'operator{op_name[len("operator"):]}'
        if friend:
            func_def = f"{return_type} {func_name}({params}){const} {{\n    // TODO: Implement\n}}\n"
        else:
            func_def = f"{return_type} {class_name}::{func_name}({params}){const} {{\n    // TODO: Implement\n}}\n"
        definitions.append(func_def)
    return definitions, remaining_content

def process_global_functions(content):
    """Extract and generate definitions for global functions without bodies."""
    global_func_pattern = r'^\s*(?!class|struct)(\w+\s+)+(\w+)(\s*\([^;]*\))\s*;'
    matches = re.finditer(global_func_pattern, content, re.MULTILINE)
    definitions = []
    for match in matches:
        return_type = match.group(1).strip()
        func_name = match.group(2).strip()
        params = match.group(3).strip()
        cleaned_params = []
        for p in params[1:-1].split(','):
            p = p.strip()
            if p:
                p = re.sub(r'\s*=\s*[^,)]+', '', p)
                cleaned_params.append(p)
        params = ', '.join(cleaned_params)
        func_def = f"{return_type} {func_name}({params}) {{\n    // TODO: Implement\n}}\n"
        definitions.append(func_def)
    return definitions

def process_header(input_file, output_file):
    """Process the header file and generate the corresponding .cpp file."""
    try:
        with open(input_file, 'r', encoding='utf-8') as f:
            content = f.read()
    except Exception as e:
        print(f"Error: Could not read file {input_file}: {e}")
        sys.exit(1)
    function_definitions = []
    while True:
        defs, content = process_class(content)
        if defs is None:
            break
        function_definitions.extend(defs)
    global_defs = process_global_functions(content)
    function_definitions.extend(global_defs)
    try:
        output = [f'#include "{input_file}"\n\n'] + function_definitions
        with open(output_file, 'w', encoding='utf-8') as f:
            f.writelines(output)
        print(f"Successfully generated {output_file}!")
    except Exception as e:
        print(f"Error: Could not write to file {output_file}: {e}")
        sys.exit(1)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Usage: python3 script.py input.h [output.cpp]")
        sys.exit(1)
    input_path = sys.argv[1]
    output_path = sys.argv[2] if len(sys.argv) >= 3 else input_path.replace('.h', '.cpp')
    process_header(input_path, output_path)

这个脚本接收两个参数,第一个是你的头文件,第二个是输出的地址,可以不提供第二个地址,则默认以cpp结尾存储再当前目录

全局脚本调用

~/.local/bin 是用户专属的可执行文件目录,推荐用于全局调用。

查看是否存在,不存在则手动创建一下

python 复制代码
mkdir -p ~/.local/bin

然后把python脚本放到这个目录下

注意看一下是否有执行权限

没有的话添加一下

python 复制代码
chmod +x ~/.local/bin/generate_cpp.py

然后需要配置环境变量

查看当前环境

python 复制代码
echo $PATH

查看这个目录是否在环境下

不在的话我们添加一下

python 复制代码
vim ~/.bashrc

把下面这个添加到最后一行

python 复制代码
export PATH="$HOME/.local/bin:$PATH"

再重启一下

python 复制代码
source ~/.bashrc

你就可以看到了

然后我们就能全局调用这个脚本

测试示例

cpp 复制代码
#pragma once
#include <iostream>

class Stonewt
{
public:
    enum Mode { STONE, POUND, INT };

private:
    enum { Lbs_per_stn = 14 };
    int stone;
    double pds_left;
    double pounds;
    Mode mode;

public:
    Stonewt(double lbs, Mode form = STONE);
    Stonewt(int stn, double lbs, Mode form = STONE);
    Stonewt()
    {
        stone = pounds = pds_left = 0;
        mode = STONE;
    }
    void stoneMode() { mode = STONE; }
    void poundMode() { mode = POUND; }
    void intMode() { mode = INT; }
    ~Stonewt(){};
    bool operator<(const Stonewt &s);
    bool operator>(const Stonewt &s);
    bool operator<=(const Stonewt &s);
    bool operator>=(const Stonewt &s);
    bool operator==(const Stonewt &s);
    bool operator!=(const Stonewt &s);
    Stonewt operator+(const Stonewt &s);
    Stonewt operator-(const Stonewt &s);
    Stonewt operator-();
    friend Stonewt operator*(const Stonewt &s1, const Stonewt &s2);
    friend std::ostream &operator<<(std::ostream &os, const Stonewt &);
    friend std::istream &operator>>(std::istream &os, Stonewt &);
};
class test:Stonewt{
public:
    void fun1();
    virtual void fun2() const;
    static void fun3();
};
void show(const Stonewt & st);
void func();

测试示例来自c++Primerplus编程练习第11章第6题

这是生成的stonewt.cpp文件

cpp 复制代码
#include "stonewt.h"

✹  Stonewt::Stonewt(double lbs, Mode form) {

  }
✹  Stonewt::Stonewt(int stn, double lbs, Mode form) {

  }
✹ bool Stonewt::operator<(const Stonewt &s) {
     
✹ }
✹ bool Stonewt::operator>(const Stonewt &s) {

✹ }
✹ bool Stonewt::operator<=(const Stonewt &s) {

✹ }
✹ bool Stonewt::operator>=(const Stonewt &s) {

✹ }
✹ bool Stonewt::operator==(const Stonewt &s) {

✹ }
✹ bool Stonewt::operator!=(const Stonewt &s) {

✹ }
✹ Stonewt Stonewt::operator+(const Stonewt &s) {

✹ }
✹ Stonewt Stonewt::operator-(const Stonewt &s) {

✹ }
  Stonewt Stonewt::operator-() {

✹ }
✹ Stonewt operator*(const Stonewt &s1, const Stonewt &s2) {

✹ }
✹ std::ostream & operator<<(std::ostream &os, const Stonewt &) {

✹ }
✹ std::istream & operator>>(std::istream &os, Stonewt &) {

✹ }
  void test::fun1() {

  }
  void test::fun2() const {

  }
  void test::fun3() {

  }
✹ void show(const Stonewt & st) {

  }
  void func() {

  }
                                                               

这些是vim的提示,实际上没有

vim中调用

注意要完成前面的全局配置

推荐安装vimplus,可以参考这里

cpp 复制代码
:!generate_cpp.py % %.cpp 

可以直接用这个调用,可以省略%.cpp

配置快捷键

添加我们自己的配置

cpp 复制代码
 vim ~/.vimrc.custom.config 

在其中添加这样的内容,你就可以使用,cpp来生成源文件了

cpp 复制代码
function! GenerateCpp()
    write
    let output = system('generate_cpp.py ' . expand('%') . ' ' . expand('%:r') . '.cpp')
    if v:shell_error
        copen
        caddexpr output
        echo "Error generating " . expand('%:r') . ".cpp"
    else
        echo "Generated " . expand('%:r') . ".cpp successfully!"
    endif
endfunction

autocmd FileType cpp,h nnoremap <silent> <leader>cpp :call GenerateCpp()<CR>  
相关推荐
阳光_你好32 分钟前
简单介绍C++中线性代数运算库Eigen
开发语言·c++·线性代数
ShineSpark1 小时前
C++面试3——const关键字的核心概念、典型场景和易错陷阱
c++·算法·面试
爱吃涮毛肚的肥肥(暂时吃不了版)4 小时前
仿腾讯会议——音频服务器部分
c++·qt·面试·职场和发展·音视频·腾讯会议
未来可期叶4 小时前
如何用Python批量解压ZIP文件?快速解决方案
python
张槊哲4 小时前
ROS2架构介绍
python·架构
DpHard4 小时前
自用Vscode 配置c++ debug环境
c++·ide·vscode
一人一萧十只猫�4 小时前
Linux SSH 远程连接全攻略:从加密原理到实战配置(含图解)
linux·服务器·网络
人间不清醒ab4 小时前
Ubuntu ping网络没有问题,但是浏览器无法访问到网络
linux·运维·ubuntu
babytiger5 小时前
为 Windows 和 Ubuntu 中设定代理服务器的详细方法
linux·windows·ubuntu
风逸hhh5 小时前
python打卡day29@浙大疏锦行
开发语言·前端·python