写于 2023 年 3 月 2 日。

需要重复处理的文件过多了,就别 Ctrl C、Ctrl V 了,写点 Python 最合适了。

代码背景

#pragma once#ifndef 都可用于防止头文件被两次编译。

不过 #pragma once 是依托微软编译器來使用,不支持跨平台。

#ifndef 的写法是 C++ 标准支持的,能够跨平台使用。

因此用 #ifndef 來替换掉原先代码中存在的 #pragma once

用用 Python 利器

一般处理多文本文件,我就会分成两块:

  1. 遍历多文件,这里即 traverse_directory,目录遍历文件的代码可复用;
  2. 文件文本处理,这里即 replace_the_marco,文本处理的代码根据需求來做修改;
import os


def replace_the_marco(cur_file_name: str) -> bool:
    flag: bool = False

    basename: str = os.path.basename(cur_file_name)
    file_name: str = basename.split(".")[0].upper()
    suffix: str = basename.split(".")[1].upper()
    macro: str = file_name + "_" + suffix + "_"
    first_sentence: str = "#ifndef " + macro
    second_sentence: str = "#define " + macro
    third_sentence: str = "#endif // " + macro

    lines: list[str] = []

    with open(cur_file_name, mode="r", encoding="utf-8") as file:
        index: int = 0  # 只找前三行
        for line in file:
            temp_item: str = line.strip()

            if index < 3:
                if temp_item == "#pragma once":
                    flag = True

            index = index + 1
            lines.append(line)
        file.close()
    if flag:
        print("\nModify the macro for " + basename + "!\n")
        with open(cur_file_name, mode="w", encoding="utf-8") as file:
            for line in lines:
                if "#pragma once" in line:
                    file.write("%s\n" % first_sentence)
                    file.write("%s\n" % second_sentence)
                else:
                    file.write("%s" % line)

            file.write("\n%s\n" % third_sentence)
            file.close()
    else:
        print("The " + basename + " does not need to be modified!\n")

    return flag


def traverse_directory(cur_dir: str):
    for cur_dir_item in os.listdir(cur_dir):
        cur_path_name: str = cur_dir + "/" + cur_dir_item

        if cur_dir_item[-4:] == ".hpp" or cur_dir_item[-2:] == ".h":
            replace_the_marco(cur_path_name)
        elif os.path.isdir(cur_path_name):
            traverse_directory(cur_path_name)


if __name__ == "__main__":
    folder_absolute_path: str = ""
    traverse_directory(folder_absolute_path)

小坑,遇到一些 Visual Studio 下创建的文件,格式为 ansi,需要转为 utf-8 才可再用上面的脚本处理,分另一个脚本文件处理此过程。这样跑完一个脚本,可以验证一个阶段。

import chardet
import codecs
import os


def ansi_to_utf_8(cur_file_name: str):
    with open(cur_file_name, "rb") as f:
        r = f.read()
    f_charInfo = chardet.detect(r)  # 获取文本编码信息
    charset = f_charInfo["encoding"]
    if charset != "utf-8" and charset != "UTF-8-SIG":
        print(cur_file_name, charset)
        f = codecs.open(cur_file_name, "r", "ansi")
        ff = f.read()
        file_object = codecs.open(cur_file_name, "w", "utf-8")
        file_object.write(ff)


def traverse_directory(cur_dir: str):
    for cur_dir_item in os.listdir(cur_dir):
        cur_path_name: str = cur_dir + "/" + cur_dir_item

        if (
            cur_dir_item[-4:] == ".hpp"
            or cur_dir_item[-2:] == ".h"
            or cur_dir_item[-4:] == ".cpp"
            or cur_dir_item[-2:] == ".c"
        ):
            ansi_to_utf_8(cur_path_name)
        elif os.path.isdir(cur_path_name):
            traverse_directory(cur_path_name)


if __name__ == "__main__":
    folder_absolute_path: str = ""
    traverse_directory(folder_absolute_path)
Last modification:January 9, 2024
兴趣使然