I have the following code:
string checkedItemListBoxPName;
string checkedItemListBoxPID;
int selectedProcessIndex;
private void processes_checkedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (e.NewValue == CheckState.Checked)
{
for (int j = 0; j < processes_checkedListBox.Items.Count; ++j)
{
if (e.Index != j)
{
processes_checkedListBox.SetItemChecked(j, false);
}
}
selectedProcessIndex = processes_checkedListBox.SelectedIndex;
MessageBox.Show(selectedProcessIndex.ToString());
string checkedProcess = processes_checkedListBox.Items[selectedProcessIndex].ToString();
string[] checkedProcessElements = checkedProcess.Split(new string[] { ".exe" }, StringSplitOptions.None);
checkedItemListBoxPName = checkedProcessElements[0];
checkedItemListBoxPID = checkedProcessElements[1].Trim();
MessageBox.Show(checkedProcessElements[0].ToString());
MessageBox.Show(checkedItemListBoxPID.ToString());
}
}
This method is called when I check a checkbox from my checkBoxList. In the beginning I am unchecking all the other previous checked boxes so that I will always have just one checked.
In selectedProcessIndex I store the index of the checked box so that I can access its text a little while after in string checkedProcess = processes_checkedListBox.Items[selectedProcessIndex].ToString();.
Everything works fine except the fact that when I check the very first box (index = 0) or the 33rd box, I receive System.IndexOutOfRangeException: Index was outside the bounds of the array.
I don't know what is going on with those specific positions. Why 0 and 33 can't be handled.
I have 35 checkboxes total, from 0 to 34, as I said.
The data from those positions is just like the other, it is visible, and has nothing special.
Any suggestion is appreciated!
I think you get this error because when you check your elements on position 0 and 33 the method checkedProcess don't return a string containing the chars ".exe". The algorithm tries to split your string. If there isn't found any ".exe" in it .split() will return an array with only one element on position zero. In this case the new splitted array is the old unsplitted string).
checkedProcessElements[1].Trim(); tries to read a value outside the arrays range because its length is only 1.
Related
I've been coding in C# (winforms) for a project for 2 weeks now. My goal is to build a GUI for an FFT-Analysis (frequency-realm).
my Problem:
I keep running into the same problem: i receive 1024 int values (one blocksize) separated by white spaces in one string via serial port and then terminated by \n into a buffer uart_buf. To obtain numeric values, i use uart_buf.split(' ') into a string[] parse_buf and then try to access a single value in ASCII-format like this: parse_buf[i] = val_buf. This i then try to form into a numeric via value = int.Parse(val_buf), without success: System.ArgumentNullException: value cant be NULL.
What I've tried:
value = int.Parse(parse_buf[i]); This returns a format exception
printing parse_buf[i] to a textbox shows an expected value (the received data is correct)
observing the main buffer uart_buf shows valid data like this: "41 30 2 0 0 0 0 0 0 0 3 40 500 69..."
starting from index 1 (or any other) instead of 0 changes nothing
What I don't get:
A single element (ergo a string) of parse_buf contains a value in text-form, e.g. "41". I want to save it to a regular string val_buf, which i should be able to parse to int. Why is every string accessed via parse_buf[i] null?
Code-Fragments:
private void displayData(object o, EventArgs e)
{
parse_buf = uart_buf.Split(' ');
tb_data.Text = parse_buf[0]; //this shows valid data in a tb
for (i = 1; i < parse_buf.Length; i++) //about 1024 loops
{
//problem area:
parse_buf[i] = val_buf;
fft = int.Parse(val_buf);
//ignore this:
f = i * 20;
chart1.Series[0].Points.AddXY(f, fft);
}
}
I usually work in C with embeded systems, so sorry for not seeing the problem instantly. Thanks.
private void DisplayData(object o, EventArgs e)
{
parse_buf = uart_buf.Split(' ');
tb_data.Text = parse_buf[0]; //this shows valid data in a tb
for (i = 0; i < parse_buf.Length; i++) //about 1024 loops
{
//problem area:
int.TryParse(parse_buf[i], out ftt);
//ignore this:
chart1.Series[0].Points.AddXY(i * 20, fft);
}
}
I'm working on something for school, just a basic score calculator. I know it's not the prettiest code, but it works and that's more what the class is focused on here at the beginning.
The only issue that I have is that whenever I click "Display" it prints out 20 0s. 20 is the length of the array. Everything else is working. It adds the number I input into the array and replaces the 0s. But I don't want it to have 0s at all unless I specifically type them in.
Any help is appreciated.
Full code:
// Creates the list that displays the score
List<string> scoreList = new List<string>();
// Array to store up to 20 scores
int[] scoreArray = new int[20];
// class level variable to store current open slot in the array
int openSlot = 0;
public Form1()
{
InitializeComponent();
}
// Initializes variables that hold our math total and count of numbers entered
int total = 0;
int count = 0;
private void btnExit_Click(object sender, System.EventArgs e)
{
this.Close();
}
private void btnAdd_Click(object sender, System.EventArgs e)
{
if (openSlot <= scoreArray.GetUpperBound(0))
{
try
{
// Basic math for conversion of entered number and calculating total numbers entered
// and the averages of those numbers
int score = Convert.ToInt32(txtScore.Text);
total += score;
count += 1;
int average = total / count;
txtScoreTotal.Text = total.ToString();
txtScoreCount.Text = count.ToString();
txtAverage.Text = average.ToString();
txtScore.Focus();
}
catch(System.FormatException) // Makes sure that the user enters valid character into box
{
MessageBox.Show("Please enter valid number into box");
return;
}
// Adds the most recent entered number to the Score List
scoreList.Add(txtScore.Text);
}
// if statement to make sure that there is still room in the array to store the
// new entry
if (openSlot > scoreArray.GetUpperBound(0)) // GetUpperBound(0) returns the index of the last element in the first dimension
{
MessageBox.Show("The array is full! The most recent number was not added.");
txtScore.SelectAll();
txtScore.Focus();
return;
}
// Assigns a variable as an integer from the score text box
// to allow us to numerically sort the numbers in the scoreArray
int scoreParse = Int32.Parse(txtScore.Text);
// move the most recent number to the current open slot in the score array
scoreArray[openSlot] = scoreParse;
// add 1 to openSlot
openSlot += 1;
}
private void btnClear_Click(object sender, EventArgs e)
{
// Clears all input fields and resets variables to 0
openSlot = 0;
total = 0;
count = 0;
txtScore.Text = "";
txtScoreTotal.Text = "";
txtScoreCount.Text = "";
txtAverage.Text = "";
txtScore.Focus();
// Clears the array and list
int[] clearScoreArray = new int[20];
scoreArray = clearScoreArray;
List<string> clearScoreList = new List<string>();
scoreList = clearScoreList;
}
private void btnDisplay_Click(object sender, EventArgs e)
{
// If array has no stored values, display a MessageBox that informs user
if (scoreArray == null || scoreArray.Length == 0)
{
MessageBox.Show("There are no numbers to display");
return;
}
//move focus to the code textbox
txtScore.Focus();
// Creates a blank string variable named scr to input the scores into
// for the MessageBox
string scr = "";
foreach (var scoreAdded in scoreArray)
{
// Adds variable scr as the string to display
scr += scoreAdded + "\n";
}
// Sorts the array from lowest to highest number
Array.Sort(scoreArray);
// Displays a message box with the scores that were added
MessageBox.Show(scr);
}
}
When you declare a set amount of arrays (In your place it's 20), they get some sort of value, normally it's 0. Keep this is mind when you are using myArrayHere.length, cause it will check how many arrays have been declared (int[] array) and initialized (... = new array[]), not how many have been modified (given a value).
Best solution, IMO is creating a function, that would know how many elements in an array you will need or how many of them you are using (just have a function, that returns the amount of used variables, by checking it with a loop, and then modifying it later on... but that is one way to fix this issue, and there are better fixes than these I pointed out, but as I see you are newer to C# (prob.) fixing your issues with ok'ish code is good, as your first project should be meant for learning, later on, you can improve it and heck, if you are looking to become a pro, take some Programming courses on how to improve your code in general).
Good luck!
-Normantas
You can use nullable if you dont want zero as default value.
int? [] array = new int?[20] ;
Welcome to SO!
When an object is initially declared there is a default initialization value. In this case, 0 is the default value for an int in C#. The default value can often be changed at the initialization of the object if there's a supporting constructor.
When the int[] scoreArray = new int[20]; is declared, all 20 variables are assigned the value of 0. This is because C# does not allow uninitialized variables.
This link shows all default initialization values for C#.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table
I am relatively new to c#, I am creating an windows application which would read all the lines from a text file. The user will input the string which needs to be replaced in Column[0] and the text with which it needs to be replaced in Column1 of the DataGridView control.
I have created two string arrays column0 and column1.
However, I am getting an error while replacing the string in line (column0, column1)
The following is my code:
string[] column0 = new string[dgvMapping.Rows.Count];
string[] column1 = new string[dgvMapping.Rows.Count];
int j = 0;
foreach(DataGridViewRow row in dgvMapping.Rows)
{
if (!string.IsNullOrEmpty(Convert.ToString(row.Cells[0].Value)))
{
column0[j] = Convert.ToString(row.Cells[0].Value);
column1[j] = Convert.ToString(row.Cells[1].Value);
j++;
}
}
var _data = string.Empty;
String[] arrayofLine = File.ReadAllLines(ofd.FileName);
using (StreamWriter sw = new StreamWriter(ofd.FileName + ".output"))
{
for (int i = 0; i < arrayofLine.Length; i++)
{
string line = arrayofLine[i];
line = line.Replace(column0[i], column1[i]);
sw.WriteLine(line);
}
}
I am using OpenFileDialog to select the file.
The Error While Executing:
You are looping around a file of unknown number of lines, and assuming that the count of lines in the grid is exactly the same as that of the file. Your code will only work if both the file and the gridView have the same number of lines.
One of the solutions, is to loop over the array of lines (as you have already did), and search for the GridViewRow in which the current line contains a key in your DGV. If this is the case, then replace all the occurences of the key by the value (obtained from the gridView) in that line, otherwise do nothing.
Check out the code below :
// Convert the row collection to a list, so that we could query it easily with Linq
List<DataGridViewRow> mySearchList = dataGridView1.Rows.Cast<DataGridViewRow>().ToList();
const int KEY_INDEX = 0; // Search index in the grid
const int VALUE_INDEX = 1; // Value (replace) index in the grid
for (int i = 0; i < arrayofLines.Length; i++)
{
string line = arrayofLines[i];
// Get data grid view Row where this line contains the key string
DataGridViewRow matchedRow = mySearchList.FirstOrDefault(obj => line.Contains(obj.Cells[KEY_INDEX].Value.ToString()));
// If this row exists, replace the key with the value (obtained from the grid)
if (matchedRow != null)
{
string key = matchedRow.Cells[KEY_INDEX].Value.ToString();
string value = matchedRow.Cells[VALUE_INDEX].Value.ToString();
line = line.Replace(key, value);
sw.WriteLine(line);
}
else
{
// Otherwise, do nothing
}
}
Stuartd is correct… there are more lines in the file than there are elements to search. I am not sure what the search is doing in a sense that it seems somewhat limited. The code appears to search for each item depending on what line it is. The searched value in column 0 and the replace value in column 1 of row 0… will only replace those values for the FIRST line in the file. The DataGridViews second row values will search/replace only the SECOND line and so on. This seems odd.
Example the two string arrays (column0 and column1) have sizes set to the number of rows in dgvMapping. Let’s say there are 5 rows in the grid, then the array sizes will be 5 strings. When you start the loop to write the strings, the loop starts at 0 and stops at the number of lines in the file. The code uses this i variable as an index into the two arrays. If there are more lines in the file, than there are rows in the grid… then you will get the error.
Again, this seems odd to do the search and replace this way. Assuming you want to search for EACH term in all the rows in column 0 and replace the found searched string with the replace string in column 1, then you will need to loop through EACH row of the grid for EACH line in the file. This will replace ALL the search/replace terms in the grid with ALL the lines in the file. If this is what you what to accomplish below is one way to achieve this, however…there are possibly better ways to accomplish this.
The code below reads the file into one big string. Then the code loops through ALL the grid rows to search/replace the strings in the big string. Hope this helps.
string bigString = File.ReadAllText(ofd.FileName);
try {
using (StreamWriter sw = new StreamWriter(ofd.FileName + ".output")) {
for (int k = 0; k < dgvMapping.Rows.Count; k++) {
if (dgvMapping.Rows[k].Cells[0].Value != null && dgvMapping.Rows[k].Cells[1].Value != null) {
string searchTerm = dgvMapping.Rows[k].Cells[0].Value.ToString();
string replaceTerm = dgvMapping.Rows[k].Cells[1].Value.ToString();
if (searchTerm != "") {
bigString = bigString.Replace(searchTerm, replaceTerm);
} else {
// one of the terms is empty
}
} else {
// one of the terms is null}
}
}
sw.WriteLine(bigString);
}
}
catch (Exception ex) {
MessageBox.Show("Write Erro: " + ex.Message);
}
I'm making a sudoku in Windows Form Application.
I have 81 textboxes and I have named them all textBox1a, textBox1b... textBox2a, textBox2b...
I want to make it so that if any of the textboxes, in any of the rows, is equal to any other textbox in the same row, then both will get the background color red while the textboxes are equal.
I tried using this code just for test:
private void textBox1a_TextChanged_1(object sender, EventArgs e)
{
while (textBox1a.Text == textBox1b.Text)
{
textBox1a.BackColor = System.Drawing.Color.Red;
textBox1b.BackColor = System.Drawing.Color.Red;
}
It didn't work, and I don't know where I should put all this code, I know I shouldn't have it in the textboxes.
Should I use a code similar to this or is it totally wrong?
You want to iterate over the collection of text boxes just once, comparing it to those that haven't yet been compared against. If you have your textboxes in an array (let's call it textBoxes), and know which one was just changed (e.g. from the textChanged handler), you could do:
void highlightDuplicates(int i) // i is the index of the box that was changed
{
int iVal = textBoxes[i].Text;
for (int j = 0; j < 82; j++)
{
// don't compare to self
if (i == j) return;
if (textBoxes[j].Text == iVal)
{
textBoxes[i].BackgroundColor = System.Drawing.Color.Red;
textBoxes[j].BackgroundColor = System.Drawing.Color.Red;
}
}
}
If you wanted to get fancier, you could put your data in something like: Dictionary<int, TextBox>, where the key is the value and the TextBox is a reference to the text box with that value. Then you can quickly test for duplicate values with Dictionary.Contains() and color the matching text box by getting its value.
I think your current code would result in an infinite loop. The textboxes' values can't change while you are still in the event handler, so that loop would never exit.
If all of your boxes are named according to one convention, you could do something like this. More than one input can use the same handler, so you can just assign this handler to all the boxes.
The following code is not tested and may contain errors
private void textBox_TextChanged(object sender, EventArgs e){
var thisBox = sender as TextBox;
//given name like "textBox1a"
var boxNumber = thisBox.Name.SubString(7,1);
var boxLetter = thisBox.Name.SubString(8,1);
//numbers (horizontal?)
for(int i = 1; i<=9; i++){
if(i.ToString() == boxNumber)
continue; //don't compare to self
var otherBox = Page.FindControl("textBox" + i + boxLetter) as TextBox;
if (otherBox.Text == thisBox.Text)
{
thisBox.BackColor = System.Drawing.Color.Red;
otherBox.BackColor = System.Drawing.Color.Red;
}
}
//letters (vertical?)
for(int i = 1; i<=9; i++){
var j = ConvertNumberToLetter(i); //up to you how to do this
if(j == boxLetter)
continue; //don't compare to self
var otherBox = Page.FindControl("textBox" + boxNumber + j) as TextBox;
if (otherBox.Text == thisBox.Text)
{
thisBox.BackColor = System.Drawing.Color.Red;
otherBox.BackColor = System.Drawing.Color.Red;
}
}
}
I believe you will be more effective if create an Array (or a List) of Integers and compare them in memory, against compare them in UI (User Interface).
For instance, you could:
1) Create an Array of 81 integers.
2) Everytime the user input a new number, you search for it in that Array. If found, set the textbox as RED, otherwise, add the new value to that array.
3) The ENTER event may be allocated fot the entire Textboxes (utilize the Handles keyword with all Textboxes; like handles Text1.enter, Text2.enter, Text3.enter ... and so forth)
Something like:
int[] NumbersByUser = new int[81];
Private Sub Textbox1.Enter(sender as object, e as EventArgs) handles Textbox1.Enter, Textbox2.Enter, Textbox3.enter ...
int UserEntry = Convert.ToInt32(Sender.text);
int ValorSelecionado = Array.Find(NumbersByUser, Z => (Z == UserEntry));
if (ValorSelecionado > 0) {
Sender.forecolor = Red;
}
else
{
NumbersByUser(Index) = UserEntry;
}
You should have a 2 dimensional array of numbers (could be one dimensional, but 2 makes more sense) let's assume its called Values. I suggest that you have each textbox have a incrementing number (starting top left, going right, then next row). Now you can do the following:
All TextBox Changed events can point to the same function. The function then takes the tag to figure out the position in the 2dim array. (X coordinate is TAG % 9 and Y coordinate is TAG / 9)
In the callback you can loop over the textboxes and colorize all boxes as you like. First do the "check row" loop (pseudo code)
var currentTextBox = ((TextBox)sender)
var x = ((int)currentTextBox.Tag) % 9
var y = ((int)currentTextBox.Tag) / 9
// First assign the current value to the backing store
Values[currentTextBox] = int.parse(currentTextBox.Text)
// assuming variable x holding the column and y holding the row of current box
// Array to hold the status of a number (is it already used?)
bool isUsed[9] = {false, false, ...}
for(int col = 0; col <= 9; i++)
{
// do not compare with self
if(col == x) continue;
isUsed[textBox] = true;
}
// now we have the status of all other boxes
if( isUsed[Values[x,y]] ) currentTextBox.Background = Red else currentTextBox.Background = Green
// now repeat the procedure for the column iterating the rows and for the blocks
I would suggest a dynamic approach to this. Consider each board item as a cell (this would be it's own class). The class would contain a numeric value and other properties that could be useful (i.e. a list of possible values).
You would then create 3 collections of the cells, these would be:
A collection of rows of 9 cells (for tracking each row)
A collection of columns of 9 cells (for tracking each column)
A collection of 3x3 cells
These collections would share references - each cell object would appear once in each collection. Each cell could also contain a reference to each of the 3 collections.
Now, when a cell value is changed, you can get references to each of the 3 collections and then apply a standard set of Sudoku logic against any of those collections.
You then have some display logic that can walk the boards of cells and output to the display (your View) your values.
Enjoy - this is a fun project.
I have a list that contains file names like f1, f2, f3,...,f6. my
program needs to output a list with file names appearing in
random order such as f4,f1,f6,f2,f3,f5.
I want to swap or shift string correctly inside a list I have a list of
size 6 named fileName already containing 6 different file names I
am swapping file names inside of a list fileName as follows and fil
is also a string for remembering current string or file name.
temp =-1;
foreach (Control control in tableLayoutPanel1.Controls) // run loop untill every control inside tablelayoutpanel1.Controls is check or read
{
Button btns = control as Button; // btn sotre the
current button in table.contr
if (btns != null) // check btn got a button from
the panel then
{
temp++;
int randomNumber = 0;
randomNumber = theArray[temp]; //this pic the random number from 0 index then 1 so on theArray already contains random number from 0 to 5 without any repitition and also tested
fil = fileName[randomNumber]; //fil for holding string
fileName[temp] = fileName[randomNumber]; // at filname[0]
swap or shift filename[randomNumber] random are between 0 to
5 and without repitition
fileName[randomNumber] = fil; // this line isnt even necessary
but to be safe i wrot
btns.BackgroundImage = images[randomNumber]; // change
btn image to current random image
copyImages.Add(images[randomNumber]);
btns.BackgroundImage = null; // i purposely doing this :)
}
Using that code I am able to swap string but I cant swap them
correctly as it only run for 6 times so it should swap 6 strings
(each with different name) inside the list on 6 different location
inside the list fileName but its not happening some strings are
showing twice or thrice, hoping someone can point out what I am
doing wrong and theres no index out of range or exception error
I tested it for like hundred time please help thanks and any idea
suggestion or piece of code will be helpful and fil just storing the string at the location of fileName[temp] :) and temp just going from 0 to 5 in a loop
i dont want to shuffle them i just want to swap them according to given index which i am doing in my code but cant to it properly theArray already contains the suffle index i just want to assign the fileName[0] index to theArray[temp] i can send you my proj if you want to have a look just send me hi to my id which show in my profile
So given you have a List of length 6 and an int[6] containing 0 to five in random order
List<String> newList = newList<String>();
foreach(int position in theArray)
{
newList.Add(filename[pos]);
}
filename.Clear();
fileName.AddRange(newList);
would be one way.
or you could simply do filename = newList and not bother with the Clear and AddRange.
You stored the wrong String in your temporary variable.
fil = fileName[temp]; // index changed here
fileName[temp] = fileName[randomNumber];
fileName[randomNumber] = fil;
This is a simple way to shuffle elements in an array. Basicly you go through the array from one end to the middle, swapping each element with one selected at random. Since each swap operation results in two elements being randomly placed, when we reach the middle, the whole array is shuffled.
void Main()
{
var arr = new string[] {"a","b","c"};
Shuffle(arr);
// arr is now shuffled
}
public static void Shuffle<T>(T[] arr)
{
Random r = new Random();
for(int i = arr.Length; i > arr.Length / 2; i--)
{
Swap(arr, r.Next(i), i -1);
}
}
private static void Swap<T>(T[] arr, int first, int second)
{
T temp = arr[first];
arr[first] = arr[second];
arr[second] = temp;
}