0

我目前正在创建的程序有问题。我已经在寻找答案,但它与我想要发生的不同,因为这里给出的是字符串。

我们被要求创建一个 FIFO 分配,这是程序作为控制台应用程序的预期流程:

输入编号。页框数:2

输入编号。要插入的页面数:4

要插入的页面:A

插入第 1 帧。产生中断。

要插入的页面:B

插入第 2 帧。产生中断。

要插入的页面:A

插入失败。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();
    }
}
4

4 回答 4

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();
于 2013-05-08T15:50:14.393 回答
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);
于 2013-11-11T04:00:22.047 回答
0

我建议你使用数组以外的东西,比如evanmcdonnal 建议的。无论如何,使用您的代码,您需要添加一个单独的变量来检测何时达到帧限制:

    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++;

        }
    }
于 2013-05-08T15:55:08.500 回答
0

您的问题是您的代码将数据结构及其方法与实际程序混淆了。你需要更多地分解你的程序。您首先需要创建一个实现 FIFO 队列的类。验证它的行为是否符合您的预期。然后,使用该类编写您需要的实际程序。

正如其他人所指出的,您真正想要的数据结构似乎是一个队列。

与某些人所说的相反(“不要使用数组”),使用数组作为后备存储来实现固定容量的队列是微不足道的。

您需要将数组用作循环缓冲区。除了数组本身,您还需要跟踪其他 3 条信息:

  • 队列头部的偏移量。这是队列中最近最少添加的项目,将是第一个删除的项目。

  • 队列尾部的偏移量。这是队列中最近添加的项目,并且将是最后删除的项目。

从理论上讲,您没有比这更多的信息。然而,有一个奇点,头部和尾部碰撞的状态要么是“队列空”状态,要么是“队列满状态”。因此,您需要跟踪队列的长度。

Dequeue()操作很简单:

  • 检查队列长度。如果小于 1,则队列为空。引发下溢异常。否则,继续。
  • 头部偏移量是下一个要移除的项目。从数组中获取该项目。
  • 清除数组槽,这样就不会留下可能会阻止对象被垃圾收集的悬空引用。
  • 减少长度。
  • 增加头指针,如果它超过数组的容量 - 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 ;
  }

}
于 2013-05-08T20:34:28.900 回答