For loop in a static method does not need {} - c#

using System;
class FirstArray
{
static void Main()
{
int numOfGrades;
double[] listOfGrades;
Console.Write("How many students in the class? ");
numOfGrades = int.Parse(Console.ReadLine());
listOfGrades = new double[numOfGrades];
ReadGrades(listOfGrades);
double sumGrades = GetGradesSum(listOfGrades);
Console.WriteLine("\n\nClass statistics\n--------------------");
Console.WriteLine("Grades sum = {0:F2}", sumGrades);
}
static void ReadGrades(double[] grades)
{
for(int i = 0; i < grades.Length; i++)
{
Console.Write("Enter the grade of student {0}:", i + 1);
grades[i] = double.Parse(Console.ReadLine());
}
}
static double GetGradesSum(double[] grades)
{
double sum = 0;
for(int i = 0; i < grades.Length; i++)
sum += grades[i];
return sum;
}
}
Hi everyone,
Why does the for loop in the GetGradeSum method not require {}? When I do put the braces in, there is a compile time errors of "unreachable code detected" and "not all code paths return a value. Does it have something to do with the return function?
Thanks in advance!

Why does the for loop in the GetGradeSum method not require {}?
Because its body is a single statement. It's much simpler to understand if you indent your code properly. Your current code is more clearly written as:
static double GetGradesSum(double[] grades)
{
double sum = 0;
for(int i = 0; i < grades.Length; i++)
sum += grades[i];
return sum;
}
Note how the return statement is not part of the loop. If it were, it would return the first grade, rather than the sum.
So the equivalent code with braces is:
static double GetGradesSum(double[] grades)
{
double sum = 0;
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i];
}
return sum;
}
It sounds like you tried to put braces around both statements, so:
// Broken
static double GetGradesSum(double[] grades)
{
double sum = 0;
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i];
return sum;
}
}
At this point, the compiler complains because it's entirely possible to reach the end of the method without returning anything - if grades has a length of 0, we'll never go into the body of the loop, so never return.
Note that LINQ makes all of this irrelevant anyway, mind you - you can just write:
using System.Linq;
...
double sumGrades = listOfGrades.Sum();

If you don't write braces {}, then only the line after the for (...) is executed inside the loop.
Basically:
for (...)
A();
B();
is equivalent to:
for (...)
{
A();
}
B();
This also answers your second question, as the return statement would be inside the loop (assuming you put } after it).

If the loop body consist of only one statement, you can omit the braces. but if you do:
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i];
return sum;
}
In this case there is no guarantee that for loop will run (e.g i < grages.Length might not be true) so you get the error.Instead you should move the return statement outside of the loop.

Braces are not required when there is only one statement to execute.
This code:
for(int i = 0; i < grades.Length; i++)
sum += grades[i];
is equivalent to this code:
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i]
}
If there is more than one statement to execute, braces are required.
On a side note, it is always more clear to use the braces than not to.

Having a for loop without brackets means you're going to apply the 'loop' on the next statement only
So
for(int i = 0; i < grades.Length; i++)
sum += grades[i];
is equivalent to
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i];
}

The indentation in the method is a bit confusing, as it can lead you into thinking that the return statement is part of the loop.
The braces around the code in the loop is only mandatory if you want to put more than one statement in the loop. If you don't have braces, then only the statement following the for clause is part of the loop.
If you add the braces for the loop, they should be only around the statement after the loop:
static double GetGradesSum(double[] grades)
{
double sum = 0;
for(int i = 0; i < grades.Length; i++)
{
sum += grades[i];
}
return sum;
}
If you instead included the return statement inside the loop, then it would only be executed if the code inside the loop was executed, so you get a compiler error telling you that it's guaranteed that the return statement is executed.

Quite Simply, all the answers here are accurate. In most languages that parallel C,
you do NOT need curly braces if you're targeting a single statement .
Meaning the VERY NEXT LINE after you initiate the for loop is the only statement included within the for loop.
If you put Braces around your return statement, you'll receive the compile error as you're including the return statement as part of the for loop.
Again, You can include braces around the singular targeted statement if you'd like as a programming aesthetic, but it's not required unless you have multiple statements you want to include within your loop.
This principle is the same for if/else statements.

Related

Printing square with non repetitive character

I want to print a rectangle like this :
&#*#
#*#&
*#&#
#&#*
But problem is that i can't find the algorithm to print this.
I only know how to print a simple rectangle/square
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
int i;
int j;
for(i = 0; i < taille; i++){
for(j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Thank you !
First things first unless you need your iterators outside of your loop, just declare them in the for declaration
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
for(int j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Second you'll need a list of the characters you want to use, given your example
char[] chars = { '&', `#`, `*`, '#' };
and we'll need a way to know which character we want to use at any given time, say an iterator we can call characterIndex for simplicity. We will increment it each iteration. If incrementing it puts it out of the range of our character array, if characterIndex == 4, we set it back to zero.
int characterIndex;
To get the scrolling effect you have, before each line we must select a characterIndex that is offset by the row
characterIndex = i % chars.Length;
Tying it all together
public static void Main(string[] args)
{
char[] chars = { '&', `#`, `*`, '#' };
int characterIndex;
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
characterIndex = i % chars.Length;
for(int j = 0; j < taille; j++){
Console.Write(chars[characterIndex]);
characterIndex++;
if(characterIndex == chars.Length)
characterIndex = 0;
}
Console.WriteLine("");
}
}
Getting the permutations by nesting for loops will only work if you know exactly how many elements there will be. Basically you need to write a for-loop for every element after the 1st.
The proper way to deal with this is Recursion. While there are cases where Recursion and nested for-loops are interchangeable. And in cases where they are, for loops have a potential speed advantage. While normally the speed rant applies to such differences, with the sheer amount of data both Recursion and Loops might have to deal with, it often maters - so best to prefer loops where possible.
Permutations is AFAIK not a case where loops and recursion are interchangeable. Recurions seems to be mandatory. Some problem as simply inherently recursive. As the recursion version is fairly well known, I will not post any example code.
You should defiitely use Recursion. With your example code I basically asume you are:
In a learning environment
You just learned recursion
A input variant recurions can effortless solve (like a 6 or 20 size input), is the next assignment

Using a nested for loop and getting unexpected repetitions in c#

I've the following code in c# visual basic 2010:
for (int i = 7; i > 0; i--)
{
Char star = '*';
string numbers = "765432" ;
//Console.WriteLine(star);
for (int a = 0; a < i; a++)
{
Console.Write(star);
}
for (int b = 0; b < i; b++)
{
numbers.TrimEnd(numbers[numbers.Length - 1]);
Console.Write(numbers);
}
Console.WriteLine();
}
Console.ReadLine();
I was expecting the outcome:
*765432
repeated on the screen 7 times, instead I get:
*****765432765432765432765432765432
****765432765432765432765432
***765432765432765432
**765432765432
*765432
(I can't display the full outcome because it doesn't come back properly on screen but it's basically the variables star and numbers displayed 7 times on line 1, 6 times on line 2 etc. until once in line 7)
My understanding is that the a and b variables declared in the for loops should dictate how many times the for loop is entered into, why are the star and numbers variables also being written 7 times then 6 times to match the number of times the loop is entered into? Especially when they are initialised as * and 765432?
This is the problem (I suspect, anyway - it's certainly a problem):
numbers.TrimEnd(numbers[numbers.Length - 1]);
Strings are immutable in .NET. TrimEnd doesn't change the existing string - it returns a reference to a new one. As highlighted in the documentation:
This method does not modify the value of the current instance. Instead, it returns a new string in which all trailing characters found in trimChars are removed from the current string.
You'd also be better off using Substring for simplicity to "remove" the last character:
numbers = numbers.Substring(0, numbers.Length - 1);
Or indeed Remove:
numbers = numbers.Remove(numbers.Length - 1);
... although this will actually fail on the 7th iteration as the string will be empty at this point. It's not really what you were trying to achieve, but I think you need to take a step back from it and think carefully about each step in the process.
TrimEnd returns a new string, it doesn't modify the original string. You have to assign it back to number. Strings are immutable.
number = numbers.TrimEnd(numbers[numbers.Length - 1]);
Check for string length before indexing its element. In your for loop you can add the condition like:
for (int b = 0; b < i && numbers.Length > 0; b++)
No. The 'a' for loop runs, outputting that many stars, and the 'b' for loop runs next, outputting that many strings. If you just want '*765432' to repeat 7 times, you need to change
for (int a = 0; a < i; a++)
{
Console.Write(star);
}
for (int b = 0; b < i; b++)
{
numbers.TrimEnd(numbers[numbers.Length - 1]);
Console.Write(numbers);
}
To
for (int a = 0; a < 7; a++)
{
Console.Write(star);
Console.Write(numbers);
}
And take out the parent loop; that's what is giving you the incrementingly shorter lines.
This produce the output you are expecting:
for (int i = 0; i < 7; i++)
{
Char star = '*';
string numbers = "765432" ;
Console.WriteLine(star);
Console.Write(numbers);
Console.WriteLine();
}
I was expecting the outcome: *765432 repeated on the screen 7 times
You never need to use TrimEnd() and multiple for loop in this situation.
public static void Main()
{
for (int i = 7; i > 0;i--)
{
char star = '*';
string numbers = "765432";
Console.WriteLine(star + numbers);
}
Console.ReadLine();
}
output:
*765432
*765432
*765432
*765432
*765432
*765432
*765432

Parallel version of code to accumulate values from list<list<double>>

I am again struggling to understand some things for parallel computation.
In the code I am working on, I have a class that extends list<list<double>>. Inside this class, I'm writing a method to return the average of the values in the list<list<double>>. This method is private.
public class myClass : list<list<double>>
{
//properties and stuff
private double average()
{
//method body
}
}
I two versions for this method, both of them working. The first version is serial:
private double average()
{
double avg = 0;
for (int i = 0; i < this.Count; i++)
{
for (int j = 0; j < this[0].Count; j++)
{
avg += this[i][j];
}
}
avg = avg / (this.Count*this[0].Count);
return avg;
}
The second version is parallel:
private double average()
{
double avg = 0;
double[] cumsum = new double[this.Count];
Parallel.For(0, this.Count, i =>
{
cumsum[i] = 0;
for (int j = 0; j < this[0].Count; j++)
{
cumsum[i] += this[i][j];
}
});
avg = cumsum.Sum() / ((this.Count * this[0].Count));
return avg;
}
As a learning exercise, I tried to mess things up by using more complex parallel threading. My idea was to make do without the intermediate array in which I sum the lines. Specifically, this was my attempt (doesn't work):
private double average()
{
double avg = 0;
Parallel.For<double>(0, this.Count, () => 0, (i, loop, sub) =>
{
for (int j = 0; j < this[0].Count; j++)
{
sub += this[i][j];
}
return sub;
},
(x) =>
{
double tot = avg;
Interlocked.CompareExchange(ref avg, tot+sub, tot);
});
return avg / ((this.Count * this[0].Count));
}
This snippet has (at least) two mistakes.
The first error it give me is on the sub += this[i][j];:
The best overloaded method match for
'System.Collections.Generic.List>.this[int]'
has some invalid arguments
I do not understand this error here, because both i and j are of type int.
Then I have a further error on Interlocked.CompareExchange(ref avg, tot+sub, tot); (expected, because I don't really understand how this method works):
The name 'sub' does not exist in the current context
Can someone point me to a correct form of the last snippet? And/or some material to clarify this things? I read from http://msdn.microsoft.com/en-us/library/dd460703.aspx but it didn't help make things clear for me.
Personally, I would use:
double sum = yourListOfList.AsParallel().SelectMany(list => list).Average();
In order to fix your method, you need to property use your loop state in the local final lambda. (You're not using x at all currently.)
double sum = 0;
var syncObj = new object();
Parallel.For<double>(0, this.Count, () => 0, (i, loop, sub) =>
{
var innerList = this[i];
for (int j = 0; j < innerList.Count; j++)
{
sub += innerList[j];
}
return sub;
},
(x) =>
{
lock(syncObj)
sum += x;
});
return sum / ((this.Count * this[0].Count));
Note that your version (and my "correction") has many drawbacks. It's assuming that each sub list is the same length as this[0], which is not guaranteed or suggested by the types.
The first error is caused because the i argument is of the long type. This is because two similar overloads exist, one with the first parameter of the int type, another with the long type. To select the "int" overload, you have to instantiate a lambda expression explicitly:
new Func<int, ParallelLoopState, double, double>((i, loop, sub) => { ... })
The second error is caused because the sub variable doesn't exist in the given scope.

Getting a value from ArrayList c#

Hi I'm not to sure how to do this but here's the code that I've got
// splits 1 to 3
int check;
for (int i = 0; i < 100; i++)
{
check = alM1((rand.next(20))+1);//error
if (!(alM3.Contains(check)))
alM3.Add(check);
if (alM3.Length == 10)
break;
}
// removes 3 from 1
for (int i = 0; i < 10; i++)
{
if (alM1.Contains(alM3(i))) //error
alM1.Remove(alM3(i)); //error
}
The error message says ArrayList is a variable but it is used like a method.
How can I write it so it produces what I want.
Thank in advance T
To access entries of the list you need to use square bracket notation.
For example:
check = alM1[(rand.next(20))+1];
and:
if (alM1.Contains(alM3[i]))

For Loop Constructs

Will this loop execute exactly N Times?
for (int i = 0; i < N; i++)
{
//statement
someMethodCall();
}
Will this loop execute at most N Times?
for (int i = 1; i < N; i++)
{
someMethodCall();
}
Will this loop execute at least N Times?
for (int i = 0; i <= N; i++)
{
//statement
someMethodCall();
}
What should I do if I need to execute the statement between m and n times, e.g. calling a method?
The answers to your three questions are yes, no, and yes, I suppose, although that third answer is a bit deceptive; it'll execute N times, no more and no less (unless there's an exception which terminates the loop abnormally.) You can write a for loop to loop a definite number of times, or until some condition becomes true, and then you have the ability to use break or return to terminate the loop early.
But there's no notion of executing "at least N times;" it's simply not part of this -- or any other -- computer language.
A loop formula can be calculated as
Math.Round (condition - initialization )/increment
In first case its
(N-0)/1 which evaluates to N times
In second case its
(N-1)/1 which evaluates to N-1 times
In third case its
(N-0+1)/1 which evaluates to N+1 times
How would I do if I need to execute statement between m and n times? For instance I want to call one method between m and n times?
then check it in condition
for (int i = m; i < n; i++)
{
someMethodCall();
}
In for loop you can have these code,
N Time
for (int i = 0; i < N; i++) {
}
N+1 Time
for (int i = 0; i <= N; i++) {
}
And if there isn't any time and you want handle it your self you can use this,
for (;;) {
//do something and don't forget use break or return !
}
OR
while(x>10){
}
and loop in loop is good as Ernest Friedman-Hill said
for (int i = 0; i <=10; i++) {
for (int i = 0; i < length; i++) {
}
}
use 2xTab for visual studio help.

Categories

Resources