显示字符和它们出现的次数?

时间:2011-02-24 09:44:21

标签: c#

我从用户那里得到一个字符串,然后把它放在一个char数组中。现在我想显示字符串中的所有字符以及它们出现的次数。我的代码如下请纠正我?

 using System;
 class count
 {
    public void charcount()
    {
       int i ;
       int count = 0;
       string s;
       Console.WriteLine("Enter the String:");
       s = Console.ReadLine();
       char[] carr = s.ToCharArray();
       for(i = 0; i < carr.Length; i++)
       {
         for(int j = 1; j < carr.Length; j++)
             {
               if(carr[j] == carr[i])
                       {
                count++;
                   }
                   else
                       {
                    return;
               }
               Console.WriteLine("The Character " + carr[i] + " appears " + count);
         }
       }        
    }

    static void Main()
    {
       count obj = new count();
       obj.charcount(); 
    }
  }

4 个答案:

答案 0 :(得分:5)

好吧,你的代码至少会遇到问题,因为你没有建立一个唯一字符列表,你可以在原始字符串中找到它们。任何出现多次字符的字符串都会显示奇怪的结果。

这是一个为您计算信息的LINQ表达式(您可以在LINQPad中运行它以立即查看结果):

void Main()
{
    string s = "This is a test, with multiple characters";
    var statistics =
        from c in s
        group c by c into g
        select new { g.Key, count = g.Count() };
    var mostFrequestFirst =
        from entry in statistics
        orderby entry.count descending
        select entry;
    foreach (var entry in mostFrequestFirst)
    {
        Debug.WriteLine("{0}: {1}", entry.Key, entry.count);
    }
}

输出:

 : 6 <-- space
t: 5
i: 4
s: 4
h: 3
a: 3
e: 3
l: 2
c: 2
r: 2
T: 1
,: 1
w: 1
m: 1
u: 1
p: 1

如果你不能使用LINQ,这是一个不使用它的例子:

void Main()
{
    string s = "This is a test, with multiple characters";
    var occurances = new Dictionary<char, int>();
    foreach (char c in s)
    {
        if (occurances.ContainsKey(c))
            occurances[c] = occurances[c] + 1;
        else
            occurances[c] = 1;
    }
    foreach (var entry in occurances)
    {
        Debug.WriteLine("{0}: {1}", entry.Key, entry.Value);
    }
}

答案 1 :(得分:1)

看起来你想要一个外部循环和一个内部循环,并且对于数组中的每个字符,你想要与int j = 1后面的每个字符进行比较。在这种情况下,您需要内部循环中的int j = i + 1

for (int i = 0; i < carr.Length; i++)
{
    for (int j = i + 1; j < carr.Length; j++)
    {
    }
}

但是你的return语句会在事物中间退出函数。您需要让循环完成,因此您要删除return

你的Console.WriteLine在内循环的每次迭代中执行,但你真的只希望它在外循环上迭代 - 一次为字符串的每个字符而不是一次i和j的每个组合。所以你需要把它推到外循环中,在内循环之外。

此外,每次开始外循环的另一次迭代时,您需要重置计数,因为您再次计数,并且,当您找到一个时,您想要开始计算 1 而不是零因为它刚出现时就出现了一次。

正如Lasse指出的那样,当你沿着外圈移动时击中相同的角色时,你会得到奇怪的输出。防止这种情况的一种简单方法是在每次匹配时将更多(向右)char [j]设置为'\ 0'(空字符),然后在外循环中,忽略计数中的空字符,例如使用{{ 1}},随着你的进展有效地剔除它们:

continue

我的第一个想法是使用像丹尼尔建议的字典,如下所示:

for(int i = 0; i < carr.Length; i++)
{
    if (carr[i] == '\0')
    {
        continue; // skip any further chars we've already set to null char
    }
    int count = 1;
    for (int j = i + 1; j < carr.Length; j++)
    {
        if(carr[j] == carr[i])
        {
            carr[j] = '\0'; // don't look for this char again later
            count++;
        }
    }
    Console.WriteLine("The Character " + carr[i] + " appears " + count);
}        

但我喜欢优雅的LINQ解决方案。

答案 2 :(得分:0)

如果您已经测试了代码,您会意识到代码是非常错误的 它的一些问题:

  • 您只有一个count变量,但您想要计算字符串中所有字符的出现次数
  • 您正在将字符串与自身进行比较,并尽快从您的方法返回,因为字符不匹配。

正确的方法是使用Dictionary<char, int>来保存每个角色的计数,如下所示:

var counts = new Dictionary<char, int>();
foreach(var c in s)
{
    int count;
    if(!counts.TryGetValue(c, out count))
    {
        counts.Add(c, 1);
    }
    else
    {
        ++counts[c];
    }
}

我没有故意使用LINQ,因为我认为您不会理解该代码。这不是冒犯。

答案 3 :(得分:0)

如果你想采用LINQ方式,这是一个相当简单的方法(我意识到它与Lasse V. Karlsen's answer非常相似,只使用不同的语法):

var s = Console.ReadLine();
foreach (var group in s.GroupBy(c => c).OrderByDescending(g => g.Count()))
{
    Console.WriteLine(" {0}: {1}", group.Key, group.Count());
}

无论你使用什么方法,逻辑都是一样的:

  • 识别每个独特的角色
  • 计算每个字符出现在文本中的次数
  • 输出结果

在我的代码示例中,s.GroupBy(c => c)负责前两个步骤。调用OrderByDescending(g => g.Count())只会对结果进行排序,以便更频繁地使用字符。结果中的每个元素都有一个Key属性(字符)和(以及其他)一个Count()方法,它将返回该字符的出现次数。