Returning array of objects from static function - c#

I am making a basic Visual Studio project.
Easiest way to explain is to show the code.
using System;
using System.Collections.Generic;
namespace testing
{
class Program
{
static void Main(string[] args)
{
int amountOfCars = getAmountOfCars();
Car[] myCars = createCars(amountOfCars);
}
public static int getAmountOfCars (){
Console.WriteLine("Amount of Cars to enter");
int amountOfCars = Convert.ToInt32(Console.ReadLine());
return amountOfCars;
}
public static Car createCars(int amountOfCars)
{
Car[] myCars = new Car[amountOfCars];
for (int i = 0; i < amountOfCars; i++)
{
Console.WriteLine("Enter brand");
string brand = Convert.ToString(Console.ReadLine());
Console.WriteLine("Enter amount of wheels");
int amountOfWheels = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter amount of seats");
int amountOfSeats = Convert.ToInt32(Console.ReadLine());
myCars[i] = new Car(brand, amountOfWheels, amountOfSeats);
}
return myCars[amountOfCars];
}
}
}
This line
Car[] myCars = createCars(amountOfCars);
Throws the following error:
Cannot implicitly convert type testing.Car to testing.Car[]
So, I then tried this to convert over
Car[] myCars = (Car[]) createCars(amountOfCars);
But it still throws the error.
Essentially I am just trying to return the array of objects from createcar function, so that it can be used within the rest of the code.
What is the best practice to solve this?

You need to return an array from createCars():
public static Car[] createCars(int amountOfCars)
{
Car[] myCars = new Car[amountOfCars];
for (int i = 0; i < amountOfCars; i++)
{
Console.WriteLine("Enter brand");
string brand = Convert.ToString(Console.ReadLine());
Console.WriteLine("Enter amount of wheels");
int amountOfWheels = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Enter amount of seats");
int amountOfSeats = Convert.ToInt32(Console.ReadLine());
myCars[i] = new Car(brand, amountOfWheels, amountOfSeats);
}
return myCars;
}

The signature of the function is
public static Car createCars(int amountOfCars)
instead of
public static Car[] createCars(int amountOfCars)
Also return just the array
return myCars;
instead of
return myCars[amountOfCars]; // This returns only one object at the amountOfCars index in the myCars array.
Also, this will trigger the ArrayIndexOutOfBoundsException as the myCars is allocated for amountOfCars and array spans from myCars[0] to myCars[amountOfCars-1]

funcion
public static int[] addFirst(int value, int count, int[] test)
{
test = test.Where(val => val != value).ToArray();
Array.Resize(ref test, test.Length + 1);
for (int i = count-1; i > 0; i--)
{
test[i] = test[i-1];
}
test[0] = value;
return test;
}
declaracion
array= addFirst(value, array.Length, array);

Related

No errors in Visual Studio, Code Executes but something not right C# (updated! problem in String.Insert)

I'm writing a program for schoolwork, that's supposed to generate a 10 000 "movie" list. A single "movie" consist of a string in a form "moviename year director". I say "movie" because movie name and director are supposed to be randomly generated with letters from a-z.
I wrote the following logic to generate one such "movie". Movie name and director are random letter combination in length between 4-10 charachters. Code gives no errors in visual studio, executes, but shows blank. If I wrote correctly, then this code should generate one such string and print it, yet console is blank.
Do while loop is there to check if, however unlikely, there is a double item in the List (this is for when I do the 10 000 version).
In short, I dont understand what am I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
namespace Experiment
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
string movie = "";
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie))
{
check = false;
}
else
{
movieList.Add(movie);
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
Strings are immutable, so calling the Insert() method on the movie string doesn't do anything to the current movie variable. Instead it returns the new string.
You are however better off changing the movie type from string to StringBuilder, which is a dynamically allocated buffer of characters, so your example becomes:
using System;
using System.Text;
using System.Collections.Generic;
namespace sotest
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
StringBuilder movie = new StringBuilder();
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie.ToString()))
{
check = false;
}
else
{
movieList.Add(movie.ToString());
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
The problem is that you are using movie.Insert incorrectly.
If you read the documentation for String.Insert it says
https://learn.microsoft.com/en-us/dotnet/api/system.string.insert?view=netframework-4.8
Returns a new string in which a specified string is inserted at a
specified index position in this instance
public string Insert (int startIndex, string value);
So it returns a new String, it does not amend the existing one. So you would need to do.
movie = movie.Insert(0, Convert.ToString(GetYear()));
However, I must also say that using String.Insert in this way is not the best approach.
You should instead look at using the StringBuilder class. It is very efficient when you want to amend strings (which are immutable objects).
You might want to read parts of this to help you understand. If you scroll down then it also suggests StringBuilder.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/
Insert() method is used to return a new string from the specified string at a specified index position. In your case, you are not capturing the updated string.
The best approach to solve this is through using StringBuilder object. Please note that StringBuilder object is much efficient rather than playing with immutable string.

How to print object of type List<string> in C#

I am new to c# and I want to print object which is of List type. How can I print this object and display list in console?
Below is my code:
class Program{
public List<double> GetPowersOf2(int input)
{
var returnList = new List<double>();
for (int i = 0; i < input + 1; i++)
{
returnList.Add(Math.Pow(2, i));
}
returnList.ForEach(Console.WriteLine);//display list from method.
return returnList;
}
static void Main(String[] args)
{
Program p = new Program();
Console.WriteLine(p.GetPowersOf2(2));//not display list...
}
}
It gives error: System.Collections.Generic.List`1[System.Double]
Please suggest solution.
Thanks in advance.
Try a simple Linq and Join the outcome into a single string:
// Let's use BigInteger instead of Double to represent 2's powers
using System.Numerics;
...
int input = 12;
string report = string.Join(Environment.NewLine, Enumerable
.Range(0, input)
.Select(index => BigInteger.Pow(2, index)));
Console.Write(report);
Outcome:
1
2
4
8
16
32
64
128
256
512
1024
2048
Using Linq:
public class Program{
public List<double> GetPowersOf2(int input)
{
var returnList = new List<double>();
for (int i = 0; i < input + 1; i++)
{
returnList.Add(Math.Pow(2, i));
}
return returnList;
}
public static void Main(String[] args)
{
Program p = new Program();
p.GetPowersOf2(2).ForEach(Console.WriteLine);
}
}
So you are aware of displaying a list in the console, as you did within the method(returnList.ForEach(Console.WriteLine);). Now you returning the list object to the calling method and now you don't know how to display it, right? Why don't you try the same here, like this:
p.GetPowersOf2(2).ForEach(Console.WriteLine);
Because the variable returnList is returning from the method, so definitely the same will receive in the calling method.
Dont return the List and just call it like that:
class Program{
public void GetPowersOf2(int input)
{
var returnList = new List<double>();
for (int i = 0; i < input + 1; i++)
{
returnList.Add(Math.Pow(2, i));
}
returnList.ForEach(Console.WriteLine);//display list from method.
//return returnList;
}
static void Main(String[] args)
{
Program p = new Program();
p.GetPowersOf2(2);
}
}
OR return it like that:
class Program{
public List<double> GetPowersOf2(int input)
{
var returnList = new List<double>();
for (int i = 0; i < input + 1; i++)
{
returnList.Add(Math.Pow(2, i));
}
//returnList.ForEach(Console.WriteLine);//display list from method.
return returnList;
}
static void Main(String[] args)
{
Program p = new Program();
p.GetPowersOf2(2).ForEach(Console.WriteLine);//not display list...
}
}
var powers=p.GetPowersOf2(2);
foreach(double power in powers) Console.Writeline(power+", ");
The reason why your original code did not work is is because the default implementation of .ToString() is to simply print the name of class. Only in certain classes is this overridden.
If you want to change the default behavior of .ToString for your list you will have to derive a class from List.
public class PrintableList<T> : List<T>
{
public override string ToString()
{
string result = "";
foreach (T obj in this)
{
result += obj.ToString() + "\n";
}
return result;
}
}
Use this in place of your list in your code, and your code will work fine.

C# Dice Roll - Assigning scores to values

Currently working on a project and need some help. Still relatively new to c#. I have created a dice rolling game in which 5 dice are rolled at once in turns between 2 players. What I am stuck on is checking through these values for a three of a kind and assigning points .For example, A player presses enter and one appears three times then the player should receive three points or if four appears three times then the player receives the points. I have tried lots of different methods using if statements and for loops but cant seem to get it working. My code is provided below.Any help would be appreciated.
Thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dice_v4
{
class Game
{
static void Main(string[] args)
{
Random RandomNum = new Random();
Player[] player1 = new Player[5];
Die[] myDie = new Die[5];
for (int i = 0; i < 5; i++)
{
myDie[i] = new Dice_v4.Die(RandomNum);
player1[i] = new Dice_v4.Player();
}
for (int i = 0; i < 2; i++) // Number of players
{
Console.Write("Enter Name for Player {0}:", i + 1);
string NewName = Console.ReadLine();
player1[i].SetName(NewName);
}
Console.WriteLine();
for (int j = 1; j < 20; j++)
{
for (int i = 0; i < 2; i++)
{
myDie[i].roll();
Console.WriteLine("{0} Rolled:{1} on the first dice", player1[i].GetName(), myDie[i].GetTopNumber());
Console.WriteLine("{0} Rolled:{1} on the second dice", player1[i].GetName(), myDie[i].GetTopNumber1());
Console.WriteLine("{0} Rolled:{1} on the third dice", player1[i].GetName(), myDie[i].GetTopNumber2());
Console.WriteLine("{0} Rolled:{1} on the fourth dice", player1[i].GetName(), myDie[i].GetTopNumber3());
Console.WriteLine("{0} Rolled:{1} on the fifth dice", player1[i].GetName(), myDie[i].GetTopNumber4());
Console.WriteLine("Total Throws:{0}", j);
Console.ReadLine(); }
}
}
}
class Die
{
private int NumberTop1; //attributes
private int NumberTop2;
private int NumberTop3;
private int NumberTop4;
private int NumberTop5;
int threepoints = 0;
private Random RandomNumGenerator;
public Die(Random RandomGenerator) // constructor
{
RandomNumGenerator = RandomGenerator; // initialises random number
}
public void roll()
{
NumberTop1 = RandomNumGenerator.Next(1, 6);
NumberTop2 = RandomNumGenerator.Next(1, 6);
NumberTop3 = RandomNumGenerator.Next(1, 6);
NumberTop4 = RandomNumGenerator.Next(1, 6);
NumberTop5 = RandomNumGenerator.Next(1, 6);
// generates random number / / Number of dice to be rolled
Console.WriteLine("\tTotal score = {0}", threepoints);
}
public int GetTopNumber()
{
return NumberTop1; // Returns number on top which equals dice roll
}
public int GetTopNumber1()
{
return NumberTop2;
}
public int GetTopNumber2()
{
return NumberTop3;
}
public int GetTopNumber3()
{
return NumberTop4;
}
public int GetTopNumber4()
{
return NumberTop5;
}
}
class Player
{
private string Name;
public void SetName(string NewName) // constructor
{
Name = NewName; // initalises name
}
public string GetName()
{
return Name; // Returns name when called
}
}
}
Advice:
Whenever you have variables or properties called something1, something2, ... - you're probably doing something wrong, and you probably want to use a list, array, hashmap...
My idea here would be to add all numbers to a list and then perhaps iterate to make a dictionary where key is the dice value and value is the count. Or you can do something else, depending which format you need for later operations.
List<int> diceValues = new List<int>();
diceValues.Add(die.GetTopNumber());
diceValues.Add(die.GetTopNumber1());
diceValues.Add(die.GetTopNumber2());
diceValues.Add(die.GetTopNumber3());
diceValues.Add(die.GetTopNumber4());
Now that you have them in a list, you can do something like:
var values = new Dictionary<int, int>();
foreach(var item in diceValues) {
if(values.Keys.Contain(item)) {
values[item]++;
} else {
values[item] = 1;
}
}
After this loop you will have a list of Dictionary items where a key will be the dice value, and the value the number of dice with that value.
E.g. if someone threw two threes, and two deuces and one four, the dictionary would look:
Key: 2, Value: 2
Key: 3, Value: 2
Key: 4, Value: 1
By iterating through these you can later make a scoring system...
I would remove these properties all along and use a list or array instead.
You declare a list:
public List<int> Roles { get; private set; }
And your roll method can become:
public void roll()
{
this.Roles = Enumerable.Range(1, 5)
.Select(i => RandomNumGenerator.Next(1, 6))
.ToList();
// Check for three of a kind:
bool threeOfAKind = this.Roles.GroupBy(i => i).Any(g => g.Count() >= 3);
// rest of your logic
Console.WriteLine("\tTotal score = {0}", threepoints);
}
Later you can access each individual roll by this.Roles[numOfRoll]

C# Console App -- Trying to access a list from else statement

This is for a data structures and algorithms class. We're just starting out with bubble sort. The instructions were to generate random, unique integers and sort them using the sorting technique of the lecture. It will be required to add different sorting techniques as well.
To generate the list of random numbers, I generated a list and then shuffled the list using the fisher-yates algorithm. So I have my unique, sorted list of whatever size I choose.
I'm getting stuck because after I generate the random list, I am having problems accessing the list to run it through BubbleSort.
Is there any way I can do this?
class Algorithms
{
static void Main(string[] args)
{
string response = "";
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
//List<int> toSort = new List<int>();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
// Shuffle(Generate(response));
// have been using the line above but adding next line for
//an idea of my problem
List<int> toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
//This doesn't work and I'm trying to figure out how it can
BubbleSort(toSort);
}
}
}
//Displays help information
public static void Help(string input)
{
Console.WriteLine("\ngenerate <integer> -- Generates a data set of intended amount of integers\n"+
"algorithm <algorithm type> -- Choose which algorithm to sort data\nexit -- exit application\n" );
}
//Generates List of integers from 0 to number choosen by user
public static List<int> Generate(string size)
{
int cutString = size.Length - 9;
string sizeSubset = size.Substring(9, cutString);
List<int> numGen = new List<int>();
int dataSetSize = Convert.ToInt32(sizeSubset);
for(int i = 0; i <= dataSetSize; i++)
{
numGen.Add(i);
// Console.WriteLine(numGen[i]);
}
return numGen;
}
//Use Fisher-Yates algorithm to shuffle the list.
static Random randomize = new Random();
public static List<int> Shuffle(List<int>makeRandom)
{
List<int> shuffled = new List<int>();
int n = makeRandom.Count;
while (n > 1)
{
n--;
int k = randomize.Next(n + 1);
int value = makeRandom[k];
makeRandom[k] = makeRandom[n];
makeRandom[n] = value;
shuffled.Add(value);
Console.WriteLine(value);
}
return shuffled;
}
public static void BubbleSort(List<int>input)
{
for(int i = 0; i <= input.Count; i++)
{
for (int j = 0; j <= (input.Count - 1); j++)
{
if (input[j] > input[j + 1])
{
int temp = input[j];
input[j] = input[j + 1];
input[j + 1] = temp;
Console.WriteLine("hello");
}
}
}
}
}
}
You defined list in scope of else if (response.ToLower().StartsWith("generate")) code block, so it is not accessible outside of that block. Move declaration to Main method scope, like this:
static void Main(string[] args)
{
string response = "";
//define your list here.
List<int> toSort = new List<int>();
//Main Console Menu
while (response != "exit")
{
Console.WriteLine("Type help for list of commands");
response = Console.ReadLine();
if (response.StartsWith("exit"))
{
Environment.Exit(0);
}
else if (response.ToLower().StartsWith("help"))
{
Help(response);
}
else if (response.ToLower().StartsWith("generate"))
{
toSort = Shuffle(Generate(response));
}
else if (response.ToLower().StartsWith("bubble"))
{
List<int> sortedList = BubbleSort(toSort);
}
}
}

How do I split an array into two different arrays?

I can't seem to figure out how to fix my code so that it works. I need the user to be able to input their first name then space then the what they scored. Then I need to split the array into two different arrays and pass them to the four different methods to display to the user what they scored, etc. Can anyone help me figure this problem out?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace proj09LEA
{
class Program
{
static void Main(string[] args)
{
// declare and array of integers
int[] array = new int[10];
Console.WriteLine("\nSaturday Coder's Bowling Team");
Console.WriteLine("Enter in a name and score for each person on the team.");
Console.WriteLine("For example, Mary 143. Just hit Enter when you are done.\n");
// fill an array with user input
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter in a name and score: ");
string userInput;
string[] parsedInput;
parsedInput = userInput.Split();
string name = parsedInput[0];
int score = int.Parse(parsedInput[1]);
}
Console.WriteLine("------------ Input Complete ------------\n");
Console.WriteLine("Here are the scores for this game:");
DisplayScore(array);
HighScore(array);
LowScore(array);
AverageScore(array);
Console.WriteLine("Press Enter to continue. . .");
Console.ReadLine();
}
static void DisplayScore(int[] array)
{
foreach (int n in array)
{
Console.WriteLine("{0}'s score was {0}.\n", array);
}
}
static void HighScore(int[] array)
{
int max = array.Max();
Console.WriteLine("Congratulations {0}, your score of {0} was the highest.", max);
}
static void LowScore(int[] array)
{
int min = array.Min();
Console.WriteLine("{0}, your score of {0} was the lowest. Better get some practice.", min);
}
static void AverageScore(int[] array)
{
int sum = array.Sum();
int average = sum / array.Length;
Console.WriteLine("The average score for this game was {0:d}.", average);
}
}
}
If you absolutely have to use simple primitive arrays, you would need two distinct arrays of the same size, to hold the names as strings and scores as ints:
class Program
{
const int MaxScores = 10; // .. Use a constant to ensure the sizes remain in sync
static void Main(string[] args)
{ ///
string[] names = new int[MaxScores];
int[] scores = new int[MaxScores];
// ... parse names into names[] and scores into scores[]
DisplayScore(names, scores);
You would then need to pass both arrays to the various methods:
static void DisplayScore(string[] names, int[] scores)
{
for(int i=0; i < MaxScores; i++)
{
Console.WriteLine("{0}'s score was {1}.\n", names[i], scores[i]);
}
}
// etc
However, there are better ways to do this, e.g. by defining a custom class for the tuple of Name, Score:
class PersonScore
{
public string Name {get; set;}
public int Score {get; set;}
}
You can then declare and pass the single array of PersonScore[] around.
PersonScore[] personScores = new PersonScore[MaxScores];
for (... prompting the user for data)
{
... parsing user input
personScores[i] = new PersonScore{Name = name, Score = score};
}
DisplayScore(personScores); // Pass around the single array
static void DisplayScore(IEnumerable personScores)
{
foreach(var personScore in personScores)
{
Console.WriteLine("{0}'s score was {1}.\n", personScore.Name, personScores.Score);
}
}
// etc - other methods
As others have mentioned, other collections are also possible alternatives to an array, most commonly List.
You can do like this. Just use Console.ReadLine() to get user input. This is what you do in your code. There are better ways to do this but following will solve your problem.Also you need to perform validation as well.
for (int i = 0; i < array.Length; i++)
{
Console.WriteLine("Enter in a name and score: ");
string userInput = Console.ReadLine();
string[] parsedInput;
parsedInput = userInput.Split(' ');
string name = parsedInput[0];
int score = int.Parse(parsedInput[1]);
array[i] = score;
}
Why you need to split array in to two arrays on containing names and other containing score. Its better to create a structure having String field for name and integer field for score and write Comparator for sorting the Array containing elements of this Data structure type and sort them.
It will solve all your problems and that too efficiently.
Not many data integrity checks in the methods you are using, but here are the extensions I use to split arrays or any type of enumerable. I have not tested these all that much, so I cannot guarantee that they will work. I have removed all my input validation, but I suggest you add those back your own way.
public static List<List<T>> Split<T>(this IEnumerable<T> collection, Int32 groupSize)
{
var collectionList = collection.ToList();
if (groupSize > collectionList.Count)
groupSize = collectionList.Count;
var chunks = new List<List<T>>();
while (collectionList.Any())
{
var chunk = collectionList.Take(groupSize);
chunks.Add(chunk.ToList());
collectionList = collectionList.Skip(groupSize).ToList();
}
return chunks;
}
public static List<List<T>> Split<T>(this IEnumerable<T> collection, Func<T, Boolean> splitFunction)
{
var collectionList = collection.ToList();
if (collectionList.IsNullOrEmpty())
return new List<List<T>>();
var indices = collectionList.FindIndices(splitFunction); // Custom method that searches for the indices that satisfy the predicate and returns the index of each matching item in the list.
if (indices.IsNullOrEmpty()) // equivalent to indices == null || !indices.Any()
return new List<List<T>> { collectionList };
var chunks = new List<List<T>>();
var lastIndex = 0;
if (indices[0] > 0)
{
chunks.Add(collectionList.Take(indices[0]).ToList());
lastIndex = indices[0];
}
for (var i = 1; i < indices.Count; i++)
{
var chunkSize = indices[i] - lastIndex;
var chunk = collectionList.Skip(lastIndex).Take(chunkSize).ToList();
if (chunk.IsNullOrEmpty())
{
break;
}
chunks.Add(chunk);
lastIndex = indices[i];
}
if (collectionList.Count - lastIndex > 0)
{
var lastChunk = collectionList.Skip(lastIndex).ToList();
chunks.Add(lastChunk);
}
return chunks;
}

Categories

Resources