2011-11-03 171 views
0

我製作這個程序只是出於興趣,並希望做得更好。我的問題是,我想做一個嵌套的循環來執行迭代,但我無法繞過它,我嘗試了很多次,但我的頭正在融化。任何幫助將不勝感激。另外由於Windows和openSuse的某些原因(從我所看到的),該程序在預期輸出後打印出一些隨機字符,解決這個問題將是一個很大的好處。謝謝 !嵌套for循環解決方案

對不起,我沒有說清楚,代碼的重點是能夠從理論上生成從AAAAAAAA到ZZZZZZZZ的每個字母組合。

1)不,這不是功課

#include <iostream> 
using namespace std; 

int main() 
{ 
    char pass [] = {'A','A','A','A','A','A','A','A'}; 
    while(pass[0] != '[') 
    { 
     pass[7]++; 

     if(pass[7]=='[') 
     { 
      pass[6]++; 
      pass[7] = 'A'; 
     } 
     if(pass[6] == '[') 
     { 
      pass[6] = 'A'; 
      pass[5]++; 
     } 
     if(pass[5] == '[') 
     { 
      pass[5] = 'A'; 
      pass[4]++; 
     } 
     if(pass[4] == '[') 
     { 
      pass[4] = 'A'; 
      pass[3]++; 
     } 
     if(pass[3] == '[') 
     { 
      pass[3] = 'A'; 
      pass[2]++; 
     } 
     if(pass[2] == '[') 
     { 
      pass[2] = 'A'; 
      pass[1]++; 
     } 
     if(pass[1] == '[') 
     { 

      pass[1] = 'A'; 
      pass[0]++; 
     } 

     cout << pass << endl; 
    } 
    return 0; 
} 
+2

這是功課嗎?如果是這樣,請標記爲這樣。 –

+1

我不明白你的代碼,你想做什麼? –

+3

關於你的第二個問題,把你的初始化改爲'{'A','A','A','A','A','A','A','A','\ 0'}' ,它會起作用。打印時您將該數組視爲C字符串。因此預計會以''\ 0''結尾。 –

回答

3

也許是這樣的:

const char char_first = 'A'; 
const char char_last = '['; 
const unsigned int passlen = 8; 

while (pass[0] != char_last) 
{ 
    ++pass[passlen - 1]; 

    for (unsigned int i = passlen - 1; i != 0; --i) 
    { 
    if (pass[i] == char_last) 
    { 
     ++pass[i - 1]; // OK, i is always > 0 
     pass[i] = char_first; 
    } 
    } 
} 

印刷,包括<string>說:

std::cout << std::string(pass, passlen) << std::endl; 

我把做的自由一些神奇的數字轉化爲常量。如果你將它重構成一個單獨的函數,你會看到這個優點。

+0

啊,這是完美的,非常感謝您的答覆..這將幫助我進入我父親的互聯網在幾年內:)! – TomSelleck

+0

沒問題 - 祝你好運!想到這一點,@ Basile將數字零字節添加到數組的想法可能是一個好主意,因爲您每次都避免構造字符串對象(儘管對控制檯的打印比這個小的額外步驟要慢幾個數量級) 。 –

3

由於(以進行輸出)您使用pass爲C字符串常量,應該空值終止。由於不是,垃圾被打印。所以,你可以把它定義爲: char pass [] = {'A','A','A','A','A','A','A','A','\0'}; 或簡單 char pass[] = "AAAAAAAAA";

+0

感謝您的回覆隊友,應該看到了! – TomSelleck

0

首先試圖找到在表達式公用部分看起來像

if(pass[7]=='[') 
    { 
     pass[6]++; 
     pass[7] = 'A'; 
    } 

你應該沿線認爲像「總有相同數量的這裏,和一個較小的數字有」。然後,用一個變量替換數字的概念,找出變量的範圍。 KerrekSB給了你一個解決方案,嘗試從你自己的推理中得出類似的代碼。

0

你只需要玩一會兒,並使其適合for-loop。

while(pass[0] != '[')成爲for (i=0; pass[0] != '['; i++)

那麼你可以只用一個取代所有IFS:

if(pass[i+1] == '[') 
    { 

     pass[i+1] = 'A'; 
     pass[i]++; 
    } 

我們是如何得出這個結論?那麼如果你檢查所有的if語句,它們之間的所有變化就是指數。您可以清楚地看到該模式,因此您只需使用變量替換索引即可。

2

我會忘記進行我自己的,只是轉換爲/從數字。你在這裏做的基本上是打印一個數字,其範圍從'A'到']',通過ASCII的魔術可以映射到0-28(爲什麼在密碼中沒有^)

打印任何數字那麼真的可以歸結爲

#include <iostream> 
#include <cmath> 

using namespace std; 

std::string format(long num, int ndigits) { 
     if(ndigits == 0) { 
       return ""; 
     } else { 
       char digit = 'A' + num % 28; 
       return format(num/28, ndigits - 1) + digit; 
     } 
} 

int main() 
{ 
     for(int i = 0 ; i < powl(28,8) ; ++i) { 
       cout << format(i, 8) << endl; 
     } 
} 

您可能仍然需要在字符數組,如果你是認真的循環工作產生十億臨時字符串代替,但原則保持不變。

0

