So I'm new to working with browsers in Win-forms and I'm stuck a particular point.
What i want to do, for the browser to open a page(I've gotten this far). Once the page is open it must navigate to a particular part(It'somewhere in the middle of the page) and select it. Then copy and store it for when i need it, just the text.
I've been able to select all the text on a page by using the following code just as an example:
WebBrowser wb = (WebBrowser)sender;
wb.Document.ExecCommand("SelectAll", false, null);
wb.Document.ExecCommand("Copy", false, null);
richTextBox1.Text = Clipboard.GetText();
It can work for my program but I want to know if there is better way that will select just the text or info I need. If i can, place them in textboxes, or straight into my database.
This is the link to the page: http://www.lolking.net/news/league-trends-jul30
I want to select and get the info from these sections of the page:
Champion Pick Rates - Top 5 Increases and Decreases
Champion Win Rates - Top 5 Increases and Decreases
Champion Ban Rates - Top 5 Increases and Decreases
Any help would be appreciated.
Your foreach loop will look like this:
foreach (var item in list_ban)
{
string rtbpicker = item.ToString();
foreach (var comp in list_Comp)
{
int count = 0; //Counts for the number of occurences
foreach (Match m in Regex.Matches(rtbpicker, "" + comp.ToString() + ""))
{
int matchindex = m.Index;
int matchlength = m.Length;
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, " "); //Count just moves the index forward by however many postions the original index was shifted
if(Regex.Matches(rtbpicker, "" + comp.ToString() + "").Count > 1)
{
count++;
}
}
}
richTextBox6.Text += rtbpicker + "\n";
//rtbBan.AppendText(rtbpicker + System.Environment.NewLine);
}
I haven't got (yet) the whole solution but I can help you a bit:
Once you got the plain text from the FULLY LOADED webBrowser, and wrote in richTextBox1, then you can print the 3 part to other textboxes:
private void button_Click(object sender, EventArgs e)
{
List<string> rawhtml = new List<string>(); //List for the whole page
List<string> list_pick = new List<string>(); //PICK section
List<string> list_win = new List<string>(); //WIN section
List<string> list_ban = new List<string>(); //BAN section
rawhtml = richTextBox1.Lines.ToList(); //FILL the page to list
int ID_pick = 0;
int ID_win = 0;
int ID_ban = 0;
int ID_cmt = 0; // We need to specify the end of BAN section
for (int i = 0; i < rawhtml.Count; i++) //Search for the line number of section-start
{
if (rawhtml[i] == "Champion Pick Rates") ID_pick = i;
if (rawhtml[i] == "Champion Win Rates") ID_win = i;
if (rawhtml[i] == "Champion Ban Rates") ID_ban = i;
if (rawhtml[i].Contains("Comments")) ID_cmt = i;
}
// PICK
for (int i = ID_pick; i < ID_pick + (ID_win - ID_pick); i++) //Calculate the start and the end line-number
{
list_pick.AddRange(Regex.Split(rawhtml[i], "(?<=[)])")); //Split the five characters, without losing the ')'
}
foreach (var item in list_pick)
{
richTextBox2.AppendText(item + System.Environment.NewLine); //Optinal: Add to richtextbox
}
// WIN
for (int i = ID_win; i < ID_win + (ID_ban - ID_win); i++)
{
list_win.AddRange(Regex.Split(rawhtml[i], "(?<=[)])"));
}
foreach (var item in list_win)
{
richTextBox3.AppendText(item + System.Environment.NewLine);
}
// BAN
for (int i = ID_ban; i < ID_ban + (ID_cmt - ID_ban); i++)
{
list_ban.AddRange(Regex.Split(rawhtml[i], "(?<=[)])"));
}
foreach (var item in list_ban)
{
richTextBox4.AppendText(item + System.Environment.NewLine);
}
}
This code will make output from "Champion Win Rates" like:
Champion Win Rates
Top Five Biggest Increases
Urgot41.38%->43.67%(+2.29%)
Kennen47.7%->49.28%(+1.58%)
Lucian51.61%->53.1%(+1.49%)
Singed48.95%->50.31%(+1.36%)
Fiora53.48%->54.71%(+1.23%)
Top Five Biggest Decreases
Kassadin48.7%->46.67%(-2.03%)
Galio53.18%->51.42%(-1.76%)
Cho'Gath48.03%->46.37%(-1.66%)
Corki50.05%->48.43%(-1.62%)
Graves49.49%->47.98%(-1.51%)
Much better... ;)
I'm faced a problem with spaces, but i can't solve it yet.
I hope you understand this, if you have any question please comment!
Ps.: Sorry for bad eng
Pss.: I know this isn't the full solution, but i must share with you :)
And now the full solution, with perfect spaces. Regex was difficult to me, but I think this is more simple, however longer too.
private void btnspace_Click(object sender, EventArgs e)
{
richTextBox6.Text = null;
for (int i = 0; i < list_ban.Count; i++)
{
string rebuilder = ""; //for the output string (one line)
List<char> temp_chars = list_ban[i].ToCharArray().ToList(); //split one line into char sequence
int number_occur = 0; //occurence counter for numbers
int minus_occur = 0;// occurence counter for '-'
for (int j = 0; j < temp_chars.Count; j++)
{
// NUMBERS
// I don't wanted to hardcode the champions :/
if (number_occur < 2 && (temp_chars[j] == '1' || temp_chars[j] == '2' || temp_chars[j] == '3' || temp_chars[j] == '4' || temp_chars[j] == '5' || temp_chars[j] == '6' || temp_chars[j] == '7' || temp_chars[j] == '8' || temp_chars[j] == '9' || temp_chars[j] == '0')) //looks pretty, isn't?
{
temp_chars.Insert(j, ' '); //insert a space into char seq
j = j + 5; // in the longest case: 12.34, so skip 5 char, or 1 2. 3 4
number_occur = number_occur + 1; //for the difference percentage we don't need spaces, so insert by number only twice
}
// NUMBERS DONE
}
for (int j = 0; j < temp_chars.Count; j++)
{
// ( and -
if (temp_chars[j] == '-' || temp_chars[j] == '(')
{
if (temp_chars[j] == '-') minus_occur = minus_occur + 1; //if the difference is negative, there will be one more minus, which doesn't need space
if (minus_occur <= 1) temp_chars.Insert(j, ' ');
j = j + 1; //avoid endless loop
}
// ( and - DONE
}
foreach (var item in temp_chars)
{
rebuilder = rebuilder + item; //rebuild the line from the char list, with spaces
}
list_ban.RemoveAt(i); //replace the old spaceless lines...
list_ban.Insert(i, rebuilder);
richTextBox1.AppendText(list_ban[i] + System.Environment.NewLine);
}
}
I hope it's clear, i tried to comment everything. Good luck, and feel free to ask. Please mention if it's working because i want to answer this question perfectly :D
Ok, so this is my final solution, it works 100%, it takes your first answer, which you can see ;p and uses my regex.matches. I think the part that i added to the foreach loops, could be done in a method so you can just call it whenever you need it. I just haven't got to that yet! :)
private void button3_Click(object sender, EventArgs e)
{
List<string> rawhtml = new List<string>(); //List for the whole page
List<string> list_pick = new List<string>(); //PICK section
List<string> list_win = new List<string>(); //WIN section
List<string> list_ban = new List<string>(); //BAN section
List<string> list_Comp = new List<string>(); //Champion names
fillchamplist(list_Comp);
rawhtml = richTextBox1.Lines.ToList(); //FILL the page to list
int ID_pick = 0;
int ID_win = 0;
int ID_ban = 0;
int ID_cmt = 0; // We need to specify the end of BAN section
for (int i = 0; i < rawhtml.Count; i++) //Search for the line number of section-start
{
if (rawhtml[i] == "Champion Pick Rates") ID_pick = i;
if (rawhtml[i] == "Champion Win Rates") ID_win = i;
if (rawhtml[i] == "Champion Ban Rates") ID_ban = i;
if (rawhtml[i].Contains("Comments")) ID_cmt = i;
}
// PICK
for (int i = ID_pick; i < ID_pick + (ID_win - ID_pick); i++) //Calculate the start and the end line-number
{
list_pick.AddRange(Regex.Split(rawhtml[i], "(?<=[)])")); //Split the five characters, without losing the ')'
}
foreach (var item in list_pick)
{
string rtbpicker = item.ToString();
foreach (var comp in list_Comp)
{
int count = 0; //To see which match we working with later
foreach (Match m in Regex.Matches(rtbpicker, "" + comp.ToString() + "")) // Checks for all matches and cycles through them
{
if (count == 2) // if the count == 2, it means that its on its 3rd match(the one we dont wana give a space to
{
}
else // puts the space in
{
int matchindex = m.Index;
int matchlength = m.Length;
if (m.Length >= 2) // only champ names are >=2
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, "\t");
}
else
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, " "); // the count variable updates he index so the space doesnt occur before the % sign
}
if (Regex.Matches(rtbpicker, "" + comp.ToString() + "").Count > 0)// just to update the index for the 2nd %
{
count++;
}
}
}
}
rtbPick.AppendText(rtbpicker + System.Environment.NewLine); //Optinal: Add to richtextbox
}
// WIN
for (int i = ID_win; i < ID_win + (ID_ban - ID_win); i++)
{
list_win.AddRange(Regex.Split(rawhtml[i], "(?<=[)])"));
}
foreach (var item in list_win)
{
string rtbpicker = item.ToString();
foreach (var comp in list_Comp)
{
int count = 0;
foreach (Match m in Regex.Matches(rtbpicker, "" + comp.ToString() + ""))
{
if (count == 2)
{
}
else
{
int matchindex = m.Index;
int matchlength = m.Length;
if (m.Length >= 2)
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, "\t");
}
else
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, " ");
}
if (Regex.Matches(rtbpicker, "" + comp.ToString() + "").Count > 0)
{
count++;
}
}
}
}
rtbWin.AppendText(rtbpicker + System.Environment.NewLine);
}
// BAN
for (int i = ID_ban; i < ID_ban + (ID_cmt - ID_ban); i++)
{
list_ban.AddRange(Regex.Split(rawhtml[i], "(?<=[)])"));
}
foreach (var item in list_ban)
{
string rtbpicker = item.ToString();
foreach (var comp in list_Comp)
{
int count = 0;
foreach (Match m in Regex.Matches(rtbpicker, "" + comp.ToString() + ""))
{
if (count == 2)
{
}
else
{
int matchindex = m.Index;
int matchlength = m.Length;
if (m.Length >= 2)
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, "\t");
}
else
{
rtbpicker = rtbpicker.Insert(matchindex + matchlength + count, " ");
}
if (Regex.Matches(rtbpicker, "" + comp.ToString() + "").Count > 0)
{
count++;
}
}
}
}
rtbBan.AppendText(rtbpicker + System.Environment.NewLine);
}
}
This is the outcome:(doesn't show the tabs here for some reason)
Champion Pick Rates
Top Five Biggest Increases
Lucian 27.75% -> 32.3% (+4.55%)
Ahri 8.7% -> 11.3% (+2.6%)
Rengar 11.25% -> 13.84% (+2.59%)
Nidalee 10.7% -> 12.93% (+2.23%)
Tristana 30.07% -> 32.02% (+1.95%)
Top Five Biggest Decreases
Caitlyn 34.44% -> 30.63% (-3.81%)
Vayne 17.25% -> 15.69% (-1.56%)
Ezreal 15.08% -> 13.6% (-1.48%)
Renekton 13.84% -> 12.6% (-1.24%)
Lee Sin 30.54% -> 23.36% (-7.18%)
Ok so :D that works perfect for me, but that's cause i know what i want the outcome to be for this specific thing. Your method also works and i would actually recommend it for scenarios.
If you got any questions, dont be afraid to ask hey :)
Related
Currently I am making a AI based on text.
I have a database with a pattern for each answer
A pattern looks like [Who is the] Winner of the World Cup 2018
[] = Optional words
<> = Needed words
When I enter the sentence Who is the Winner of the World Cup 2018 my method should return the indentifier of the answer.
My database has 2 rows called "AnswerIndentifier" and "Pattern"
I did it myself and programmed this algoryhm:
private static bool MatchesPattern(string text, string pattern)
{
List<string> patternTokens = new List<string>();
string tok = "";
pattern = pattern.ToLower() + "[";
int state = 0;
for(int i = 0; i < pattern.ToCharArray().Length; i++)
{
char token = pattern[i];
if(token == '[')
{
if(tok != "")
{
patternTokens.Add("NEC" + char.MaxValue + tok);
tok = "";
}
state = 1;
continue;
}
if(token == ']' && state == 1)
{
i++;
state = 0;
patternTokens.Add("OPT" + char.MaxValue + tok);
tok = "";
continue;
}
if(token == ' ' && i + 1 < text.ToCharArray().Length && text[i + 1] == '[')
continue;
tok += token;
}
string[] patternTokensCopy = new string[patternTokens.Count];
for(int i = 0; i < patternTokens.Count; i++)
patternTokensCopy[i] = patternTokens[i];
int max = (int) Math.Pow(2, patternTokens.Where(x => x.StartsWith("OPT")).ToList().Count);
for(int i = 0; i < max; i++)
{
string binary = Convert.ToString(i, 2).PadLeft(patternTokensCopy.Where(x => x.StartsWith("OPT")).ToList().Count, '0');
for(int x = 0; x < patternTokensCopy.Where(t => t.StartsWith("OPT")).ToList().Count; x++)
if(binary[x] == '0')
{
List<string> optionalTokens = new List<string>();
foreach(string curpattern in patternTokensCopy)
if(curpattern.StartsWith("OPT"))
optionalTokens.Add(curpattern);
patternTokens.Remove(optionalTokens[x]);
}
string patternAsSentence = "";
foreach(string patternToken in patternTokens)
patternAsSentence += patternToken.Split(char.MaxValue)[1] + " ";
while(patternAsSentence[patternAsSentence.Length - 1] == ' ')
patternAsSentence = patternAsSentence.Substring(0, patternAsSentence.Length - 1);
patternAsSentence = patternAsSentence.Replace("\r", "").Replace(" ", " ");
int similarity = StringSimilarity.GetStringSimilarity(patternAsSentence, text);
if(text.Length < 6)
{
if(text == patternAsSentence)
return true;
}
else
{
if(similarity <= 6)
return true;
}
patternTokens = new List<string>();
patternTokensCopy.ToList().ForEach(x => patternTokens.Add(x));
}
return false;
}
The only changes are that the needed text must not marked with <> and the similarity check(see C# - Compare String Similarity)
I am a beginner in C# and i am trying to make a "hangman" game. I got stuck at the process when the player guess a letter.
If the word for example is DATA, the application only gets the first A in DATA.
I understand that i have to loop the word to get all the A´s but i am having touble with making it work!
here is my code for the method myGuess:
public void myGuess(String letter)
{
int plats = 0;
string wordToGuess = label4.Text;
plats = wordToGuess.IndexOf(letter);
string wordToShow = label5.Text;
//ersätt "_" med bokstaven på alla positioner bokstaven dyker upp
wordToShow = wordToShow.Substring(0, wordToGuess.IndexOf(letter)) + letter +
wordToShow.Substring(plats + 1, wordToShow.Length - (plats + 1));
label5.Text = wordToShow;
}
I have been trying to google it but because i am a beginner i don't understand the
suggestions people give. Hopefully it is a way to loop for more than one letter with IndexOf?
IndexOf returns the index of the first instance of the character in the string. You could manipulate your string using substring, but you'd be making it more complicated than you need to need. Instead, you can just loop through each of the characters in the String with a for loop:
for (int i = 0; i < wordToGuess.Length; i++ )
{
if (WordToGuess[i] == letter)
{
//Update the correctly guessed letters, (using value of i to determine which letter to make visible.)
}
}
label5.Text = wordToShow;
You can use this:
label4(wordToGuess): DATA
label5(wordToShow): ****
When you call myGuess('A')
label4(wordToGuess): DATA
label5(wordToShow): *A*A
When you call myGuess('T')
label4(wordToGuess): DATA
label5(wordToShow): *ATA
...
public void myGuess(char letter)
{
string wordToGuess = label4.Text;
string wordToShow = label5.Text;
if (wordToShow.Length == 0)
{
for (int i = 0; i < wordToGuess.Length; i++)
wordToShow += "*";
}
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i] == letter || wordToGuess[i] == wordToShow[i])
wordToShow = wordToShow.Remove(i,1).Insert(i, Char.ToString(letter));
}
label5.Text = wordToShow;
}
Here's a long solution that's probably overly generic.
List<int> findIndexes(string myStr, char letter)
{
var foundIndexes = new List<int>();
for (int i = 0; i < myStr.Length; i++)
{
if (myStr[i] == letter)
foundIndexes.Add(i);
}
return foundIndexes;
}
string ReplaceIndex(string s, int index, char letter){
return s.Substring(0, index )
+ letter
+ s.Substring(index + 1, s.Length - (index + 1));
}
void Main()
{
string s= "data";
string wordToShow = "____";
var letter = 'a';
var indexes = findIndexes(s, letter);
foreach (var index in indexes)
{
wordToShow = ReplaceIndex(wordToShow, index, letter);
}
Console.WriteLine (wordToShow);
}
A simple for loop should handle it.
for (int i = 0; i < wordToGuess.Length; i++)
{
if (wordToGuess[i].ToString().Equals(letter.ToString(), System.StringComparison.InvariantCultureIgnoreCase))
{
wordToShow = string.Format("{0}{1}{2}", wordToShow.Substring(0, i), letter, wordToShow.Substring(i, wordToShow.Length - (i + 1)));
}
}
Here's a fiddle: http://dotnetfiddle.net/UATeVJ
I am trying to read the data in a text file which is separated by commas. My problem, is that one of my data pieces has a comma within it. An example of what the text file looks like is:
a, b, "c, d", e, f.
I want to be able to take the comma between c and d and change it to a semicolon so that I can still use the string.Split() method.
using (StreamReader reader = new StreamReader("file.txt"))
{
string line;
while ((line = reader.ReadLine ()) != null) {
bool firstQuote = false;
for (int i = 0; i < line.Length; i++)
{
if (line [i] == '"' )
{
firstQuote = true;
}
else if (firstQuote == true)
{
if (line [i] == '"')
{
break;
}
if ((line [i] == ','))
{
line = line.Substring (0, i) + ";" + line.Substring (i + 1, (line.Length - 1) - i);
}
}
}
Console.WriteLine (line);
}
I am having a problem. Instead of producing
a, b, "c; d", e, f
it is producing
a, b, "c; d"; e; f
It is replacing all of the following commas with semicolons instead of just the comma in the quotes. Can anybody help me fix my existing code?
Basically if you find a closing " you recognize it as it was an opening quote.
Change the line:
firstQuote = true;
to
firstQuote = !firstQuote;
and it should work.
You need to reset firstquote to false after you hit the second quote.
else if (firstQuote == true) {
if (line [i] == '"') {
firstquote = false;
break;
}
Here is a simple application to get the required result
static void Main(string[] args)
{
String str = "a,b,\"c,d\",e,f,\"g,h\",i,j,k,l,\"m,n,o\"";
int firstQuoteIndex = 0;
int secodQuoteIndex = 0;
Console.WriteLine(str);
bool iteration = false;
//String manipulation
//if count is even then count/2 is the number of pairs of double quotes we are having
//so we have to traverse count/2 times.
int count = str.Count(s => s.Equals('"'));
if (count >= 2)
{
firstQuoteIndex = str.IndexOf("\"");
for (int i = 0; i < count / 2; i++)
{
if (iteration)
{
firstQuoteIndex = str.IndexOf("\"", firstQuoteIndex + 1);
}
secodQuoteIndex = str.IndexOf("\"", firstQuoteIndex + 1);
string temp = str.Substring(firstQuoteIndex + 1, secodQuoteIndex - (firstQuoteIndex + 1));
firstQuoteIndex = secodQuoteIndex + 1;
if (count / 2 > 1)
iteration = true;
string temp2= temp.Replace(',', ';');
str = str.Replace(temp, temp2);
Console.WriteLine(temp);
}
}
Console.WriteLine(str);
Console.ReadLine();
}
Please feel free to ask in case of doubt
string line = "a,b,mc,dm,e,f,mk,lm,g,h";
string result =replacestr(line, 'm', ',', ';');
public string replacestr(string line,char seperator,char oldchr,char newchr)
{
int cnt = 0;
StringBuilder b = new StringBuilder();
foreach (char chr in line)
{
if (cnt == 1 && chr == seperator)
{
b[b.ToString().LastIndexOf(oldchr)] = newchr;
b.Append(chr);
cnt = 0;
}
else
{
if (chr == seperator)
cnt = 1;
b.Append(chr);
}
}
return b.ToString();
}
I have this:
string curr = "";
if (emails.SelectedItem != null)
{
for (int i = 0; i <= 19; i++)
{
curr = (emails.SelectedItem.ToString()[i] + "." +
emails.SelectedItem.ToString()[i + 1]);
clone.Items.Add(curr);
}
}
However, whenever I run it, it gives me the "index was out of bounds of the array" error.
Why? What's the fix?
Also, how do I make it add the rest of the string (not just i + 1) to clone?
EXPLANATION OF CODE:
I'm trying to insert a period (.) after one letter of the word, then add it to clone. After that, I want to add a period after the SECOND letter, add to clone, period after third letter, add, etc...
However, I don't want to have it be t.h.i.s.i.s.t.h.e.n.a.m.e, I want it to just have one period at a time.
It should look like:
a.ntimatter
an.timatter
ant.imatter
anti.matter
etc...
if (emails.SelectedItem != null)
{
var item = emails.SelectedItem.ToString();
for (int i = 1; i < item.Length; i++)
{
clone.Items.Add(item.Insert(i, "."));
}
}
Try this
if (emails.SelectedItem != null) {
string text = emails.SelectedItem.ToString();
for (int i = 1; i < text.Length; i++) {
string textWithPeriod = text.Substring(0, i) + "." + text.Substring(i);
clone.Items.Add(textWithPeriod);
}
}
I am trying to get a count of all the times a byte sequences occurs in another byte sequences. It cannot however re-use a bytes if it already counted them. For example given the string
k.k.k.k.k.k. let's assume the byte sequence was k.k it would then find only 3 occurrences rather than 5 because they would be broke down like: [k.k].[k.k].[k.k]. and not like [k.[k].[k].[k].[k].k] where they over lap and essentially just shift 2 to the right.
Ideally the idea is to get an idea how a compression dictionary or run time encoding might look. so the goal would be to get
k.k.k.k.k.k. down to just 2 parts, as (k.k.k.) is the biggest and best symbol you can have.
Here is source so far:
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.IO;
static class Compression
{
static int Main(string[] args)
{
List<byte> bytes = File.ReadAllBytes("ok.txt").ToList();
List<List<int>> list = new List<List<int>>();
// Starting Numbers of bytes - This can be changed manually.
int StartingNumBytes = bytes.Count;
for (int i = StartingNumBytes; i > 0; i--)
{
Console.WriteLine("i: " + i);
for (int ii = 0; ii < bytes.Count - i; ii++)
{
Console.WriteLine("ii: " + i);
// New pattern comes with refresh data.
List<byte> pattern = new List<byte>();
for (int iii = 0; iii < i; iii++)
{
pattern.Add(bytes[ii + iii]);
}
DisplayBinary(bytes, "red");
DisplayBinary(pattern, "green");
int matches = 0;
// foreach (var position in bytes.ToArray().Locate(pattern.ToArray()))
for (int position = 0; position < bytes.Count; position++) {
if (pattern.Count > (bytes.Count - position))
{
continue;
}
for (int iiii = 0; iiii < pattern.Count; iiii++)
{
if (bytes[position + iiii] != pattern[iiii])
{
//Have to use goto because C# doesn't support continue <level>
goto outer;
}
}
// If it made it this far, it has found a match.
matches++;
Console.WriteLine("Matches: " + matches + " Orig Count: " + bytes.Count + " POS: " + position);
if (matches > 1)
{
int numBytesToRemove = pattern.Count;
for (int ra = 0; ra < numBytesToRemove; ra++)
{
// Remove it at the position it was found at, once it
// deletes the first one, the list will shift left and you'll need to be here again.
bytes.RemoveAt(position);
}
DisplayBinary(bytes, "red");
Console.WriteLine(pattern.Count + " Bytes removed.");
// Since you deleted some bytes, set the position less because you will need to redo the pos.
position = position - 1;
}
outer:
continue;
}
List<int> sublist = new List<int>();
sublist.Add(matches);
sublist.Add(pattern.Count);
// Some sort of calculation to determine how good the symbol was
sublist.Add(bytes.Count-((matches * pattern.Count)-matches));
list.Add(sublist);
}
}
Display(list);
Console.Read();
return 0;
}
static void DisplayBinary(List<byte> bytes, string color="white")
{
switch(color){
case "green":
Console.ForegroundColor = ConsoleColor.Green;
break;
case "red":
Console.ForegroundColor = ConsoleColor.Red;
break;
default:
break;
}
for (int i=0; i<bytes.Count; i++)
{
if (i % 8 ==0)
Console.WriteLine();
Console.Write(GetIntBinaryString(bytes[i]) + " ");
}
Console.WriteLine();
Console.ResetColor();
}
static string GetIntBinaryString(int n)
{
char[] b = new char[8];
int pos = 7;
int i = 0;
while (i < 8)
{
if ((n & (1 << i)) != 0)
{
b[pos] = '1';
}
else
{
b[pos] = '0';
}
pos--;
i++;
}
//return new string(b).TrimStart('0');
return new string(b);
}
static void Display(List<List<int>> list)
{
//
// Display everything in the List.
//
Console.WriteLine("Elements:");
foreach (var sublist in list)
{
foreach (var value in sublist)
{
Console.Write("{0,4}", value);
}
Console.WriteLine();
}
//
// Display total count.
//
int count = 0;
foreach (var sublist in list)
{
count += sublist.Count;
}
Console.WriteLine("Count:");
Console.WriteLine(count);
}
static public int SearchBytePattern(byte[] pattern, byte[] bytes)
{
int matches = 0;
// precomputing this shaves some seconds from the loop execution
int maxloop = bytes.Length - pattern.Length;
for (int i = 0; i < maxloop; i++)
{
if (pattern[0] == bytes[i])
{
bool ismatch = true;
for (int j = 1; j < pattern.Length; j++)
{
if (bytes[i + j] != pattern[j])
{
ismatch = false;
break;
}
}
if (ismatch)
{
matches++;
i += pattern.Length - 1;
}
}
}
return matches;
}
}
Refer to the post to get the non binary of the file should be, here is the binary data:
011010110010111001101011001011100110101100101110011010110010111001101011001011100110101100101110 I am hope to have it smaller than how it started.
private static int CountOccurences(byte[] target, byte[] pattern)
{
var targetString = BitConverter.ToString(target);
var patternString = BitConverter.ToString(pattern);
return new Regex(patternString).Matches(targetString).Count;
}
With this solution you'd have access to the individual indexes that matched (while enumerating) or you could call Count() on the result to see how many matches there were:
public static IEnumerable<int> Find<T>(T[] pattern, T[] sequence, bool overlap)
{
int i = 0;
while (i < sequence.Length - pattern.Length + 1)
{
if (pattern.SequenceEqual(sequence.Skip(i).Take(pattern.Length)))
{
yield return i;
i += overlap ? 1 : pattern.Length;
}
else
{
i++;
}
}
}
Call it with overlap: false to solve your problem or overlap: true to see the overlapped matches (if you're interested.)
I have a couple of other methods with slightly different API (along with better performance) here, including one that work directly on streams of bytes.
quick and dirty with no regex. although i'm not sure if it answers the intent of the question, it should be relatively fast. i think i am going to run some timing tests against regex to see for sure the relative speeds:
private int CountOccurrences(string TestString, string TestPattern)
{
int PatternCount = 0;
int SearchIndex = 0;
if (TestPattern.Length == 0)
throw new ApplicationException("CountOccurrences: Unable to process because TestPattern has zero length.");
if (TestString.Length == 0)
return 0;
do
{
SearchIndex = TestString.IndexOf(TestPattern, SearchIndex);
if (SearchIndex >= 0)
{
++PatternCount;
SearchIndex += TestPattern.Length;
}
}
while ((SearchIndex >= 0) && (SearchIndex < TestString.Length));
return PatternCount;
}
private void btnTest_Click(object sender, EventArgs e)
{
string TestString1 = "k.k.k.k.k.k.k.k.k.k.k.k";
string TestPattern1 = "k.k";
System.Console.WriteLine(CountOccurrences(TestString1, TestPattern1).ToString()); // outputs 6
System.Console.WriteLine(CountOccurrences(TestString1 + ".k", TestPattern1).ToString()); // still 6
System.Console.WriteLine(CountOccurrences(TestString1, TestPattern1 + ".").ToString()); // only 5
}