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

C語言小專案實戰:C 風格註釋轉 C++ 風格註釋轉換器

     編輯:關於C

專案目標

編寫程式讀取 input.c,將所有 /* ... */ 風格註釋轉換為 // ... 風格,結果寫入 output.c。需正確處理巢狀、換行、連續註釋、字符串字面量等邊界情況。

狀態機設計

採用有限狀態機(FSM)建模,四種狀態:

  • NULL_STATE:普通代碼區
  • C_STATE:處於 /* ... */ 註釋內部
  • CPP_STATE:處於 // ... 註釋內部
  • END_STATE:文件結束

狀態轉移圖(文字版):

NULL_STATE --'/'-> 看下一字符:
    '*' -> 輸出 "//",進入 C_STATE
    '/' -> 輸出 "//",進入 CPP_STATE
    其他 -> 輸出原字符,留在 NULL_STATE
C_STATE -- 讀字符:
    '*' -> 看下一字符:
        '/' -> 註釋結束,輸出換行(如需),進入 NULL_STATE
        '*' -> 輸出 '*',留在 C_STATE
        其他 -> 輸出 '*'+該字符,留在 C_STATE
    '\n' -> 輸出 "\n//",留在 C_STATE
    EOF -> 進入 END_STATE
CPP_STATE -- 讀字符:
    '\n' -> 輸出 '\n',進入 NULL_STATE
    EOF -> 進入 END_STATE
    其他 -> 原樣輸出,留在 CPP_STATE

核心代碼結構

/* comment_covert.h */
#ifndef COMMENT_CONVERT_H
#define COMMENT_CONVERT_H
#include <stdio.h>

typedef enum { NULL_STATE, C_STATE, CPP_STATE, END_STATE } State;

void CommentConvert(FILE *in, FILE *out);
void Do_Null_State(FILE *in, FILE *out);
void Do_C_State(FILE *in, FILE *out);
void Do_CPP_State(FILE *in, FILE *out);

#define READ_FILE  "input.c"
#define WRITE_FILE "output.c"
#endif

/* comment_covert.c */
#include "comment_covert.h"

static State state = NULL_STATE;

void Do_Null_State(FILE *in, FILE *out) {
    int c1 = fgetc(in), c2;
    switch (c1) {
        case '/':
            c2 = fgetc(in);
            if (c2 == '*') { fputc('/',out); fputc('/',out); state = C_STATE; }
            else if (c2 == '/') { fputc('/',out); fputc('/',out); state = CPP_STATE; }
            else { fputc('/',out); fputc(c2,out); }
            break;
        case EOF: state = END_STATE; break;
        default: fputc(c1,out);
    }
}

void Do_C_State(FILE *in, FILE *out) {
    int c1 = fgetc(in), c2, c3;
    switch (c1) {
        case '*':
            c2 = fgetc(in);
            if (c2 == '/') {                 // 註釋結束
                c3 = fgetc(in);
                if (c3 != '\n') fputc('\n',out);
                if (c3 == '/') ungetc(c3,in); // 避免吞掉下一註釋開頭
                fputc(c3,out);
                state = NULL_STATE;
            } else if (c2 == '*') {          // 連續 *
                c3 = fgetc(in);
                fputc('*',out);
                if (c3 == '/') state = NULL_STATE;
            } else { fputc('*',out); fputc(c2,out); }
            break;
        case '\n': fputc('\n',out); fputc('/',out); fputc('/',out); break;
        case EOF: state = END_STATE; break;
        default: fputc(c1,out);
    }
}

void Do_CPP_State(FILE *in, FILE *out) {
    int c = fgetc(in);
    if (c == '\n') { fputc('\n',out); state = NULL_STATE; }
    else if (c == EOF) state = END_STATE;
    else fputc(c,out);
}

void CommentConvert(FILE *in, FILE *out) {
    while (state != END_STATE) {
        switch (state) {
            case NULL_STATE: Do_Null_State(in,out); break;
            case C_STATE:    Do_C_State(in,out);    break;
            case CPP_STATE:  Do_CPP_State(in,out);  break;
        }
    }
}

/* test.c */
#include "comment_covert.h"
#include <stdlib.h>

int main(void) {
    FILE *in = fopen(READ_FILE, "r");
    FILE *out = fopen(WRITE_FILE, "w");
    if (!in || !out) { perror("file open"); return EXIT_FAILURE; }
    puts("***** 註釋轉換開始 *****");
    CommentConvert(in, out);
    puts("***** 註釋轉換結束 *****");
    fclose(in); fclose(out);
    return 0;
}

測試用例覆蓋

輸入片段預期輸出說明
/* comment */// comment\n單行塊註釋
/* line1\nline2 */// line1\n// line2\n多行轉換,每行加 //
code /*cmt*/ morecode // cmt\n more行內塊註釋,結尾換行
/* /* nest */ */// /* nest */\n巢狀註釋,內層 * / 視為普通字符
// /* not a block */// /* not a block */\nC++ 註釋內內容不再解析
"string /* not comment */"原樣輸出字符串字面量保護(本實現未處理,進階可擴展)

擴展方向

  1. 加入字符串/字符字面量狀態,避免誤轉換 "/*"。
  2. 支援命令列參數指定輸入輸出文件。
  3. 輸出轉換統計(行數、註釋數)。
  4. 整合至編輯器外掛或 CI 流水線自動格式化。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved