2014-10-06 52 views
0

我在寫一個小程序,將所有出現的正整數轉換爲二進制整數。所以我怎麼寫這個:不能遍歷字符串與迭代器:但是我的版本與索引確實工作

我有一個函數numbersToBinary需要一個字符串和修改它,所以它將包含二進制形式的數字,而不是十進制。

void numbersToBinary(string &src) 
{ 
    for (string::iterator iter = src.begin(); iter != src.end(); iter++) 
    { 
     if (isdigit(*iter)) 
     { 
      string::iterator numberStart = iter++; //numberStart = iter; 
      while ((iter != src.end()) && (isdigit(*iter))) 
      { 
       iter++; 
      } 
      string ins = decimalToBinary(string(numberStart, iter)); 
      src.replace(numberStart, iter, ins); 
     } 
    } 

} 

問題是此函數在用以數字結尾的字符串調用時會在替換方法中捕獲異常。

這裏是一個gist:代碼,你也可以在這裏看到:github。單元測試是可用

MWE:

using namespace std; 

int main() { 
    string example = "String123Primer"; 
    numbersToBinary(example); 
    cout << example << endl; //"String1111011Primer 
    return 0; 
} 

功能,它實際工作:

void numbersToBinary(string &src) 
{ 
    for (int i = 0; i < src.length(); ++i) 
     { 
     if (isdigit(src[i])) 
      { 
       int numberStart = i++; //numberStart = iter; 
       while (src.length() != i && (isdigit(src[i]))) 
       { 
        ++i; 
       } 
       string ins = decimalToBinary(src.substr(numberStart, i-numberStart)); 
       src.replace(numberStart, i-numberStart, ins); 
      } 
     } 

     } 

編輯:我創造了這個功能的新版本:

void numbersToBinary(string &src) { 
    string newString; 
    for (string::iterator iter = src.begin(); iter != src.end(); iter++) { 
     if (isdigit(*iter)) { 
      string::iterator numberStart = iter++; //numberStart = iter; 
      while ((iter != src.end()) && (isdigit(*iter))) { 
       iter++; 
      } 
      string ins = decimalToBinary(string(numberStart, iter)); 
      newString.append(ins); 
     } 
     else 
      newString.push_back(*iter); 

    } 
    src = newString; 
} 

但事實證明,條件(iter!= src.end())永遠不會是假的,即使當我到達字符串末尾時:

Breakpoint 2, numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:58 
    58     newString.append(ins); 
    (gdb) print ins 
    $40 = "1101" 
    (gdb) s 
    51   for (string::iterator iter = src.begin(); iter != src.end(); iter++) { 
    (gdb) print iter 
    $41 = 0 '\000' 
    (gdb) s 
    __gnu_cxx::__normal_iterator<char*, std::string>::operator++ (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:757 
    757   { return __normal_iterator(_M_current++); } 
    (gdb) s 
    __gnu_cxx::__normal_iterator<char*, std::string>::__normal_iterator (this=0x7fffffffd780, [email protected]: 0x6a1a10 "") at /usr/include/c++/4.9.1/bits/stl_iterator.h:729 
    729   : _M_current(__i) { } 
    (gdb) s 
    __gnu_cxx::operator!=<char*, std::string> (__lhs=16 '\020', __rhs=0 '\000') at /usr/include/c++/4.9.1/bits/stl_iterator.h:832 
    832   { return __lhs.base() != __rhs.base(); } 
    (gdb) s 
    __gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd7d0) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794 
    794   { return _M_current; } 
    (gdb) s 
    __gnu_cxx::__normal_iterator<char*, std::string>::base (this=0x7fffffffd810) at /usr/include/c++/4.9.1/bits/stl_iterator.h:794 
    794   { return _M_current; } 
    (gdb) s 
    numbersToBinary (src="My favourite number is13and nevermind 13") at /home/pasha/projects/miem/Replacer/func.cpp:52 
    52    if (isdigit(*iter)) { 
    (gdb) print iter 
    $42 = 16 '\020' 
    (gdb) print src.end() 
    $43 = 0 '\000' 

編輯:令人難以置信的是,如果我添加此

if (iter == src.end()) break; 

的for循環結束之前,它的工作原理!這是什麼???

+6

迭代可以通過調用'std :: string :: replace'來失效。 – crashmstr 2014-10-06 19:21:44

+0

您應該創建一個新的'result'字符串並將其返回 – 2014-10-06 19:22:49

+0

問題是字符串中可能存在多個整數。我怎麼能處理這個?在調用'replace' – pashazz 2014-10-06 19:26:09

回答

1

關於更新(與... 更新)代碼...

編輯:令人難以置信的是,如果我添加此

if (iter == src.end()) break; 

的for循環結束之前,它的工作原理!這是什麼???

它不可思議。這就是for循環的工作原理。您需要了解何時執行for循環的步驟的步驟與何時執行條件的步驟進行評估。

條件評估完成後循環體(重新)進入。遞增步驟完成後循環體完成後,之前返回循環的最後一個條件eval。

簡而言之,如果你的內部數字循環將它運行到src.end(),那麼你的for循環遞增步驟會遞增已經在序列末尾的迭代器。請記住,for循環增量在每次迭代完成後,但在下一個條件測試之前完成。

因此,

void numbersToBinary(string &src) 
{ 
    string newString; 
    string::iterator iter = src.begin(); 
    while (iter != src.end()) 
    { 
     if (isdigit(*iter)) 
     { 
      string::iterator numberStart = iter++; //numberStart = iter; 
      while ((iter != src.end()) && (isdigit(*iter))) { 
       ++iter; 
      } 
      string ins = decimalToBinary(string(numberStart, iter)); 
      newString.append(ins); 
     } 
     else 
     { 
      newString.push_back(*iter++); 
     } 

    } 
    src = newString; 
} 

幾個方法可以做到你嘗試什麼人。你也可以在循環結束粘硬中斷,如果iter已抵達src.end()(儘管它似乎有些多餘,檢查那裏,因爲我們已經知道它被設置爲src.end():數字環路)

+0

謝謝,這很有道理。 – pashazz 2014-10-07 07:16:37

0

在您致電replace後,原始字符串值不再存在。所以迭代器的一部分不再有效。當你再次循環時,iter是不再存在的值的一部分的迭代器,因此將其與end進行比較,完全不同的值的結尾是沒有意義的。撥打replace後,您需要將iter設置爲新字符串中正確的新值,然後再將其與end進行比較。

相關問題