2013-10-29 62 views
0

我必須編寫一個使用散列表的程序,並且鍵/值由用戶輸入。在這個程序中,我必須輸出所有的密鑰,但是如果任何密鑰以小的'a'開始,我必須以大的'A'開始。我在最後一步遇到問題。更改C中散列表中字符串的一個元素#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Collections; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Hashtable hashtable = new Hashtable(); 
      for (int i = 0; i < 10; i++) 
      { 
       Console.WriteLine("Vnesete kluc"); 
       string kluc = Console.ReadLine(); 
       Console.WriteLine("Vnesete podatok"); 
       string podatok = Console.ReadLine(); 
       hashtable.Add(kluc, podatok); 
      } 

      foreach (string klucevi in hashtable.Keys) 
      { 
       if (klucevi[0] == 'a') 
       { 
        klucevi[0] = 'A'; 
       } 
       Console.WriteLine(klucevi); 
      } 

     } 
    } 
} 

我在哪裏,我將字符串的第一個元素,如果它是「a」到「A」線得到一個錯誤。

+1

什麼是你得到的錯誤? – Josh

+0

錯誤:索引器'string.this [int]'的屬性不能分配給 - 它是隻讀的。 – user2699298

+1

這是因爲字符串是不可變的。你不能像這樣改變鑰匙。 –

回答

3

不能動態地更改密鑰。最簡單的方法是檢查前的關鍵您添加到集合:

for (int i = 0; i < 10; i++) 
{ 
    Console.WriteLine("Vnesete kluc"); 
    string kluc = Console.ReadLine(); 
    if (kluc.StartsWith("a")) 
     kluc = "A" + kluc.Substring(1); 
    Console.WriteLine("Vnesete podatok"); 
    string podatok = Console.ReadLine(); 
    hashtable.Add(kluc, podatok); 
} 
1

你的問題與散列表無關。你有一個編譯錯誤,因爲在.NET中字符串是不可變的。

其次,這是不相關的,foreach循環變量不能分配給。

所以,與其

foreach (string klucevi in *whatever*) 
{ 
    if (klucevi[0] == 'a') 
    { 
     klucevi[0] = 'A'; 
    } 
    Console.WriteLine(klucevi); 
} 

使用

foreach (string klucevi in *whatever*) 
{ 
    var temp = klucevi; 

    if (temp[0] == 'a') 
    { 
     StringBuilder sb = new StringBuilder(temp); 

     sb[0] = 'A'; 

     temp = sb.ToString(); 
    } 
    Console.WriteLine(temp); 
} 

不要忘了包括using System.Text;聲明。

更新: 上面的aswer顯示了一種通用的方式來修改.NET中的字符串,而不僅僅是替換一個字符。

此外,一些人對這種方法的有效性表示擔憂。他們錯了。更多信息請見Strings Undocumented

更新2: 我喜歡受到挑戰。雖然這對於手頭的問題來說完全沒有關係,但討論已經結束了關於使用StringBuilder的效率,與使用"A" + temp.Substring(1)相比。因爲我喜歡事實,並且我假設有些讀者會同意,所以我跑了一點基準。

我使用.NET 4.5作爲32位和64位進程在64位Windows 7機器上運行測試。事實證明,StringBuilder方法總是比替代方法快20%左右。內存使用情況大致相同。因人而異。

對於那些誰關心重複測試,這裏的源代碼:

using System; 
using System.Diagnostics; 
using System.Text; 

static class Program 
{ 
    static void Main(string[] args) 
    { 
     for (int length = 50; length <= 51200; length = length * 2) 
     { 
      string input = new string(' ', length); 

      // warm up 
      PerformTest(input, 1); 

      // actual test 
      PerformTest(input, 100000); 
     } 
    } 

    static void PerformTest(string input, int iterations) 
    { 
     GC.Collect(); 
     GC.WaitForFullGCComplete(); 

     int gcRuns = GC.CollectionCount(0); 

     Stopwatch sw = Stopwatch.StartNew(); 

     for (int i = iterations; i > 0; i--) 
     { 
      StringBuilder sb = new StringBuilder(input); 

      sb[0] = 'A'; 

      input = sb.ToString(); 
     } 

     long ticksWithStringBuilder = sw.ElapsedTicks; 
     int gcRunsWithStringBuilder = GC.CollectionCount(0) - gcRuns; 

     GC.Collect(); 
     GC.WaitForFullGCComplete(); 

     gcRuns = GC.CollectionCount(0); 

     sw = Stopwatch.StartNew(); 

     for (int i = iterations; i > 0; i--) 
     { 
      input = "A" + input.Substring(1); 
     } 

     long ticksWithConcatSubstring = sw.ElapsedTicks; 
     int gcRunsWithConcatSubstring = GC.CollectionCount(0) - gcRuns; 

     if (iterations > 1) 
     { 
      Console.WriteLine(
       "String length: {0, 5} With StringBuilder {1, 9} ticks {2, 5} GC runs, alternative {3, 9} ticks {4, 5} GC Runs, speed ratio {5:0.00}", 
       input.Length, 
       ticksWithStringBuilder, gcRunsWithStringBuilder, 
       ticksWithConcatSubstring, gcRunsWithConcatSubstring, 
       ((double)ticksWithStringBuilder)/((double)ticksWithConcatSubstring)); 
     } 
    } 
} 
+2

您無法更改「foreach迭代」變量。 'klucevi = sb.ToString();'不會編譯。即使這樣做,它也不會改變散列表中的鍵值。 –

+0

這是一個非常醜陋的(更不用說效率低下)的方式來改變字符串的第一個字符。另外,第一個評論說的是什麼。 –

+0

@AhmedKRAIEM是的,我注意到這太遲了。我已經更新了我的答案。 –

相關問題