c#中的FIFO字符串分配

本文关键字:分配 字符串 FIFO 中的 | 更新日期: 2023-09-27 18:12:34

我现在正在创建的程序有问题。我已经找过答案了,但这和我想要的不一样因为这里给出的是字符串。

我们被要求创建一个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();
    }
}

c#中的FIFO字符串分配

不使用数组。"先进先出"模型是一个队列http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx

如果你使用Queue,它将保持顺序。你只允许删除第一个条目。这个概念就像一个交通队列,前面的物体必须在其他物体移动之前离开。在排队之前,只需执行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();

我建议您使用数组以外的东西,就像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++;
        }
    }

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

你真正想要的数据结构,似乎是一个队列,正如其他人注意到的。

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

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

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

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

理论上,你不需要比这更多的信息。然而,存在一个奇点,即头部和尾部碰撞的状态要么是"队列空"状态,要么是"队列满"状态。因此,您需要跟踪队列的长度。

Dequeue()操作简单:

  • 检查队列长度。如果小于1,则队列为空。抛出下溢异常。否则,继续。
  • 头偏移是下一个要删除的项。从数组中获取该项。
  • 清除数组槽,这样就不会留下可能阻止对象被垃圾收集的悬空引用。
  • 递减长度
  • 增加头指针,如果超过数组的容量,则换行为零- 1。最简单的方法是通过模运算:

    OffsetHead = (OffsetHead+1) % MyBackingStoreArray.Length ;
    
  • 返回移除的物品

Enqueue()操作并不复杂,但有一种特殊情况,当队列为空时:

  • 查看队列长度
  • 如果队列长度为0,将第一项添加到队列中:
    • 将项目添加到偏移量为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 ;
  }
}

我打赌这会有帮助。打开这一页,使用相同的例子。

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