2010-06-18 64 views
0

好的,所以希望我可以解釋這個足夠的細節,以便有人能夠幫助我..我正在編寫一個應用程序在C#一個文本文件並替換正好是文件名的特定文本,併爲給定文件名的每個單一組合打印一個新的文本文件。改變文件名文本的特定位置有它們自己的一組可能的文件名,被列爲下面描述的一個數組。無論每個位置有多少個文件名可用,以及多少個文件名總位置,程序都應該運行。如果你真的想讓它變得很棒,那麼可以稍微優化一下,因爲知道在任何單個文本文件中都不應該複製文件名。在基本文本文件中創建特定行的每個組合的文本文件

text是構成整個文件基礎的一行數組。

lineNum保存文件名條目行位置的數組。

previousFiles是以前使用的文件名的數組,從文件中已有的文件開始。

files是可能的文件名的鋸齒狀的2維陣列,其中files[1]將用於第二位置

這裏所有可能的文件名的陣列的它如何與3個獨立的文件名地點工作的示例中,第一個給出3個可能的文件名,第二個給出8個可能的文件名,第三個給出3個可能的文件名。

哦,並假設buildNewFile的作品。

 int iterator = 0; 
     for (int a = 0; a < 3; a++) 
     { 
      for (int b = 0; b < 8; b++) 
      { 
       for (int c = 0; c < 3; c++) 
       { 
        iterator++; 
        text[lineNums[0]] = text[lineNums[0]].Replace(previousFiles[0], files[0][a]); 
        text[lineNums[1]] = text[lineNums[1]].Replace(previousFiles[0], files[0][a]); 
        text[lineNums[2]] = text[lineNums[2]].Replace(previousFiles[1], files[1][b]); 
        text[lineNums[3]] = text[lineNums[3]].Replace(previousFiles[1], files[1][b]); 
        text[lineNums[4]] = text[lineNums[4]].Replace(previousFiles[2], files[2][c]); 
        text[lineNums[5]] = text[lineNums[5]].Replace(previousFiles[2], files[2][c]); 
        previousFiles = new string[] { files[0][a], files[1][b], files[2][c] }; 
        buildNewFile(text, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn"); 
       } 
      } 
     } 

如果你們可以幫助我,非常感謝你,我只是無法弄清楚如何遞歸或任何事情。如果您有任何問題,我會回答並在此處進行編輯以反映這一點。

回答

1

我花了一段時間才弄清楚你真的想做什麼。這個問題可以在不遞歸的情況下解決,訣竅是查看您擁有的數據並將其轉換爲更有用的格式。您的「files」數組是最不方便的數組。訣竅是將數據轉換爲可用的排列。爲此,我建議利用yield並使用返回IEnumerable的方法。它的代碼是在這裏:

public IEnumerable<string[]> GenerateFileNameStream(string[][] files) 
{ 
    int[] current_indices = new int[files.Length]; 
    current_indices.Initialize(); 
    List<string> file_names = new List<string>(); 

    while (current_indices[0] < files[0].Length) 
    { 
     file_names.Clear(); 

     for (var index_index = 0; index_index < current_indices.Length; index_index++) 
     { 
      file_names.Add(files[index_index][current_indices[index_index]]); 
     } 

     yield return file_names.ToArray(); 

     // increment the indices, trickle down as needed 
     for (var check_index = 0; check_index < current_indices.Length; check_index++) 
     { 
      current_indices[check_index]++; 

      // if the index hasn't rolled over, we're done here 
      if (current_indices[check_index] < files[check_index].Length) break; 

      // if the last location rolls over, then we are totally done 
      if (check_index == current_indices.Length - 1) yield break; 

      // reset this index, increment the next one in the next iteration 
      current_indices[check_index] = 0; 
     } 
    } 
} 

基本上,它跟蹤當前的指數爲files 2D陣列的每一行和每一當前索引處返回的文件名。然後它增加第一個索引。如果第一個索引翻轉,那麼它將重置爲0,然後遞增下一個索引。這樣我們可以迭代文件名的每個排列。

現在,看看lineNumfiles之間的關係,我假設文件中的每個位置都被複制到兩行。其餘的代碼在這裏:

public void MakeItWork(string[][] files, int[] lineNum, string[] text, string[] previousFiles) 
{ 
    var iterator = 0; 
    var filenames = GenerateFileNameStream(files); 

    // work a copy of the text, assume the "previousFiles" are in this text 
    var text_copy = new string[text.Length]; 

    foreach (var filenameset in filenames) 
    { 
     iterator++; 
     Array.Copy(text, text_copy, text.Length); 

     for (var line_index = 0; line_index < lineNum.Length; line_index++) 
     { 
      var line_number = lineNum[line_index]; 
      text[line_number] = text[line_number].Replace(previousFiles[line_index], filenameset[line_index/2]); 
     } 

     buildNewFile(text_copy, Info.baseFolder + "networks\\" + Info.dsnFilename + iterator + ".dsn"); 
    } 
} 

這段代碼只是從枚舉數中得到結果併爲你生成文件。根據您的示例代碼的假設是每個文件的位置每個文件使用兩次(因爲lineNum數組的長度是位置計數的files的兩倍。

我還沒有完全測試所有的代碼,但算法的關鍵在那裏。關鍵是將您的數據轉換爲更有用的形式,然後對其進行處理。我在這裏提出問題時提出的另一個建議是將問題更多地描述爲「問題」,而不是現有解決方案的條款。如果您詳細描述了您試圖實現的目標而不是顯示代碼,則可以獲得有關該問題的更多見解。

相關問題