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

C++ 遞迴解析檔案副檔名:支援多層擴展名(如 .tar.gz)

     編輯:關於C

需求分析

給定檔案路徑字串,提取**最內層副檔名**(最後一個 `.` 之後的部分)。需支援:

  • 單層:`test.txt` → `txt`
  • 多層:`archive.tar.gz` → `gz`、`video.mp4.bak` → `bak`
  • 無副檔名:`README` → `README`(或空)
  • 隱藏檔:`.bashrc` → `bashrc`(視作無副檔名)

MFC CString 遞迴實作


#include  // MFC 核心,含 CString

// 遞迴取得最內層副檔名
CString GetExtName(CString fileName) {
    int pos = fileName.Find('.'); // 找第一個 '.'
    if (pos == -1) {
        return fileName; // 無 '.',整個字串視為「副檔名」(或按需求回傳空)
    }
    // 找到 '.',遞迴處理其後子串
    return GetExtName(fileName.Mid(pos + 1));
}

執行流程追蹤:`archive.tar.gz`

  1. `Find('.')` → 7 (`archive.`),`Mid(8)` → `tar.gz`
  2. 2. 遞迴 `GetExtName("tar.gz")`:`Find('.')` → 3,`Mid(4)` → `gz` 3. 遞迴 `GetExtName("gz")`:`Find('.')` → -1,回傳 `gz` 4. 層層回傳 → 最終 `gz`

標準 C++ 實作(無 MFC 依賴)


#include 
#include 

// 迭代版:更高效、無棧溢位風險
std::string get_extension(std::string_view filename) {
    size_t pos = filename.rfind('.'); // 找最後一個 '.'
    if (pos == std::string_view::npos || pos == 0) // 無 '.' 或開頭即 '.'
        return std::string(filename); // 或回傳空串 ""
    return std::string(filename.substr(pos + 1));
}

// 遞迴版(教學用)
std::string get_extension_recursive(std::string_view filename) {
    size_t pos = filename.find('.'); // 找第一個 '.'
    if (pos == std::string_view::npos)
        return std::string(filename);
    return get_extension_recursive(filename.substr(pos + 1));
}

關鍵差異:標準庫用 `rfind`(反向查找)一次定位,**遞迴版用 `find` 多次切片**。迭代版 O(n) 單次掃描,遞迴版 O(k·n) 多次掃描(k 為層數)。

主程式測試框架


int main() {
    std::string input;
    while (true) {
        std::cout << "輸入檔名 (空行結束): ";
        if (!std::getline(std::cin, input) || input.empty()) break;

        std::string ext = get_extension(input);
        if (ext == "txt") std::cout << "輸出: txt\n";
        else if (ext == "wmv") std::cout << "輸出: wmv\n";
        else if (ext == "exe") std::cout << "輸出: exe\n";
        else std::cout << "輸出: " << ext << " (未識別類型)\n";
    }
    return 0;
}

測試案例與預期輸出

輸入遞迴/迭代輸出說明
`11.exe``exe`單層
`11.exe.wmv``wmv`雙層,取最內層
`111.exe.wmv.txt``txt`三層
`README``README`無點號,全回傳
`.bashrc``bashrc`隱藏檔,視為無副檔名
`archive.tar.gz``gz`常見壓縮檔
`file.``""` (空串)結尾為點,副檔名為空

遞迴 vs 迭代:效能與安全性對比

維度遞迴版迭代版 (rfind)
時間複雜度O(k·n)O(n)
空間複雜度O(k) 棧幀O(1)
最大層數限制受限於棧大小(通常 >1000 安全)無限制
程式碼簡潔度高(函數式風格)中
生產環境建議❌ 不推薦✅ 推薦

常見邊界情況處理


// 需求:隱藏檔 .bashrc 視為「無副檔名」,回傳空串
std::string get_ext_strict(std::string_view fn) {
    size_t pos = fn.rfind('.');
    if (pos == std::string_view::npos || pos == 0 || pos == fn.size() - 1)
        return ""; // 無點、點在開頭、點在結尾
    return std::string(fn.substr(pos + 1));
}

總結

檔案副檔名解析是字串處理的基礎題。**遞迴寫法**展示了「問題分解為子問題」的思維,適合教學;**迭代 `rfind` 寫法**才是工業級標準——單次掃描、常數空間、無棧溢位風險。實際專案中請直接使用 `` (C++17) 的 `path.extension()`,它已正規化處理所有平台差異與邊界情況。

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