Pointer in C# reset's after leaving a Class - c#

I have a class Form1 and a class MyList. I want to create a program that puts character into List and has a pointer that shows on next one.
My problem is that everytime when I call class MyList, the pointer resets.
How can I solve the problem.
It is a school project an it must be done on this way, with pointers.
Thanks for all answers!
namespace Data {
public partial class Form1 : Form
{
char character = "a"
int index = 0;
MyList a = new MyList();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e) //On click get new index and character and put in a List.
{
a.PutIn(index, character);
}
}
}
MyList class:
namespace Data
{
public unsafe struct list
{
public char x;
public list* next;
}
public unsafe partial class MyList
{
list* first = null;
list* last = null;
int index;
public unsafe MyList() { Initialize(); }
public unsafe void Initialize()
{
first = null;
last = null;
index = -1;
}
~MyList()
{
do{
Emty(0);
}while (!IsEmpty());
}
public unsafe void PutIn(int place, char character)
{
if (((index+1)<place)||(place<0))
MessageBox.Show("Index is too high!");
else
{
if (IsEmpty())
{
list temp = new list();
list* temp_pointer = &temp;
temp_pointer->next = null;
temp_pointer->x = character;
first = temp_pointer;
last = temp_pointer;
temp_pointer = null;
index++;
}
else if (place == (index + 1))
{
list temp = new list();
list* temp_pointer = &temp;
temp_pointer->next = null;
temp_pointer->x = character;
last->next = temp_pointer;
last = temp_pointer;
temp_pointer = null;
index++;
}
}
}
}

The problem is that you are allocating list as a local and it is not guaranteed to last any longer than the scope in which it is defined (in fact, the guarantee only makes sense for managed code anyway - the runtime compiler can get rid of it long before the scope ends if it wants to).
You really want to allocate the object somewhere where it will last a bit longer. The simplest approach is to use Marshal.AllocHGlobal to allocate a bit of memory on the unmanaged heap. You free that memory using Marshal.FreeHGlobal. This is roughly equivalent to using new and delete in C.
I started with your code sample, but had to change a few things to avoid going mad. This doesn't mean that the final sample is 100% correct or a good way of implementing this, I was still only changing a few things in your code to make it work. In a real implementation, I'd make the whole thing a bit differently - if you're interested in some good practices for working with C# and pointers in C# (or in general), you might want to post your full, working code to Code Review - you'll get a lot of good feedback there.
Sample code, including adding and removing items from the list:
void Main()
{
var list = new MyList();
list.InsertAt(0, 'A');
list.InsertAt(1, 'B');
list.InsertAt(2, 'C');
list.InsertAt(1, 'X');
Console.WriteLine(string.Join(", ", list.Select(i => i.ToString())));
list.RemoveAt(1);
Console.WriteLine(string.Join(", ", list.Select(i => i.ToString())));
}
public unsafe struct list
{
public char x;
public list* next;
}
public unsafe class MyList : IEnumerable<char>
{
list* first;
list* last;
int count;
public int Count { get { return count; } }
public bool IsEmpty() { return count == 0; }
private void Remove(list* previous, list* current)
{
if (first == current) first = current->next;
if (last == current) last = previous;
if (previous != null) previous->next = current->next;
Console.WriteLine
(
"Removing {0}, first {1}, last {2}, count {3}",
current->x,
first == null ? '-' : first->x,
last == null ? '-' : last->x,
count
);
count--;
Marshal.FreeHGlobal(new IntPtr(current));
}
public void RemoveAt(int index)
{
if (count < index || index < 0)
throw new ArgumentOutOfRangeException("Index is out of range!");
var current = first;
if (index == 0)
{
Remove(null, current);
return;
}
for (var i = 0; i < index - 1; i++)
{
current = current->next;
}
Remove(current, current->next);
}
~MyList()
{
do
{
RemoveAt(0);
}
while (!IsEmpty());
}
private list* InsertAfter(list* previousItem, char character)
{
var newItem = (list*)Marshal.AllocHGlobal(sizeof(list));
newItem->next = previousItem == null ? null : previousItem->next;
newItem->x = character;
if (previousItem == last) last = newItem;
if (previousItem != null) previousItem->next = newItem;
count++;
Console.WriteLine
(
"Added {0} after {1}, first {2}, last {3}, count {4}",
character,
previousItem == null ? '-' : previousItem->x,
first == null ? '-' : first->x,
last == null ? '-' : last->x,
count
);
return newItem;
}
public void InsertAt(int index, char character)
{
if (count < index || index < 0)
throw new ArgumentOutOfRangeException("Index is out of range!");
if (index == 0)
{
var newItem = InsertAfter(null, character);
if (first != null) newItem->next = first;
first = newItem;
}
else if (index == 1)
{
InsertAfter(first, character);
}
else if (index == count)
{
InsertAfter(last, character);
}
else
{
var current = first;
for (var i = 0; i < index - 2; i++)
{
current = current->next;
}
InsertAfter(current, character);
}
}
private class MyListEnumerator : IEnumerator<char>
{
private MyList list;
private list* current;
public MyListEnumerator(MyList list)
{
this.list = list;
this.current = null;
}
public void Reset() { current = null; }
public bool MoveNext()
{
if (current == null) current = list.first;
else current = current->next;
return current != null;
}
public char Current
{
get
{
if (current == null) throw new InvalidOperationException();
return current->x;
}
}
object IEnumerator.Current { get { return (object)Current; } }
public void Dispose() {}
}
public IEnumerator<char> GetEnumerator() { return new MyListEnumerator(this); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}

Related

Backtrack in a Generic list

I want to create a backtrack that select's me the best value of tasks in my generic list.
This is how my generic list looks.
I have a method that sorts my list by the price. I have 3 type of "task" Urgent,Return and Normal.
I fill my list up that my Urgent tasks as first (sorted by the price) then return tasks and then normal. And i want the highest value of price in 8 hours but I need to finish urgent first and then return tasks if I still have time and last the normal tasks.
class GenerikusLancoltLista<T> : IEnumerable
{
class ListaElem
{
public T data;
public ListElement next;
}
ListaElem Head;
public GenerikusLancoltLista()
{
Head = null;
}
public void PrioritasiSorBeszuras(T paste)
{
ListElement new = new ListElement();
uj.data = paste;
if (Head == null)
{ Head = new; }
else
{
if ((Head.data as IComparable).CompareTo(paste) >= 0)
{
new.next = Head;
Head = new;
}
else
{
ListElement p = Head;
ListElement e = null;
while (p != null && (p.data as IComparable).CompareTo(paste) < 0)
{
e = p;
p = p.next;
}
if (p == null)
{ e.next = new; }
else
{
new.next = p;
e.next = new;
}
}
}
}
My base task looks like this
interface ITask:IComparable
{
string Name { get; }
int price { get; }
int hour { get; }
int Priority { get; }
}
So I know bactrack should look something like this.
But I dont know how to figure it out a solution that works.
abstract class BacktrackBase
{
int N;
GenerikusLancoltLista<ITask> R;
int[] M;
public BacktrackBase(int n, GenerikusLancoltLista<ITask> r, int[] m)
{
N = n;
R = r;
M = m;
}
protected abstract bool Ft(int level, ITask task);
protected abstract bool Fk(int level, ITask task, ITask[] E);
void Backtrack(int level,Task[] E, ref bool have)
{
int i = -1;
while (!have && i <M[level] - 1)
{
i++;
if (Ft(level, R[level, i]))
{
if (Fk(level, R[level, i], E))
{
E[level] = R[level, i];
if (level == N - 1)
{
have = true;
}
else
{
Backtrack(level + 1, E, ref have);
}
}
}
}
}
I want to fill my 8 hours with works with the best value
for example a work looks like this: Dog walking,10000,3
so "name","price","time"
Each work has a type, "urgent","return","normal".
I need to fit urgent works first with in my 8 hours with the best value.

InsertInOrder Function for a Linkedlist

I'm trying to create a function InsertInOrder() that inserts an item in the correct place without disturbing the order.
Ex:
LinkedList before [3,5,6] after inserting 4 ---> [3,4,5,6].
I have created the function but some reason it's not working as expected.
I'm testing the code on a Windows form application by entering ISBNs,
What went wrong:
First I inserted 23, then I inserted 10, expecting to be placed before 23 but here's what happened (image below):
What went wrong
Please find the code below:
LinkListGen Class
class LinkListGen<T> where T : IComparable
{
private LinkGen<T> list;
public LinkListGen()
{
list = null;
}
public void AddItem(T item)
{
list = new LinkGen<T>(item, list); //create a new link on the front of the list
}
public void AppendItem(T item)
{
LinkGen<T> temp = list;
if (temp == null)
{
list = new LinkGen<T>(item);
}
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item);
}
}
public string DisplayList()
{
string buffer = "";
LinkGen<T> temp = list; //temp starts beginning of list
while (temp != null) //not at end of list
{
buffer = buffer + temp.Data.ToString() + ",";
temp = temp.Next; //move along a link
}
return buffer;
}
public void RemoveItem(T item)
{
LinkGen<T> temp = list;
LinkListGen<T> newList = new LinkListGen<T>();
while (temp != null)
{
if (item.CompareTo(temp.Data) != 0)
{
newList.AppendItem(temp.Data);
}
temp = temp.Next;
}
list = newList.list;
}
public void InsertInOrder (T item)
{
LinkGen<T> temp = list;
LinkListGen<T> newList = new LinkListGen<T>();
if (list == null)
{
AppendItem(item);
}
else
{
while (temp != null)
{
if(list.Data.CompareTo(item) < 0)
{
newList.AppendItem(list.Data);
temp = temp.Next;
}
else if(list.Data.CompareTo(item) > 0)
{
newList.AppendItem(item);
newList.AppendItem(list.Data);
temp = temp.Next;
}
newList.AppendItem(list.Data);
temp = temp.Next;
}
}
}
}
Windows Form App code
public partial class Form1 : Form
{
LinkListGen<Book> ISBNList = new LinkListGen<Book>();
public Form1()
{
InitializeComponent();
}
private void AddButton_Click(object sender, EventArgs e)
{
double insertedISBN = Convert.ToDouble(ISBNTextBox.Text);
Book newBook = new Book(insertedISBN);
ISBNList.InsertInOrder(newBook);
DisplayLabel.Text = ISBNList.DisplayList();
}
private void RemoveButton_Click(object sender, EventArgs e)
{
double insertedISBN = Convert.ToDouble(ISBNTextBox.Text);
Book removeBook = new Book(insertedISBN);
ISBNList.RemoveItem(removeBook);
DisplayLabel.Text = ISBNList.DisplayList();
}
}
Your problem, that you call AppendItem at InsertInOrder, which adds element to the end of the list, instead pure pointer manipulation.
At the same time, you shouldn't recreate list at InsertInOrder to avoid memory/time overhead.
Try next code, not tested:
public void InsertInOrder(T item)
{
var node = new LinkGen<T>(item);
if (list == null)
{
list = node;
return;
}
var current = list;
while (current != null)
{
if (current.Data.CompareTo(item) < 0)
{
// current is last element
if (current.Next == null)
{
current.Next = node;
break;
}
// current.Next.Data is equal or greater than new value
// so set new node.Next to current.Next and current.Next to new node
if (current.Next.Data.CompareTo(item) >= 0)
{
node.Next = current.Next;
current.Next = node;
break;
}
}
current = current.Next;
}
}

Linq: ForEach item return the number of items needed to get n unique items starting at that item

Lets say I have a list of items:
[a,b,b,a,c,d,a,d,b,c]
and I need to know, for each item, how many items along do I have to traverse till I get n unique items, (and return eg -1, or otherwise indicate if that's not possible)
So here, if n = 4, I would return
[6,5,4,6,5,5,4,-1,-1,-1]
since
a,b,b,a,c,d contains 4 unique elements
b,b,a,c,d contains 4 unique elements
b,a,c,d contains 4 unique elements,
a,c,d,a,d,b contains 4 unique elements
etc.
I used
List.Select((x,i) => {
var range = List.Skip(i).GroupBy(y => y).Take(n);
if (range.Count() == n)
return range.SelectMany(y => y).Count();
return -1;
});
Although i'm pretty sure this is horribly non-performant.
To try to minimize overhead, I created a ListSpan extension class for managing subparts of a List - something like ArraySegment for List, but (loosely) modeled on Span:
public class ListSpan<T> : IEnumerable<T>, IEnumerable {
List<T> baseList;
int start;
int len;
public ListSpan(List<T> src, int start = 0, int? len = null) {
baseList = src;
this.start = start;
this.len = len ?? (baseList.Count - start);
if (this.start + this.len > baseList.Count)
throw new ArgumentException("start+len > Count for ListSpan");
}
public T this[int n]
{
get
{
return baseList[start + n];
}
set
{
baseList[start + n] = value;
}
}
public class ListSpanEnumerator<Te> : IEnumerator<Te>, IEnumerator {
int pos;
List<Te> baseList;
int end;
Te cur = default(Te);
public ListSpanEnumerator(ListSpan<Te> src) {
pos = src.start - 1;
baseList = src.baseList;
end = src.start + src.len;
}
public Te Current => cur;
object IEnumerator.Current => Current;
public bool MoveNext() {
if (++pos < end) {
cur = baseList[pos];
return true;
}
else {
cur = default(Te);
return false;
}
}
public void Reset() => pos = 0;
public void Dispose() { }
}
public IEnumerator<T> GetEnumerator() => new ListSpanEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public static class ListExt {
public static ListSpan<T> Slice<T>(this List<T> src, int start = 0, int? len = null) => new ListSpan<T>(src, start, len);
}
Then I created an extension method to return the distance (in Take terms) required to get n unique items from an IEnumerable:
public static class IEnumerableExt {
public static int DistanceToUnique<T>(this IEnumerable<T> src, int n, IEqualityComparer<T> cmp = null) {
var hs = new HashSet<T>(cmp ?? EqualityComparer<T>.Default);
var pos = 0;
using (var e = src.GetEnumerator()) {
while (e.MoveNext()) {
++pos;
hs.Add(e.Current);
if (hs.Count == n)
return pos;
}
}
return -1;
}
}
Now the answer is relatively straight forward:
var ans = Enumerable.Range(0, src.Count).Select(p => src.Slice(p).DistanceToUnique(n));
Basically I go through each position in the original (src) List and compute the distance to n unique values from that position using a ListSpan of the List starting at that position.
This still isn't terribly efficient in that I am creating a HashSet for every element in the original List and putting all the following elements in it, and traversing the elements up to k! times for a k element List. Still trying to come up with something really efficient.

CustomList class, what is a good way to remove at a specified index?

I have created a CustomList class with some methods such as Add(), Set(), and RemoveAt(). This CustomList class is meant to mimic the behavior of the List<> class without actually using it.
When debugging my program I noticed that when I input the index of the string I want removed, my code successfully removes that string. But when I call the print method, it double prints the last string in the array. I'm assuming the error is within RemoveAt() and not Print() because Print() works perfectly fine when RemoveAt() is not called. I was wondering if anybody could point me in the right direction.
class CustomList
{
private int count;
private String[] data;
public int Count
{
get { return count; }
set { value = count; }
}
public CustomList(int arrayNum)
{
data = new String[arrayNum];
}
public CustomList(): this(4)
{
}
public void Add (String item)
{
if (count > data.Length)
{
String[] temp = new String[count * 2];
for (int i = 0; i < data.Length; i++)
{
temp[i] = data[i];
}
data = temp;
}
data[count] = item;
count++;
}
public int IndexOf (String item)
{
for (int i = 0; i < data.Length; i++)
{
if (data[i].Contains(item))
{
return i;
}
}
return -1;
}
public bool Contains (String item)
{
if (IndexOf(item) == -1)
{
return false;
}
return true;
}
public void RemoveAt(int index)
{
if (index < count && index >= 0)
{
Array.Copy(data, index + 1, data, index, Count - (index + 1));
count--;
}
}
public bool Remove(String item)
{
if (data.Contains(item))
{
int index = Array.IndexOf(data, item);
RemoveAt(index);
return true;
}
return false;
}
public void Print()
{
for (int i = 0; i < count; i++)
{
Console.WriteLine(data[i]);
}
}
I'm a little confused with what you're saying, #germi. When I set the size to 4 and enter 4 strings, it successfully prints the 4 items in the array:
Your print loop should go from 0 to count-1, not from 0 to count. If you have 3 items (count == 3) then the indexes of those items are 0, 1, 2.
You're only getting away with accessing one too many items because of the way you're implementing Remove, which doesn't shrink the array (and so there still is a now-unused element at that index).
Change the <= into a <.
Also, the RemoveAt method should do count--, not Count--.

Object reference not set to an instance of an object- Linked List Example

I am seeing following errors :
Object reference not set to an instance of an object!
Check to determinate if the object is null before calling the method!
I made a small test program for Sorted Linked Lists.
Here is the code where the error comes!
public void Insert(double data)
{
Link newLink = new Link(data);
Link current = first;
Link previous = null;
if (first == null)
{
first = newLink;
}
else
{
while (data > current.DData && current != null)
{
previous = current;
current = current.Next;
}
previous.Next = newLink;
newLink.Next = current;
}
}
It says that the current referenc is null while (data > current.DData && current != null), but I assigned it: current = first;
The rest is the complete code of the Program!
class Link
{
double dData;
Link next=null;
public Link Next
{
get { return next; }
set { next = value; }
}
public double DData
{
get { return dData; }
set { dData = value; }
}
public Link(double dData)
{
this.dData = dData;
}
public void DisplayLink()
{
Console.WriteLine("Link : "+ dData);
}
}
class SortedList
{
Link first;
public SortedList()
{
first = null;
}
public bool IsEmpty()
{
return (this.first == null);
}
public void Insert(double data)
{
Link newLink = new Link(data);
Link current = first;
Link previous = null;
if (first == null)
{
first = newLink;
}
else
{
while (data > current.DData && current != null)
{
previous = current;
current = current.Next;
}
previous.Next = newLink;
newLink.Next = current;
}
}
public Link Remove()
{
Link temp = first;
first = first.Next;
return temp;
}
public void DisplayList()
{
Link current;
current = first;
Console.WriteLine("Display the List!");
while (current != null)
{
current.DisplayLink();
current = current.Next;
}
}
}
class SortedListApp
{
public void TestSortedList()
{
SortedList newList = new SortedList();
newList.Insert(20);
newList.Insert(22);
newList.Insert(100);
newList.Insert(1000);
newList.Insert(15);
newList.Insert(11);
newList.DisplayList();
newList.Remove();
newList.DisplayList();
}
}
You are perhaps assuming that the while loop is breaking on the first iteration which it's not it's the assignment in the while loop that eventually breaks it.
Eventually current is NULL based on your code, you even test for it - change it to this and it should be fine:
while (current != null && data > current.DData)
{
previous = current;
current = current.Next;
}
Agree that you have done
current = first;
but then the beginning of your class first is null
class SortedList
{
Link first;
please assign something to first else it will be null

Categories