Problem with inserting a node at the end of LinkedList - c#

So I have a problem with this insertLast function in LinkedList.
public static void insertLast(LinkedList<Person> list, Person data)
{
LinkedListNode<Person> head= list.First;
LinkedListNode<Person> rez = new LinkedListNode<Person>(data);
if(head == null)
{
head = rez;
return;
}
LinkedListNode<Person> temp = head;
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = rez;
}
I don't even know if this code will insert at the end because I can't test it because at this code temp.Next = rez; i get error:
"Property or indexer 'LinkedListNode.Next' cannot be assigned to -- it is read-only."
So if I understand correctly.Next is read-only so I can't use it like this. Now does anybody knows how to fix this?
I would really appreciate!
I can't use AddLast method because I have to create my own function.

You can't use AddLast()...but can you use AddAfter()?
public static void insertLast(LinkedList<Person> list, Person data)
{
if (list.Count == 0)
{
list.AddFirst(data);
}
else
{
list.AddAfter(list.Last, data);
}
}

Kindly, add this only two lines as below:
private void btnAddAtTheEnd_Click(object sender, EventArgs e)
{
treeView1.Focus();
treeView1.SelectedNode = treeView1.Nodes[treeView1.Nodes.Count - 1];
}
I hope it helps you ^_^

Related

How to select a GuiComboBox Entry in SAP

I want to script our sap. Actually, I'm scripting the comboboxes. But I don't know, how to select a specific item.
SAPFEWSELib.dll included as refernece
public static bool SelectComboBoxItem(string ItemText)
{
int i = 0, ItInd = -1;
SAPFEWSELib.GuiComboBox GCB = GetComboBox(GFW, Criteria, Type); /*This function returns the SAPFEWSELib.GuiComboBox and works correctly*/
if (GCB != null)
{
foreach (SAPFEWSELib.GuiComboBoxEntry Entry in GCB.Entries)
{
if (Entry.Value.ToUpper().IndexOf(Item.ToUpper()) != -1)
{
/*How to select this Entry?*/
/*GCB.Entries.Item(Entry.Pos).Select() is a not contained methode*/
/*GCB.Entries.Item(Entry.Pos).Selected = true This functions for GuiTableRows and GuiGridViewRows, but not here*/
return true;
} else {
i++;
}
}
}else{
throw new System.Exception("ERROR: Unable to find combobox with current criteria!");
}
return false;
}
Does anybody has an Idea?
Ok, got it.
GCB.Value = Entry.Value;
In my testcase, the combobox was not changeable, so it never functioned.

What is this ArgumentOutOfRangeException caused by?

