簡體   English   中英

在C ++字符串中找到第一個printf格式序列

[英]Find the first printf format sequence in a C++ string

我搜索了一種最簡潔有效的方法來查找C ++字符串中的第一個printf格式序列(轉換規范)(我不能使用std::regex因為它們尚未在大多數編譯器中實現)。

因此,問題在於編寫一個優化函數,該printf將從輸入字符串str返回第一個printf格式序列pos的開頭及其長度n

inline void detect(const std::string& str, int& pos, int& n);

例如,用於:

  • %d > pos = 0n = 2
  • the answer is: %05d > pos = 15n = 4
  • the answer is: %% %4.2f haha > pos = 18n = 5

怎么做(歡迎聰明又狡猾的方式)?

向前掃描% ,然后從那里解析內容。 有一些古怪的東西,但是還不錯(不確定您要使其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("0123456789.-*+lLzhtj #'").find(ch) != std::string::npos) ... 

現在,這就是您的作業。 請報告您獲得的年級。

編輯:應該注意的是,上面的代碼接受了常規printf將“拒絕”的某些事情,例如“%....... 5 ...... 6f”,“%5.8d”, “%-5-6d”或“%----- 09 --- 5555555555555555555llllld”。 如果您想讓代碼拒絕此類事情,那么這並不是很多額外的工作,只需要一點點邏輯來檢查“檢查特殊字符或數字”中的“我們以前看過此字符”,然后在大多數情況下,特殊字符只能被允許一次。 正如評論所言,我可能錯過了幾個有效的格式說明符。 如果您還需要處理“'c'不允許使用此'l'”或此類規則,則將變得更加棘手。 但是,如果輸入的內容不是“惡意的”(​​例如,您要注釋有效的C源文件中的哪一行存在格式說明符),則上述內容應該可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM