Align numbers in RichTextBox - c#

I want to print a multiplication table in C# but it's not aligned!
When we type a number "n" in textbox means: n*n table.
What can I do?
for (int i = 1; i <= Convert.ToInt32(textBox1.Text); i++)
{
for (int j = 1; j <= Convert.ToInt32(textBox1.Text); j++)
{
richTextBox1.Text += Convert.ToString(i * j) + " ";
}
richTextBox1.Text += "\n";
}

Set the font of RichTextBox to the monospaced font Courier New, then add the text to RichTextBox using String.Format and setting alignment for the result of multiplication. Use a positive number to align right and use a negative number to align left:
var n = 5;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
this.richTextBox1.AppendText(string.Format("{0,3}", i * j));
}
this.richTextBox1.AppendText(Environment.NewLine);
}
Instead of format the result by {0,3} you can use below code to format based on maximum length of characters is a number which belongs to n*n:
Left Aligned:
string.Format("{0,-" +((n*n).ToString().Length + 1).ToString() +"}", i * j)
Right Aligned:
string.Format("{0," +((n*n).ToString().Length + 1).ToString() +"}", i * j)

If you want to align using spaces, you need to use a monospaced font (like Courier, or Consolas), otherwise you can use tabs: numbers won't be aligned this way though, and since numbers in your routine can get considerably big, you may end up having your numbers occupy more than the tab separation, and will get inconsistencies in the alignment if that happens.
As a general rule, if you want to align any kind of text box, go with a monospaced font.
You can pad with spaces, using, for example, String.PadLeft or String.PadRight.
This would be as simple as changing:
richTextBox1.Text += Convert.ToString(i * j) + " ";
With
richTextBox1.Text += Convert.ToString(i * j).PadLeft(5);
However this would assume all numbers are at maximum 5 characters in width.
For your precise routine, you could calculate the maximum width though, so you'd end up with something like:
// convert your input only once
int myNumber = Convert.ToInt32(textBox1.Text);
// pad with the maximum possible length, plus one space
int padAmount = (myNumber * myNumber).ToString().Length + 1;
for (int i = 1; i <= myNumber; i++)
{
for (int j = 1; j <= myNumber; j++)
{
// pad your input by the amount of spaces needed to fit all possible numbers
richTextBox1.Text += (i*j).ToString().PadLeft(padAmount);
}
}
// use Environment.NewLine instead of `\n`
richTextBox1.Text += Environment.NewLine;
Here's a fiddle. It's (for obvious reasons) for console, so in my fiddle the input number is fixed (it's in myNumber) and the output is just a string (instead of richTextBox1.Text), but it should show how it works.
Although I've made a few changes (I only convert the input number once, and use Environment.NewLine instead of \n), this is far from optimal though, you should build your string (using a StringBuilder) and assign it at once, instead of adding to the Text property. I've made a fiddle with this approach, and memory consumption has gone down by over 30mb (to just a handful of kb) just by using StringBuilder.

I think the best solution is using a tab instead of a special font and padding with white spaces.
For tabs you must add a "\t" after every number. The "\t" will be evaluated as an tab-character.
for (int i = 1; i <= Convert.ToInt32(textBox1.Text); i++)
{
for (int j = 1; j <= Convert.ToInt32(textBox1.Text); j++)
{
richTextBox1.Text += Convert.ToString(i * j) + "\t "; //here at the end
}
richTextBox1.Text += "\n";
}
But it is important, that a tab has a fixed width. In case your numbers are too long, you need 2 tabs for short numbers. But for small tables like yours it is no problem.
You can change the position of the tabs with the SelectionTabs property:
this.richTextBox1.SelectionTabs = new[] { 20, 40, 60, 80 };
BTW, you should use a StringBuilder to concatenate multiple string parts to one. And it would be more effective to parse the number from textBox1 only once and not during every iteration.
var sb = new StringBuilder(); //In namespace System.Text
var x = Convert.ToInt32(textBox1.Text); //parse only once
for (int i = 1; i <= x; i++)
{
for (int j = 1; j <= x; j++)
{
sb.Append(Convert.ToString(i * j));
sb.Append("\t ");
}
sb.Append("\n");
}
richTextBox1.Text += sb.ToString();

Related

How to reverse the print out of numbers

I'm currently trying to learn C# for my university degree and I can't work out how to get my code to print out only the even numbers from 0-100 starting at the largest number i.e 100 down too 0. I have the code printing the output from smallest to largest but cannot get it to go the other way around.
Can anyone give me a hand?
This is my code:
Console.WriteLine("Print first 100 even No in reverse");
for (int i = 1; i < 100; i++)
{
if (i % 2 == 0)
{
Console.Write(i + " ");
}
}
You need to replace your code with this code:
Console.WriteLine("Print first 100 even No in reverse");
for (int i = 100; i >= 0 ; i--)
{
if (i % 2 == 0)
{
Console.Write(i + " ");
}
}
you just need to start your loop from 100 and decrease from there:
for (int i = 100; i >= 0; i--)
use ">" instead of ">=" operator, if you don't want the zero included

C# cant understand count

I am trying to count words in this program but i don't understand why the program is counting for 1 number less than it must be.
For example:
sun is hot
program will show me that there is only 2 words.
Console.WriteLine("enter your text here");
string text = Convert.ToString(Console.ReadLine());
int count = 0;
text = text.Trim();
for (int i = 0; i < text.Length - 1; i++)
{
if (text[i] == 32)
{
if (text[i + 1] != 32)
{
count++;
}
}
}
Console.WriteLine(count);
Regular expression works the best for this.
var str = "this,is:my test string!with(difffent?.seperators";
int count = Regex.Matches(str, #"[\w]+").Count;
the result is 8.
Counts all words, does not include spaces or any special characters, regardless if they repeat or not.

How to print array with constant row space in C#?

I am trying to print a jagged array with a some kind of 'constant row spacing' to make it more clear to read. Here's default output which I receive :
And I wish to receive something similar to this :
Here is my array printing code :
for (int i = 0; i < level; i++)
{
for (int j = 0; j < level; j++)
Console.Write(string.Format("{0} ", matrix[i][j].ToString("0.00")));
Console.Write(Environment.NewLine + Environment.NewLine);
}
Any quick and simple way to reach this?
Here's an example for padding with width of 5 to the left
string.Format("{0:-5}", matrix[i][j].ToString("0.00"))
You can see here more options how you can pad with spaces

Displaying the values of a multidimensional array in a MessageBox

I am just now learning about multi-dimensional arrays and message boxes. I am currently have a issue in creating 2 columns in my message box. I can currently get it to print up the random numbers I need, but only in one column. Thanks for the help!
string msg = "";
Random numb = new Random();
int[,] thing = new int[ 10, 2 ];
thing[0, 0] = numb.Next(0,10);
thing[0, 1] = numb.Next(0,10);
thing[1, 0] = numb.Next(0,10);
thing[1, 1] = numb.Next(0,10);
thing[2, 0] = numb.Next(0,10);
thing[2, 1] = numb.Next(0,10);
thing[3, 0] = numb.Next(0,10);
thing[3, 1] = numb.Next(0,10);
thing[4, 0] = numb.Next(0,10);
thing[4, 1] = numb.Next(0,10);
thing[5, 0] = numb.Next(0,10);
thing[5, 1] = numb.Next(0,10);
thing[6, 0] = numb.Next(0,10);
thing[6, 1] = numb.Next(0,10);
thing[7, 0] = numb.Next(0,10);
thing[7, 1] = numb.Next(0,10);
thing[8, 0] = numb.Next(0,10);
thing[8, 1] = numb.Next(0,10);
thing[9, 0] = numb.Next(0,10);
thing[9, 1] = numb.Next(0,10);
foreach (int x in thing)
msg = msg + x + "\n";
MessageBox.Show(msg, "Table");
Change this:
foreach (int x in thing)
msg = msg + x + "\n";
MessageBox.Show(msg, "Table");
To :
for (int i = 0; i < thing.GetLength(0); i++)
msg += String.Format("{0} {1}\n", thing[i, 0], thing[i, 1]);
//msg += thing[i, 0] + " " + thing[i, 1] + "\n";
MessageBox.Show(msg, "Table");
Explanation:
Method GetLength(0) returns length of dimension for our x (it's basically like array.Length for simple array but with specific dimension) and we use i variable and for loop to iterate through it. In y we have only 2 elements so we can just use [0] and [1] indexes as we know there are only two elements there. This explains the line:
msg += thing[i, 0] + " " + thing[i, 1] + "\n";
Be careful with concatenating string like that, as if you don't add this space " " between your numbers compiler will just add them, so element like [33, 10] will be concatenated to string like : "43 \n" instead of "33 10 \n".
P.S.
So let's use String.Format method to make sure it's formatted well :
msg += String.Format("{0} {1}\n", thing[i, 0], thing[i, 1]);
I suspect that this question is a duplicate of an existing one, but I cannot find the appropriate precedent. So maybe we are in need of an answer explaining how to format a two-dimensional array for output. This is such an answer. :)
First thing to keep in mind is that the fact that you are displaying this using MessageBox is only barely relevant. What you are really asking is how to format a two-dimensional array as a string, where that string includes line-breaks between rows in your data, and the columns are lined up in the output. Once you have that string, you can display in any context that uses a fixed-space font (which is actually not the MessageBox…but it is not hard to create your own Form to use as a message box, where you can specify the font used to display the text) and have the output appear as you seem to be asking for.
For example, here's a console program that does what you want:
static void Main(string[] args)
{
StringBuilder sb = new StringBuilder();
Random random = new Random();
int[,] array = new int[10, 2];
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = random.Next(10);
if (j > 0)
{
sb.Append(", ");
}
sb.Append(array[i, j]);
}
sb.AppendLine();
}
Console.WriteLine(sb);
}
Note that I have consolidated the initialization of the array and the formatting of the values into a single piece of code. I have also used nested for loops to index each individual element in the array; this allows two things:
To initialize the array using loops instead of explicitly writing out each element as you did in your example.
To make it easy to recognize the end of a row in the array so that a line-break can be added to the output.
In your example, your random numbers are only ever a single digit. But if you were to want to format numbers that could vary in their number of digits, you would want to pad the output with spaces for the shorter numbers, so that the numbers in the columns of your output lined up. You can do that by adding a width specifier to the output, like this:
sb.AppendFormat("{0,2}", array[i, j]);
In the above, rather than using the default formatting as the previous code example does, I am explicitly specifying a format (and calling AppendFormat() instead of Append() to do so), and in that explicit format, I have included the text ,2, to indicate that I want the output string to have a minimum width of two characters. The method will add spaces as necessary to ensure that.
I have also changed from simple string concatenation to the use of StringBuilder. In your original example, string concatenation is probably not horrible, but it's also not a good habit to get into. When you are repeatedly appending text in a loop, you should always use StringBuilder. Otherwise, an excessive number of objects may be created, and as well an excessive amount of time spent copying character data may be spent. Using StringBuilder allows the text to be concatenated more efficiently.

