2016-09-15 134 views
1

有沒有一種方便的方法來解析c + +中的string::iterator的整數?對於這個特定的問題,我只關心非負整數,但所有這些解決方案都可以很容易地擴展爲任意整數。請注意,與similar questions不同,我沒有對原始字符串的引用,只有一個迭代器,例如C++從字符串指針解析int

int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
    // ... 
} 

我可以想到很多方法,但沒有一個很棒。另外需要注意的是,我沒有聲明stl頭文件,而且我假定一切都在std命名空間中完成。希望這不會讓這些例子太難以解析。

  1. 分配一個新的字符串,然後調用Stoi旅館:

    int parse_next_int(string::iterator begin, string::iterator end) { 
         string::iterator num_end = find_if(
          begin, end, [](char c)->bool{return !isdigit(c);}); 
         string to_parse(begin, num_end); 
         return stoi(to_parse); 
    } 
    

    這樣做的缺點是,我最終的東西,大概可以被動態解析分配一個新的緩衝區。

  2. 不安全地視爲c字符串。

    int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
        return atoi(&(*begin)); 
    } 
    

    這將一定程度上工作,但如果它擊中了字符串的結尾,它不是沒有空值終止的(這是不符合C++字符串的保證),它會段錯誤,所以雖然漂亮,簡潔,這可能是最不好。

  3. 寫自己:

    int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
         int result = 0; 
         while (begin != end && isdigit(*begin)) { 
          result = result * 10 + (*begin++ - '0'); 
         } 
         return result; 
    } 
    

    這工作是簡單的,但它也嚴重依賴的問題,而不是非常容錯。

有一些主要依靠更加寬容STL電話,同時仍然簡單,避免不必要的複製緩衝區顯著不同的方法?

+2

只是間接通過迭代器,你得到的字符串。然後你可以使用任何你會使用的方法,如果你有字符串。 – Barmar

+0

'strtol'比'atoi'更可取。 (但都有問題,你不能限制他們'結束')。你的選項3會導致一些輸入的未定義行爲(與atoi相同的問題) –

回答

3

如果你有機會來提高你可以使用:

int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
    return boost::lexical_cast<int>(&(*begin), std::distance(begin, end)); 
} 
+0

我不是很傾向於單獨使用boost,但是從我可以收集的信息看來,這個調用似乎避免了爲整型類型分配stringstream,所以這看起來像是一個有效的答案。我仍然在更多地考慮實施。 – Erik

1
  1. 從迭代器創建std::string
  2. string創建一個std::istringstream
  3. istringstream中提取整數。

int parse_next_int(std::string::iterator begin, std::string::iterator end) { 
    std::string s(begin, end); 
    std::istringstream str(s); 
    int i; 
    str >> i; 
    return i; 
} 

PS添加錯誤處理代碼,使其生產價值。

+0

是的,我想到了這一點,但這與「stoi」選項沒有什麼不同,你也可以一直複製到最後,很貴。你提到一個更好的方法來做字符串複製,但我會更新問題來反映。 – Erik

+0

@Erik,'stoi'也應該有效。我對這兩種方法之間的低水平差異沒有感覺。 –

0

注意,由於C++ 11,std::string小號保證是空值終止,所以您提領和治療,如-aC-string解決方案根本不是不安全的;並且在解釋發生了什麼的評論時,我會投票選出解決這個問題的最佳解決方案。

+0

[null只是另一個字符](http://stackoverflow.com/questions/11752705/does-string-contain-null-terminator) – wally

1

不要使用atoi,如果數字超過INT_MAX,會導致未定義的行爲。你的選擇3有同樣的問題。

我的建議是:

  1. 查找數結束時,使用find_ifstrchr或任何其他方法;如果您願意,可以領先-+
  2. 空終止子字符串
  3. 使用strtol轉換,用代碼來處理所有的溢出情況。

關於空終止,您可以選擇下列之一:

  • 複製到自動陣列(最簡單的選項)。
  • 如果end實際上並不是字符串的末尾,那麼在那裏寫一個臨時的空終止符,然後恢復舊的字符。