Adding to an array c# - c#

I have an array int Stack[] of size 5. I want to implement a method Push(value) that will push value into the last available slot of the array. Example: if array is empty and I use Push(1), now there is a 1 on position 0 of the array; but if the array has 3 values and I use Push(1), there will be a 1 on position 3 (since the array starts at 0, for a total of 4 values in the array). How may I do this?

public class Stack{
int items[];
int top;
public Stack(int size){
items=new int[size];
top=0;
}
public void Push(int val){
if(!IsFull()){
items[top++]=val;
}
}
public int Pop(){
if(!IsEmpty()){
return items[--top];
}else{
//-1 is for invalid op or just you can chech before calling Pop()
//is stack empty or not
return -1;
}
}
public bool IsFull()=>top==items.Length;
public bool IsEmpty()=>top==0;
}

For this purpose you have List<T>
https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=net-6.0
Of course you can do that with an array as well, but that would mean that you have to make a new array for each Push() execution, which is completely unnecessary when you can use a list

Related

Getting the number of elements in a generic array

For a school project, I need to return the number of elements in a generic array (a T[] array).
In the constructor I set the array like this:
T[] arr = new T[100];
arr.add(3);
arr.add(2);
arr.add(1);
To find the size of the array I tried array.length, however this return the capacity which would be 100 but it should be 3.
How could I find the correct answer 3?
EDIT:
The add function is a simple function that checks if the size is smaller than default_capacity add data to array. Size variable is crucial and the function expects the total number of elements in the array.
public void Add(T x)
{
if(size < DEFAULT_CAPACITY)
{
array[size] = x;
}
}
Here the array has not a capacity of 100: it has 100 items.
An array has no capacity, it has Length items...
For example, an array of 100 integers has 100 boxes initialized to 0.
And an array has no add method...
You may use a List<T> instead and you'll have Count property and Add method.
List<> is more smooth and usefull than arrays, but a little less optimized.
If the work is to use a such initialized array, you may use #itsme86 advice in question comment.
But here what is add method in your code?
You can use your intended array like that:
public class GenericArray<T>
{
public readonly T[] arr = new T[100];
}
var myArray = new GenericArray<int>();
myArray.arr[0] = 3;
myArray.arr[1] = 2;
myArray.arr[10] = 1;
And you still have 100 items: myArray.arr.Length is 100.
You can use a generic list like that:
public class GenericList<T>
{
public readonly List<T> list = new List<T>(100);
}
var myList = new GenericList<int>();
myList.list.Add(3);
myList.list.Add(2);
myList.list.Add(1);
And here you have 3 items: myList.list.Count is 3.
The list has here a capacity of 100: it means you can add items without resizing the internal array.

How to push 0 item to the stack of int?

I have a simple stack implementation. But I cant realize how programmer solve the following problem: It is not possible to push a 0 to the stack. How to do that? I mean how to track is it a 0 value or just end of the stack? Or its not a problem in my implementation?
public class Stack: IStack
{
private int[] s;
private int N = 0;
public Stack(int N)
{
s = new int[N];
}
public void push(int x)
{
s[N++] = x;
if (N >= s.Length)
{
Array.Resize(ref s, s.Length*2);
}
}
public int pop()
{
s[N] = 0;
return s[--N];
}
}
You are already tracking the last element of the stack with N (or rather, N - 1). You don't need to verify whether the element is 0, and your implementation actually doesn't distinguish between zeroes and other numbers.
In the implementation you provided, it is perfectly possible to push a 0 into the stack.
By the way, I would reimplement your pop() method like this:
public int? pop()
{
if (N != 0)
{
return s[--N];
}
else
{
return null;
}
}
This way, it returns null in case the stack is empty.
You should realize that it doesn't matter what the values S[N], S[N+1], ... are since you are only using the values S[0..N-1] for your implementation. You consider the part S[N...] as uninitialized and adding a new element, even 0, causes S[N] to become initialized as the new value.
You can push 0 nothing prevents it. N is equal to number of elements, it's also used to track index of next item to push N == (index of last element + 1). The problem i see is that if you run pop() too many times you will get IndexOutOfRangeException.
You can add IsEmpty property like this:
public bool IsEmpty
{
get { return N < 1; }
}

C# Add value to array through user input

I want to add elements to my array through a user input.
I know this can be done very easy using a list but i have to use an array.
The problem with the code is that the array.lenght will always be 1.
I want the array to have the same size as the total amount of elements in it, so
size of the array shouldnt be set when declaring the array.
I thought that if you add an element to an array it will copy the previous values + the added value and create a new array.
UPDATED WITH ANSWER
public static void Add(int x){
if (Item == null) // First time need to initialize your variable
{
Item = new int[1];
}
else
{
Array.Resize<int>(ref Item, Item.Length + 1);
}
Item[Item.Length-1] = x; //fixed Item.Length -> Item.Length-1
}
Use List<int> instead of an explicit array, which will dynamically size for you, and use the Add() method to add elements at the end.
I didn't test in VS. Here you go:
namespace ConsoleApplication1
{
class Program
{
static int[] Item; //Fixed int Item[] to int[] Item
static void Main(string[] args)
{
Add(3);
Add(4);
Add(6);
}
public static void Add(int x){
if (Item == null) // First time need to initialize your variable
{
Item = new int[1];
}
else
{
Array.Resize<int>(ref Item, Item.Length + 1);
}
Item[Item.Length-1] = x; //fixed Item.Length -> Item.Length-1
}
}
}
This should resize your array by one each time and then set the last item to what you are trying to add. Note that this is VERY inefficient.
Lists grow as you add elements to it. Arrays have a constant size. If you must use arrays, the easiest way to do it, is to create an array that is big enough to hold the entered elements.
private int[] _items = new int[100];
private int _count;
public void Add(int x)
{
_items[_count++] = x;
}
You also need to keep track of the number of elements already inserted (I used the field _count here);
As an example, you can then enumerate all the items like this:
for (int i = 0; i < _count; i++) {
Console.WriteLine(_items[i]);
}
You can make the items accessible publicly like this:
public int[] Items { get { return _items; } }
public int Count { get { return _count; } }
UPDATE
If you want to grow the array size automatically, this is best done by doubling the actual size, when the array becomes too small. It's a good compromise between speed and memory efficiency (this is how lists work internally).
private int[] _items = new int[8];
private int _count;
public void Add(int x)
{
if (_count == _items.Lengh) {
Array.Resize(ref _items, 2 * _items.Length);
}
_items[_count++] = x;
}
However, keep in mind that this changes the array reference. So no permanent copy of this array reference should be stored anywhere else.

Reading in a binary file containing an unknown quantity of structures (C#)

Ok, so I currently have a binary file containing an unknown number of structs like this:
private struct sTestStruct
{
public int numberOne;
public int numberTwo;
public int[] numbers; // This is ALWAYS 128 ints long.
public bool trueFalse;
}
So far, I use the following to read all the structs into a List<>:
List<sTestStruct> structList = new List<sTestStruct>();
while (binReader.BaseStream.Position < binReader.BaseStream.Length)
{
sTestStruct temp = new sTestStruct();
temp.numberOne = binReader.ReadInt32();
temp.numberTwo = binReader.ReadInt32();
temp.numbers = new int[128];
for (int i = 0; i < temp.numbers.Length; i++)
{
temp.numbers[i] = binReader.ReadInt32();
}
temp.trueFalse = binReader.ReadBoolean();
// Add to List<>
structList.Add(temp);
}
I don't really want to do this, as only one of the structs can be displayed to the user at once, so there is no point reading in more than one record at a time. So I thought that I could read in a specific record using something like:
fileStream.Seek(sizeof(sTestStruct) * index, SeekOrigin.Begin);
But it wont let me as it doesn't know the size of the sTestStruct, the structure wont let me predefine the array size, so how do I go about this??
The sTestStruct is not stored in one consecutive are of memory and sizeof(sTestStruct) is not directly related to the size of the records in the file. The numbers members is a reference to an array which you allocate youself in your reading code.
But you can easily specify the record size in code since it is a constant value. This code will seek to the record at index. You can then read one record using the body of your loop.
const Int32 RecordSize = (2 + 128)*sizeof(Int32) + sizeof(Boolean);
fileStream.Seek(RecordSize * index, SeekOrigin.Begin);
If you have many different fixed sized records and you are afraid that manually entering the record size for each record is error prone you could devise a scheme based on reflection and custom attributes.
Create an attribute to define the size of arrays:
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class ArraySizeAttribute : Attribute {
public ArraySizeAttribute(Int32 length) {
Length = length;
}
public Int32 Length { get; private set; }
}
Use the attribute on your record type:
private struct sTestStruct {
public int numberOne;
public int numberTwo;
[ArraySize(128)]
public int[] numbers; // This is ALWAYS 128 ints long.
public bool trueFalse;
}
You can then compute the size of the record using this sample code:
Int32 GetRecordSize(Type recordType) {
return recordType.GetFields().Select(fieldInfo => GetFieldSize(fieldInfo)).Sum();
}
Int32 GetFieldSize(FieldInfo fieldInfo) {
if (fieldInfo.FieldType.IsArray) {
// The size of an array is the size of the array elements multiplied by the
// length of the array.
var arraySizeAttribute = (ArraySizeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(ArraySizeAttribute));
if (arraySizeAttribute == null)
throw new InvalidOperationException("Missing ArraySizeAttribute on array.");
return GetTypeSize(fieldInfo.FieldType.GetElementType())*arraySizeAttribute.Length;
}
else
return GetTypeSize(fieldInfo.FieldType);
}
Int32 GetTypeSize(Type type) {
if (type == typeof(Int32))
return 4;
else if (type == typeof(Boolean))
return 1;
else
throw new InvalidOperationException("Unexpected type.");
}
Use it like this:
var recordSize = GetRecordSize(typeof(sTestStruct));
fileStream.Seek(recordSize * index, SeekOrigin.Begin);
You will probably have to expand a little on this code to use it in production.
From everything I have read, the way you are doing it is the best method to read in binary data as it has the fewest gotchas where things can go wrong.
Define your struct like this:
struct sTestStruct
{
public int numberOne;
public int numberTwo;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=128)]
public int[] numbers; // This is ALWAYS 128 ints long.
public bool trueFalse;
}
And use Marshal.Sizeof(typeof(sTestStruct)).

c# array function argument pass one dimension

Let say I got this function :
void int Calculate(double[] array) {}
And in my main I got this array:
double[,] myArray = new double[3,3];
How can I call Calculate(...) ?
I try (that's don't compile) :
double[] mySingleArray = myArray[0];
What I want to avoid is unnecessary loop (for).
I declare a regular array, but if a jagged array or any other type of array works better, it's fine for me.
I use c# 3.5
First, let's declare your Calculate() method like this:
int Calculate(IEnumerable<double> doubles)
Don't worry, you can still pass an array to that code. You might also need IList<double>, but 9 times out of 10 the IEnumerable is good enough. The main thing is that this will let us use the yield keyword to slice up your array in an efficient way:
public static IEnumerable<T> Slice(this T[,] values)
{
return Slice(values, 0, 0);
}
public static IEnumerable<T> Slice(this T[,] values, int index)
{
return Slice(values, 0, index);
}
public static IEnumerable<T> Slice(this T[,] values, int dimension, int index)
{
int length = values.GetUpperBound(dimension);
int[] point = new int[values.Rank];
point[dimension] = index;
dimension = 1 - dimension;// only works for rank == 2
for (int i = 0; i < length; i++)
{
point[dimension] = i;
yield return (T)values.GetValue(point);
}
}
It still needs some work because it only works with rank 2 arrays, but it should be fine for the example you posted.
Now you can call your calculate function like this:
Calculate(myArray.Slice(0));
Note that due to the way IEnumerable and the yield statement work the for loop in the code I posted is essentially free. It won't run until you actually iterate the items in your Calculate method, and even there runs in a "just-in-time" fashion so that the whole algorithm remains O(n).
It gets even more interesting when you share what your Calculate method is doing. You might be able to express it as a simple Aggregate + lambda expression. For example, let's say your calculate method returned the number of items > 5:
myArray.Slice(0).Count(x => x > 5);
Or say it summed all the items:
myArray.Slice().Sum();
A jagged array works the way you want:
double[][] jaggedArray = new double[][100];
for (int i = 0; i < jaggedArray.Length; ++i)
jaggedArray[i] = new double[100];
myFunction(jaggedArray[0]);
You can have different sizes for each array in this way.
A jagged array would let you split out the first array!
The Slice() method given above will get you a single row from your array, which seems to match the sample given in your question.
However, if you want a one dimensional array that contains all the elements in the rectangular array, you can use something like this, which is also O(n).
public static T[] Flatten<T>(this T[,] array)
where T : struct
{
int size = Marshal.SizeOf(array[0, 0]);
int totalSize = Buffer.ByteLength(array);
T[] result = new T[totalSize / size];
Buffer.BlockCopy(array, 0, result, 0, totalSize);
return result;
}

Categories