In the program i am currently building, i need to do a frequency analysis of the letter occurance in a string I know how to do this in c++ and the code for that is

#include <iostream>
using namespace std;


	// Function to increment the letter count in the counters array
	char add_letter( char letter, int letterCount[] ) 
	{
	// Only deal with lower case letters
	char lower_case_letter = tolower(letter);
 
	// Check if character is a letter
	if ( lower_case_letter >= 'a' && lower_case_letter <= 'z' ) 
	{
    ++letterCount[ lower_case_letter - 'a' ];
	}
 
	return letter;
	}

int main()
{
	int i=0;
	int count = 0;
	char string[600];
	char c;
	// One integer for each  letter
	int counters[26] = { 0 };

	cout << "Write something here: ";
	//the Answer to life, the Universe, and everything IS 42.
	cin.getline (string,600);
	
	// Pass each character to the add_letter
	// function until null-terminator is reached
	
	// Counting the number of occurences of each letter in this sentence
	
	char *sentence = string;
	while ( add_letter(*sentence++, counters) );
 
	// Display results
	for (int i = 0; i < 26; ++i) 
	{
		if ( counters[i] ) { 
		cout << '\n' << char(i + 'a') << ": " << counters[i] << '\n';
		}
	}
 
  
	//count number of words
	while (string[i])
	{
		c=int(string[i]);
		if (isspace(c)) count++;
		//putchar (c);		
		i++;

	}
	 	count++;	

	//Output: Number of words
	cout << "\nthe number of words are: " << count << " ";
	//Number of times letter appears

	return 0;
}

How ever i need to do it in c# and my linited knowledge of the similarities of both i have converted it manually to this:

using System;

	// Function to increment the letter count in the counters array
	private sbyte add_letter(sbyte letter, int[] letterCount)
	{
	// Only deal with lower case letters
	sbyte lower_case_letter = char.ToLower(letter);

	// Check if character is a letter
	if (lower_case_letter >= 'a' && lower_case_letter <= 'z')
	{
	++letterCount[lower_case_letter - 'a'];
	}

	return letter;
	}

static int Main()
{
	int i = 0;
	int count = 0;
	string @string = new string(new char[600]);
	sbyte c;
	// One integer for each  letter
	int[] counters = {0};

	Console.Write("Write something here: ");
	//the Answer to life, the Universe, and everything IS 42.
	@string = Console.ReadLine();

	// Pass each character to the add_letter
	// function until null-terminator is reached

	// Counting the number of occurences of each letter in this sentence

	sbyte *sentence = @string;
	while (add_letter(*sentence++, counters));
 
	// Display results
	for (int i = 0; i < 26; ++i)
	{
		if (counters[i] != 0)
		{
		Console.Write('\n');
		Console.Write((sbyte)(i + 'a'));
		Console.Write(": ");
		Console.Write(counters[i]);
		Console.Write('\n');
		}
	}


	//count number of words
	while (@string[i])
	{
		c = (int)(@string[i]);
		if (char.IsWhiteSpace(c))
			count++;
		//putchar (c);		
		i++;

	}
		 count++;

	//Output: Number of words
	Console.Write("\nthe number of words are: ");
	Console.Write(count);
	Console.Write(" ");
	//Number of times letter appears

	return 0;
}

As you can all imagine this has come up with multiple errors. and after speneding quite a few days on this i wounder whether there was anyone who can see where i have gone wrong or could know a much better way of doing this.

What i input is :the Answer to life, the Universe, and everything IS 42.
The outpur should be :
a=2
d=1
e=8
f=1
g=1
h=3
i=4
l=1
n=4
o=1
r=3
s=3
t=4
u=1
v=2
w=1
y=1

the number of words are: 10

I like using dictionaries for things like this:

dictionary<char,int> myDict = new dictionary<char,int>();
foreach (char c in myString)
   myDict[c]++;

You should also note that in C# pointers must be used in an unsafe context (they will throw exceptions otherwise). And really there's not a lot of good reasons to use them.

Edited 4 Years Ago by skatamatic: n/a

dictionary<char,int> myDict = new dictionary<char,int>();
foreach (char c in myString)
   myDict[c]++;

Thanks very much, so are you suggesting i use the above code for that line of code where the pointer is? or

sbyte *sentence = @string;
	while (add_letter(*sentence++, counters));

or you suggesting to use dictionary code instead of another part?

The 3 lines of code I provided will cover everything except for word counting and the output to the console. Here is an example implementation:

static int main()
        {
            string @string = new string(new char[600]);
            int iWords = 0;
            Console.Write("Write something here: ");
            @string = Console.ReadLine();

            foreach (KeyValuePair<char, int> k in GetLetterCounts(@string))
            {
                if (char.IsLetterOrDigit(k.Key))
                    Console.Write(k.Key + " : " + k.Value + Environment.NewLine);
                else if (k.Key == ' ')
                    iWords = k.Value;
            }
            Console.Write(Environment.NewLine + "Total Words: " + iWords.ToString());
        }
        private Dictionary<char, int> GetLetterCounts(string argString)
        {
            Dictionary<char, int> myDict = new Dictionary<char, int>();
            foreach (char c in argString)
                myDict[char.ToLower(c)]++;
            return myDict;
        }

To sort the dictionary (a to z for instance) LINQ does a good job:

var q = myDict.OrderByAscending(kvp => kvp.Key);
foreach (var item in q)
    Console.WriteLine(item.Key + " : " + item.Value);         }

Edited 4 Years Ago by skatamatic: n/a

If you're allowed to use Linq:

using System;
using System.Linq;

namespace DW_400863
{
   class Program
   {
      static void Main(string[] args)
      {
         string strInput = "the Answer to life, the Universe, and everything IS 42";

         (// ILookup<char, char>
            from c in strInput.ToLower().ToCharArray().OrderBy(c => c)
            where char.IsLetter(c)
            select c
         ).ToLookup(k => k, v => v).ToList().ForEach(c2c =>
            Console.WriteLine("{0}={1}", c2c.Key, c2c.Count()));

         Console.WriteLine("\nThe number of words are {0}", strInput.Split(' ').Count());
      }
   }
}

...but in case you need to have the greatest occurrence first:

using System;
using System.Linq;

namespace DW_400863
{
   class Program
   {
      static void Main(string[] args)
      {
         string strInput = "the Answer to life, the Universe, and everything IS 42";

         (// ILookup<char, char>
            from c in strInput.ToLower().ToCharArray().OrderBy(c => c)
            where char.IsLetter(c)
            select c
         ).ToLookup(k => k, v => v)
         .OrderByDescending(v => v.Count())
         .ToList()
         .ForEach(c2c => Console.WriteLine("{0}={1}", c2c.Key, c2c.Count()));

         Console.WriteLine("\nThe number of words are {0}", strInput.Split(' ').Count());
      }
   }
}
This question has already been answered. Start a new discussion instead.