Access array inside a constructor - c#

This Is for homework.
I have googled this and searched within stackoverflow, but I can not seem to find the answer. Perhaps my terminology is incorrect.
I am learning TDD for a class and my C# skills are rusty and limited.
I am trying to write a stack class. When I try to initiate an array inside the constructor, the methods cannot access it.
I'm sure it is something simple that I am missing.
Here is the code what i have tried so far :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace tdd_programmingTest
{
class Stack
{
int index = 0;
public Stack()
{
int[] items;
}
public void Push(int p)
{
items[index] = p;
index++;
}
public int Pop()
{
index--;
return items[index];
}
internal int IndexState()
{
return index;
}
}
}
I'm not looking for someone to write the code for me, just point me in the right direction. Thank you.

What you have here is a local variable:
public Stack()
{
int[] items;
}
It exits only inside of the Stack() constructor, and only for the lifetime of its execution.
You need to declare items as a field (member variable):
class Stack
{
private int index = 0;
private int[] items; // <-- move it here, and mark it private
public Stack()
{
}
// ...
}
But you have bigger problems. This is just a reference to an array which you haven't created yet.
So, you need to instantiate an array:
int[] items = new int[SIZE];
...but what size will you use? Once you create the array, it can not grow. You'll have to allocate a larger array and copy it, once you run out of space. This auto-self-expansion is how many ADT's work under the hood.
Speaking of running out of space, you'd better pay attention to your array's bounds in Push() and Pop()!
EDIT: So you need to specify a size. Just add a parameter to the constructor.
class Stack
{
private int index = 0;
private int[] items;
public Stack(int initialSize)
{
items = new int[initialSize];
}
public Stack() : Stack(100)
{
}
}

Put int[] items; outside of the constructor and add size parameter to the constructor to specify the size of items:
class Stack
{
int index = 0;
int[] items = new int[0];
public Stack(int size)
{
items = new int[size]; // initiate items with size
}
public void Push(int p)
{
items[index] = p;
index++;
}
public int Pop()
{
index--;
return items[index];
}
internal int IndexState()
{
return index;
}
}

Related

I can't use a foreach loop twice in my code, why?

I am currently trying to learn C# and I am giving it a shot to implement Queue from scratch.
Currently I am trying to implement foreach functionality so I can print out my queue.
I have an issue when I use a foreach loop twice in my code it wont print anything the second time I use it. I have managed to see that my Current method in the Queue class isn't being used the second time I use the foreach loop (with help of the print statement of the int position variable, which doesnt print out anything the second time a foreach is being used).
I appreciate any help to understand why I can't use a foreach loop twice in my code. And if there is anything else which can be improved with my code, that would be greatly appreciated as well.
The RunTest class below is where I test my implementation of my Queue class.
namespace RunTest
{
class RunTest
{
public static void Main(string[] args){
Queue<string> queueOfStrings = new Queue<string>();
queueOfStrings.Enqueue("Dog");
queueOfStrings.Enqueue("Cat");
queueOfStrings.Enqueue("Mouse");
queueOfStrings.Enqueue("Bird");
System.Console.WriteLine("Foreach: \n");
foreach(string item in queueOfStrings){
System.Console.WriteLine(item);
}
System.Console.WriteLine("\n");
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Dequeue : "+queueOfStrings.Dequeue());
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Foreach: ");
foreach(string item2 in queueOfStrings){
System.Console.WriteLine(item2);
}
}
}
}
And here is my Queue class:
using System;
using System.Collections;
using System.Collections.Generic;
public class Queue<T> : IEnumerator,IEnumerable{
private LinkedList<T> list = new LinkedList<T>();
private T[] storeElements;
private int position = -1;
public Queue()
{
Console.WriteLine("Queue initialized \n");
}
public void Enqueue(T data){
list.AddFirst(data);
}
public int Count(){
return list.Count;
}
public void Clear(){
list.Clear();
}
public T Dequeue(){
T data = list.Last.Value;
list.RemoveLast();
return data;
}
public T Peek(){
return list.Last.Value;
}
private void ToArray(){
storeElements = new T[Count()];
list.CopyTo(storeElements, 0);
Array.Reverse(storeElements);
}
//IEnumerator and IEnumerable require these methods.
public IEnumerator GetEnumerator()
{
ToArray();
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < Count());
}
//IEnumerable
public void Reset()
{
position = 0;
}
//IEnumerable
public object Current
{
get { System.Console.WriteLine(position); return storeElements[position];}
}
}
Using the queue itself as the enumerator isn't a great idea-- it will really limit how the class can be used. Imagine for example if you wanted to check the queue for duplicates-- you'd have to create a nested loop, which means two simultaneous enumerators. It simply wouldn't work because there is only one position variable.
Take a look at how built-in classes do it. They return a new instance of a separate enumerator class (e.g. an array will create a SZArrayEnumerator). In your case, you can probably leverage the enumerator provided by the backing field itself, like this:
public IEnumerator GetEnumerator()
{
ToArray();
return storeElements.GetEnumerator();
}

How can I populate a string array with a parameter method C#

I am trying to populate a string array called "items" with a pre written method called "insert".
The project has pre written code "b.insert("apple");" etc etc and the method given is "public void insert(T item)". I have to write the code in this method to make the "insert" function work. I have to pass "item" into "items" array but my for loop simply gives me the output "milk" 10 times. Because of this, I know that "item" value is simply changing to the last string passed in the insert method. Would I have to write a nested for loop where "item" is a counter? In this case "item" cannot be a counter because it is a string type. Should I convert "item" into an array?
I'm not sure why such a seemingly simple task has me stumped by I've been at it for hours and at this point I just want to sort it out for the sake of sanity.
thanks in advance
class Program
{
static void Main(string[] args)
{
BoundedBag<string> b = new BoundedBag<string>("ShoppingList", 10);
b.insert("apple");
b.insert("eggs");
b.insert("milk");
Console.WriteLine(b);
Console.ReadKey();
}
}
public interface Bag<T> where T : class
{
void insert(T item);
string getName();
bool isEmpty();
}
public class BoundedBag<T> : Bag<T> where T : class
{
private string bagName; // the name of the bag
protected int size; // max size of the bag
private int lastIndex;
protected T[] items;
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
rnd = new Random();
items = new T[size];
}
public string getName()
{
return bagName;
}
public bool isEmpty()
{
return lastIndex == -1;
}
public bool isFull()
{
if(items.Length >= size)
{
return true;
}
else { return false;}
}
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
for (int i = 0; i < size; i++)
{
items[i] = item;
}
}
}
You only want to insert one item into your array on insert so you shouldn't have a loop at all. Use the lastIndex field to insert one item into the appropriate place in the array:
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
if(isFull())
{
throw new FullBagException();
}
items[++lastIndex] = item;
}
Unfortunately your isFull method is also broken and your isEmpty method won't work properly unless you change the constructor.
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
items = new T[size];
lastIndex = -1;
}
public bool isFull()
{
return lastIndex == size - 1;
}

Can't Call arrays in main method

I'm practicing methods, but the problem is I want to separate inputting and sorting, the display method will be the main, I'm having trouble fixing this calling from other class.
This is my script :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CaseProblem
{
class Method
{
static void MethodInput()
{
int[] array = new int[5];
int i;
// loop for accepting values in array
for (i = 0; i < 5; i++)
{
Console.Write("Enter number:\t");
array[i] = int.Parse(Console.ReadLine());
}
}
public static void MethodSort()
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
}
class Program
{
static void Main(int[]array)
{
//sorting array value;
Array.Sort(array); //use array's sort function
Method.MethodSort(array);
Console.ReadLine();
}
}
}
Thank you for your help
First of all Main() ( or "EntryPoint" as we should call it ) cannot have int[] as an input parameter but string[] instead you should learn basics of programming before starting to actually code something.
Second thing :
I want to separate inputting and sorting
You can create an object called Input
public class Input
{
public static void Write(string message)
{
Console.WriteLine(message);
}
public static int? ReadInt(string reason)
{
Write(reason);
string userInput = Console.ReadLine();
int parsed = 0;
if(int.TryParse(userInput, out parsed))
return (int?)parsed;
return null;
}
}
This will be your "InputLogic" which you can use as Input.ReadInt("Please specify your age: ");
Next you can make an Operations object :
public class Operations
{
public void Display(int[] arr)
{
foreach(int i in arr)
{
// and since you have "Input" class that can display things
Input.Write(i.ToString());
}
}
public void Sort(ref int[] arr)
{
Array.Sort(arr);
}
}
Now the last thing is to combine it within your Program
class Program
{
static void Main(string[] args)
{
int[] arr = new int[5];
for(int i = 0; i < arr.Length; i++)
{
int? input = null;
while( !( input = Input.ReadInt("Give me number") ).HasValue ) { }
arr[i] = input.Value;
}
Operations op = new Operations();
op.Display(arr);
op.Sort(ref arr);
op.Display(arr);
}
}
Well, you are missing the parameter for the called function.
public static void MethodSort(int[] array)
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
note: not tested
Okay, you have two errors, both in this method:
public static void MethodSort()
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}
as well as how you call it:
Method.MethodSort(array);
The first problem is that the method uses the variable array, which doesn't exist in that method's scope.
The second problem is that you are passing array to the call to Method.MethodSort, but that method isn't configured to take a parameter.
There are two ways to approach solving this: remove array entirely, or change the method to accept it. Now, you obviously cannot remove array, as the whole point is to do stuff with it. Therefore, the logical solution is to add array as a parameter to your method:
public static void MethodSort(int[] array)
{
foreach (int i in array)
{
Console.Write(" {0}", i);
}
}

With Statement in C# like that of AS3/GML

I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.

Faster enumeration: Leveraging Array Enumeration