I have a problem that drives me nuts. I am using a generic List that throws an ArgumentOutOfRangeException whenever I try to assign its first (or last?) index to a variable. It's a pretty large pile of code, hence I'll try to extract only the relevant stuff. So here it is:
private string GetRuleByName(string name, List<string> rules)
{
if(rules != null)
{
List<string> todo = new List<string>();
todo.AddRange(rules);
while(rules.Count != 0)
{
string r = todo[0]; // <- Error 'ArgumentOutOfRangeException' here
todo.RemoveAt(0);
// ...
}
}
}
That's how I call the method:
void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
string currentRule = GetRuleByName(treeView.SelectedNode.FullPath, ruleCollection)
// the string list "ruleCollection" always contains
// strings and thus is never empty
}
Even though it's not a very detailed presentation of what's going on, as I had to cut off a piece of some complicated code, I really hope someone else might see what produces the error.
Big thanks in advance for at least having a look!
EDIT:
This is how the method looks like. I haven't altered anything, to show what's really inside it. I hope it makes sense for somebody:
private Rule GetRuleByNameOrId(string stName, List<Rule> rules)
{
if(rules != null)
{
string searchName = stName.ToLower().Trim();
string subName = "";
int slashPos = searchName.IndexOf('/');
if(slashPos != -1)
{
if(slashPos != searchName.Length)
subName = searchName.Substring(slashPos + 1);
searchName = searchName.Substring(0, slashPos);
}
List<Rule> todo = new List<Rule>();
todo.AddRange(rules);
while(todo.Count != 0)
{
Rule r = (Rule)todo[0];
todo.RemoveAt(0);
if(r.Name.ToLower() == searchName || r.Id.ToLower() == searchName)
{
if(subName != "")
{
Rule subRule = GetRuleByNameOrId(subName, r.Children);
if(subRule != null)
return subRule;
}
else
{
return r;
}
}
if(r.Children != null && r.Children.Count != 0)
todo.AddRange(r.Children);
}//end while
}//end if(rules != null)
return null;
}
Sounds like you want the following:
private string GetRuleByName(string name, List<string> rules)
{
if(rules != null)
{
List<string> todo = new List<string>();
todo.AddRange(rules);
while(todo.Count != 0) // <-- Minor mod here
{
string r = todo[0];
todo.RemoveAt(0);
// ...
}
}
}
Otherwise you are infinitely looping on rules.Count as the size of rules is not changing
This works fine until todo is empty, then you get the exception because element 0 no longer exists as you've removed them all!
Are you sure you don't want this instead:
while(rules.Count != 0)
{
string r = rules[0]; // <- Error 'ArgumentOutOfRangeException' here
rules.RemoveAt(0);
?
The way you've written it now, you've got a loop that would actually be infinite, except that you eventually remove all the elements from the todo list, at which point you throw the exception (because in an empty list even the 0-th element doesn't exist).

c# winform Invoke throws NullReferenceException

i'm working on an winform(mdi) pro. And I need to update a dataGridView control when i get new data from another thread. and when new data comes and i'm dragging the dataGridview scroll, it throw a nullreference exception in dataGridView.Invoke. i have searched for few days and drove google crazy,but didn't help.
the code like this:
public void ReceiveNewData(object sender, UpateEventArgs ex)
{
if (this.dataGridView.InvokeRequired)
{
dataGridView.Invoke(new UpateEventHandler(ReceiveNewData), new object[] { this, ex });
}
else
this.BindNewData();
}
private void BindNewData()
{
if (dataGridView!= null && (QuoteMember.listOneClickQuoteItem != null || QuoteMember.listMarketingQuoteItem != null))
{
DataTable dataSource = PublicFunction.ToDataTable(QuoteMember.listOneClickQuoteItem);
if (dataSource != null)
dataSource.Merge(PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem), true);
else
dataSource = PublicFunction.ToDataTable(QuoteMember.listMarketingQuoteItem);
dataGridView.DataSource = dataSource;
}
}
public PublicFunction
{
public static DataTable ToDataTable(List dataSource)
{
if(dataSource != null)
return ToDataTable((dataSource.ToArray()), 1);
return null;
}
public static DataTable ToDataTable(List dataSource)
{
if (dataSource != null)
return ToDataTable((dataSource.ToArray()), 2);
return null;
}
private static DataTable ToDataTable(QuoteItemBase[] m, int type)
{
DataTable dsTemp = null;
if (type == 1)
{
dsTemp = new DataTable("OneClickQuote");
}
else if (type == 2)
{
dsTemp = new DataTable("MarketingQuote");
}
else
dsTemp = new DataTable("temptable");
dsTemp.Columns.Add("Date");
dsTemp.Columns.Add("Time");
dsTemp.Columns.Add("NO");
dsTemp.Columns.Add("Name");
if (m == null)
return dsTemp;
foreach (var item in m)
{
DataRow drTemp = dsTemp.NewRow();
drTemp["Date"] = item.date;
drTemp["Time"] = item.time;
drTemp["NO"] = item.no;
drTemp["Name"] = item.name;
dsTemp.Rows.Add(drTemp);
}
return dsTemp;
}
}
PS:
if new data comes and i'm not dragging scroll bar, it works fine.
any ideas?
thank you !
I found that when you invoke a control and set bindings (or clear them)
and an object is set to null this can throw a null reference exception, this is reflected through invoke giving an error, this error however is somewhere else in your code:
quick example:
public class test : Form
{
public test()
{
Thread t = new Thread(start);
t.Start();
}
public void start()
{
LoadCompleteEvent();
}
public void LoadComplete() //fired by LoadCompleteEvent();
{
if(this.InvokeIsRequired)
{
//do invoke
//and return
}
comboBoxEditBrand.Properties.Items.Clear();
comboBoxEditBrand.Properties.Items.AddRange(ListOfStuff.ToArray());
}
public void comboBoxEditBrand_SelectedItemChanged(object sender, eventargs e) // fired as control is changed
{
//error here!!
if(comboBoxEditBrand.SelectedItem == SomeBrandItem) //<- this is where the error is thrown!! check for null first!
{
//do something
}
}
}
it's something like this.. this code will probably not throw the error because A) it's from the top of my head and B) it's made up. BUT this is kind of what bugged me for half a morning as to WHY this error was thrown.
just place
if(comboBoxEditBrand.SelectedItem == null)
return;
where it says //error here!! and it should work again.
Make sure you switch to the Gui thread before you invoke

