%03dみたいなファイル名からIDを取り出したい。sscanfを使う場合、「%03d」だと、「0005」など、3桁でない番号を拾えないので、いっそ%dのほうがいい。
#include <iostream> int main() { std::string pattern = "myfile_%d.txt"; std::string fname = "myfile_002010.txt"; int id; sscanf(fname.c_str(), pattern.c_str(), &id); printf("%d\n", id); }
#include <iostream> #include <regex> int main() { std::string pattern = "myfile_(\\d+)\\.txt"; std::regex reg_fname(pattern); std::string fname = "myfile_0001.txt"; std::smatch match; if (std::regex_search(fname, match, reg_fname)) { if (match.size() >= 2) { int id = std::stoi(match[1].str().c_str()); } } }
使う側としては正規表現を知らないと分かりづらいので%dを含んだ文字列を正規表現に変換することを考える。
.や+などの記号をエスケープした後で、%dを\d+に置換する。
#include <iostream> #include <regex>
// 正規表現の特殊文字をエスケープする関数 std::string escapeRegexSpecialCharacters(const std::string& str) { // 正規表現の特殊文字を定義 std::regex special_chars(R"([.^$*+?{}[\]()|\\])"); // 各特殊文字をエスケープシーケンスに置き換える return std::regex_replace(str, special_chars, R"(\$&)"); }
// パターンを正規表現に変換する関数 std::string convertPatternToRegex(const std::string& pattern) { std::string regex_pattern; // この処理により、 // "my+file_%d.txt" → "my\+file_%d\.txt" // のように、特殊文字をエスケープした文字列になる regex_pattern = escapeRegexSpecialCharacters(pattern); // %d または %0xd (例: %05d) を正規表現パターンに置換 // この処理により、 // "my\+file_%d\.txt" → "my\+file_(\d+)\.txt" std::regex d_pattern(R"(%\d*d)"); regex_pattern = std::regex_replace(regex_pattern, d_pattern, R"((\d+))"); return regex_pattern; }
int main() { // ファイル名のパターン std::string pattern = "my+file_%d.txt"; // ファイル名のパターンを正規表現に変換 std::string reg_pattern = convertPatternToRegex(pattern); std::regex regexpattern = std::regex(reg_pattern); // このファイル名から番号を取り出す std::string fname = "my+file_002010.txt"; std::smatch match; if (std::regex_search(fname, match, regexpattern)) { if (match.size() >= 2) { int id = std::stoi(match[1].str().c_str()); std::cout << id << std::endl; } } }