So, I have a class with an array inside. Currently, my strategy for enumerating over the class's items is to use the code, foreach (item x in classInstance.InsideArray) . I would much rather use foreach (item x in classInstance) and make the array private. My main concern is that I really need to avoid anything slow; the array gets hit a lot (and has a couple hundred items). It is vital that enumerating over this array is cheap. One thought was to just have the class implement IEnumerable<item>, but InsideArray.getEnumerator() only gives me a non-generic enumerator. I also tried implementing the IEnumerable interface. This worked but was very slow, possibly due to boxing.
Is there a way to make the class itself enumerable without a performance hit?
Normal Code:
//Class
public class Foo {
//Stuff
public Item[,] InsideArray {get; private set;}
}
//Iteration. Shows up all over the place
foreach (Item x in classInstance.InsideArray)
{
//doStuff
}
Adjusted, much slower code:
//Class
public class Foo : IEnumerable {
//Stuff
private Item[,] InsideArray;
System.Collections.IEnumerator System.Collections.IEnumerable GetEnumerator()
{
return InsideArray.GetEnumerator();
}
}
//Iteration. Shows up all over the place
foreach (Item x in classInstance)
{
//doStuff
}
Note: Adding an implementation for the nongeneric iterator is possible and faster than my slow solution, but it is still a bit worse than just using the array directly. I was hoping there was a way to somehow tell C#, "hey, when I ask you to iterate over this object iterate over it's array, just as fast," but apparently that is not quite possible...at least from the answers suggested thus far.
A bespoke iterator might make it quicker (edited to return as known type):
Basic: 2468ms - -2049509440
Bespoke: 1087ms - -2049509440
(you would use the ArrayIterator directly as Foo's GetEnumerator - essentially copying the code from ArrayEnumerator.GetEnumerator; my point is to show that a typed iterator is faster than the interface)
With code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
class Foo
{
public struct ArrayIterator<T> : IEnumerator<T>
{
private int x, y;
private readonly int width, height;
private T[,] data;
public ArrayIterator(T[,] data)
{
this.data = data;
this.width = data.GetLength(0);
this.height = data.GetLength(1);
x = y = 0;
}
public void Dispose() { data = null; }
public bool MoveNext()
{
if (++x >= width)
{
x = 0;
y++;
}
return y < height;
}
public void Reset() { x = y = 0; }
public T Current { get { return data[x, y]; } }
object IEnumerator.Current { get { return data[x, y]; } }
}
public sealed class ArrayEnumerator<T> : IEnumerable<T>
{
private readonly T[,] arr;
public ArrayEnumerator(T[,] arr) { this.arr = arr; }
public ArrayIterator<T> GetEnumerator()
{
return new ArrayIterator<T>(arr);
}
System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public int[,] data;
public IEnumerable<int> Basic()
{
foreach (int i in data) yield return i;
}
public ArrayEnumerator<int> Bespoke()
{
return new ArrayEnumerator<int>(data);
}
public Foo()
{
data = new int[500, 500];
for (int x = 0; x < 500; x++)
for (int y = 0; y < 500; y++)
{
data[x, y] = x + y;
}
}
static void Main()
{
Test(1); // for JIT
Test(500); // for real
Console.ReadKey(); // pause
}
static void Test(int count)
{
Foo foo = new Foo();
int chk;
Stopwatch watch = Stopwatch.StartNew();
chk = 0;
for (int i = 0; i < count; i++)
{
foreach (int j in foo.Basic())
{
chk += j;
}
}
watch.Stop();
Console.WriteLine("Basic: " + watch.ElapsedMilliseconds + "ms - " + chk);
watch = Stopwatch.StartNew();
chk = 0;
for (int i = 0; i < count; i++)
{
foreach (int j in foo.Bespoke())
{
chk += j;
}
}
watch.Stop();
Console.WriteLine("Bespoke: " + watch.ElapsedMilliseconds + "ms - " + chk);
}
}
Cast your array to IEnumerable<item> before calling GetEnumerator() and you'll get the generic IEnumerator. For example:
string[] names = { "Jon", "Marc" };
IEnumerator<string> enumerable = ((IEnumerable<string>)names).GetEnumerator();
It may well still be a bit slower than enumerating the array directly with foreach (which the C# compiler does in a different way) but at least you won't have anything else in the way.
EDIT:
Okay, you said your other attempt used an indexer. You could try this approach, although I don't think it'll be any faster:
public IEnumerable<Item> Items
{
get
{
foreach (Item x in items)
{
yield return x;
}
}
}
An alternative would be to try to avoid using a two-dimensional array to start with. Is that an absolute requirement? How often are you iterating over a single array after creating it? It may be worth taking a slight hit at creation time to make iteration cheaper.
EDIT: Another suggestion, which is slightly off the wall... instead of passing the iterator back to the caller, why not get the caller to say what to do with each item, using a delegate?
public void ForEachItem(Action action)
{
foreach (Item item in items)
{
action(item);
}
}
Downsides:
You incur the penalty of a delegate call on each access.
It's hard to break out of the loop (other than by throwing an exception). There are different ways of approaching this, but let's cross that bridge when we come to it.
Developers who aren't familiar with delegates may get a bit confused.
How about adding an indexer to the class:
public MyInsideArrayType this[int index]
{
get{return this.insideArray[index];
}
And if you REALLY need foreach capabilities:
public IEnumerable<MyInsideArrayType> GetEnumerator()
{
for(int i = 0; i<this.insideArray.Count;i++)
{
yield return this[i];
}
}
All forms of iteration are cheap. If anyone in this day-and-age managed to somehow write and publish an expensive iterator they would be (rightly) burned at the stake.
Premature optimization is evil.
Cheers. Keith.

Categories

Resources