我有一个班级Form1
和一个班级MyList
。我想创建一个程序,将字符放入List并有一个指针,显示在下一个。
我的问题是每次调用类MyList
时,指针都会重置。
我该如何解决这个问题。 这是一个学校项目,必须以这种方式完成,使用指针。
感谢所有答案!
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类:
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++;
}
}
}
}
答案 0 :(得分:0)
问题在于您将list
分配为本地,并且不能保证其持续时间超过定义它的范围(实际上,保证仅对托管代码有意义 - 如果想要的话,运行时编译器可以在范围结束之前很久就摆脱它。
你真的想要将对象分配到会持续更长时间的地方。最简单的方法是使用Marshal.AllocHGlobal
在非托管堆上分配一些内存。您可以使用Marshal.FreeHGlobal
释放该内存。这大致相当于在C中使用new
和delete
。
我从你的代码示例开始,但不得不改变一些事情以避免发疯。这并不意味着最终样本是100%正确的或者是实现这一目标的好方法,我仍然只是改变代码中的一些东西以使其工作。在一个真正的实现中,我会使整个事情有所不同 - 如果您对使用C#和C#(或一般)指针的一些好习惯感兴趣,您可能想要发布完整的,代码审查的工作代码 - 你会在那里得到很多好的反馈。
示例代码,包括在列表中添加和删除项目:
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(); }
}