向前掃描%
,然後從那裏解析內容。有一些古怪的,但不是那麼糟糕(不知道你想把它做成inline
壽)。一般原則(我只是打字,因爲我可能不是最好的代碼形式 - 我沒有試圖編譯它)。
inline void detect(const std::string& str, int& pos, int& n)
{
std::string::size_type last_pos = 0;
for(;;)
{
last_pos = str.find('%', last_pos)
if (last_pos == std::string::npos)
break; // Not found anythin.
if (last_pos == str.length()-1)
break; // Found stray '%' at the end of the string.
char ch = str[last_pos+1];
if (ch == '%') // double percent -> escaped %. Go on for next.
{
last_pos += 2;
continue;
}
pos = last_pos;
do
{
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'')
{
last_pos++;
ch = str[last_pos+1];
}
else
{
// The below string may need appending to depending on version
// of printf.
if (string("AacdeEfFgGiopusxX").find(ch) != std::string::npos)
{
// Do something about invalid string?
}
n = last_pos - pos;
return;
}
} while (last_pos < str.length());
}
}
EDIT2:該位可能是更好的寫法如下:
if (isdigit(ch)) || ch == '.' || ch == '-' || ch == '*' ||
ch == '+' || ch == 'l' || ch == 'L' || ch == 'z' ||
ch == 'h' || ch == 't' || ch == 'j' || ch == ' ' ||
ch == '#' || ch == '\'') ...
if (string(".-*+lLzhtj #'").find(ch) != std::string::npos) ...
現在,那是你完成家庭作業。請回報你得到什麼等級。
編輯:應該指出的是,一些常規printf將「拒絕」的東西被上面的代碼所接受,例如, 「%....... 5 ...... 6f」,「%5.8d」,「%-5-6d」或「%----- 09 --- 5555555555555555llllld」。如果你想要代碼拒絕這些事情,這不是一個額外的工作量,只需要一點邏輯來檢查「我們看過這個字符之前」的「檢查特殊字符或數字」,並且在大多數情況下,只能允許一次特殊字符。正如評論所說,我可能錯過了一些有效的格式說明符。如果你還需要應對「這個''''不允許'c''或這樣的規則,它會變得更加棘手。但是,如果輸入不是「惡意的」(例如,你想註釋在哪一行上有格式說明符在工作的C源文件中),上述應該工作得很好。
爲什麼不只是抓住一個開源的'printf'實現,並將解析器位從其中解壓出來? –
你不需要正則表達式。 printf格式說明符格式可以從左到右一次一個字符地解析。 –
如果您查看完整的['printf()'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html)格式的POSIX規範,則會出現很多可能出現的字符在格式規範中。例如,'%100 $#+ - 0'* 101 $。* 102 $ llX'可能是'有效'的,儘管標誌的某些組合沒有意義。 –