Bạn nghiên cứu lớp List<>
nó có đủ các phương thức như add, insert, delete... để giúp bạn làm cái tập hợp đó dễ dàng
Ví dụ
Visual C# Code:
Chào các anh chị, các bạn,
Hiện tôi đang làm một chương trình mô phỏng theo TotalCommander nhưng code trên C#. Tôi đang phân vân về việc xây dựng một cơ chế có thể lưu lại 'history of folder-path' mà tôi đã duyệt qua.
Ví dụ tôi muốn tập hợp này gồm 32 chỗ chứa, mỗi lần duyệt qua một đường dẫn thư mục (nếu OK) thì tập hợp này sẽ add đường dẫn vừa duyệt. Đến một lúc nào đó khi tôi duyệt hết 32 lần thì tập hợp này sẽ tự remove phần tử đầu tiên và sẽ add tiếp một phần tử mới vào cuối tập hợp khi duyệt tiếp (con trỏ luôn trỏ tới phần tử cuối trong tập hợp).
Chương trình của tôi sẽ có 2 nút 'Next' và 'Previous' để thao tác với tập hợp này (2 nút này sẽ ẩn hiện ứng với vị trí đang trỏ tới trong tập hợp).
Các anh chị, các bạn có thể đề xuất cho tôi một hướng làm được không? Nếu anh chị, các bạn không chê cười và muốn góp sức thực hiện project này có thể cho tôi địa chị mail và tôi sẽ invite các anh chị vào SVN host project này tại Assembla.com
Cám ơn rất nhiều
Bạn nghiên cứu lớp List<>
nó có đủ các phương thức như add, insert, delete... để giúp bạn làm cái tập hợp đó dễ dàng
Ví dụ
Visual C# Code:
Mình từ Caulacbovb qua)
Giã từ VB6 đến với VB.Net, C# và Java.![]()
Cám ơn bạn rất nhiều, mình đã tìm hiểu kể cả Stack và Queue trước đó rồi. Lớp List<T> mình muốn tập hợp của mình có một Capacity nhất định = 32, trong khi List sẽ tự tăng không gian chứa có nghĩa nó cũng không tự remove phần tử đầu tiên.![]()
Theo ý mình nên viết một tập hợp gần như LinkedList và Queue. Cũng đang tìm tòi nhiều...![]()
Nếu bài viết của mình có khó hiểu thì xin các bạn hãy liên tưởng tới cách hoạt động của 2 nút 'Next' và 'Previous' trên trình duyệt web.![]()
Cám ơn
Phù, rốt cuộc cũng có thể làm được một số yêu cầu về cái tập hợp này. Sau đây mình xin phép được share code nếu có bạn nào cần.
Trước hết tập hợp này gần giống như Queue, vì nó sẽ có một không gian chứa nhất định và không tự gia tăng kích thước khi đầy.
Visual C# Code:
/// <summary> /// /// Represent a FIFO collection of object. It have a specified capacity and /// will automatically remove its element when out of container-space. /// /// This class cannot be inherited. /// /// </summary> /// /// <typeparam name="T">Type-Generic</typeparam> { /// <summary> /// /// Constructor for a new <code>HistoryQueue<T></code>. /// /// </summary> { mSize = iHead = iTail = 0; } /// <summary> /// /// If the <code>HistoryQueue</code> is full, it will automatically remove the first element, /// and then add the new element. /// /// </summary> /// /// <param name="element">New element</param> { // Size is full... { Dequeue(); // Removes the first element. NormalEnqueue(element); // Adds new element then. } NormalEnqueue(element); } /// <summary> /// /// Adds a new element to the last place of <code>HistoryQueue</code> normally. /// /// </summary> /// /// <param name="element">New element</param> { mContainerSpace[iTail] = element; iTail = (iTail + 1) % mContainerSpace.Length; mSize++; } /// <summary> /// /// Removes element at the first place in <code>HistoryQueue</code>. /// /// </summary> { // Queue is empty... iHead = (iHead + 1) % mContainerSpace.Length; mSize--; } /// <summary> /// /// Clears all element in <code>HistoryQueue</code>. /// /// </summary> { Array.Clear(mContainerSpace, iHead, mSize); { Array.Clear(mContainerSpace, iHead, mContainerSpace.Length - iHead); Array.Clear(mContainerSpace, 0, iTail); } mSize = iHead = iTail = 0; } /// <summary> /// /// Check if the <code>HistoryQueue</code> is full. /// /// </summary> /// /// <returns><code>true</code> if the <code>HistoryQueue</code> is full; otherwise <code>false</code>.</returns> { } /// <summary> /// /// Check if the <code>HistoryQueue</code> is empty. /// /// </summary> /// /// <returns><code>true</code> if the <code>HistoryQueue</code> is full; otherwise <code>false</code>.</returns> { } ... // Code for IEnumerator<T> comming soon...
Trước đây mình cũng đã làm việc nhiều với lập trình Generic bên Java và biết qua Interface là Iterator dùng để duyệt tập hợp. Mình cũng tìm hiểu được một Interface tương tự như trong C# đó là IEnumerator<T> mình cũng đã viết và demo thử cho HistoryQueue thành công, tuy nhiên mình cần sửa chữa lại một tí và sẽ post trong thời gian ngắn nhất (do mình muốn khi duyệt qua HistoryQueue thì duyệt từ cuối đến đầu theo yêu cầu bài toán của mình - con trỏ lun trỏ tới phần tử cuối).
Chào các bạn,
Mình đã hoàn thành phần Enumerator cho duyệt dữ liệu, và test vấn đề của mình. Nhưng đã có một vài vấn đề nảy sinh như sau:
Trước hết minh xin tóm tắt lại
+ Mình muốn có một navigator giống như 2 nút Next và Previous trên trình duyệt web hoặc giống như cơ chế Undo và Redo, nhưng những Collection trong .NET theo mình nghĩ chưa hỗ trợ được cho bài toán của mình. Collection mình cần là sẽ Add phần tử vào đầu danh sách, khi đã đầy thì sẽ tự xóa phần tử ở cuối và add tiếp vào đầu.
+ Để làm một cơ chế Navigator thì phải cần tới 2 Collection như vậy. Khi muốn duyệt ngược (undo) về một phần tử thì sẽ Peek phần tử đầu trong danh sách 1 và add nó vào danh sách 2. Như vậy phương thức Peek sẽ lấy và remove phần tử đầu tiên trong collection. Khi muốn duyệt tới phần tử trước đó (redo) thì sẽ Peek phần tử đầu trong danh sách 2 và add nó lại vào danh sách 1. Và trong phương thức Peek của mình đã xảy ra một số vấn đề. Mình xin đưa code sau để các bạn tham khảo và nếu có thể phát hiện và giúp mình thì mình rất trân trọng.
Trước hết là về Code cho Collection:
Visual C# Code:
{ /// <summary> /// /// An <code>Interface</code> to build a history-factory. /// /// </summary> { /// <summary> /// /// Checks if there is more next element to point. /// /// </summary> /// /// <returns><c>true</c> if there is still more next element; otherwise <c>false</c>.</returns> /// <summary> /// /// Moves to the next element. /// /// </summary> /// /// <returns>Next element.</returns> T MoveNext(); /// <summary> /// /// Sets the pointer to its first initializing position. /// /// </summary> } }
Visual C# Code:
{ /// <summary> /// /// Represents a FIFO collection of object. It has a specified capacity and /// will automatically remove its element when out of container-space. /// /// This class cannot be inherited. /// /// </summary> /// /// <author>O'Wicked Fox</author> /// /// <typeparam name="T">Type-Generic</typeparam> { #region --- field(s) --- #endregion #region --- constructor(s) --- /// <summary> /// /// Constructs a new <code>HistoryQueue<T></code>. /// /// </summary> { mSize = iHead = iTail = 0; } #endregion #region --- method(s) --- /// <summary> /// /// If the <c>HistoryQueue</c> is full, it will automatically dequeue the first element, /// and then enqueue the new element. /// /// </summary> /// /// <param name="element">New element.</param> { // Size is full... { Dequeue(); // Dequeues the first element. NormalEnqueue(element); // Enqueues new element then. } NormalEnqueue(element); } /// <summary> /// /// Enqueues a new element to the tail-index of <c>HistoryQueue</c> normally. /// /// </summary> /// /// <param name="element">New element.</param> { mContainerSpace[iTail] = element; iTail = (iTail + 1) % mContainerSpace.Length; mSize++; } /// <summary> /// /// Dequeues element at head-index in <c>HistoryQueue</c>. /// /// </summary> /// ///<returns></returns> { // Queue is empty... // Dequeues at head-index. iHead = (iHead + 1) % mContainerSpace.Length; mSize--; } /// <summary> /// /// Dequeues element at tail-index in <c>HistoryQueue</c>. /// /// </summary> /// /// <returns></returns> { // Queue is empty... // Dequeues at tail-index. // if (iTail == 0) // { // iTail = mSize; // // T peekingOne = mContainerSpace[iTail -1]; // // //mContainerSpace[iTail] = default(T); // // iTail = (iTail - 1) % mContainerSpace.Length; // // //mContainerSpace[iTail] = default(T); // // mSize--; // // return peekingOne; // } // else if (iTail < 0) { // iTail = Math.Abs(1 - mSize); // // T peekingOne = mContainerSpace[iTail]; // // iTail = (iTail) % mContainerSpace.Length; // // mSize--; // // return peekingOne; // } { { iTail = mSize - 1; peekingOne = mContainerSpace[iTail]; iTail = iTail % mContainerSpace.Length; mSize--; } { peekingOne = mContainerSpace[iTail - 1]; iTail = (iTail - 1) % mContainerSpace.Length; mSize--; } //return peekingOne; } { { peekingOne = mContainerSpace[iTail - 1]; iTail = mContainerSpace.Length; mSize--; } { peekingOne = mContainerSpace[iTail - 1]; //mSize--; //mContainerSpace[iTail] = default(T); //iTail = mSize - iTail; mSize--; iTail = mContainerSpace.Length; } } return peekingOne; } /// <summary> /// /// Dismisses all element(s) in <c>HistoryQueue</c>. /// /// </summary> { Array.Clear(mContainerSpace, iHead, mSize); { Array.Clear(mContainerSpace, iHead, mContainerSpace.Length - iHead); Array.Clear(mContainerSpace, 0, iTail); } mSize = iHead = iTail = 0; } /// <summary> /// /// Gets a Type-Generic object by its index. /// /// </summary> /// /// <param name="index">Type-Generic object's index number.</param> /// /// <returns>Type-Generic element.</returns> { } /// <summary> /// /// Enumerates each element in <c>HistoryQueue</c> from tail to head. /// /// </summary> /// /// <returns></returns> { } #endregion #region --- property(es) --- { } /// <summary> /// /// Checks if the <c>HistoryQueue</c> is full. /// /// </summary> /// /// <returns><code>true</code> if the <code>HistoryQueue</code> is full; otherwise <code>false</code>.</returns> { } /// <summary> /// /// Checks if the <code>HistoryQueue</code> is empty. /// /// </summary> /// /// <returns><code>true</code> if the <code>HistoryQueue</code> is full; otherwise <code>false</code>.</returns> { } #endregion /// <summary> /// /// Represents a history engine. /// /// </summary> { #region --- fiend(s) --- private T mCurrent; #endregion #region --- constructor(s) --- /// <summary> /// /// /// /// </summary> /// /// <param name="queue"></param> { mQueue = queue; mIndex = mQueue.mSize; } #endregion #region --- implements IHistoryIterator<T> --- { --mIndex; { mIndex = -2; } } { mCurrent = mQueue.GetElement(mIndex); return mCurrent; } { mIndex = -1; } public T Current { { { } return mCurrent; } } #endregion #region --- implements IDisposable --- { mIndex = -2; } #endregion } #endregion } }
Code cho form Demo
Các bạn có thể xây dự giao diện như hình sau:Visual C# Code:
{ /// <summary> /// Description of FormHistoryQueueDemo. /// </summary> { { InitializeComponent(); } { queue.Enqueue(textboxElement.Text); labelElement.Text = textboxElement.Text; textboxElement.Clear(); textboxElement.Focus(); } { } { queue.Dequeue(); } { queue.Clear(); } listviewContainerSpace.Clear(); listviewTemp.Clear(); item.Text=history.MoveNext(); item.ImageIndex = 0; listviewContainerSpace.Items.Add(item); } item.Text=temphistory.MoveNext(); item.ImageIndex = 0; listviewTemp.Items.Add(item); } } } } else { } } { queue.Enqueue(peeknext); labelElement.Text = peeknext; } { temp.Enqueue(peekpre); labelElement.Text = peekpre; } } }
Các bạn thử Enqueue khoãng 8 phần tử sẽ thấy lỗi khi duyệt do iTail chưa sử lý kỹ. Tôi cũng đang cố gắng.
Chào các bạn, mình vừa tìm được 1 project có thể giúp mình làm được bài này rùi (codeproject). Các bạn có thể tham khảo link dưới đây:
Cũng có những điều hay đáng học trong bài viết này.Code:http://www.codeproject.com/KB/cs/generic_undo_redo.aspx
Cheer!