While I am trying to debug this code (in C# WinForms), it shows an error
"use of unassigned local variable" at 'arrlist[i]'
Since I'm comparing it with a database variable, I cannot initialize the size of the array.
This is the code:
if (count != 0)
{
OleDbCommand cmd1 = new OleDbCommand(
"select seat_no, booking_date, show_time "+
"from tickets "+
"where ticket_no = (select max(ticket_no) from tickets)", c);
OleDbDataReader oledb1 = cmd1.ExecuteReader();
oledb1.Read();
string retr_seats = oledb1.GetString(0);
char comma = ',';
string[] strarray = retr_seats.Split(comma);
int ticket_length = strarray.Length;
string[] arrlist;
int i = 0;
foreach(var control in this.Controls)
{
if(control is Label)
{
arrlist[i] = control.ToString();
i++;
}
}
for(var j=0;j<=ticket_length;j++)
{
for (var k = 0; k <= i-1; k++)
{
if (arrlist[k].Contains(strarray[j]))
{
MessageBox.Show(strarray[j]);
}
}
}
}
Please help me
You need to initialize the variable arrlist. Change this line:
string[] arrlist;
To this:
string[] arrlist = new string[this.Controls.Count]; // Must be big enough.
Or better, use a dynamically sized container such as a List<string>.
List<string> arrList = new List<string>();
foreach(var control in this.Controls)
{
if(control is Label)
{
arrlist.Add(control.ToString());
}
}
Or use LINQ to get the result directly:
string[] arrlist = this.Controls
.OfType<Label>()
.Select(control => control.ToString())
.ToArray();
Change your array to a list, and add values to the list. You can then index the list elements directly, or if you need an array, you can use .ToArray() on the list instance.
Also note that your for loop over j will go out of bounds on strarray unless you change the comparison to < ticket_length from <= ticket_length.
...
var arrlist = new List<string>();
foreach(var control in this.Controls)
if(control is Label)
{
arrlist.Add(control.ToString());
}
for(var j=0;j<ticket_length;j++)
for (var k = 0; k < arrlist.Count; k++)
if (arrlist[k].Contains(strarray[j]))
MessageBox.Show(strarray[j]);
string[] arrlist;
....
arrlist[i] = control.ToString();
you lost initialization like: arrlist = new string[count];
The problem is that arrlist is defined, but not initialized.
You need to initialize it, like this:
string[] arrlist = new arrlist[size];
If you don't know how big it will be, it is better to use a list:
List<string> arrlist = new List<string>();
and to add items: arrlist.add("some string");
Related
I have a data set from which I need to isolate and feedback non-unique values across multiple columns. (Think multi column primary key violation in database table). I am currently doing this by concatenating those columns on each row into a List<string>. Doing a count of the item in the list and if greater than 1 adding an error message to another column on the same row - that bit's important, I need to be able to provide feedback on the position of the duplicate/s, not just the fact that there is a duplicate.
The problem is speed, although this technically works, it doesn't work well as a practical solution because I will potentially be working with data sets of several hundred thousand rows
Code:
List<string> mylist = new List<string>();
string ThisConcat = "";
for (int i = 0; i < dtLogData.Rows.Count-1; i++)
{
foreach (int ColNum in ColNumList)
{
ThisConcat += dtLogData.Rows[i].Field<string>(ColNum-1);
}
mylist.Add(ThisConcat);
ThisConcat = "";
}
Then:
for (int i = 0; i < dtLogData.Rows.Count-1; i++)
{
int count = mylist.Count(j => j == mylist[i]);
if (count > 1)
{
dtLogData.Rows[i][ColCnt] = MyErrorString;
}
}
I'll give you a slightly different solution. This assumes you are willing to add another column to the DataTable:
dtLogData.Columns.Add("hash");
Then you cast the table:
var t = dtLogData.AsEnumerable();
First you compute the concatenated string and get a hold of the rows. You can do this in two ways. If you want to limit the columns to certain indexes (like your original code):
var rows = t.Select(row =>
{
StringBuilder builder = new StringBuilder();
ColNumList.ForEach(i => builder.Append(row[i]));
row["hash"] = builder.ToString();
return row;
}
);
Or if you just want to use all columns:
var rows = t.Select(row =>
{
row["hash"] = string.Join("", row.ItemArray.Select(i => i.ToString()));
return row;
}
);
You then grab all the rows with duplicates and mark them accordingly:
foreach (var dataRow in rows.GroupBy(r => r["hash"]).Where(g => g.Count() > 1).SelectMany(g => g))
{
dataRow[ColCnt] = MyErrorString;
}
You could use Dictionary<string, List<DataRow>> instead of List<string> and store row references to each ThisConcat tupel.
Dictionary<string, List<DataRow>> mylist = new Dictionary<string, List<DataRow>>();
string ThisConcat = "";
for (int i = 0; i < dtLogData.Rows.Count - 1; i++) {
foreach (int ColNum in ColNumList) {
ThisConcat += dtLogData.Rows[i].Field<string>(ColNum - 1);
}
if (! mylist.ContainsKey(ThisConcat))
mylist[ThisConcat] = new List<DataRow>();
mylist[ThisConcat].Add(dtLogData.Rows[i]);
ThisConcat = "";
}
foreach (var p in mylist) {
if (p.Value.Count > 1) {
foreach (var r in p.Value) {
r[ColCnt] = MyErrorString;
}
}
}
You call mylist.Count for each row. If you have n rows with almost different tuples, you get quadratic runtime complexity O(n^2). The code above should have linear complexity O(n).
You try can replacing the first bit of code with this one:
List<string> mylist = new List<string>();
StringBuilder sb;
foreach (DataRow row in dtLogData.Rows)
{
sb = new StringBuilder();
ColNumList.ForEach(i => sb.Append(row[i - 1]));
mylist.Add(sb.ToString());
}
And the second part with:
mylist.Select((a, b) => new { count = mylist.Where(c => c.Equals(a)).Count(), index = b })
.Where(e => e.count > 1).ToList().ForEach(f => dtLogData.Rows[f.index][ColCnt] = MyErrorString);
Gotta love them downvotes with no explanation
So I have this kind of code (I'm assigning values to XAML elements
), which begs for a "for" loop.
Day1d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(1));
Day2d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(2));
Day3d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(3));
Day4d.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(4));
Day1t.Text = "°" + (myWeatherForecast.forecastlist[1].temp).ToString();
Day2t.Text = "°" + (myWeatherForecast.forecastlist[2].temp).ToString();
Day3t.Text = "°" + (myWeatherForecast.forecastlist[3].temp).ToString();
Day4t.Text = "°" + (myWeatherForecast.forecastlist[4].temp).ToString();
But all my attempts to include "i" in variable name failed miserably. Is there a way to achieve this?
You can create a loop where you iterate over the instances:
int counter = 1; // are you sure it shouldn't start at 0?
foreach (TextBox tb in new TextBox[] { Day1d, Day2d, Day3d, Day4d })
{
tb.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(counter));
counter++;
}
counter = 1;
foreach (TextBox tb in new TextBox[] { Day1t, Day2t, Day3t, Day4t })
{
tb.Text = "°" + (myWeatherForecast.forecastlist[counter].temp).ToString();
counter++;
}
You can't compose the name of the variable using another variable. The way to do this would be to create a List and then iterate over that List
var textBoxes1 = new List<TextBox> { Day1d, Day2d, Day3d, Day4d }
var textBoxes2 = new List<TextBox> { Day1t, Day2t, Day3t, Day4t }
foreach (var textbox in textBoxes1)
{
var index = textBoxes1.IndexOf(textBox) + 1;
textbox.Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(index));
}
foreach (var textbox in textBoxes2)
{
var index = textBoxes2.IndexOf(textBox) + 1;
textbox.Text = "°" + (myWeatherForecast.forecastlist[index].temp).ToString();
}
NOTE: You can solve this in different ways:
using arrays instead of lists
keeping your own counter, instead of doing IndexOf
using a for loop, instead of a foreach
Which one is better is mostly based on opinion (although my method is not the fastest, but it doesn't matter if you only have 4 items)
You can use FindName assuming you are using WPF.
Try:
for (int i = 1; i < 5; i++)
{
((TextBox)this.FindName("Day" + i + "d")).Text = string.Format("{0:dd/MM}", DateTime.Today.AddDays(i));
((TextBox)this.FindName("Day" + i + "t")).Text = "°" + (myWeatherForecast.forecastlist[i].temp).ToString();
}
I have a checkedlistbox in which i am populating items like:
Biology+Physics+Chemistry
English+Urdu+Islamiyat
and so on. Now when i retrieve the values of selected items by splitting them on the basis of '+' sign, it gives me an output like:
Biology
Physics
ChemistryEnglish
Urdu
Islamiyat
Now you can look at the output as all values are right except ChemistryEnglish which have got concatenated. What should i be doing so to make this right? I want the output like this:
Biology
Physics
Chemistry
English
Urdu
Islamiyat
UPDATED
MY CODE IS:
String items = "";
string SQLString = "";
if (this.subjects_listbox.CheckedItems.Count != 0)
{
for (int i = 0; i < this.subjects_listbox.Items.Count; i++)
{
items += this.subjects_listbox.CheckedItems[i].ToString();
}
} //
String[] subNames = items.Split('+');
foreach (var item in subNames)
{
MessageBox.Show(item);
}
Finally i achieved my goal this by doing this:
String items = "";
string SQLString = "";
if (this.subjects_listbox.CheckedItems.Count != 0)
{
for (int i = 0; i < this.subjects_listbox.Items.Count; i++)
{
items += this.subjects_listbox.CheckedItems[i].ToString() + "+";
}
} //
String[] subNames = items.Split('+');
foreach (var item in subNames)
{
MessageBox.Show(item);
}
I think you need to split out the items in the CheckedListBox individually before you do what you are doing with items. Take the following code (assuming myCheckedListBox is the name of your CheckedListBox)
var subNameList = new List<string>();
foreach (var item in myCheckedListBox.Items)
{
foreach (string subName in (item.ToString().Split('+'))
{
subNameList.Add(subName);
}
}
This will result in you having a list of strings at the end in subNameList. You may want to use myCheckedListBox.CheckedItems rather than myCheckedListBox.Items depending on your use case.
I achieved my goal by doing this:
String items = "";
string SQLString = "";
if (this.subjects_listbox.CheckedItems.Count != 0)
{
for (int i = 0; i < this.subjects_listbox.Items.Count; i++)
{
items += this.subjects_listbox.CheckedItems[i].ToString() + "+";
}
}
String[] subNames = items.Split('+');
foreach (var item in subNames)
{
MessageBox.Show(item);
}
string[] board = new string[9];
for (var i = 0; i < 9; i++)
{
board[i] = (textBox1.Text);
}
I'm trying to make a loop which puts the text of textboxes in the array, but I can't figure out how to put the i variable in the 'textBox.Text' statement. I've tried this:
board[i] = ("textBox" + i + ".Text");
But this returns 'textBox1.Text'. How do I make the textbox.Text statement 'compatible' with the for loop?
You didn't tell us what API are you using as #Jeppe Stig Nielsen commented.
Asp.net? WPF? Windows Forms?
In Asp.net you can use FindControl method
string[] board = new string[9];
for (var i = 0; i < 9; i++)
{
board[i] = ((TextBox)FindControl("textBox" + i)).Text
}
In WPF you can use FindName method:
string[] board = new string[9];
for (var i = 0; i < 9; i++)
{
board[i] = ((TextBox)this.FindName("textBox" + i)).Text;
}
Use more meaningful control names if you want to maintain your code sometime. The business logic should not be dependent on control names.
However, if you want to get an array of all textboxes in a container control like the form you could also use LINQ:
string[] board = this.Controls.OfType<TextBox>()
.Where(txt => txt.Name.StartsWith("textBox"))
.Select(txt => txt.Text)
.ToArray();
If you only want to take textboxes from 1-9:
var txtNames = Enumerable.Range(1, 9).Select(i => "textBox" + i);
string[] board = this.Controls.OfType<TextBox>()
.Where(txt => txtNames.Contains(txt.Name))
.Select(txt => txt.Text)
.ToArray();
Try this ,
string[] arr= new String[3];
for (int i = 0; i <= 2; i++)
{
TextBox testTextBox = (TextBox)this.Controls["textBox" + i.ToString()];
arr[i] = testTextBox.Text;
}
We are currently programming a student information system. What we have so far is a checkboxlist that contains all the modules for the course that the selected student is enrolled on. These values are both stored in the database. What we are trying to do is have the List item values within the checkboxlist selected/ticked based upon the modules they are currently studying, based on what is stored in the database.
Here is our c# code:
string connectionString = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(connectionString);
myConnection.Open();
string com5 = "SELECT ModuleID FROM StudentModules WHERE StudentID = #StudentID";
SqlCommand myCommand5 = new SqlCommand(com5, myConnection);
StudentIDLabel.Text = SearchText.Text;
int StudentIDint = Convert.ToInt32(StudentIDLabel.Text);
myCommand5.Parameters.AddWithValue("#StudentID", StudentIDint);
string compareModules = myCommand5.ExecuteScalar().ToString();
var listOfStrings = new List<string>();
SqlDataReader reader = myCommand5.ExecuteReader();
while (reader.Read())
{
String currentValue = reader.ToString();
listOfStrings.Add(currentValue);
}
string[] arrayOfStrings = listOfStrings.ToArray();
foreach (ListItem li in this.CbOptional.Items)
{
for (int x = 0; x < arrayOfStrings.Length; x++)
{
if (li.Value.ToString() == arrayOfStrings[x])
{
li.Selected = true;
}
else
{
li.Selected = false;
}
}
}
From what we can see there seems to be an issue with IF statement, when comparing values from the checkbox list with values from the array.
We tested the else clause near the bottom of the above code, with "li.Selected = true" to make sure the code was running through the foreach statement correctly. All items within the checkbox list displayed as ticked. So this leads us to believe there is definitely something wrong with the IF statement inside the FOR loop.
Any ideas on this would be greatly appreciated.
Thanks
You dont need to run two for loops. You can just iterate through array and check if there is list item which is having same value as array element on specific index.
Try this.
for (int x = 0; x < arrayOfStrings.Length; x++)
{
ListItem listItemtoSelect = this.CbOptional.Items.FindByValue(arrayOfStrings[x]);
if (listItemtoSelect != null)
{
listItemtoSelect.Selected = true;
}
}
Since the List<string> will compare with the text only not value you should use this
repace li.Value with li.Text
for (int x = 0; x < arrayOfStrings.Length; x++)
{
if (li.Text.ToString() == arrayOfStrings[x])
{
li.Selected = true;
}
else
{
li.Selected = false;
}
}
In the inner loop, you are comparing the value of ListItem variable with each element in the array. Therefore, if the first element matches, the value is overwritten by the value of comparison with second element, and so on. Instead, you could try to check if the value of that particular ListItem matches any value in the list of strings retrieved from DB. You can do this like so:
if(listOfStrings.Contains(li.Value.ToString()))
{
li.Selected = true;
}
Note that you do not need to convert the listOfStrings variable to an array, the Contains method works on Lists.