开发者

displaying characters and how many times they appear?

开发者 https://www.devze.com 2023-02-13 07:29 出处:网络
I get a string from the user and then put it in a char array. Now I want to display all the characters in the string along with how many times they appear. My code is as follows Ple开发者_开发技巧ase

I get a string from the user and then put it in a char array. Now I want to display all the characters in the string along with how many times they appear. My code is as follows Ple开发者_开发技巧ase Correct me ?

 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(); 
    }
  }


Well, your code will at least have problems due to the fact that you don't build a list of unique characters, you find them in the original string. Any string with characters that appear multiple times will show odd results.

Here's a LINQ expression that calculates the information for you (you can run this in LINQPad to immediately see the results):

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);
    }
}

Output:

 : 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

If you can't use LINQ, here's an example that doesn't use that:

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);
    }
}


It looks like you want an outer loop and an inner loop, and for each char in the array, you want to compare to each that follows with int j = 1. In that case, you want int j = i + 1 in the inner loop:

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

But your return statement exits the function right in the middle of things. You need to let the loops complete, so you want to remove that return.

Your Console.WriteLine executes on every iteration of the inner loop, but you really only want it to iterate on the outer loop -- once for each character of the string and not once for every combination of i and j. So you need to push that to the outer loop, outside of the inner loop.

Also, you need to reset the count every time you begin another iteration of the outer loop, because you are counting again, and, you want to start counting at 1 not zero when you find a character because it just appeared once as you first reach it.

And as Lasse points out, you'll get strange output when you hit the same character as you move along the outer loop. An easy way to prevent that is to set the further (rightwards) char[j] to '\0' (null character) on every match, and then in the outer loop, ignore null characters in your counting for example by using continue, effectively culling them as you go along:

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);
}        

My first thought would be to use a Dictionary as Daniel suggests, like this:

    var dict = new Dictionary<char, int>();

    string s = "This is a test, with multiple characters";

    foreach (var c in s)
    {
        if (dict.ContainsKey(c))
        {
            dict[c]++;
        }
        else
        {
            dict[c] = 1;
        }
    }

    foreach (var k in dict.Keys)
    {
        Console.WriteLine("{0}: {1}", k, dict[k]);
    }

But I like the elegant LINQ solutions.


If you would have tested your code, you would have realized, that the code is very wrong.
Some of its problems:

  • You have only one count variable, although you want to count the occurences of all characters in your string
  • You are comparing the string with itself and return from your method, as soon, as the characters don't match.

The right way would be to use a Dictionary<char, int> to hold the count for each character, something like this:

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];
    }
}

I didn't use LINQ on purpose, because I don't think you would understand that code. That's no offence.


If you want to go the LINQ way, this is a fairly brief way to do it (which I realize is pretty much the same as Lasse V. Karlsen's answer, only using different syntax):

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

The logic is the same whatever approach you use:

  • Identify each unique character
  • Count how many times each character occurs in the text
  • Output the result

In my code sample, s.GroupBy(c => c) takes care of the first two steps. The call OrderByDescending(g => g.Count()) will just sort the result so that more frequent characters come first. Each element in the result has a Key property (the character) and (amongst others) a Count() method that will return the number of occurrences for that character.

0

精彩评论

暂无评论...
验证码 换一张
取 消