Finding and replacing text in c# - c#

I need to add functionality in my program so that any file imported it will find the text within the "" of the addTestingPageContentText method as seen below. The two values on each line will then be added to a datagridview which has 2 columns so first text in first column then second in the 2nd column. How would i go about Finding the "sometext" ?
addTestingPageContentText("Sometext", "Sometext");
addTestingPageContentText("Sometext2", "Sometext2");
... continues n number of times.

Neither fast nor efficient, but it's easier to understand for those new to regular expressions:
while (!endOfFile)
{
//get the next line of the file
string line = file.readLine();
EDIT: //Trim WhiteSpaces at start
line = line.Trim();
//check for your string
if (line.StartsWith("addTestingPageContentText"))
{
int start1;
int start2;
//get the first something by finding a "
for (start1 = 0; start1 < line.Length; start1++)
{
if (line.Substring(start1, 1) == '"'.ToString())
{
start1++;
break;
}
}
//get the end of the first something
for (start2 = start1; start2 < line.Length; start2++)
{
if (line.Substring(start2, 1) == '"'.ToString())
{
start2--;
break;
}
}
string sometext1 = line.Substring(start1, start2 - start1);
//get the second something by finding a "
for (start1 = start2 + 2; start1 < line.Length; start1++)
{
if (line.Substring(start1, 1) == '"'.ToString())
{
start1++;
break;
}
}
//get the end of the second something
for (start2 = start1; start2 < line.Length; start2++)
{
if (line.Substring(start2, 1) == '"'.ToString())
{
start2--;
break;
}
}
string sometext2 = line.Substring(start1, start2 - start1);
}
}
However I would seriously recommend going through some of the great tutorials out there on the internet. This is quite a good one

The expression "\"[^"]*\"" would find each...

Related

C#: Need to split a string into a string[] and keeping the delimiter (also a string) at the beginning of the string

