首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C語言工具:C 風格註解轉 C++ 風格註解轉換器

     編輯:關於C

原始碼處理實戰:/* */ 註解批量轉換為 // 註解

實作一個過濾器程式,讀取 C 原始檔,將所有 /* ... */ 區塊註解轉換為 // 行註解,支援巢狀、混合、空註解等邊界情況。

輸入輸出範例

輸入 (input.c):
/*int i = 0;*/
/*int y = 0;*/int j = 0;
/*int x = 0;/*12345678*/
/*
int h = 0;
int g = 0;
int j = 0;
*/int q = 0;
/**//**/
/* ****** */
// /*1234567890*/

輸出 (output.c):
//int i = 0;


//int y = 0;
int j = 0;
//int x = 0;/*12345678


//
//int h = 0;
//int g = 0;
//int j = 0//
int q = 0;
//


// ******

// /*1234567890*/

狀態機設計

核心採用有限狀態自動機 (FSM),兩種主要狀態:

  • TAG_END (0):不在區塊註解中
  • TAG_BEGIN (1):在區塊註解內部

完整轉換邏輯

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>

typedef enum { FILE_ERROR, FILE_SUCCESS, OTHER_ERROR, NO_MATCH } Status;
typedef enum { TAG_BEGIN, TAG_END } TagState;

Status convert_comments(FILE *in, FILE *out) {
    int ch1, ch2;
    TagState state = TAG_END;
    
    while ((ch1 = fgetc(in)) != EOF) {
        switch (ch1) {
            case '/':
                ch2 = fgetc(in);
                if (ch2 == '*' && state == TAG_END) {
                    // 開始區塊註解 -> 轉為行註解
                    fputc('/', out); fputc('/', out);
                    state = TAG_BEGIN;
                } else if (ch2 == '/') {
                    // 已是行註解,原樣複製
                    fputc('/', out); fputc('/', out);
                    while ((ch2 = fgetc(in)) != EOF && ch2 != '\n')
                        fputc(ch2, out);
                    state = TAG_END;
                } else {
                    fputc('/', out);
                    if (ch2 != EOF) fputc(ch2, out);
                }
                break;
                
            case '*':
                ch2 = fgetc(in);
                if (ch2 == '/' && state == TAG_BEGIN) {
                    // 結束區塊註解
                    fputc(' ', out); // 保留空格避免語法錯誤
                    state = TAG_END;
                } else if (ch2 == '*') {
                    // 註解內的 * 字符
                    fputc('*', out);
                    fseek(in, -1, SEEK_CUR); // 退回一字符
                } else {
                    fputc('*', out);
                    if (ch2 != EOF) fputc(ch2, out);
                }
                break;
                
            case '\n':
                if (state == TAG_BEGIN) {
                    // 區塊註解跨行 -> 每行加 //
                    fputc('\n', out);
                    fputc('/', out); fputc('/', out);
                } else {
                    fputc('\n', out);
                }
                break;
                
            default:
                fputc(ch1, out);
        }
    }
    
    return (state == TAG_END) ? FILE_SUCCESS : NO_MATCH;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "用法: %s <輸入檔> <輸出檔>\n", argv[0]);
        return 1;
    }
    
    FILE *in = fopen(argv[1], "r");
    FILE *out = fopen(argv[2], "w");
    if (!in || !out) {
        perror("檔案開啟失敗");
        return 1;
    }
    
    Status result = convert_comments(in, out);
    fclose(in); fclose(out);
    
    switch (result) {
        case FILE_SUCCESS: puts("轉換成功"); break;
        case FILE_ERROR:   fprintf(stderr, "檔案錯誤: %d\n", errno); break;
        case NO_MATCH:     puts("註解不匹配(未閉合)"); break;
        default:           puts("其他錯誤");
    }
    return 0;
}

狀態轉換表

當前狀態輸入字符動作下一狀態
TAG_END/ *輸出 //TAG_BEGIN
TAG_BEGIN* /輸出空格TAG_END
TAG_BEGIN\n輸出 \n //TAG_BEGIN
TAG_END/ /複製整行TAG_END
任意其他原樣輸出不變

邊界情況處理

  • 空註解:/**/ → //\n//
  • 巢狀註解:C 標準不支援巢狀,內層 /* 視為普通字符
  • 字串字面值:"/* not comment */" 不應轉換(本實作未處理,需加入字串狀態)
  • 行續行符:\ 結尾的註解行需特殊處理

擴展建議

  • 加入字串/字符字面值狀態,避免誤轉換
  • 支援 C++ 原始檔(處理 // 內的 /*)
  • 整合到建構系統作為前處理步驟
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved