C# Array number sorting - c#

I have an array of numbers jumbled up from 0-9.
How do I sort them in ascending order?
Array.Sort doesn't work for me. Is there another way to do it?
Thanks in advance.
EDIT:
Array.Sort gives me this error.
Argument 1: cannot convert from 'string' to 'System.Array'
Right now it gives me this output:
0) VersionInfo.xml
2) luizafroes_singapore2951478702.xml
3) virua837890738.xml
4) darkwizar9102314425644.xml
5) snarterz_584609551.xml
6) alysiayeo594136055.xml
1) z-a-n-n2306499277.xml
7) zhangliyi_memories932668799030.xml
8) andy_tan911368887723.xml
9) config.xml
k are the numbers from 0-9
string[] valnames = rk2.GetValueNames();
foreach (string k in valnames)
{
if (k == "MRUListEx")
{
continue;
}
Byte[] byteValue = (Byte[])rk2.GetValue(k);
UnicodeEncoding unicode = new UnicodeEncoding();
string val = unicode.GetString(byteValue);
Array.Sort(k); //Error here
richTextBoxRecentDoc.AppendText("\n" + k + ") " + val + "\n");
}

Your problem is that k is not an Array but a string !
I have the feeling that this is what you want to do :
string[] valnames = rk2.GetValueNames();
valnames = valnames.OrderBy (s => int.Parse(s)).ToArray();
for (int i= 0 ; i < balnames.Lenght ; i++)
{
k = valenames[i];
if (k == "MRUListEx")
{
continue;
}
Byte[] byteValue = (Byte[])rk2.GetValue(k);
UnicodeEncoding unicode = new UnicodeEncoding();
string val = unicode.GetString(byteValue);
richTextBoxRecentDoc.AppendText("\n" + i + ") " + val + "\n");
}

Are you sure you have an array in integers or have you stored an array of System.Object, in which case you'll have problems with leading space.

You are trying to sort a String. That's not possible.
This code will give you the output you want:
string[] valnames = rk2.GetValueNames();
for (int i = valnames.Length - 1; i >= 0; i--)
{
string k = valnames[i];
if (k == "MRUListEx")
continue;
Byte[] byteValue = (Byte[])rk2.GetValue(k);
UnicodeEncoding unicode = new UnicodeEncoding();
string val = unicode.GetString(byteValue);
richTextBoxRecentDoc.AppendText("\n" + k + ") " + val + "\n");
}

Related

smaller string gives bigger file size

I am having a bit of a conundrum here... basically I am performing some very very basic file compression steps as follows:
open file and read as string/into a string
parse through the string, and replace repeating patterns with smaller size of text that represents the pattern (ex: aaaaaaaaaaa (11 chars) is replaced with [a#$%11] (8 chars))
save the new, smaller string, into a separate file (can compare sizes)
For some reason, even though the new string in memory is like, 3% smaller than the original string, when I save the string into a file, the file itself is BIGGER than the original file on the file system?? How is that even possible? If someone could explain that to me it would be great!
Here is the code I am using to do this:
void bkg_DoWork(object sender, DoWorkEventArgs e)
{
try
{
string file = File.ReadAllText(this.txt_CompressFilename.Text);
int olength = file.Length;
int nlength = 0;
decimal pct = 0;
string lastchar = "";
int count = 0;
List<RepeatingPattern> SinglePatterns = new List<RepeatingPattern>();
List<RepeatingPattern> DoublePatterns = new List<RepeatingPattern>();
List<RepeatingPattern> TriplePatterns = new List<RepeatingPattern>();
List<RepeatingPattern> QuadruplePatterns = new List<RepeatingPattern>();
UpdateProgress("Read file contents", 0, 1, 6);
UpdateProgress("Finding single character replacements.", pct, 1, 6);
//single character replaces.
for (int i = 0; i < olength; i++)
{
if (file[i].ToString() == lastchar)
count += 1;
else
{
//create a pattern, if the count is more than what a pattern's compressed pattern looks like to save space... 8 chars
//[a#$%#]
if (count > 7)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!SinglePatterns.Contains(ptn))
SinglePatterns.Add(ptn);
}
count = 0;
lastchar = file[i].ToString();
}
}
//handle possible trailing pattern
if (count > 7)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!SinglePatterns.Contains(ptn))
SinglePatterns.Add(ptn);
}
if (SinglePatterns.Count > 0)
for (int i = 0; i < SinglePatterns.Count; i++)
file = file.Replace(SinglePatterns[i].ToString(), SinglePatterns[i].ToReplaceString());
nlength = file.Length;
pct = (decimal)(((double)(olength - nlength) / olength) * 100);
UpdateProgress("Found and replaced " + SinglePatterns.Count, pct, 2, 6);
UpdateProgress("Finding double character replacements.", pct, 2, 6);
lastchar = "";
count = 0;
//double character replaces.
for (int i = 0; i + 1 < file.Length; i = i + 2)
{
if ("" + file[i] + "" + file[i + 1] == lastchar)
count += 1;
else
{
//create a pattern, if the count is more than what a pattern's compressed pattern looks like to save space... 8 chars
//[aa#$%#]
if (count > 8)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!DoublePatterns.Contains(ptn))
DoublePatterns.Add(ptn);
}
count = 0;
lastchar = "" + file[i] + "" + file[i + 1];
}
}
//handle possible trailing pattern
if (count > 8)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!DoublePatterns.Contains(ptn))
DoublePatterns.Add(ptn);
}
if (DoublePatterns.Count > 0)
for (int i = 0; i < DoublePatterns.Count; i++)
file = file.Replace(DoublePatterns[i].ToString(), DoublePatterns[i].ToReplaceString());
nlength = file.Length;
pct = (decimal)(((double)(olength - nlength) / olength) * 100);
UpdateProgress("Found and replaced " + DoublePatterns.Count, pct, 3, 6);
UpdateProgress("Finding triple character replacements.", pct, 3, 6);
lastchar = "";
count = 0;
//triple character replaces.
for (int i = 0; i + 2 < file.Length; i = i + 3)
{
if ("" + file[i] + "" + file[i + 1] + "" + file[i + 2] == lastchar)
count += 1;
else
{
//create a pattern, if the count is more than what a pattern's compressed pattern looks like to save space... 8 chars
//[aaa#$%#]
if (count > 9)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!TriplePatterns.Contains(ptn))
TriplePatterns.Add(ptn);
}
count = 0;
lastchar = "" + file[i] + "" + file[i + 1] + "" + file[i + 2];
}
}
//handle possible trailing pattern
if (count > 9)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!TriplePatterns.Contains(ptn))
TriplePatterns.Add(ptn);
}
if (TriplePatterns.Count > 0)
for (int i = 0; i < TriplePatterns.Count; i++)
file = file.Replace(TriplePatterns[i].ToString(), TriplePatterns[i].ToReplaceString());
nlength = file.Length;
pct = (decimal)(((double)(olength - nlength) / olength) * 100);
UpdateProgress("Found and replaced " + TriplePatterns.Count, pct, 4, 6);
UpdateProgress("Finding quadruple character replacements.", pct, 4, 6);
lastchar = "";
count = 0;
//triple character replaces.
for (int i = 0; i + 3 < file.Length; i = i + 4)
{
if ("" + file[i] + "" + file[i + 1] + "" + file[i + 2] + "" + file[i + 3] == lastchar)
count += 1;
else
{
//create a pattern, if the count is more than what a pattern's compressed pattern looks like to save space... 8 chars
//[aaaa#$%#]
if (count > 10)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!QuadruplePatterns.Contains(ptn))
QuadruplePatterns.Add(ptn);
}
count = 0;
lastchar = "" + file[i] + "" + file[i + 1] + "" + file[i + 2] + "" + file[i + 3];
}
}
//Handle possible trailing pattern
if (count > 10)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!QuadruplePatterns.Contains(ptn))
QuadruplePatterns.Add(ptn);
}
if (QuadruplePatterns.Count > 0)
for (int i = 0; i < QuadruplePatterns.Count; i++)
file = file.Replace(QuadruplePatterns[i].ToString(), QuadruplePatterns[i].ToReplaceString());
nlength = file.Length;
pct = (decimal)(((double)(olength - nlength) / olength) * 100);
UpdateProgress("Found and replaced " + QuadruplePatterns.Count, pct, 5, 6);
UpdateProgress("Saving new .cmp file...", pct, 5, 6);
string newpath = this.txt_FolderName.Text + "\\" + Path.GetFileName(this.txt_CompressFilename.Text);
newpath = newpath.Substring(0, newpath.LastIndexOf("."));
newpath = newpath + ".cmp";
File.WriteAllText(newpath, file);
stopwatch.Stop();
UpdateProgress("Compression completed! Time to compress file: " + string.Format("{0}", stopwatch.Elapsed), pct, 6, 6);
string report = "Compression report\n\n";
FileInfo inf = new FileInfo(this.txt_CompressFilename.Text);
FileInfo infNew = new FileInfo(newpath);
report += "Single character replacements made: " + SinglePatterns.Count + "\n\n";
report += "Double character replacements made: " + DoublePatterns.Count + "\n\n";
report += "Triple character replacements made: " + TriplePatterns.Count + "\n\n";
report += "Quadruple character replacements made: " + QuadruplePatterns.Count + "\n\n";
report += "Total compression ration achieved in string: " + pct + "% \n\n";
report += "Old file size: " + inf.Length + "\nNew file size: " + infNew.Length + " in bytes.";
report += "Total time to achieve compression: " + string.Format("{0}", stopwatch.Elapsed);
e.Result = report;
}
catch (Exception ex)
{
e.Result = ex;
}
}
Here is the code for the RepeatingPattern class...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Compressor
{
public class RepeatingPattern : IEquatable<RepeatingPattern>
{
public string RepeatingChar { get; set; }
public int Count { get; set; }
public RepeatingPattern()
{
this.RepeatingChar = "";
this.Count = -1;
}
public RepeatingPattern(string rchar, int count)
{
this.RepeatingChar = rchar;
this.Count = count;
}
public RepeatingPattern(string FromReplaceString)
{
FromReplaceString = FromReplaceString.Replace("[", "").Replace("]", "");
List<string> parts = FromReplaceString.Split(new string[] { "#$%" }, StringSplitOptions.None).ToList();
if (parts.Count != 2)
throw new ArgumentException("Invalid argument count. Must be in this format: [a#$%N]");
try
{
this.RepeatingChar = parts[0];
this.Count = int.Parse(parts[1]);
}
catch (Exception ex)
{
throw new ArgumentException("Unable to cast the argument and create an object from it. Error: " + ex.Message);
}
}
public override bool Equals(object obj)
{
RepeatingPattern tmp = obj as RepeatingPattern;
if (tmp != null)
return base.Equals(tmp);
else
throw new Exception("Invalid comparison type. Both objects must be of type RepeatingPattern");
}
public bool Equals(RepeatingPattern tmp)
{
return this.RepeatingChar == tmp.RepeatingChar && this.Count == tmp.Count;
}
public override int GetHashCode()
{
return this.RepeatingChar.GetHashCode() ^ this.Count.GetHashCode();
}
public override string ToString()
{
string retval = "";
for (int i = 0; i < this.Count; i++)
retval += this.RepeatingChar;
return retval;
}
public string ToReplaceString()
{
return "[" + this.RepeatingChar + "#$%" + this.Count + "]";
}
}
}
Out of curiosity, I have made an attempt at the code. Some differences:
I made a helper function to find runs in the text
I build a new string (using StringBuilder) as I go through the old string instead of replacing in the old string
I think my code is a bit simpler than yours. I have tested with:
Input: "aaaaaaaaaaabbbcdcdcdcdcdcdxxxxxxxxxxxxxxxxxxhello"
Output: "[a#$%11]bbb[cd#$%6][x#$%18]hello"
Here's the code. This is a first draft. Probably lots of improvements to make:
static int FindRun(string s, int start, int length)
{
if (start + length >= s.Length) return 0;
int numRuns = 0;
string pattern = s.Substring(start, length);
for (int i = start + length; i <= s.Length - length; i += length)
{
if (s.Substring(i, length) == pattern) numRuns += 1;
else break;
}
return numRuns;
}
static string EncodeString(string src)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < src.Length; i++)
{
string theRun = null;
int numRuns = 0;
// Find runs of lengths 4, 3, 2, 1
for (int j = 4; j >= 1; j--)
{
int runs = FindRun(src, i, j);
if (runs > 1) // Run found!
{
// Save it for later. Want to append the longest run
theRun = src.Substring(i, j);
numRuns = runs;
}
}
// No run? Just append the letter
if (theRun == null)
{
sb.Append(src[i]);
}
else
{
// This is the size of the run
int replacementStringSize = (numRuns * theRun.Length) + (theRun.Length - 1);
// This is the code to use as a replacement
String runCode = String.Format("[{0}#$%{1}]", theRun, numRuns + 1);
// Only append if the code length is smaller than the original run
if (runCode.Length < replacementStringSize)
{
sb.Append(runCode);
}
else
{
// Don't encode. Put original run back
for (int j = 0; j <= numRuns; j++)
{
sb.Append(theRun);
}
}
// Skip over the run
i += replacementStringSize;
}
}
return sb.ToString();
}
The root cause of the much larger output files is because of encoding. ChromeSetup.exe is 1,397,976 bytes. When the file is read in using File.ReadAllText it attempts to detect the string encoding. The string is 1,327,384 characters long in this case. Here's the key though, because of encoding each character isn't necessarily a single byte. For example in UTF-8 each character is 1 to 4 bytes. So then when the result string is written out a single character could become multiple bytes.
For reading/writing executables/binary files you're better off using File.ReadAllBytes()`File.WriteAllBytes()`.
While attempting to run your code I came across several other bugs. Here are the bugs I found.
1) In the double/triple/quad character replaces the for loop bounds should check up to the character that will be used.
//double character replaces.
for (int i = 0; i < file.Length; i = i + 2)
{
if ("" + file[i] + "" + file[i + 1] == lastchar)
This will cause an out of index exception if the file string is an odd number of characters. Add in a + 1 to fix this.
for (int i = 0; i + 1 < file.Length; i = i + 2)
For the triple this will be + 2, for quad + 3.
2) If the string ends with a repeating pattern this isn't handled correctly. In the for loops the pattern count is only checked when a different char is encountered. So if the pattern is at the end of the string it isn't detected. You could handle this by checking the count after the for loop.
if (count > 7)
{
//create and add a pattern to the list if necessary.
RepeatingPattern ptn = new RepeatingPattern(lastchar.ToString(), count);
if (!SinglePatterns.Contains(ptn))
SinglePatterns.Add(ptn);
}
3) count and lastchar should be reset before each for loop. If one for loop ends with count = 17 and the next for loop runs it would add a repeating pattern of count 17, which has already been replaced.
4) As others have mentioned, doing replacements in your input string as you go along has the potential to cause issues.
If you can post your RepeatingPattern code and your input text file we can run down the exact cause of your larger output file.
Edit: Running with your RepeatingPattern code I see another small bug. The pattern "aaaaaaaaaa" becomes "[a#$%9]a". it should be replacing one more character. This could be making your output string slightly longer than expected. To fix this, in the replacement for loops set count to 1 (instead of 0) when a new pattern is started.

Creating a simple equation calculator with C#

So this is a bit of homework I have. I have to create a calculator application that asks for user input then calculates it. The input must be in an equation format. For example: " x = 3 + 8 ", " x = 6 - 3 " or x = " 6 - 3 * 9 ".
My approach to this problem is to first break down the string user input and store it into an array of char:
private char[] userInput;
string input = Console.ReadLine();
input = input.Replace(" " ,"");
userInput = input.ToCharArray();
At this point, userInput will contain all char from input. Next, I look for the variable of equation by looping through the array, this should give me the first alphabet character it found:
char var = 'x';
for (int i = 0; i < userInput.Length; i++)
{
char c = userInput[i];
if (Char.IsLetter(c)){
var = c;
break;
}
}
Next, I will break the equation up with variable one side and all of the number and operator in the other side, separated by '=', then add all number and operator to a new char array:
//get '=' position
int equalPos = 0;
for (int i = 0; i < userInput.Length; i++)
{
char c = userInput[i];
if (Char.IsSymbol(c))
{
if (c.Equals('='))
{
equalPos = i;
break;
}
}
}
//add equation to new array
rightSide = new char[userInput.Length-equalPos];
int a = 0;
for (int i = equalPos + 1; i < userInput.Length; i++)
{
char c = userInput[i];
rightSide[a] = c;
a++;
}
At this point, the rightSide array will contain all of the number and operator as character. I can calculate this part by using System.Data.DataTable().Compute(). However, if I am not allowed to use any library, how could I implement this? The equation should only contain 1 variable(always appear on the left side of the equation), four basic operators (+-/*) and no parenthesis.
Your answer can be divided into two parts
First How to convert char array to a string type
Second How to convert a string to a executable code block
For the first part use this method:
char[] chars;
string s = new string(chars);
For the Second part IT IS TOO DIFFiCULT to find a way without any pre-written code to do so then you must use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, search for CompileAssemblyFromFile.
If you first split the string by the = operator you will get the right and left hand side. So on the right hand side of the equation, if the equation is 'x = 6 * 2 + 1', we have '6 * 2 + 1', so we can compute that and follow standard BIDMAS rules using a loop and switch:
i have removed all error checking, this solution is for when a user inputs a perfect equation in the form 'x = {equation}' or '{equation} = x'
Also to note, a string is a char[]
//get user input
Console.Write("Enter equation:");
string input = Console.ReadLine();
string[] splitInput = input.Split('=');
int index = char.IsLetter(splitInput[0].Replace(" ", "")[0]) ? 1 : 0;
string sideWithEquation = splitInput[index];
//Compute right hand side
string[] equation = sideWithEquation.Split(' ');
Using BIDMAS, and ignoring brackets and indices, we compute divison and multiplication first.
//compute for * and /
for (int i = 1; i < equation.Length - 1; i++)
{
string item = equation[i];
int num = 0;
switch (item)
{
case "*":
num = Convert.ToInt32(equation[i - 1]) * Convert.ToInt32(equation[i + 1]);
break;
case "/":
num = Convert.ToInt32(equation[i - 1]) / Convert.ToInt32(equation[i + 1]);
break;
}
if (num > 0)
{
equation[i - 1] = "";
equation[i] = "";
equation[i + 1] = num.ToString();
}
}
And then we comoute for addition and subtraction
//Now compute for + and -
equation = string.Join(" ", equation).Split(' ');
for (int i = 1; i < equation.Length - 1; i++)
{
string item = equation[i];
int num = 0;
switch (item)
{
case "+":
num = Convert.ToInt32(equation[i - 1]) + Convert.ToInt32(equation[i + 1]);
break;
case "-":
num = Convert.ToInt32(equation[i - 1]) - Convert.ToInt32(equation[i + 1]);
break;
}
if (num > 0)
{
equation[i - 1] = "";
equation[i] = "";
equation[i + 1] = num.ToString();
}
}
and then to display the value of x to the user again
string total = string.Join("", equation);
//display what x is
Console.WriteLine($"x = {int.Parse(total)}" );

Cannot print array elements in loop, error cannot convert from 'string' to 'string[]'

I am trying to print each line of string in my array into a separate text file, but I cannot seem to have the array with index in my data source, I keep getting in my data source at the WriteAllLines() method, the error:
Error CS1503 Argument 2: cannot convert from 'string' to 'string[]'
for having T_tag[l].
Can somebody help me understand this error?
string[] Colmn_No = ColmnN.ToArray();
int ArrayLength = Colmn_No.Length;
string[] Cleantag = new string[ArrayLength];
string[] CleanCage = new string[ArrayLength];
for (int i = 0; i <= ArrayLength - 1; i++)
{
Cleantag[i] = Colmn_SmpNm[i].Trim().ToUpper();
CleanCage[i] = Colmn_Cage[i].Trim().ToUpper();
}
string[] T_tag = new string[ArrayLength];
string[] A_tag = new string[ArrayLength];
for (int k = 0, l=0, m=0; k <= ArrayLength - 1; k++)
{
if (Cleantag[k].StartsWith("T"))
{
T_tag[l] = "<T>"+ Cleantag[k]+"</T><C>C</C><V>"+ CleanCage[k]+"</V>";
System.IO.File.WriteAllLines((RRfolder + "//" + Cleantag[k] + ".txt"), T_tag[l]);
l++;
}
//System.IO.File.WriteAllLines((RRfolder + "//" + Cleantag[k] + ".txt"), T_tag[l]);
1) Write 1 line
System.IO.File.WriteAllText((RRfolder + "//" + Cleantag[k] + ".txt"), T_tag[l]);
2) Or, write all lines (do that outside the for-loop)
System.IO.File.WriteAllLines((RRfolder + "//" + Cleantag[k] + ".txt"), T_tag);

Convert a Hex String to comma separated Hex String c#

I want to input a series of Hex numbers into a textBox and when the user hits a button separate each byte with a comma. AAFFBCEE becomes AA,FF,BC,EE (no comma on last byte). how can I convert a string value to this format?
string temp = "aaff4455";
string temp2 = "";
int size = temp.Length;
for (int i = 0; i < size; i += 2)
{
temp2 += temp.Substring(i, 2);
if ((i+2) < size)
temp2 += ",";
}
Why not use a 1-liner?
var str = "AABBCCDD";
var result = "";
str.ToCharArray()
.Select((c, i) => new { i, c })
.ToList()
.ForEach(c => result += (c.i > 0 && c.i % 2 == 0) ? "," + c.c : c.c.ToString());
(I'm still learning Linq so be nice!)

How can i read string values from a table , and append to a single string

I am reading all the string values from a table and adding to an array as follows.
da2.Fill(ds, "DNAiusTwitter_Table");
int counts = ds.Tables[0].Rows.Count;
for (int i = 0; i < counts; i++)
{
names[i, 0] = ds.Tables[0].Rows[i][3].ToString();
}
How can I get string append = 'name1','name2','name3','name4'; How can I pass those values to this below code:
for (int i = 0; i < 1; i++)
{
HtmlGenericControl scriptTagLinks = new HtmlGenericControl("script");
scriptTagLinks.Attributes["type"] = "text/javascript";
string scrip1 = "$(function () {$(\"[src='" + names[i, 0] + "']\"" + ").pinit();});";
var scrip = "var tweetUsers=['" +append + "'," + "'" + splitted[3]+"']";
scriptTagLinks.InnerHtml = scrip;
this.Controls.Add(scriptTagLinks);
}
If you don't need the array later in code, I would use a StringBuilder (System.Text namespace), it has better memory allocation if your table changes in size.
da2.Fill(ds, "DNAiusTwitter_Table");
int counts = ds.Tables[0].Rows.Count;
StringBuilder appendString = new StringBuilder();
for (int i = 0; i < counts; i++)
{
appendString.AppendFormat("{0},", ds.Tables[0].Rows[i][3].ToString());
}
This will add all the data to the builder, then in the second code snippet, do the following to convert the builder to a string stripping off the additional comma at the end. Also I don't think you need the for loop (loop through 1?) in the second snippet or is the 1 in the for loop a typo?
var scrip = "var tweetUsers=['" + appendString.ToString().TrimEnd(new char[] { ',' }) + "'," + "'" + splitted[3]+"']";
use string.join() method
Example
string.Join(your_array, ",")

Categories