I think I am too dumb to solve this problem...
I have some formulas which need to be "translated" from one syntax to another.
Let's say I have a formula that goes like that (it's a simple one, others have many "Ceilings" in it):
string formulaString = "If([Param1] = 0, 1, Ceiling([Param2] / 0.55) * [Param3])";
I need to replace "Ceiling()" with "Ceiling(; 1)" (basically, insert "; 1" before the ")").
My attempt is to split the fomulaString at "Ceiling(" so I am able to iterate through the string array and insert my string at the correct index (counting every "(" and ")" to get the right index)
What I have so far:
//splits correct, but loses "CEILING("
string[] parts = formulaString.Split(new[] { "CEILING(" }, StringSplitOptions.None);
//splits almost correct, "CEILING(" is in another group
string[] parts = Regex.Split(formulaString, #"(CEILING\()");
//splits almost every letter
string[] parts = Regex.Split(formulaString, #"(?=[(CEILING\()])");
When everything is done, I concat the string so I have my complete formula again.
What do I have to set as Regex pattern to achieve this sample? (Or any other method that will help me)
part1 = "If([Param1] = 0, 1, ";
part2 = "Ceiling([Param2] / 0.55) * [Param3])";
//part3 = next "CEILING(" in a longer formula and so on...
As I mention in a comment, you almost got it: (?=Ceiling). This is incomplete for your use case unfortunately.
I need to replace "Ceiling()" with "Ceiling(; 1)" (basically, insert "; 1" before the ")").
Depending on your regex engine (for example JS) this works:
string[] parts = Regex.Split(formulaString, #"(?<=Ceiling\([^)]*(?=\)))");
string modifiedFormula = String.join("; 1", parts);
The regex
(?<=Ceiling\([^)]*(?=\)))
(?<= ) Positive lookbehind
Ceiling\( Search for literal "Ceiling("
[^)] Match any char which is not ")" ..
* .. 0 or more times
(?=\)) Positive lookahead for ")", effectively making us stop before the ")"
This regex is a zero-assertion, therefore nothing is lost and it will cut your strings before the last ")" in every "Ceiling()".
This solution would break whenever you have nested "Ceiling()". Then your only solution would be writing your own parser for the same reasons why you can't parse markup with regex.
Regex.Replace(formulaString, #"(?<=Ceiling\()(.*?)(?=\))","$1; 1");
Note: This will not work for nested "Ceilings", but it does for Ceiling(), It will also not work fir Ceiling(AnotherFunc(x)). For that you need something like:
Regex.Replace(formulaString, #"(?<=Ceiling\()((.*\((?>[^()]+|(?1))*\))*|[^\)]*)(\))","$1; 1$3");
but I could not get that to work with .NET, only in JavaScript.
This is my solution:
private string ConvertCeiling(string formula)
{
int ceilingsCount = formula.CountOccurences("Ceiling(");
int startIndex = 0;
int bracketCounter;
for (int i = 0; i < ceilingsCount; i++)
{
startIndex = formula.IndexOf("Ceiling(", startIndex);
bracketCounter = 0;
for (int j = 0; j < formula.Length; j++)
{
if (j < startIndex) continue;
var c = formula[j];
if (c == '(')
{
bracketCounter++;
}
if (c == ')')
{
bracketCounter--;
if (bracketCounter == 0)
{
// found end
formula = formula.Insert(j, "; 1");
startIndex++;
break;
}
}
}
}
return formula;
}
And CountOccurence:
public static int CountOccurences(this string value, string parameter)
{
int counter = 0;
int startIndex = 0;
int indexOfCeiling;
do
{
indexOfCeiling = value.IndexOf(parameter, startIndex);
if (indexOfCeiling < 0)
{
break;
}
else
{
startIndex = indexOfCeiling + 1;
counter++;
}
} while (true);
return counter;
}

C# - split a RichTextBox line in two based on the caret position

I've got a RichTextBox, here referred to as box.
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
That line there fetches the line the caret is in. It works excellently.
However, I have a need to get two strings from this. The first is everything on that line UP to the caret, and the second is everything on that line AFTER it.
For instance, if the line is How is you|r day going?, with | representing the caret, I would get How is you and r day going?, separately.
I wrote this monstrosity, which works:
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
string linebefore = "";
for (int i = 0; i < allbefore.Length; i++)
{
linebefore += allbefore[i];
if (allbefore[i] == '\n')
linebefore = "";
}
string lineafter = "";
for (int i = 0; i < allafter.Length; i++)
{
if (allafter[i] == '\n')
break;
else
lineafter += allafter[i];
}
It gives me the result I want, but involves looping through EVERY character in the entire box, which just hurts. Is there an easy way to do this I'm just missing? Thanks.
This might do the trick for you
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
var listOfStrings = new List<string>();
string[] splitedBox = currentline.Split('|');
foreach(string sp in splitedBox)
{
string[] lineleft = sp.Split('\n');
listOfStrings.Add(lineleft[lineleft.Count() - 1]);
}
In the first approach we are splitting the line by char | than finding if we have any \n if it exsist we are taking the values accordingly
Another approach could be
string box = "How is \n you|r day \n going?";
bool alllinesremoved = true;
while(alllinesremoved)
{
if(box.Contains('\n'))
{
if(box.IndexOf('\n') > box.IndexOf('|'))
{
box = box.Remove(box.IndexOf('\n'), (box.Length - box.IndexOf('\n')));
}
else
{
box = box.Remove(0, box.IndexOf('\n') + 1);
}
}
else
{
alllinesremoved = false;
}
}
string[] splitedBox = box.Split('|');
in the second approach we are removing the characters before and after the \n and then splitting the string. I think the second one seems more good to me.
Have you tried using line.split? Not sure if this is what you want.
Store the position of \n using indexOf and, if >= 0, that is, the string contains it, use substring and assign the value otherwise.
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
int newLinePos = allBefore.lastIndexOf("\n");
string lineBefore = ((newLinePos >= 0) ? (allBefore.substring(newLinePos + 1)) : (allBefore));
newLinePos = allafter.indexOf("\n");
string lineAfter = ((newLinePost >= 0) ? (allAfter.substring(0, newLinePos)) : (allAfter));

If a word in a foreach loop contains xxx, show previous word

If a word matches with a string I compare with, I want to see the previous word I checked. Sounds very hard to understand, so I hope the code explains it a bit better:
String line = "qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
foreach (string word in words)
{
if (word.Contains("xxx"))
{
Console.WriteLine(word.Last);
Console.Writeline(word.Next); //It doenst work this way, but I hope you understand the idea
}
}
What you need to do is have a variable that maintains the current state of your search. In your case, it's pretty simple as all you want to remember is the last word checked:
string line = "qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
string previousWord = "";
foreach (string word in words)
{
if (word.Contains("xxx"))
{
Console.WriteLine(previousWord);
}
previousWord = word;
}
Just store the last word you checked.
In addition, you should be using String.IndexOf() if you have any need for culture or case sensitivity awareness.
String line = "qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
string previous = words.First();
string next = "";
foreach (string word in words)
{
var currentIndex = (Array.IndexOf(words, word));
if (currentIndex + 1 < words.Length)
{
next = words[currentIndex + 1];
}
if (word.IndexOf("xxx", StringComparison.CurrentCulture) > -1)
{
Console.WriteLine(previous);
if (next == word)
{
Console.WriteLine("The match was the last word and no next word is available.");
}
else
{
Console.WriteLine(next);
}
}
else
{
previous = word;
}
}
In this particular case, "asdfg" is outputted as the previous and "zxcvb" is next. However, if you are looking instead for "zxcvb" as the match, "The match was the last word and no next word is available." would be outputted.
Just use a for loop instead of a foreach
String line = "qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
for (int i = 0; i < words.Length; i++)
{
if (words[i].Contains("xxx"))
{
// Check to make sure you to go beyond the first element
if (i - 1 > -1)
{
// Previous word
Console.WriteLine(words[i - 1]);
}
// Check to make sure you to go beyond the last element
if (i + 1 < words.Length)
{
// Next word
Console.WriteLine(words[i + 1]);
}
}
}
Console.ReadLine();
Results:
asdfg
zxcvb
Without Loop
You could also use Array.IndexOf()
String line = "qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
int index = Array.IndexOf(words, "xxx");
// Check to make sure you to go beyond the first element
if (index - 1 > -1)
{
// Previous word
Console.WriteLine(words[index - 1]);
}
// Check to make sure you to go beyond the last element
if (index != -1 && index + 1 < words.Length)
{
// Next word
Console.WriteLine(words[index + 1]);
}
Console.ReadLine();
String line = "xxx/qwerty/asdfg/xxx/zxcvb";
string[] words = line.Split('/');
for (int i = 0; i < words.Length; i++)
{
if (words[i].Contains("xxx"))
{
Console.WriteLine(words[i]); //current word
if (i == 0)
Console.WriteLine("No Previous Word");
else
Console.WriteLine(words[i - 1]); //PreviousWord
if (i == words.Length - 1)
Console.WriteLine("No Next Word");
else
Console.WriteLine(words[i + 1]); //NextWord
}
}
words[words.IndexOf(word) - 1] should do the trick.
Edit: Forget this. Almo's is nicer and not prone to Exceptions.

Generating new Sudoku grid C#

I’m trying to make a C# application using Visual Studio 2008, that solves Sudoku puzzles.
My problem is that I can’t seem to figure the code for generating a new puzzle by the application. The idea that I’m trying to implement is as follows:
Start with an empty puzzle
Generate numbers for all cells in the puzzle
Empty the appropriate number of cells, based on required level of difficulty
Solve the puzzle
Is the score for the puzzle in the acceptable range for the required level of difficulty?
6a. If NO -> Regenerate puzzle (go to 1.)
6b. If YES -> Puzzle generated (display it)
Used code for “New game” button:
//--------------------------------------------------
// Starting a new game menu button
//--------------------------------------------------
public void NewToolStripMenuItem_Click(System.Object sender, System.EventArgs e)
{
if (GameStarted) // this cheking part seems to work (message is displayed and game gets saved if selected)
{
MsgBoxResult response = (MsgBoxResult)(MessageBox.Show("Doriți salvarea jocului curent?", "Salvează jocul curent...", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question));
if (response == MsgBoxResult.Yes)
{
SaveGameToDisk(false);
}
else if (response == MsgBoxResult.Cancel)
{
return;
}
}
// Changing the cursor while generating
System.Windows.Forms.Cursor.Current = Cursors.WaitCursor;
ToolStripStatusLabel1.Text = "Se generează un puzzle nou...";
// Creating an instance for the SudokuPuzzle class
SudokuPuzzle sp = new SudokuPuzzle();
string puzzle = string.Empty;
// Determining the difficulty level selected (from menu objects)
if (EasyToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(1);
}
else if (MediumToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(2);
}
else if (DifficultToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(3);
}
else if (ExtremelyDifficultToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(4);
}
else if (EmptyPuzzleToolStripMenuItem.Checked)
{
puzzle = sp.GetPuzzle(5);
}
// Changing to default cursor
System.Windows.Forms.Cursor.Current = Cursors.Default;
StartNewGame();
// Initialisation of the grid
int counter = 0;
for (int row = 1; row <= 9; row++)
{
for (int col = 1; col <= 9; col++)
{
if (puzzle[counter].ToString() != "0")
{
SetCell(col, row, System.Convert.ToInt32(puzzle[counter].ToString()), (short)0);
}
counter++;
}
}
}
So the code for the next function called, GetPuzzle(1) :
//--------------------------------------------------
// Obtaining a new puzzle (of the required level)
//--------------------------------------------------
public string GetPuzzle(int level)
{
int score = 0;
string result;
do
{
result = GenerateNewPuzzle(level, ref score);
if (result != string.Empty)
{
// Verify if the generated puzzle is of the selected dificulty
switch (level)
{
// The average for dificutly 1
case 1:
if (score >= 42 && score <= 46)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 2
case 2:
if (score >= 49 && score <= 53)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 3 case 3:
if (score >= 56 && score <= 60)
{
goto endOfDoLoop;
}
break;
// The average for dificutly 4
case 4:
if (score >= 112 && score <= 116)
{
goto endOfDoLoop;
}
break;
}
}
} while (!false); // loops ending
endOfDoLoop:
return result;
}
Next function used is GenerateNewPuzzle():
//--------------------------------------------------
// Generating a new puzzle
//--------------------------------------------------
public string GenerateNewPuzzle(int level, ref int score)
{
int c;
int r;
string str;
int numberofemptycells = 0;
// Initializing the entire grid
for (r = 1; r <= 9; r++)
{
for (c = 1; c <= 9; c++)
{
actual[c, r] = 0;
possible[c, r] = string.Empty;
}
}
// Empty the stacks used
ActualStack.Clear();
PossibleStack.Clear();
// Complete by solving an empty grid
try
{
// First used logical methods to solve the grid
if (!SolvePuzzle())
{
// Then use brute force
SolvePuzzleByBruteForce();
}
}
catch (Exception)
{
// If there’s any error, return emptry string
return string.Empty;
}
// Create a copy for the actual array
actual_backup = (int[,])(actual.Clone());
// Set the number of empty cells based on the difficulty level
switch (level)
{
// For difficulty level 1
case 1:
numberofemptycells = RandomNumber(40, 45);
break;
// For difficulty level 2
case 2:
numberofemptycells = RandomNumber(46, 49);
break;
// For difficulty level 3
case 3:
numberofemptycells = RandomNumber(50, 53);
break;
// For difficulty level 4
case 4:
numberofemptycells = RandomNumber(54, 58);
break;
}
// Empty the stacks used by brute force
ActualStack.Clear();
PossibleStack.Clear();
BruteForceStop = false;
// Create empty cells
CreateEmptyCells(numberofemptycells);
// Convert the values from the actual array to string
str = string.Empty;
for (r = 1; r <= 9; r++)
{
for (c = 1; c <= 9; c++)
{
str += (string)(actual[c, r].ToString());
}
}
// Verrify that the puzzle has only one solution
int tries = 0;
do
{
totalscore = 0;
try
{
if (!SolvePuzzle())
{
// If puzzle is not solved and difficulty level is 1-3
if (level < 4)
{
// Choose another combination of cells to empty
VacateAnotherPairOfCells(ref str);
tries++;
}
else
{
// Puzzles of difficulty 4 don’t guranty a single solution
SolvePuzzleByBruteForce();
goto endOfDoLoop;
}
}
else
{
// The puzzle has 1 solution
goto endOfDoLoop;
}
}
catch (Exception)
{
return string.Empty;
}
// If too many tries are executed, exit at 50
if (tries > 50)
{
return string.Empty;
}
}
while (true);
endOfDoLoop:
// Return the obtained score and the puzzle as a string
score = totalscore;
return str;
}
And last useful (I think) function, VacateAnotherPairOfCells():
//--------------------------------------------------
// Empty another pair of cells
//--------------------------------------------------
private void VacateAnotherPairOfCells(ref string str)
{
int c;
int r;
// Search for a pair of cells to empty (the empty cells should be simetrical from the center of the grid)
do
{
c = RandomNumber(1, 9);
r = RandomNumber(1, 9);
} while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) == 0));
// Restore the value of the cell from the backup array
str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), (string)(actual_backup[c, r].ToString()));
// Restore the value of the simetrical cell
str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), (string)(actual_backup[10 - c, 10 - r].ToString()));
// Search for another pair of cells that can be emptyed
do
{
c = RandomNumber(1, 9);
r = RandomNumber(1, 9);
} while (!(int.Parse(str[(c - 1) + (r - 1) * 9].ToString()) != 0));
// Delete the cell from the string
str = str.Remove(System.Convert.ToInt32((c - 1) + (r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((c - 1) + (r - 1) * 9), "0");
// Delete the simetrical cell from the string
str = str.Remove(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), 1);
str = str.Insert(System.Convert.ToInt32((10 - c - 1) + (10 - r - 1) * 9), "0");
// Reinitilisation of the grid
short counter = (short)0;
for (int row = 1; row <= 9; row++)
{
for (int col = 1; col <= 9; col++)
{
if (System.Convert.ToInt32(str[counter].ToString()) != 0)
{
actual[col, row] = System.Convert.ToInt32(str[counter].ToString());
possible[col, row] = (string)(str[counter].ToString());
}
else
{
actual[col, row] = 0;
possible[col, row] = string.Empty;
}
counter++;
}
}
}
} }
The rest of the functions and code I didn't think to be necessary as everything else works. If I import an empty or partial puzzle the application can automatically solve it using the same methods used for solving the automatically generated grids. But when I click "New puzzle" from the menu, the application gets stuck with no error (so I have to kill the process).
Maybe this isn't the easiest method to generate a valid board, and I apologize for the length of the code, but I really need to fix and use this one. I tried to fix this myself, many times, but in the last 2 months I came to no solution (just a lot of frustration from my incompetence in this matter)… So I would appreciate any kind of help that I could get from here.
Problem solved!
There is actually no problem with the code above, my problem was given to the fact that I had some coding mistake in "SolvePuzzleByBruteForce()" function. The function in question was not posted here, so the code above needs no correction and it functions properly.
I can put the "SolvePuzzleByBruteForce()" if anyone wants to, but I find it irrelevant given the fact that it's nothing special and the internet is full of such functions anyway.
To reply to the comments:
#HighCore the use of goto is not relevant to my question.
#Mark Lakata the question was not vague. I stated the problem, the thing it needed to do, and the code used. And it wasn't homework problem as I'm not in school, nor would I try 2 months to make a homework.
#Wilson thank you for your comments, it helped me trace down and figure out the problem in the bad function.

