Reading values out from an ArrayList in an independent function - c#

I am having troubling reading my values out of an ArrayList. The compiler goes into the ReadOutFromArray function, but skips the Console.WriteLine(st)? Can anyone tell me where I went wrong. Been on it for a couple of hours chasing my tail. Thanks.
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace BoolEx
{
class Program
{
static void Decision(ArrayList decis)
{
bool ans = true;
decis = new ArrayList();
//ArrayList aList = new ArrayList();
while (ans)
{
Console.WriteLine("1=True 0=False");
int x = Int32.Parse(Console.ReadLine());
if (x == 1)
{
ans = true;
}
else
{
ans = false;
}
if (ans == true)
{
ReadInArray(decis);
}
else
{
ReadOutArray(decis);
}
}
}
static void ReadInArray(ArrayList f)
{
f= new ArrayList();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
static void ReadOutArray(ArrayList d)
{
d = new ArrayList();
ReadInArray(d);
foreach (string st in d)
{
Console.WriteLine(st);
}
}
static void Main(string[] args)
{
ArrayList g = new ArrayList();
Decision(g);
}
}
}

The problem is your ReadInArray method:
static void ReadInArray(ArrayList f)
{
f= new ArrayList();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
In the first line of the method, you're basically saying, "I don't care what ArrayList reference was passed in - I'm going to overwrite the local variable f with a reference to a new ArrayList."
I suspect you meant something like this:
static void ReadInArray(ArrayList f)
{
f.Clear();
Console.WriteLine("Enter in a name");
f.Add(Console.ReadLine());
}
If you don't understand why that changes things, see my parameter passing article.
Other things you should consider:
If you're only going to read a single line, why not use something like this:
static string ReadNameFromUser()
{
Console.WriteLine("Enter in a name");
return Console.ReadLine();
}
The same sort of thing occurs elsewhere. Don't try to use collections for all your input and output. Returning a value is much clearer than populating a list which is passed into the method.
Given that you can obviously refer to generic collections (given your using directives) you should really consider using List<string> instead of ArrayList
Code like this:
if (x == 1)
{
ans = true;
}
else
{
ans = false;
}
... would be better written as
ans = (x == 1);
(The brackets are optional, but help readability.)
Code like this:
if (ans == true)
is better written as:
if (ans)

Although I do agree with everything Skeet has mentioned, it appears the poster is trying to understand some things and I think
Jon might have missed that.
First if all you want to do is fill a list and print it try this:
static void (main)
{
ArrayList l = new ArrayList();
FillMyList(l);
DisplayMyList(l);
}
public static void FillMyList(ArrayList temp)
{
for(int i = 0; i < 10; i++)
temp.Add(i);
}
public static void DisplayMyList(ArrayList temp)
{
foreach(int i in temp)
Console.WriteLine(i);
}
Second thing is take what Jon Skeet has mentioned and definately understand some things. Booleans are just true / false (unless you introduce the nullable types) but for now keep it simple.
ArrayList is really old school, it kind of suffers like the HashTable in that you can easily run into trouble adding different data types into the object (read up on boxing of data types and unboxing).
Finally, you should really replace anything with this System.Collection.ArrayList to System.Collections.Generic.List.
The list class is a generic class and is made available so that you don't have to deal with the issues that you could encounter when dealing with array lists or hash tables.
Edit
I noticed you were asking users to add items to the list. You can do this using a do while loop instead of the for loop I posted, something to this effect (note i have not tested any of this):
public static void FillMyList(ArrayList temp)
{
char c='y';
do {
Console.WriteLine("Enter a value");
int x = Int32.Parse(Console.ReadLine());
temp.Add(x);
Console.WriteLine("Continue adding numbers to list, if so type y");
char c = Console.ReadLine();
}while(c=='y' || c=='Y');
}
Again I am just giving you examples here, you will have to handle user input in case someone doesn't enter the correct information, exceptions, etc.

Related

Update PointF Value Using Extension Method in C# [duplicate]

I want to be able to write extension methods so that I can say:
lines.ForceSpaceGroupsToBeTabs();
instead of:
lines = lines.ForceSpaceGroupsToBeTabs();
However, the following code currently outputs:
....one
........two
instead of:
Tone
TTtwo
What do I have to change in the following code to make it output:
Tone
TTtwo
(note that for visibility, . = space, T = \t):
using System;
using System.Collections.Generic;
namespace TestExtended82343
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("....one");
lines.Add("........two");
lines.ForceSpaceGroupsToBeTabs();
lines.ForEach(l => Console.WriteLine(l));
Console.ReadLine();
}
}
public static class Helpers
{
public static void ForceSpaceGroupsToBeTabs(this List<string> originalLines)
{
string spaceGroup = new String('.', 4);
List<string> lines = new List<string>();
foreach (var originalLine in originalLines)
{
lines.Add(originalLine.Replace(spaceGroup, "T"));
}
originalLines = lines;
}
}
}
You have to modify the contents of the List<string> passed to the extension method, not the variable that holds the reference to the list:
public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
string spaceGroup = new String('.', 4);
for (int i = 0; i < lines.Count; i++)
{
lines[i] = lines[i].Replace(spaceGroup, "T");
}
}
You'd have to change the contents of the original list - just reassigning the parameter to have a different value isn't going to do it. Something like this:
public static void ForceSpaceGroupsToBeTabs(this List<string> lines)
{
string spaceGroup = new String('.', 4);
for (int i = 0; i < lines.Count; i++)
{
lines[i] = lines[i].Replace(spaceGroup, "T");
}
}
It's worth noting that this has nothing to do with extension methods. Imagine you'd just called:
Helpers.ForceSpaceGroupsToBeTabs(lines);
... because that's what the code is effectively translated into. There's nothing special about the fact that it's an extension method; if you change the code so that the "normal" static method will work, then it'll work as an extension method too. As noted in the comments, one thing you can't do with an extension method is make the first parameter a ref parameter.
(EDIT: I realise this is the exact same code that dtb posted, although we arrived there independently. I'm keeping this answer anyway, as it's got more than code.)
If it's a reference type, you'd have to change it's contents. If it's a value type you're passing in, you're out of luck. The very existence of extension methods is put into place to support functional paradigms in C#, and those functional paradigms, by their very essence, tend towards immutability of types, hence the inability to change the value off of which the extension method is called.
In other words, while you could do it, it may not be in keeping with the "spirit" of functional programming.

