2010-12-15 79 views
1

我想知道如果你能告訴我重複字符串的最有效方法是什麼。我需要創建一個長度爲33554432字節的字符串,重複字符串「hello,world」,直到它填充該緩衝區。什麼是最好的辦法,在這種情況下,C很容易:代碼翻譯:重複一個字符串,直到最大值

for (i = 0; i < BIGSTRINGLEN - step; i += step) 
     memcpy(bigstring+i, *s, step); 

謝謝。

+2

你認爲1個字符== 1個字節嗎?因爲對於純ASCII編碼是正確的,但對於其他編碼,它可能是錯誤的... – digEmAll 2010-12-15 18:38:28

回答

3

的有效方法是使用一個StringBuilder

string text = "hello, world"; 
StringBuilder builder = new StringBuilder(BIGSTRINGLEN); 
while (builder.Length + text.Length <= BIGSTRINGLEN) { 
    builder.Append(text); 
} 
string result = builder.ToString(); 
+4

如果初始化StringBuilder所需的長度,效率會更高:new StringBuilder(BIGSTRINGLEN); – codymanix 2010-12-15 18:36:33

+0

@codymanix,你說得對,回答更新。謝謝:) – 2010-12-15 18:37:43

+0

+1發佈幾乎完全相同的答案,我剛剛發佈! – wageoghe 2010-12-15 18:39:49

1

我不知道這是否是最有效的方式,但如果你使用.NET 3.5或更高版本,這可能是工作:

String.Join("", System.Linq.Enumerable.Repeat("hello, world", 2796203).ToArray()).Substring(0, 33554432); 

如果你想要的長度是動態的,那麼你就可以用簡單的數學替換一些硬編碼的數字。

+0

嗯......我在Mono上,沒有LinQ。相應地更新標籤。謝謝。 – 2010-12-15 18:33:17

+0

沒有Linq?傷心!那麼我會看弗雷德裏克的答案。不管你做什麼,如果使用大字符串,你應該使用字符串連接的StringBuilder。 – 2010-12-15 18:35:08

+0

你知道ToArray() - 調用創建一個包含2796203個字符串的數組,你是否(我知道它是必需的String.Join)。如果沒有這個ToArray(),你的方法將具有與StringBuilder大致相同的性能,因爲String.Join在內部使用StringBuilder,所以枚舉器的開銷很小。 – codymanix 2010-12-15 18:40:51

2

首先,你希望字符串是33554432個字節長,或字符? .NET和C#使用16位字符,因此它們不相同。

如果你想要33554432個字符,天真的解決方案將是字符串連接。見Frédéric Hamidi的答案。

如果你想要個字節,你需要做一些更有趣:

int targetLength = 33554432; 
string filler = "hello, world"; 
byte[] target = new byte[targetLength]; 

// Convert filler to bytes. Can use other encodings here. 
// I am using ASCII to match C++ output. 
byte[] fillerBytes = Encoding.ASCII.GetBytes(filler); 
//byte[] fillerBytes = Encoding.Unicode.GetBytes(filler); 
//byte[] fillerBytes = Encoding.UTF8.GetBytes(filler); 

int position = 0; 
while((position + fillerBytes.Length) < target.Length) 
{ 
    fillerBytes.CopyTo(target, position); 
    position += fillerBytes.Length; 
} 

// At this point, need to possibly do a partial copy. 
if (position < target.Length) 
{ 
    int bytesNecessary = target.Length - position; 
    Array.Copy(fillerBytes, 0, target, position, bytesNecessary); 
} 
+2

我試過這個...字符串concat帶走了永遠... stringbuilder是232ms ... – 2010-12-15 18:39:28

+0

因爲OP提到的效率我認爲它不適合給字符串連接作爲例子,即使你提到它是一個天真的實現。儘管答案的其餘部分+1。 – Davy8 2010-12-15 18:41:33

+0

是的......我忘了'StringBuilder',因爲Java現在轉換爲自動使用它。我適當地修改了我的答案。 – jdmichal 2010-12-15 18:41:36

0

這個是什麼?將StringBuilder設置爲最大預期大小,然後添加所需的字符串,只要添加另一個字符串不會超過所需的最大大小。

StringBuilder sb = new StringBuilder(33554432); 
    int max = sb.MaxCapacity; 
    String hello = "hello, world"; 

    while (sb.Length + hello.Length <= max) 
    { 
    sb.Append(hello); 
    } 

    string longString = sb.ToString(); 
0

這可避免重複添加字符串的循環。相反,我將字符串「加倍」,直到接近正確的長度,然後適當地將「加倍」部分放在一起。

static string Repeat(string s, int length) { 
     if (length < s.Length) { 
      return s.Substring(0, length); 
     } 
     var list = new List<string>(); 

     StringBuilder t = new StringBuilder(s); 
     do { 
      string temp = t.ToString(); 
      list.Add(temp); 
      t.Append(temp); 
     } while(t.Length < length); 

     int index = list.Count - 1; 
     StringBuilder sb = new StringBuilder(length); 
     while (sb.Length < length) { 
      while (list[index].Length > length) { 
       index--; 
      } 
      if (list[index].Length <= length - sb.Length) { 
       sb.Append(list[index]); 
      } 
      else { 
       sb.Append(list[index].Substring(0, length - sb.Length)); 
      } 
     } 
     return sb.ToString(); 

    } 

因此,例如,在輸入(「你好,世界!」,64),我們所建立的字符串

13: Hello, World! 
26: Hello, World!Hello, World! 
52: Hello, World!Hello, World!Hello, World!Hello, World! 

然後,我們將通過長度52的字符串串聯到構建結果長度爲12的字符串的長度爲12的子串。

我當然假設按字節表示長度。否則,您可以使用編碼輕鬆修改上述內容,以便按字節獲取所需內容。

+0

給我:使用時間(float):315.9855毫秒,stringbuilder仍然是最好的...雖然我明白你的觀點。 – 2010-12-15 18:51:31

+0

對一個輸入的一個測試會告訴你什麼。 – jason 2010-12-15 18:52:18

+0

除非你的宇宙只是這個字符串,並且數字加倍,在這種情況下它會告訴你所有你想知道的東西! – 2010-12-15 18:54:20