C# For Loop with LIST using LINQ

I'm using LINQ and returning a list to my Business Logic Layer. I'mtrying to change one of the values in the list (changing the 'star' rating to an image with the number of stars).
Although the counter (i) appears to be working, the FOR loop is not working correctly. The first time through it stops at the correct IF but then it pops out at the ELSE statement for everything and all values end up with "star0.png." It appears as though I'm not cycling through the list??? Thanks in advance!
for (int i = 0; i < ReviewList.Count; i++)
{
string serviceCode = ReviewList[i].SERVICE.SERVICE_DESC;
if (serviceCode == "*")
{
ReviewList[i].SERVICE.SERVICE_DESC = "star1.png";
}
else if (serviceCode == "**")
{
ReviewList[i].SERVICE.SERVICE_DESC = "star2.png";
}
else if (serviceCode == "***")
{
ReviewList[i].SERVICE.SERVICE_DESC = "star3.png";
}
else if (serviceCode == "****")
{
ReviewList[i].SERVICE.SERVICE_DESC = "star4.png";
}
else
{
ReviewList[i].SERVICE.SERVICE_DESC = "star0.png";
}
}
If all values end up at star0.png, then you are cycling through the list. The fact that the else statement is the only code being executed for each element suggests a logical error -- did you perhaps mean to do something like this?
string serviceCode = ReviewList[i].SERVICE.SERVICE_CODE;
I dont think its an issue of the for loop working properly... your syntax is good and as written will iterate ReviewList.Count # of times.
I would step through and verify the contents of ReviewList first.
Let me know what you find
If you know each item will consist of a number of stars, why not do this?:
for (int i = 0; i < ReviewList.Count; i++)
{
string serviceCode = ReviewList[i].SERVICE.SERVICE_DESC;
ReviewList[i].SERVICE.SERVICE_DESC = "star" + serviceCode.Length + ".png";
}
Protection on double pass and with else condition
for (int i = 0; i < ReviewList.Count; i++)
{
string serviceCode = ReviewList[i].SERVICE.SERVICE_DESC;
if(!serviceCode.Contains(".png")) { // once name set should not be modified
if(serviceCode.Contains("*"))
ReviewList[i].SERVICE.SERVICE_DESC = "star" + serviceCode.Length + ".png";
else
ReviewList[i].SERVICE.SERVICE_DESC = "star0.png";
}
}
alternate LINQ approach
ReviewList.ForEach(rs=>if(!rs.SERVICE.SERVICE_DESC.Contains(".png"))
{ rs.SERVICE.SERVICE_DESC =
"star" + rs.SERVICE.SERVICE_DESC.Length + ".png"});

Categories