Single Linked List : remove method

I am writing a single linked list in C#, could you please suggest to me if there any way to write a better remove method than the one I have:
using System;
class Node
{
public int data = int.MinValue;
public Node m_NextNode;
public Node(int data_in)
{
data = data_in;
}
public Node()
{
}
}
class LinkedList
{
private Node m_HeadNode;
public void InsertData(int data)
{
Node aCurrentNode = m_HeadNode;
if(m_HeadNode == null)
{
m_HeadNode = new Node();
m_HeadNode.data = data;
}
else
{
while(aCurrentNode.m_NextNode != null)
aCurrentNode = aCurrentNode.m_NextNode;
aCurrentNode.m_NextNode = new Node();
aCurrentNode.m_NextNode.data = data;
}
}
public void DisplayData()
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
Console.WriteLine("the value is {0}", aCurrentNode.data);
aCurrentNode = aCurrentNode.m_NextNode;
}
}
public void RemoveData(int data)
{
Node aCurrentNode = m_HeadNode;
while (aCurrentNode != null)
{
//if the data is present in head
//remove the head and reset the head
if (m_HeadNode.data == data)
{
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
}
else
{
//else save the previous node
Node previousNode = aCurrentNode;
if (aCurrentNode != null)
{
//store the current node
Node NextNode = aCurrentNode.m_NextNode;
if (NextNode != null)
{
//store the next node
Node tempNode = NextNode.m_NextNode;
if (NextNode.data == data)
{
previousNode.m_NextNode = tempNode;
NextNode = null;
}
}
aCurrentNode = aCurrentNode.m_NextNode;
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
LinkedList aLinkedList = new LinkedList();
aLinkedList.InsertData(10);
aLinkedList.InsertData(20);
aLinkedList.InsertData(30);
aLinkedList.InsertData(40);
aLinkedList.DisplayData();
aLinkedList.RemoveData(10);
aLinkedList.RemoveData(40);
aLinkedList.RemoveData(20);
aLinkedList.RemoveData(30);
aLinkedList.DisplayData();
Console.Read();
}
}
I would pull the 'if removing the head node' out of the while loop, and make the while loop simpler. Just keep track of the current and previous nodes, and switch the reference when you find the node to remove.
public void RemoveData(int data)
{
if (m_HeadNode == null)
return;
if (m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
else
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
break;
}
previous = current;
current = current.m_NextNode;
}
}
}
Is RemoveData supposed to remove one instance of that integer from the list, or all instances? The previous method removes just the first one, here's one that removes all of them.
public void RemoveAllData(int data)
{
while (m_HeadNode != null && m_HeadNode.data == data)
{
m_HeadNode = m_HeadNode.m_NextNode;
}
if(m_HeadNode != null)
{
Node previous = m_HeadNode;
Node current = m_HeadNode.m_NextNode;
while (current != null)
{
if (current.data == data)
{
// If we're removing the last entry in the list, current.Next
// will be null. That's OK, because setting previous.Next to
// null is the proper way to set the end of the list.
previous.m_NextNode = current.m_NextNode;
// If we remove the current node, then we don't need to move
// forward in the list. The reference to previous.Next, below,
// will now point one element forward than it did before.
}
else
{
// Only move forward in the list if we actually need to,
// if we didn't remove an item.
previous = current;
}
current = previous.m_NextNode;
}
}
}
You have a line you do not need:
m_HeadNode = null;
m_HeadNode = aCurrentNode.m_NextNode;
You don't need to set m_HeadNode to null before you set it to something else.
public bool RemoveNode(int data) {
Node prev = null;
for (Node node = head; node != null; node = node.next) {
if (node.data == data) {
if (prev == null) head = node.next;
else prev.next = node.next;
return true;
}
prev = node;
}
return false;
}
public void RemoveData(int data)
{
if(null == m_HeadNode) return;
if(m_HeadNode.data == data)
{
// remove first node
}
else
{
Node current = m_HeadNode;
while((null != current.m_NextNode) && (current.m_NextNode.data != data))
current = current.m_NextNode;
if(null != current.m_NextNode)
{
// do remove node (since this sounds like homework, I'll leave that to you)
}
}
}
with only one local variable.
There is a bug in you code, imagine you have list that has 3 elements with data = 5 and you want to remove 5, you codes stores the head in aCurrentNode and starts the loop. There the condition is true so you move the head to the next. but aCurrentNode is not updated so in the next iteration it's pointing to the previous Head and aCurrentNode.m_NextNod would be your current Head, Hence you got yourself in a never ending loop!
public void Remove(int data)
{
for(var cur = new Node {Next = Head}; cur.Next != null; cur = cur.Next)
{
if (cur.Next.Data != data) continue;
if (cur.Next == Head)
Head = Head.Next;
else
cur.Next = cur.Next.Next;
}
}
a trick to make you loop simpler is to start with a fake node that points to head. This way you don't need to place an If to check head differently, however you need an if to set the head. the other trick is to check for next nodes data. that way you don't need to keep a previous Node.
public SLElement Remove(int index)
{
SLElement prev = _root;
if (prev == null) return null;
SLElement curr = _root._next;
for (int i = 1; i < index; i++)
{
if (curr == null) return null;
prev = curr;
curr = curr._next;
}
prev._next = curr._next;
curr._next = null;
return curr;
}
This deletes the element with a specific index, not with a specific value.
To Make really simple. Please follow the link. Below is a code snippet to remove item from a single link list.
public void DeleteNode(int nodeIndex)
{
int indexCounter = 0;
Node TempNode = StartNode;
Node PreviousNode = null;
while (TempNode.AddressHolder != null)
{
if (indexCounter == nodeIndex)
{
PreviousNode.AddressHolder = TempNode.AddressHolder;
break;
}
indexCounter++;
PreviousNode = TempNode;
TempNode = TempNode.AddressHolder;
}
}

Null Reference in editing a task scheduler trigger in c#

if (t != null) is always null why help..
when ever i try to get value in the variable name t it always gets in the else part but i am sure that there is valuse in tat variable.
private void button3_Click(object sender, EventArgs e)
{
try
{
if (search=="")
{
}
else
{
if (textBox1.Text=="")
{
MessageBox.Show("Select A Task Or Find One");
}
else
{
search = textBox1.Text;
}
}
if (search != null)
{
t = tasks.OpenTask(search);
if (textBox2.Text!="")
{
short hour = short.Parse(textBox2.Text.Substring(0, 2));
short minute = short.Parse(textBox2.Text.Substring(3, 2));
if (t != null) // this is null dont know why
{
foreach (Trigger tr in t.Triggers)
{
if (tr is StartableTrigger)
{
(tr as StartableTrigger).StartHour = hour;
(tr as StartableTrigger).StartMinute = minute;
}
}
t.Save();
t.Close();
}
tasks.Dispose();
button2.Visible = true;
textBox3.Visible = true;
search = "";
}
else
{
MessageBox.Show("Enter Time ");
}
}
}
catch (Exception b)
{
MessageBox.Show(b.ToString());
// MessageBox.Show("Select A Task From The List ");
}
}
help guys .. well i tried it to debug but didnt get a break through..
t is null because tasks.OpenTask(search) returns null.
Probably there is no task matching your search criteria.
Why are you disposing of tasks in the first place?
Any place in your source ,where you have written something like this MyClass t = new MyClass().. where t is your class object. If you have not declared,It will always come null.
Or might be you have declared something like this
private Task t; but forgot to add new keyword. Checkout!!!

Categories