Array searching in C# throwing error

I'm playing around with C# trying to get the basics down pat, but I'm stumped on this odd error. I'm trying to search through an array of names, and then return the location of any matches. At the moment I'm just printing the name, but I'm able to get the location.
For some reason though, when I type a name I want to search for and hit enter, the program crashes saying "ArraySearch.exe has stopped working". Any idea whats wrong??
Pardon the nooby questions, I'm still new to this language/paradigm :p
Thanks! :)
using System;
public class Test
{
public static void Main()
{
string[] stringArray = {"Nathan", "Bob", "Tom"};
bool [] matches = new bool[stringArray.Length];
string searchTerm = Console.ReadLine();
for(int i = 1;i<=stringArray.Length;i++){
if (searchTerm == stringArray[i - 1]){
matches[i] = true;
}
}
for(int i = 1;i<=stringArray.Length;i++){
if (matches[i]){
Console.WriteLine("We found another " + stringArray[i - 1]);
}
}
}
}
i will reach 3, which will give Out of range exception here:
matches[i] = true;
This would be easy to spot using debugging. (Try to learn using it. Very useful)
matches has 3 elements so the index ranges from 0 to 2.
using System;
public class Test
{
public static void Main()
{
string[] stringArray = { "Nathan", "Bob", "Tom" };
bool[] matches = new bool[stringArray.Length];
string searchTerm = "Bob";
for (int i = 1; i <= stringArray.Length; i++)
{
if (searchTerm == stringArray[i - 1])
{
matches[i - 1] = true;
}
}
for (int i = 1; i <= stringArray.Length; i++)
{
if (matches[i - 1])
{
Console.WriteLine("We found another " + stringArray[i - 1]);
}
}
}
}
See the fix above. It was failing because the bool array does not have an item at index 3. 3 is 1 index more than its last index, i.e. 2.
Its indexes are 0,1,2. which in turn store 3 elements just as u require.
When looping through arrays it is best to get used to using the actual indexes.
So i would suggest looping from 0 until array.length - 1. That way u have a direct reference to every element in the array.
I would strongly suggest using lambda's for this kind of processing.
Much fewer lines and simple to understand.
For example:
using System;
using System.Linq;
namespace ConsoleApplication5
{
public class Test
{
public static void Main()
{
string[] stringArray = { "Nathan", "Bob", "Tom" };
bool exists = stringArray.Any(x => x.Equals("Nathan"));
Console.WriteLine(exists);
}
}
}
The above method call, Any(), does the search for you. There are many options to explore. You can replace Any() with First(), Last() etc. If i were you I would definitely explore the System.Linq library for these kind of operations on collections.
(Remember that an array is also a collection)

Why do i get: "Error 2 Argument 1: cannot convert from 'int' to 'TRAINING1.Node<int>' " error?

this is a function that is supposed to take a list and reverse it. i do not know why i get this error.
public static void What(List<int> lst)
{
Stack<int> st1 = new Stack<int>();
while (!lst.IsEmpty())
{
**st1.Push(lst.Remove(lst.GetFirst().GetInfo());**
}
Node<int> pos = lst.GetFirst();
while (!st1.IsEmpty())
{
pos = lst.Insert(pos, st1.Pop());
}
}
st1 is a Stack<int>, which means that it is a strongly-typed stack of ints. You cannot add Node<int> to this list, if the is no implicit convertion from Node<int> to int. Anyway, try to use next code as an example of working with stack:
public static void Reverse(List<int> lst)
{
Stack<int> st1 = new Stack<int>();
while (lst.Count != 0)
{
var item = lst[0];
lst.RemoveAt(0);
st1.Push(item);
}
while (st1.Count != 0)
{
lst.Add(st1.Pop());
}
}
This is not an efficient solution and has a huge amount of drawbacks. I just want to illustrate correct reversing method using stack as close as possible to your case.
You can make method Reverse generic, but the are already implemented behavior in Linq.
Consider using Reverse Linq method. If you want just to reverse List<int>, use myList.Reverse().ToList(). It will return the same List<int> but in reversed order.

Assign values to a group of variables using recursion in C#?

How can I assign values to a group of variables using recursion in C#?
I can easily do it with a simple procedure, but I have no idea how to do it using recursion.
public void Assign()
{
Console.Write("Name: ");
Name = Console.ReadLine();
Console.Write("e-mail: ");
Email = Console.ReadLine();
Console.Write("Phone Number: ");
Phone = int.Parse(Console.ReadLine());
}
Thanks for the help.
If you're going to use recursion, you've got to have some sort of local context that's sufficient to accomplish whatever work you're going to do in your function, and you've got to know when / where to stop (and start popping your stack).
Your example looks like (if anything at all) a loop.
Your problem seems like homework because textbooks usually use this kind of horrible questions to teach recursion.
namespace Homework
{
class Recursion
{
static string[] nameList = new string[5];
static void Main(string[] args)
{
AssignNames(0);
Console.WriteLine("The names are:");
foreach(string name in nameList)
{
Console.WriteLine(name);
}
Console.ReadKey();
}
static void AssignNames(int index)
{
if (index == nameList.Length) return;
Console.Write("Enter name #{0}: ", index + 1);
nameList[index] = Console.ReadLine();
AssignNames(index + 1);
}
}
}

Please help me understand anonymous delegates?

I've downloaded the VCSharpSample pack from Microsoft and started reading on Anonymous Delegates. I can more or less understand what the code is doing, but I don't understand the reason behind it. Maybe if you gave me some examples where it would result in cleaner code and easier maintainability then I could wrap my head around it. :)
Can you help?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
delegate decimal CalculateBonus(decimal sales);
class Player
{
public string Name;
public decimal Score;
public decimal Bonus;
public CalculateBonus calculation_algorithm;
}
class Program
{
static decimal calculateStandardBonus(decimal sales)
{
return sales / 10;
}
static void Main(string[] args)
{
decimal multiplier = 2;
CalculateBonus standard_bonus = new CalculateBonus(calculateStandardBonus);
CalculateBonus enhanced_bonus = delegate(decimal sales) { return multiplier * sales / 10; };
Player[] players = new Player[5];
for (int i = 0; i < 5; i++)
{
players[i] = new Player();
}
players[0].Name = "Sergio";
players[0].Score = 240;
players[0].calculation_algorithm = standard_bonus;
players[1].Name = "Sergio";
players[1].Score = 240;
players[1].calculation_algorithm = enhanced_bonus;
players[2].Name = "Caro";
players[2].Score = 89;
players[2].calculation_algorithm = standard_bonus;
players[3].Name = "Andy";
players[3].Score = 38;
players[3].calculation_algorithm = enhanced_bonus;
players[4].Name = "Hugo";
players[4].Score = 600;
players[4].calculation_algorithm = enhanced_bonus;
foreach (Player player in players)
{
PerformCalculationBonus(player);
}
foreach (Player player in players)
{
DisplayPersonalDetails(player);
}
Console.ReadLine();
}
public static void PerformCalculationBonus(Player player)
{
player.Bonus = player.calculation_algorithm(player.Score);
}
public static void DisplayPersonalDetails(Player player)
{
Console.WriteLine(player.Name);
Console.WriteLine(player.Score);
Console.WriteLine(player.Bonus);
Console.WriteLine("---------------");
}
}
}
Anonymous delegates are designed to help you make code more readable by being able to define the behavior of a simple delegate inline in another method. This means that if you're dealing with something that requires a delegate (an event handler, for example), you can define the behavior right in the code rather than creating a dedicated function for it.
In addition, they're the precursor for lambda expressions. Things like LINQ to Objects (any of the methods that operate on IEnumerable<T>) use delegates to perform queries on objects. For example, if you have a collection of strings and you want a query that finds all of them that are five characters long, you can do that with a lambda:
List<string> strings = ...
var query = strings.Where(s => s.Length == 5);
Or you could do it with an anonymous delegate:
var query = strings.Where(delegate(string s) { return s.Length == 5; });
If you didn't have these, your code would look something like this:
var query = strings.Where(IsFiveCharacters);
...
private bool IsFiveCharacters(string input)
{
return input.Length == 5;
}
It's important to realize, though, that lambdas and anonymous delegates are just compiler features. When your code is compiled, it does actually create regular functions like in the last example, but they're hidden and named using characters that are illegal in the language being used. There's a lot of logic that goes around them when doing things like closures (where you access a variable that exists outside of the lambda/anonymous delegate declaration), as well.
The benefit is that you don't have to look somewhere else for the code to do a one-time lookup/change/calculation/whatever. It's a bit annoying to have to add a function (or a whole other class for a function!) you'll only ever use in one place, and then you have to look back later and see what that bit of code was and why it's needed and whether it still is.
With an anonymous delegate, the code is right there in the code that uses it.

Categories

Resources