StackoverflowException when filling array - c#

I usually spend my time reading and trying to answer the Excel VBA questions but I am trying to learn C# now. Can someone help me understand why I get a StackOverflowException error on the second to last line in my code?
I am trying to fill an array via a method.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Console.WriteLine(numbers);
Console.ReadKey();
}
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return GenerateNumbers();
}
}
}

You are confusing the weird VBA way of returning functions with C#. You are returning an infinite recursion, which can be easily fixed by using this:
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return num; //you don't return the function name but a variable
}

A stack overflow is an undesirable condition in which a particular
computer program tries to use more memory space than the call stack
has available. In programming, the call stack is a buffer that stores
requests that need to be handled. http://whatis.techtarget.com/definition/stack-overflow
static int[] GenerateNumbers()
{
int[] num = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
return GenerateNumbers(); //Here is where the problem happens
}
The problem lies with the return part. You are calling the same function in the same function creating a stack of the same function again and again and... You get the picture.
Change it to
return num;

By calling return GenerateNumbers() at the end of your function, you are running that function over and over again infinitely because there is no way to break the recursion, causing the stack overflow. You should instead use return num

This is what you're esentially doing:
void Main()
{
FlipPage();
}
void FlipPage()
{
FlipPage();
}
So like that blond you keep flipping that page in all eternity

Related

C# can't use the "Length" function [duplicate]

This question already has answers here:
All possible array initialization syntaxes
(19 answers)
Closed 2 years ago.
I am now learning how to use the For Loops in C#, but when I try to compile my program, three errors in the console appear and one of them says that int doesn't have a definition for Lenght (I'm just not showing the errors because they are in portuguese), any idea about why this is happening?
using System;
namespace Giraffe
{
class Program
{
static void Main(string[] args)
{
int luckyNumbers = {4, 8, 15, 16, 23, 42};
for (int i = 0; i < luckyNumbers.Length; i++)
{
Console.WriteLine(luckyNumbers[i]);
}
Console.ReadLine();
}
}
}
You have an incorrect array declaration, change it to
int[] luckyNumbers = {4, 8, 15, 16, 23, 42};
You current declaration int luckyNumbers = {4, 8, 15, 16, 23, 42}; is invalid, you can't assign an array instance to int variable, therefore Length property isn't available

How can I make my procedure for finding the Nth most frequent element in an array more efficient and compact?

Here's an example of a solution I came up with
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
var countlist = arr.Aggregate(new Dictionary<int,int>(), (D,i) => {
D[i] = D.ContainsKey(i) ? (D[i] + 1) : 1;
return D;
})
.AsQueryable()
.OrderByDescending(x => x.Value)
.Select(x => x.Key)
.ToList();
// print the element which appears with the second
// highest frequency in arr
Console.WriteLine(countlist[2]); // should print 3
}
}
At the very least, I would like to figure out how to
Cut down the query clauses by at least one. While I don't see any redundancy, this is the type of LINQ query where I fret about all the overhead of all the intermediate structures created.
Figure out how to not return an entire list at the end. I just want the 2nd element in the enumerated sequence; I shouldn't need to return the entire list for the purpose of getting a single element out of it.
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
var lookup = arr.ToLookup(t => t);
var result = lookup.OrderByDescending(t => t.Count());
Console.WriteLine(result.ElementAt(1).Key);
I would do this.
int[] arr = new int[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
int rank =2;
var item = arr.GroupBy(x=>x) // Group them
.OrderByDescending(x=>x.Count()) // Sort based on number of occurrences
.Skip(rank-1) // Traverse to the position
.FirstOrDefault(); // Take the element
if(item!= null)
{
Console.WriteLine(item.Key);
// output - 3
}
I started to answer, saw the above answers and thought I'd compare them instead.
Here is the Fiddle here.
I put a stopwatch on each and took the number of ticks for each one. The results were:
Orignal: 50600
Berkser: 15970
Tommy: 3413
Hari: 1601
user3185569: 1571
It appears #user3185569 has a slightly faster algorithm than Hari and is about 30-40 times quicker than the OP's origanal version. Note is #user3185569 answer above it appears his is faster when scaled.
update: The numbers I posted above were run on my pc. Using .net fiddle to execute produces different results:
Orignal: 46842
Berkser: 44620
Tommy: 11922
Hari: 13095
user3185569: 16491
Putting the Berkser algortihm slightly faster. I'm not entirely clear why this is the case, as I'm targeting the same .net version.
I came up with the the following mash of Linq and a dictionary as what you're looking for is essentialy an ordered dictionary
void Run()
{
int[] arr = new int[] { 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
int[] unique = arr.Distinct().ToArray();
Dictionary<int, int> dictionary = unique.ToDictionary(k => k, v => 0);
for(int i = 0; i < arr.Length; i++)
{
if(dictionary.ContainsKey(arr[i]))
{
dictionary[arr[i]]++;
}
}
List<KeyValuePair<int, int>> solution = dictionary.ToList();
solution.Sort((x,y)=>-1* x.Value.CompareTo(y.Value));
System.Console.WriteLine(solution[2].Key);
}

C# array of references without unsafe

I found similar topics, but I could not solve the problem I has reading them.
I want to do in C# the same thing like in C is array of pointers, but I do not want to use in C# pointers because it requires to use "unsafe".
How to build an array of " ref to int" that when I change any element of that array then I will also change that what it refs to at the same time the variable that it points to ( Like in C - array of pointers).
Best regards,
Chris
If performance is not a concern, than one common workaround is to use lambda to capture the access to value type variable:
Sample:
class GetSetPair<T>
{
public Func<T> Get {get;set;}
public Action<T> Set {get;set;}
}
var referencesToInt = new List<GetSetPair<int>>();
int value = 42;
referencesToInt.Add(new GetSetPair<int>{Get=()=>value, Set = v => value = v});
referencesToInt[0].Set(33);
Console.WriteLine(value); // 33
value = 22;
Console.WriteLine(referencesToInt[0].Get()); //22
Arrays are reference types, and therefore you can pass around references to that array. For example, given the following program:
public class Program
{
public static Random rnd = new Random();
public static int[] array2;
public static void Main()
{
int[] array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
PrintArray(array);
array[4] = rnd.Next();
PrintArray(array);
ModArray(array, 2);
PrintArray(array);
array2 = array; //This makes array2 reference array1
ModArray(array2, 8); //Operate on the array2 reference
PrintArray(array); //Changes are reflected in array
PrintArray(array2); //And in array2
Console.ReadKey(true);
}
public static void PrintArray(int[] array)
{
foreach (var e in array)
Console.Write(e + ", ");
Console.WriteLine();
}
public static void ModArray(int[] array, int i)
{
array[i] = rnd.Next();
}
}
Will give the following output:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, <- Original
1, 2, 3, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in Main
1, 2, 102109069, 4, 744477516, 6, 7, 8, 9, 10, <- Modified in ModArray
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array, after modifying array2
1, 2, 102109069, 4, 744477516, 6, 7, 8, 1776657318, 10, <- array2
So in a sense, you can pass around a reference to the array, modify that reference, and have it reflected in all of its copies.
The caveat here is that anybody who "owns" a reference to the original array cannot reassign that array (or resize it). It can modify the elements of the array, but it can't make the original array point to a new instance (which is what happens when it is resized). Also, as Jon Skeet mentioned in his comment, the danger is that if you were doing this in a different method other than Main, if the array goes out of scope, what would happen to array2?
See Also:
Is int[] a reference type or a value type?
Are arrays or lists passed by default by reference in c#?

Best way to construct the algorithm of tree in C#

I have a small problem in finding the most efficient solution. I have a number, for example 10, of student ids. And some of those ids are relative(siblings) to each other. For those who are siblings leave only one of them for identifing, and doesn't matter which, first one is fine.
For example, the student ids
original
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
where 1, 2, 3 are one family siblings, and 8, 9 are another. At the end I should have:
expected
1, 4, 5, 6, 7, 8, 10
I am doing it through loop.
UPDATE:
I just stopped to implement it, because it gets bigger and bigger. This is a big picture of what I have in my mind. I just gathered all sibling ids for each given id row by row, and then I was going to iterate per each. But like I said it's wasting time.
Code (in conceptual)
static string Trimsiblings(string ppl) {
string[] pids=ppl.Split(',');
Stack<string> personid=new Stack<string>();
foreach(string pid in pids) {
// access database and check for all sibling
// is for each individual pid
// such as in example above
// row 1: field 1=1, field2=2, field3=3
// row 2: field 1=8, field2=9
query = Select..where ..id = pid; // this line is pesudo code
for(int i=0; i<query.Length; i++) {
foreach(string pid in pids) {
if(query.field1==pid) {
personid.Push(pid);
}
}
}
}
}
For an efficient code, it essential to notice that the one member (e.g., the first) of each family of siblings is irrelevant because it will stay in the output. That is, we simply have to
Create a list of items that must not appear in the output
Actually remove them
Of course, this only works under the assumption that every sibling actually appears in the original list of ids.
In code:
int[] ids = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int families = new int[2][] {
new int [] {1, 2, 3},
new int [] {8, 9}
};
var itemsToOmit = siblings.
Select(family => family.Skip(1)).
Aggregate((family1, family2) => family1.Concat(family2));
var cleanedIds = ids.Except(itemsToOmit);
Edit: Since you mention that you are not too familiar with the syntax, I will give some further explanations
The expressions I've used are extension methods that are part of the System.LINQ namespace
The Select method transforms one sequence into another sequence. Since families is sequence of sequences, family will be a sequence of siblings in the same family (i.e., 1, 2, 3 and 8, 9 in this particular case)
The Skip method skips a number of elements of a sequence. Here, I've decided to always skip the first element (for reasons, see above)
The Aggregate method combines element of a sequence into a single element. Here, all families of siblings are just concatenated to each other (except for the first sibling of each family which has been omitted via Skip)
The Except method returns all elements of a sequence that are not in the sequence that is given as an argument.
I hope this clarifies things a bit.
Here's how
public static String Trimsiblings(String ppl) {
var table=GetSiblingTable();
var pids=ppl.Split(',');
return
String.Join(", ", (
from id in pids.Select(x => int.Parse(x))
where (
from row in table.AsEnumerable()
select
from DataColumn column in table.Columns
let data=row[column.ColumnName]
where DBNull.Value!=data
select int.Parse((String)data)
).All(x => false==x.Contains(id)||x.First()==id)
select id.ToString()).ToArray()
);
}
// emulation of getting table from database
public static DataTable GetSiblingTable() {
var dt=new DataTable();
// define field1, ..., fieldn
for(int n=3, i=1+n; i-->1; dt.Columns.Add("field"+i))
;
dt.Rows.Add(new object[] { 1, 2, 3 });
dt.Rows.Add(new object[] { 8, 9 });
return dt;
}
public static void TestMethod() {
Console.WriteLine("{0}", Trimsiblings("1, 2, 3, 4, 5, 6, 7, 8, 9, 10"));
}
comment to request why(if you need).

How do I shift items in an array in C#?

Let's say that I have an array of strings like this:
1, 2, 3, 4, 5, 6, 7, 8
and I want to shift the elements of the array such that
The first element always remains fixed
Only the remaining elements get shifted like so ...
The last element in the array becomes the 2nd element and is shifted through the array with each pass.
Pass #1: 1, 2, 3, 4, 5, 6, 7, 8
Pass #2: 1, 8, 2, 3, 4, 5, 6, 7
Pass #3: 1, 7, 8, 2, 3, 4, 5, 6
Pass #4: 1, 6, 7, 8, 2, 3, 4, 5
Any assistance would be greatly appreciated.
Because this looks like homework, I'm posting an unnecessary complex, but very hip LINQ solution:
int[] array = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
int[] result = array.Take(1)
.Concat(array.Reverse().Take(1))
.Concat(array.Skip(1).Reverse().Skip(1).Reverse())
.ToArray();
Probably the fastest way to do this in C# is to use Array.Copy. I don't know much about pointers in C# so there's probably a way of doing it that's even faster and avoids the array bounds checks and such but the following should work. It makes several assumptions and doesn't check for errors but you can fix it up.
void Shift<T>(T[] array) {
T last = array[array.Length-1];
Array.Copy(array, 1, array, 2, array.Length-2);
array[1]=last;
}
EDIT
Optionally, there is Buffer.BlockCopy which according to this post performs fewer validations but internally copies the block the same way.
Because this looks like homework, I'm not going to solve it for you, but I have a couple of suggestions:
Remember to not overwrite data if it isn't somewhere else already. You're going to need a temporary variable.
Try traversing the array from the end to the beginning. The problem is probably simpler that way, though it can be done from front-to-back.
Make sure your algorithm works for an arbitrary-length array, not just one that's of size 8, as your example gave.
Although sounds like homework like others suggest, if changing to a List<>, you can get what you want with the following...
List<int> Nums2 = new List<int>();
for( int i = 1; i < 9; i++ )
Nums2.Add(i);
for (int i = 1; i < 10; i++)
{
Nums2.Insert( 1, Nums2[ Nums2.Count -1] );
Nums2.RemoveAt(Nums2.Count -1);
}
Define this:
public static class Extensions
{
public static IEnumerable<T> Rotate<T>(this IEnumerable<T> enuml)
{
var count = enuml.Count();
return enuml
.Skip(count - 1)
.Concat(enuml.Take(count - 1));
}
public static IEnumerable<T> SkipAndRotate<T>(this IEnumerable<T> enuml)
{
return enum
.Take(1)
.Concat(
enuml.Skip(1).Rotate()
);
}
}
Then call it like so:
var array = new [] { 1, 2, 3, 4, 5, 6, 7, 8 };
var pass1 = array.SkipAndRotate().ToArray();
var pass2 = pass1.SkipAndRotate().ToArray();
var pass3 = pass2.SkipAndRotate().ToArray();
var pass4 = pass3.SkipAndRotate().ToArray();
There's some repeated code there that you might want to refactor. And of course, I haven't compiled this so caveat emptor!
This is similar to Josh Einstein's but it will do it manually and will allow you to specify how many elements to preserve at the beginning.
static void ShiftArray<T>(T[] array, int elementsToPreserve)
{
T temp = array[array.Length - 1];
for (int i = array.Length - 1; i > elementsToPreserve; i--)
{
array[i] = array[i - 1];
}
array[elementsToPreserve] = temp;
}
Consumed:
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8 };
ShiftArray(array, 2);
First pass: 1 2 8 3 4 5 6 7

Categories