對於初學者來說,這絕對不是嵌套循環的情況。事實上, 整個代碼歸結爲:

pass = initialPattern(); 
while (isValidPattern(pass)) { 
    nextPattern(pass); 
    std::cout << pass << std::endl; 
} 

(但我不知道,如果你真的不意味着 增量之前來做輸出。)

現在,所有你需要做的就是定義合格的類型和相關的功能;你甚至可以考慮 把所有的東西都放在一個類中,因爲所有的函數都在 相同的數據實例上運行。

從您的代碼判斷,pass應該是std::string與8 個字符;初始化可寫成:

std::string pass(8, 'A'); 

isValidPattern顯然只看第一個字符。 (我不 確定這是正確的,但是這是你的代碼做什麼。)喜歡的東西:

bool 
isValidPattern(std::string const& pattern) 
{ 
    return pattern[0] != '['; 
} 

根據你的代碼,但這樣的:

struct NotIsUpper 
{ 
    bool operator()(char ch) const 
    { 
     return ! ::isupper(static_cast<unsigned char>(ch)); 
    } 
}; 

bool 
isValidPattern(std::string const& pattern) 
{ 
    return pattern.size() == 8 
     && std::find_if(pattern.begin(), pattern.end(), NotIsUpper()) 
       == pattern.end(); 
} 

似乎更合適。 (當然,如果你做任何形式的 文字編碼,你已經有NotIsUpper和它的兄弟姐妹在 你的工具包。)

最後,nextPattern似乎沒有什麼比一個多位數以上 增量,其中數據以big-endian順序存儲。所以 以下(經典)算法似乎適當:

void 
nextPattern(std::string& pattern) 
{ 
    static char const firstDigit = 'A'; 
    static char const lastDigit = 'Z'; 
    static std::string const invalidPattern(1, '['); 

    std::string::reverse_iterator current = pattern.rbegin(); 
    std::string::reverse_iterator end = pattern.rend(); 
    while (current != end && *current == lastDigit) { 
     *current = firstDigit; 
     ++ current; 
    } 
    if (current != end) { 
     ++ *current; 
    } else { 
     pattern = invalidPattern; 
    } 
} 

形式上,有標準不能保證這些字母將 在連續的升序進行編碼,所以最大的可移植性, 你應該在實際上使用的值爲std::vector<int>,其值爲 ,範圍爲[0, 26),並將這些值映射到輸出的字母。如果您將所有這些操作放在一個類中,則此 將會變得微不足道,因爲 內部表示形式對客戶端代碼不可見。 喜歡的東西:

class PatternGenerator 
{ 
    std::vector<int> myData; 
public: 
    explicit PatternGenerator() 
     : myData(8, 0) 
    { 
    } 

    void next() 
    { 
     static int const lastDigit = 26; 

     std::vector<int>::reverse_iterator current = pattern.rbegin(); 
     std::vector<int>::reverse_iterator end = pattern.rend(); 
     while (current != end && *current == lastDigit - 1) { 
      *current = 0; 
      ++ current; 
     } 
     if (current != end) { 
      ++ *current; 
     } else { 
      myData.front() = lastDigit; 
     } 
    } 

    bool isValid() const 
    { 
     return myData.front() < lastDigit; 
    } 

    friend std::ostream& operator<<(
     std::ostream& dest, PatternGenerator const& obj) 
    { 
     static char const characterMap[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
     for (std::vector<int>::iterator current = obj.myData.current(); 
       current != obj.myData.end(): 
       ++ current) { 
      dest << characterMap[*current]; 
     } 
     return dest; 
    } 
}; 

(注意,之類的東西isValid變得更簡單,因爲他們可以依賴的類不變)

考慮到這一點,你必須寫的是:

int 
main() 
{ 
    PatternGenerator pass; 
    while (pass.isValid()) { 
     std::cout << pass << std::endl; 
     pass.next(); 
    } 
    return 0; 
} 
+0

這是否有人試圖欺騙學生不做功課?我可以立即看到嵌套循環解決方案,這是一個非常有效的用例。當然,我也不會爲它編寫完整的代碼清單,但是... –

+0

@KarlKnechtel不,不過,我承認基於類的解決方案對於簡單的作業分配可能會有點遠(但向學生展示如何將這些內容寫入行業是一件好事)。但是,對於嵌套循環來說,這絕對不是一個例子,從我的解釋中應該可以看出。如果你想用嵌套循環的話來說,你並沒有把問題分解到足以編寫正確和可維護的代碼。增加模式的問題與循環所有模式的問題完全無關,應該分開。 –

+0

我認爲循環索引是* encoding *模式,所以......:無論如何,看起來好像OP的主要興趣在於弄清楚如何處理嵌套循環的邏輯。 –

0

要做嵌套循環,你需要把它從裏面翻出來。

你已經寫了代碼思想如下:遍歷最後一個符號的所有可能性,然後更改倒數第二次,然後返回等等。就像從1開始計數,到10並且放入一個十列中的1個,等等

嵌套循環以另一種方式工作:通過第一個符號的可能性,允許內部循環每次處理其他符號的可能性。即「按照從上百位開始的所有那些數字,然後以1開始的數字等等」列出所有這些數字。在最外層的循環中,您只需爲第一個數字設置該值,並且嵌套循環會處理其餘部分。