Order of operations when working with array index - c#

Consider this loop:
int[] myArray = new int[10];
int myIndex = 0;
for (int i = 0; i < 10; i++)
{
myArray[myIndex++] = myIndex;
Console.WriteLine(myArray[i]);
}
This yields:
1
2
3
...
Because myIndex is post-incremented, and the right side is evaluated first, shouldn't the array index 0 contain 0?
Can someone explain this order-of-operations misunderstanding for me?

The right side isn't necessarily evaluated first. Similar to:
foo.Bar.Baz = a + b;
In the above code, foo.Bar is evaluated first, then a + b, then the set_Baz method is called to set the Baz property to whatever is evaluated on the right.
So in your code, if you break it into pieces, it looks like this:
var index = i;
// post-incremented in the original code means this comes after the line above,
// but not after the line below it.
i += 1;
myArray[index] = i;

first run:
myArray[myIndex++] = myIndex;
* *
| |
zero one
myIndex++ gets executed after myArray[myIndex++], but any subsequent calls with have the already incremented variable.

The myIndex++ is executing before the value is being set because the array index takes precident so it knows what array index to set the value to.

The...
myArray[myIndex++] = myIndex;
...is equivalend to...
int tmp = myIndex;
++myIndex;
myArray[tmp] = myIndex;

The myIndex++ is evaluated first, followed by the left side and finally the assign operator, according to precedence

Related

Why is the output giving me a value of +1?

The code
public static void InitializeArray(ref double[] doubleA)
{
//array init using foreach
int i = 0;
foreach (double dub in doubleA)
{
doubleA[i++] = i + .5;
}
}
is giving me an output of
doubleA[0] = 1.5 instead of .5
doubleA[1] = 2.5 instead of 1.5
and so on
I'm not understanding why it's doing that. As I understand it, doubleA[0] should be getting 0.5 because I'm only adding 0.5 so where is the extra 1 coming from? I'm thinking it's from int i but for i=0, shouldn't it evaluate to doubleA[0] = 0 + .5?
So far I have tried writing doubleA[i++] = i + .5; instead which gives each element in the array just the value of 0.5.
So let's start with i = 0
doubleA[i++] = i + .5;
Here you are accessing position 0 of the array, but also adding 1 to the value of i. When i == 0, the expression i++ will be the value 0, but the value of the variable i is incremented such that the new value of i is 1.
On the right hand side, this new value of i is used (1) and added to 0.5. Giving a value of 1.5 which is assigned back to index 0 of the array (as indicated on the left hand side of the assignment).
I could go on, but I think you probably get it by now...
Further reading on operator ++
This is because i is being incremented in your key: doubleA[i++]. i++ will increment the key by one, AFTER returning it. When it's used later (as the value), its value has already been incremented. So now you're setting it to 1 + 0.5.
Let's break this down, and show you the functional equivalent, and you'll see exactly what this is happening:
public static void InitializeArray(ref double[] doubleA)
{
//array init using foreach
int i = 0;
foreach (double dub in doubleA)
{
int key = i;
i = i + 1;
doubleA[key] = i + .5;
}
}

Setting int using for loop in one line?

I'm interested in doing something like this (C#):
int sum = 0;
for (int i = 0; i < 5; i++)
sum += i;
But I would like to do it on one line. Something like:
int sum = (embedded loop)
Is there any way to do this on one line? I'm looking to apply this to a more complex string manipulation algorithm so I can't simply replace the loop with an arithmatic formula.
So you want to loop and do something in one line?
First off, writing it in one line isn't going to make it run faster. You are still going to loop, you are still going to be O(n). For the particular problem you have in your question you can do something like:
var sum = Enumerable.Range(0,5).Sum();
This will basically make a collection of the numbers 0,1,2...4 and sum them.
More generally, since you want to do something, you might use the Aggregate function. For example:
var str = Enumerable.Range(0,5).Aggregate("",(p,c) => p + c); // Note: not efficient at all
Will take the values 0,1,...4 and do string concatenation with them (using a string builder would be better) to give you the string 01234.
Edit:
I'm trying to loop through a list of words and make each one title case, then return the string[].join(" ") of it
In that case, something like:
var result = string.Join(" ", myListOfWords.Select(w => char.ToUpper(w[0]) + w.Substring(1)));
Should work fine.
If you don't mind that 'sum' only is in scope of the for loop you could do this:
for (int i = 0, sum = 0; i < 5; sum += i, ++i) { // do something }
for(int i=0,sum = 0; i<5; sum+=i,++i){}

IndexOutOfRange Exception Thrown on Setting Int value to Array

On my app a teacher can have several classes, and when I exclude a teacher's profile I have to, first, delete his classes. I'm trying to put each class_id of this teacher on an int array, to later delete all classes which the id is contained inside this array.
This is my code so far:
int x = 0;
int[] count = new int[x];
while (reader_SelectedClasses.Read())
{
if(x != 0)
{
x++;
count = new int[x];
}
count[x] = _class.Class_id = reader_SelectedClasses.GetInt16("class_id");
}
And this is what
reader_SelectedClasses.Read()
does:
select class_id from tbl_class where user_id = " + id + ";
And this is the return, when I try this on MySQL:
But it gives me back an IndexOutOfRangeException when I run the code on my DAO class. What am I missing? Already went here but didn't quite understand. Can someone please explain on few words and post and fixed code for this?
You need to learn how to use a debugger and step through your program.
count = new int[x]; discards what was in count and creates a new array that contains zeroes. This array's indexes go from 0 to x - 1.
count[x] = ... sets the array element at index x which according to the previous line is one past the end of the array.
You need to set count = new int[x] only once, at the beginning of your program, and set count[x] = ... only if x >= 0 and x < count.Length.
You are getting IndexOutOfRange Exception because you are trying to access element from array which is out of range.
At first line you are setting x = 1. Hoping that controller enters while loop and as x is 1 it doesn't enter if loop and it executes next statement. But count[1] (x = 1) is not allowed as you have created array with only one element and that you can access with count[0]. (Array indexing starts from 0)
You are trying to achieve a List behavior with an array.
Obviously, the IndexOutOfRangeException is because you initialize an empty array and then try to add values to it in a non-existing cell.
Try to convert to List<int>:
List<int> count = new List<int>();
while (reader_SelectedClasses.Read())
{
int classId = _class.Class_id = reader_SelectedClasses.GetInt16("class_id");
count.Add(classId);
}
If you really need an array out of it you can do:
int[] countArray = count.ToArray()

Increase an int by one

On another page I've said that nr = 0
var number = this.NavigationContext.QueryString["nr"];
int Nr = Convert.ToInt16(number);
And this works, Nr = 0
Now I want to upgrade Nr by one:
int next = Nr++;
Unfortunately this doesn't work... next = 0 too, but it supposed to be 1.
Could someone explain to me what I'm doing wrong?
Nr++ increments and returns the original value of Nr.
++Nr increments and returns the new value of Nr. So what you want is:
int next = ++Nr;
In C# (or C++), the statement
int next = Nr++;
translates to, "assign the value of Nr to variable next, and then increment Nr by 1.
If you want Nr to increment first, your statement should look like this:
int next = ++Nr;
Here is the definition of the ++ operator: http://msdn.microsoft.com/en-us/library/36x43w8w.aspx
the problem is ...Nr is incremented after Nr set to next use next=Nr+1;
There are two increment operators - pre-increment ++c and post-increment c++.
var x = ++c; is equivalent to
c = c + 1;
var x = c;
while var x = c++; is equivalent to
var x = c;
c = c + 1;
and therefore x either receives the value before or after c got incremented.

Add from one list to another

I have been trying to 'transport' the first two elements from list A to list B without copying them.
At the start, list A has four int values. In the end I want List A and B to both have 2 int values.
I'm trying something like this:
int a = 1;
int b = 2;
int c = 3;
int d = 4;
TestA.Add(a);
TestA.Add(b);
TestA.Add(c);
TestA.Add(d);
for (int i=0; i<2; i++)
{
TestB.AddRange(TestA[i]);
}
I get a IEnummerable conversion error. I'm sure I'm doing it in a very naive way, and I'd appreciate some help here. Thanks.
What's wrong with simple Take/Skip combination?
TestB = TestA.Take(2).ToList();
TestA = TestA.Skip(2).ToList();
Enumerable.Take - takes N elements from beginning of the collection.
Enumerable.Skip - skips N elements from beginning of the collection and takes all others.

Categories

Resources