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();
}
}
不使用数组。"先进先出"模型是一个队列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<T> 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);