C# coding guideline of how to use AsParallel() / Parellel.ForEach()

I want to calculate Jaccard similarity on 10 000 texts.
Jaccard Similarity is easy to calculate : length of the intersect divided by the length of the union.
string sTtxt1 = "some text one";
string sTtxt2 = "some text two";
string sTtxt3 = "some text three";
HashSet<string[]> hashText= new HashSet<string[]>();
hashText.Add(sTtxt1);
hashText.Add(sTtxt2);
hashText.Add(sTtxt3);
double[,] dSimilarityValue;
for (int i = 0; i < hashText.Count; i++)
{
dSimilarityValue[i, i] = 100.00;
for (int j = i + 1; j < dSimilarityValue.Count; j++)
{
dSimilarityValue[i, j] = (double) hashText.ElementAt(i).Intersect(hashText.ElementAt(j)).Count() / (double) hashText.ElementAt(i).Union(hashText.ElementAt(j)).Count();
}
}
With .NET4, What rules should I use to parallelizing ?
Thank you!
Just make the inner loop parallel for
Parallel Class
Parallel.For(0, N, i =>
{
// Do Work.
});
Parallel.For(j, dSimilarityValue.Count, i =>
{
dSimilarityValue[i, j] =
(double)hashText.ElementAt(i).Intersect(hashText.ElementAt(j)).Count() /
(double)hashText.ElementAt(i).Union(hashText.ElementAt(j)).Count();
});
And I think it would be better to declare the size of the Array in new.
Don't know what you mean by "rules".

Categories

Resources