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