首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 語言 sscanf 靈活解析帶/不帶括號的算術表達式:分步匹配策略

     編輯:程式設計疑難解答

問題場景

需解析字符串提取兩個操作數和運算符,格式可能帶括號 `(-5)+(-6)` 或不帶 `5+6`。單一 `sscanf` 格式串難以兼容兩種格式。

核心方案:預處理統一格式 + 固定格式解析

步驟 1:移除括號 (若存在)

void remove_parentheses(char *str) {
    char *src = str, *dst = str;
    while (*src) {
        if (*src != '(' && *src != ')') {
            *dst++ = *src;
        }
        src++;
    }
    *dst = '\0';
}

// 測試
char expr1[] = "(-5)+(-6)";
char expr2[] = "5+6";
remove_parentheses(expr1); // 變為 "-5+-6" (注意雙符號)
remove_parentheses(expr2); // 保持 "5+6"

注意:`(-5)+(-6)` 移除括號後變為 `-5+-6`,出現連續符號,需進一步規範化或解析器支持負數。

步驟 2:規範化運算符周圍空格 (可選,便於分詞)

// 簡單版:確保運算符前後有空格
void normalize_ops(char *str) {
    // 實現略:遍歷插入空格,處理負數符號不加空格
    // 如 "-5+-6" -> "-5 + -6" 或 "-5 + (-6)" 視解析器而定
}

步驟 3:統一 sscanf 解析

// 假設規範化後為 "操作數 運算符 操作數" 格式,如 "-5 + -6" 或 "5 + 6"
int parse_expression(const char *str, double *a, char *op, double *b) {
    // 格式:%lf 跳過空格讀雙精度, %c 讀運算符(含符號), %lf 讀第二數
    // 注意:%c 不跳過空格,需在格式串加空格 "%lf %c %lf"
    int ret = sscanf(str, "%lf %c %lf", a, op, b);
    return ret == 3; // 成功解析三項
}

// 測試
double n1, n2; char oper;
parse_expression("-5 + -6", &n1, &oper, &n2); // n1=-5, oper='+', n2=-6 成功
parse_expression("5 + 6", &n1, &oper, &n2);   // n1=5, oper='+', n2=6 成功

進階:完整健壯解析器框架

typedef struct {
    double left;
    char op;
    double right;
    bool valid;
} ExprResult;

ExprResult parse_flexible(const char *input) {
    ExprResult res = {0};
    char buf[256];
    strncpy(buf, input, sizeof(buf)-1);
    
    // 1. 移除所有括號
    remove_parentheses(buf);
    
    // 2. 規範化:運算符前後加空格,合併連續符號 (-- -> +, +- -> -)
    normalize_operators(buf); // 需實現符號合併邏輯
    
    // 3. 解析
    if (sscanf(buf, "%lf %c %lf", &res.left, &res.op, &res.right) == 3) {
        res.valid = true;
    }
    return res;
}

替代方案:手寫狀態機解析器 (更靈活、無依賴)

對於計算器類應用,建議直接實現遞歸下降解析器或Shunting-yard 算法 (參考文章 26442),原生支持括號、優先級、負數、函數,比 `sscanf` 組合更清晰、可擴展。

總結

`sscanf` 單一格式串無法同時匹配帶/不帶括號格式。工程上採用 **預處理移除括號 → 規範化運算符格式 → 固定格式 `sscanf` 解析** 三步走策略。長遠看,手寫表達式解析器 (遞歸下降/Shunting-yard) 是更專業、可維護的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved