2013-05-08 96 views
0

我目前遇到了我現在創建的程序有問題。我已經在尋找答案,但它與我想要發生的不同,因爲這裏給出的是字符串。C#中的FIFO字符串分配#

我們被要求創建一個FIFO分配,這裏是程序作爲控制檯應用程序的流量預計:

輸入no。頁框:2

輸入no。的頁將被插入:要被插入4

頁:插在幀1中斷產生的

要插入的頁面:B

插入幀2.產生中斷。要被插入

頁:甲

插入失敗。 A是常駐頁面。

要插入的頁面:C

插入幀1.產生中斷。

根據FIFO分配算法,如果插入新的不同頁面,它將刪除插入幀中的最早頁面。如果該頁面已經在框架中,則頁面插入將被拒絕。

我已經做了一個,雖然我目前在試圖找出如何找到數組中最早插入的元素。

我希望你能幫助我。我已經花了很多時間,但我不知道該怎麼做。這裏是我的代碼。:

class Program 
{ 
    static void Main(string[] args) 
    { 
     int f, p, interrupt; 

     Console.WriteLine("Enter the number of frames: "); 
     f = Int32.Parse(Console.ReadLine()); 
     string[] frame = new string[f]; 
     Console.WriteLine("Enter the number of pages: "); 
     p = Int32.Parse(Console.ReadLine()); 

     for (int i = 0; i < p; i++) { 


      Console.WriteLine("Page to be inserted: "); 

      string x = Console.ReadLine(); 

      if (frame.Contains(x)) 
      { 

       Console.WriteLine(x + " is a resident page."); 


      } 
      else { 

       frame[i] = x; 
       Console.WriteLine("Inserted in frame " + (i + 1) + ". Interrupt generated")); 
       interrupt +=1; 

      } 
     } 





     Console.ReadKey(); 
    } 
} 
+2

你能不能嘗試使用隊列爲目的。它內置了FIFO處理功能。 http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx – 2013-05-08 15:51:15

回答

6

不要使用數組。 「先入先出」模式是隊列http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx

如果您使用隊列,它將保留訂單。您只能刪除第一個項目。它的概念就是它像一個交通隊列一樣工作,前面的物體在其他任何物體移動之前都必須移動。在排隊之前,只需執行for each或LINQ查詢以確保該項目不重複。 Dequeue方法將始終刪除添加到隊列中的第一個項目。

// for each example. For LINQ just use Where then check the length of the IEnumerable 
// if it 0 then item is unique. 
bool duplicate = false; 
foreach (string s in MyQueue) 
{ 
    if (s == inputString) 
     duplicate = true; 
} 

if (!duplicate) 
    MyQueue.Enqueue(inputString); 



// to get first item added simply do 
string firstIn = MyQueue.Dequeue(); 
+0

我們的教授沒有教我們這個概念,但我會研究它,所以我可以將它應用到我的程序中。非常感謝你的幫助! – 2013-05-08 16:22:15

+0

@PatrickJamesLim是的,我覺得有點奇怪。我通過寫作來教這些東西;堆棧,隊列,鏈表,哈希表和二叉搜索樹在C++中。隊列絕對是你想要的,我很驚訝你沒有被指示使用它,因爲它是計算機科學中用於FIFO的模型。 *當他要求您在下一次作業中使用LIFO時提示使用堆棧:p – evanmcdonnal 2013-05-08 16:32:27

+0

我實際上是IT學員,這就是爲什麼我們沒有深入瞭解操作系統概念的更多細節。這很糟糕,因爲我們得到的最遠的編程概念是數組和OOP編程的一個小介紹。我必須自己學習成功的概念,這很難。我試圖猜測他下次會要求我們使用LRU製作一個程序。再次感謝! >。< – 2013-05-09 01:37:36

0

我建議你使用除了數組之外的東西,比如evanmcdonnal suggested。總之,用你的代碼,你需要,當你達到極限幀添加一個單獨的變量來檢測:

int j= 0; 

    for (int i = 0; i < p; i++) { 


     Console.WriteLine("Page to be inserted: "); 

     string x = Console.ReadLine(); 

     if (frame.Contains(x)) 
     { 

      Console.WriteLine(x + " is a resident page."); 


     } 
     else { 

      if(j >= f) 
       int insertAt = 0; 
      else 
       int insertAt = j; 

      frame[insertAt ] = x; 
      Console.WriteLine("Inserted in frame " + (insertAt + 1) + ". Interrupt generated")); 
      interrupt +=1; 

      j++; 

     } 
    } 
0

您的問題是你的代碼混淆的數據結構,以及它與實際的程序方法。你需要更多地分解你的程序。您需要首先創建一個實現您的FIFO隊列的類。驗證它的行爲是否符合您的預期。然後,使用該類編寫您需要的實際程序。

正如其他人所指出的,您實際需要的數據結構似乎是一個隊列。

與某些人所說的(「不使用數組」)相反,固定容量的隊列使用數組作爲後備存儲實現是微不足道的。

您需要將您的數組用作循環緩衝區。除了陣列本身,你需要跟蹤其他3條信息:

  • 隊列的偏移量。這是隊列中最近添加的項目中最少的項目,並且將被刪除。

  • 隊列的尾部的偏移量。這是隊列中最近添加的項目,並且是最後刪除的項目。

從理論上講,您不再需要任何信息。然而,有一個奇點,頭部和尾部相撞的狀態是'排隊空'狀態或'排隊滿狀態'。因此,您需要跟蹤隊列的長度。

Dequeue()操作是容易的:

  • 檢查隊列長度。如果小於1,則隊列爲空。拋出一個下溢異常。否則,繼續。
  • 頭部偏移量是要移除的下一個項目。從數組中獲取該項目。
  • 清除數組插槽,因此不會留下可能會阻止對象被垃圾收集的懸掛引用。
  • 減少長度。
  • 遞增頭指針,如果它超過了磁盤陣列的capacacity包裝爲零 - 1。要做到這一點是通過模運算的最簡單方法:

    OffsetHead = (OffsetHead+1) % MyBackingStoreArray.Length ; 
    
  • 將卸下的物品。

Enqueue()操作並不複雜得多,雖然有一個特殊的情況下,當隊列爲空:

  • 檢查隊列長度。
  • 如果隊列長度爲0,第一個項目添加到隊列:
    • 的項添加到陣列在偏移0
    • 設置偏移量到頭部和偏移到尾爲0。
  • 如果隊列長度是> 0,

    • 偏移到所述第一空閒時隙是1過去當前尾指針,模與上述陣列的長度。
    • 如果計算的偏移量與隊列頭部的偏移量衝突,則隊列已滿:拋出溢出異常。
    • 否則,將該新項目添加到該計算出的偏移量的數組中。
    • 將尾部的偏移量設置爲計算偏移量。
  • 最後,增加隊列長度。

您可能要實施的其它操作:

  • Peek()。有時查看隊列中的下一個項目而不排出隊列可能會很有用。
  • Contains()。形式上,隊列是一個不透明的數據結構。您只能將項目添加到尾部並將其從頭部移除。然而,檢查是否已經入隊是有用的,但我認爲使用集合式語義來裝飾隊列將會是一個更好的設計。

對於將隊列的當前長度作爲屬性公開也非常有用。

你應該可以從那裏弄清楚。如果你還沒有弄明白,我會在明天實施這個答案。

。 。 。

正如所承諾的,這裏的固定長度的隊列的實現:

class ArrayQueue<T> 
{ 
    private T[] backingStore ; 
    private int head ; // offset to head of the queue (least recently added item) 
    private int tail ; // offset to tail of the queue (most recently added item) 

    /// <summary> 
    /// current queue length 
    /// </summary> 
    public int Length { get ; private set ; } 
    /// <summary> 
    /// Maximum Queue Length 
    /// </summary> 
    public int Capacity { get { return this.backingStore.Length ; } } 

    /// <summary> 
    /// Add an item to the queue 
    /// </summary> 
    /// <param name="value"></param> 
    public void Enqueue(T value) 
    { 

    if (Length == 0) 
    { 
     this.backingStore[0] = value ; 
     this.head = 0 ; 
     this.tail = 0 ; 
    } 
    else 
    { 
     // A head/tail collision means the queue is full: throw an overflow exception 
     if (this.tail == this.head) { throw new OverflowException("Maximum capacity exceeded") ; } 
     this.backingStore[this.tail] = value ; 
    } 

    // increment the tail and the length, wrapping the tail point if necessary 
    this.tail = (this.tail+1) % this.backingStore.Length ; 
    ++this.Length ; 

    return ; 
    } 

    /// <summary> 
    /// Remove the next (oldest) item from the queue 
    /// </summary> 
    /// <returns></returns> 
    public T Dequeue() 
    { 
    if (this.Length < 1) { throw new InvalidOperationException("queue is empty") ; } 

    T value = this.backingStore[head] ; 
    this.backingStore[head] = default(T) ; // lose the reference so the newly dequeued item can be garbage-collected. 

    --this.Length; 
    this.head = (this.head+1) % this.backingStore.Length ; 

    return value ; 
    } 

    /// <summary> 
    /// Examine the head of the queue, without removing it 
    /// </summary> 
    /// <returns></returns> 
    public T Peek() 
    { 
    if (this.Length < 1) { throw new InvalidOperationException("queue is empty") ; } 

    T value = this.backingStore[head] ; 
    return value ; 
    } 

    /// <summary> 
    /// Clear/Empty the queue 
    /// </summary> 
    public void Clear() 
    { 
    // clear any object references to the queue so they can be garbage-collected 
    Array.Clear(this.backingStore,0,this.backingStore.Length); 
    this.head = 0 ; 
    this.tail = 0 ; 
    this.Length = 0 ; 
    return ; 
    } 

    /// <summary> 
    /// indicates whether or not the specified item is present in the queue 
    /// </summary> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public bool Contains(T value) 
    { 
    bool found = false ; 
    for (int i = 0 ; !found && i < this.Length ; ++i) 
    { 
     int p = (this.head+1) % this.Capacity ; 
     found = this.backingStore[p].Equals(value) ; 
    } 
    return found ; 
    } 

    /// <summary> 
    /// Create an instance of an ArrayQueue&lt;T&gt; having the specified fixed capacity 
    /// </summary> 
    /// <param name="capacity"></param> 
    /// <returns></returns> 
    public static ArrayQueue<T> CreateInstance(int capacity) 
    { 
    if (capacity < 0) throw new ArgumentOutOfRangeException("capacity","capacity must be non-negative"); 

    ArrayQueue<T> instance = new ArrayQueue<T>(capacity) ; 

    return instance ; 
    } 

    /// <summary> 
    /// private (and only constructor) 
    /// </summary> 
    /// <param name="capacity"></param> 
    private ArrayQueue(int capacity) 
    { 
    this.backingStore = new T[capacity] ; 
    this.Clear() ; 
    return ; 
    } 

} 
+0

我目前正試圖實現這一點。不過,我希望你明天能給我一個答案,並將其與我的工作進行比較。先生,非常感謝你。 – 2013-05-09 02:04:10

0

我敢打賭,這將幫助。打開此頁面並使用相同的示例。

http://msdn.microsoft.com/en-us/library/ee789351(v=vs.110).aspx

只是使這種變化的Main()方法下的線。

 // Create a scheduler that uses 1 threads first-in, first-out (FIFO) execution order. 
     LimitedConcurrencyLevelTaskScheduler lcts = new LimitedConcurrencyLevelTaskScheduler(1);