How to pass an array between methods? - c#

I'm following along in a book and trying the 'challenges'. Here I'm running into a problem with properly returning and passing an array between methods. Something goes wrong with returning the array, especially from the second method, and then passing it to third to print.
I understand the stack, heap, values and references on the conceptual level, but something clearly goes
wrong.
Each method appears to work otherwise.
using System;
namespace PracticeArray
{
class Program
{
static int[] GenerateNumbers()
{
Console.WriteLine("Enter a number to generate array from:");
string input = Console.ReadLine();
int inputNumber = Convert.ToInt32(input);
int[] generatedArray = new int[inputNumber];
for (int i = 0; i < generatedArray.Length; i++)
{
generatedArray[i] = i;
}
return generatedArray;
}
static int[] Reverse(int[] arrayToReverse)
{
int count = arrayToReverse.Length;
int[] arrayToReturn = new int[count];
count--;
for (int i = 0; i < arrayToReturn.Length; i++)
{
arrayToReturn[i] = arrayToReverse[count--];
}
return arrayToReturn;
}
static void PrintNumbers(int[] numbersToPrint)
{
foreach (int singleNumber in numbersToPrint)
{
Console.Write(singleNumber + ", ");
}
}
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Reverse(numbers);
PrintNumbers(numbers);
}
}
}

The problem
The array you return is a new array:
Take a look in your Reverse function. You create a new array called arrayToReturn and return that array. You also never modify the original input array arrayToReverse.
static int[] Reverse(int[] arrayToReverse) // this input array is never modified
{
int count = arrayToReverse.Length;
// ...
arrayToReturn = new int[count]; // Here is the new array
// ...
return arrayToReturn; // you return the new array
}
Now look at where you called Reverse you passed in some generated numbers, but you ignore the return value of the function so you never find out what the new array is. Remember we already established above that you don't modify the elements of the input array. So numbers will remain unchanged.
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
Reverse(numbers); // you ignored the return value of `Reverse`
PrintNumbers(numbers); // These are the original unreversed numbers
}
To Fix
Option #1 - New variable to store the result
To fix this, store the array returned from Reverse in a variable and print those numbers.
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
int[] reversedNumbers = Reverse(numbers);
PrintNumbers(reversedNumbers);
}
Option #2 - Reuse the same variable to store the result
In this option you simply discard the original array by taking the new reversed numbers array returned from Reverse and assigning it to the numbers variable. After that assignment, numbers will refer to the reversed array that was returned from Reverse. The original array is orphaned and forgotten - eventually garbage collected.
static void Main(string[] args)
{
int[] numbers = GenerateNumbers();
// repurpose the `numbers` variable to store the result.
numbers = Reverse(numbers);
PrintNumbers(numbers);
}

Related

C# Array in array

I'm stuck trying to create array of arrays..
This is what i have for now, i would appreciate if someone could point me to right direction.
I have .txt file which has paths to images and each string has desired output separated with "|" like so:
":\\\img.png|1"
I'm trying to create array that has 2 columns and number of imagepaths as rows. Col 0 being a array of flattened rgb values of the image and col 1 being output as int.
I'm getting error from line Data[i][0] = Flat;
"Cannot implicitly convert type 'int[]' to 'int'"
It might be obvious to more experienced coders here but i cant wrap my head around this.
static int[][] CreateDataSet(string DatasetPath)
{
string[] Lines = File.ReadAllLines(DatasetPath);
int[][] Data = new int[Lines.GetUpperBound(0)][];
for (int i = 0; i <= Lines.GetUpperBound(0); i++)
{
Data[i] = new int[2];
string[] StringSplit = Lines[i].Split('|');
Data[i][1] = Convert.ToInt32(StringSplit[1]);
int[] Flat = FlattenArray(ImagetoArray(StringSplit[0]));
Data[i][0] = Flat;
}
return Data;
}
In an array, all elements must have same type (or at least must be assignable to a variable of the element's type).
You have two options.
The bad one: use array of objects.
object[][] data;
Now you can put everything in that array, but it will be slow (boxing of value types) and untyped (hard to use and to maintain).
Instead of a jagged array, use tuples.
(int[] FlattenedImage, int Output)[] data;
That looks a little bit weird, but it's actually very useful. It's strongly typed, it prevents boxing, and it uses nice and modern language features.
The big problem here is you have an int and an int[]. So the [0] index of Data must itself be an array, rather than merely an integer. And since the [0] and [1] subscripts are different types, you're really gonna need a completely different kind of data structure here.
Here's an example using Tuples:
static IEnumerable<(int, int[])> CreateDataSet(string DatasetPath)
{
var result = new List<(int, int[])> = new List<(int, int[])>();
foreach(string line in File.ReadLines(DatasetPath))
{
var lineData = line.Split('|');
yield return (int.Parse(linedata[1]), FlattenArray(ImageToArray(lineData[0])) );
}
}
or with linq:
static IEnumerable<(int, int[])> CreateDataSet(string DatasetPath)
{
return File.ReadLines(DatasetPath).Select(line => {
var data = line.Split('|');
return ( int.Parse(data[1]), FlattenArray(ImageToArray(data[0])) );
});
}
If you would create a class or a struct to containt the data it would look something like this:
class ImageData
{
public int[] FlatImate { get; }
public int Number { get; }
public ImageData(int[] flatImage, int number)
{
FlatImage = flatImage;
Number = number;
}
}
static ImageData[] CreateDataSet(string datasetPath)
{
string[] lines = File.ReadAllLines(datasetPath);
ImageData[] data = new ImageData[Lines.GetUpperBound(0)];
for (int i = 0; i <= lines.GetUpperBound(0); i++)
{
string[] stringSplit = lines[i].Split('|');
int number = Convert.ToInt32(stringSplit[1]);
int[] flat = FlattenArray(ImagetoArray(StringSplit[0]));
data[i] = new ImageData(flat, number);
}
return data;
}

Creating new class instance in a loop

I've just started learning about methods and classes, I would like to know if I can have something like,
CarsSold Day1 = new CarsSold();
in a for loop where it will create a new instance of a new day each time it runs. For example on the second time the loop runs I want it to create an instance like this,
CarsSold Day2 = new CarsSold();
I have tried to use an array but either it cant be done with arrays or I'm using the wrong syntax. Thanks in advance.
Full code
class Program
{
static void Main(string[] args)
{
int[] weekDay = new int[7];
int userInput;
int x;
for (x = 0; x < weekDay.Length; x++)
{
Console.Write("Enter the number of cars sold: ");
bool ifInt = int.TryParse(Console.ReadLine(), out userInput);
CarsSold Day[x] = new CarsSold(userInput);
}
}
}
The problem is how you're trying to define your array. The syntax is invalid, and you're doing it in the wrong place.
You should define the array before your loop, and then only assign values to the array within the loop.
static void Main(string[] args)
{
int userInput;
CarsSold[] days = new CarsSold[7]; // create an array with 7 items
int x;
for (x = 0; x < days.Length; x++)
{
Console.Write("Enter the number of cars sold: ");
bool ifInt = int.TryParse(Console.ReadLine(), out userInput);
days[x] = new CarsSold(userInput); // assign a value to the days array at position x.
}
}
Note also that arrays start from 0, not 1, so the first item is actually days[0], and the last is days[6] (for a 7-item array). I took the liberty of removing weekDays since it wasn't needed here, and replaced it in the loop with days.Length.
Arrays can have set amount of things in them, so if you declare an array like this
object[] objectArray = new object[10];
Then that array can hold only 10 objects. If you want to add anything to an array you have to chose an index to which that thing will be assigned to, for example:
objectArray[2] = "some value";
in Your case you could iterate through the array and add new object to each index like this
for (var i = 0; i < objectArray.Length; i++)
{
objectArray[i] = new YourObject();
}
If the amount of objects you want to store is unknown and can change then you should use collections, for example a List
List<object> listOfObjects = new List<object>();
Now if you want to add anything to that list you simply do
listOfObjects.Add(itemYouWantToAddToTheList);
You access lists the same way you would access arrays, so you can use indexes like
var someValue = listOfObjects[0];
As you probably noticed this list has a generic parameter <object>, it tells the list what type of data it can store, in my example its the object type so it can pretty much store anything, but you can set it to string or int or any other type like your own class types and then this list would store only those types of objects.
If you don't know the number of days, then:
IList<CarsSold> soldCarsList = new List<CarsSold>();
foreach(var day in Days)
{
soldCarsList.Add(new CarsSold());
}
If you know the number of days(e.g:7), then:
CarsSold[] soldCarsArray = new CarsSold[7];
for (int i = 0; i < days.Length; x++)
{
soldCarsArray[i] = new CarsSold();
}

Return Values With Arrays

I am quite new to programming and I just need help with what I am doing wrong.
This is the code I have so far. Yes, this is for homework, but I am confused on what I have to do next.
In the CreateRandomlyFilledArray method, I have to create an allocated array. This method will take as it's only parameter an integer, The array is then created inside the method, filled with values that have been randomly created by the method. (values can be from 0 to 100).
The array will then be passed (as a parameter) to the PrintArray method, which will take as it's single parameter an array of integers, and will print out everything in the array.
class Returning_An_Array
{
public void RunExercise()
{
ArrayReturnMethods m = new ArrayReturnMethods();
int[] nums1;
nums1 = m.CreateRandomlyFilledArray(10);
m.PrintArray(nums1);
}
}
class ArrayReturnMethods
{
public int[] CreateRandomlyFilledArray( int size )
{
int[] newNums = new int[size];
for (int value = 0; value < newNums.Length; value++)
{
return newNums;
}
return newNums;
}
public void Printarray( int[] value )
{
for(int i = 0; i < value.Length; i++)
{
Console.WriteLine("value is: {0}", value[i]);
}
}
}
Thank you so much!!
Avoid asking homework question here. Especially when a bit of reading would solve your issue. Good luck with your homework. : )
class Program
{
/*
I assume you are trying to
1. Create an array of integers
2. Store random numbers (between 0 and 100) inside that array
3. Print the numbers in the array
You have alot of reading to do as theres alot of fundemental mistakes in both your approach and code.
*/
static void Main(string[] args)
{
// creating an array with random numbers
ArrayMethods m = new ArrayMethods();
int[] nums1;
nums1 = m.CreateRandomlyFilledArray(10);
m.Printarray(nums1);
}
class ArrayMethods
{
/*
- First you have to fill the array with random numbers
In your solution, you have created "CreateRandomlyFilledArray".
1. You created the a new array of integers which is good
2. The way you attempted to fill the new array is incorrect
*/
public int[] CreateRandomlyFilledArray(int size)
{
int[] newNums = new int[size];
Random numGen = new Random(); // This will be used to generate random numbers
for (int elementNum = 0; elementNum < newNums.Length; elementNum++)
{
// here we will put a random number in every position of the array using the random number generator
newNums[elementNum] = numGen.Next(0, 100); // we pass in you minimum and maximum into the next function and it will return a random number between them
}
// here we will return the array with the random numbers
return newNums;
}
/*
- This function prints out each item in an integer array
1. You do not need to a return value as you will not be returning any thing so, Use "void".
*/
public void Printarray(int[] value)
{
for (int i = 0; i < value.Length; i++)
{
Console.WriteLine("value is: {0}", value[i]);
}
}
}
}

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;
}

Difficulty with passing arrays and manipulating data in arrays (Homework) c#

So I am doing a Homework assignment for c#. The assignment requires the use of 2 arrays, one to hold names and the other to hold scores. We are then to calculate the average score, display the below average scores, and display the scores according to name. I am having a significant amount of difficulty passing the arrays by reference/value in order to use the data in them and maintain my code using separate modules. The arrays have to hold up to 100 individual pieces of data.
class Program
{
static void Main(string[] args)
{
string[] playerNames = new string[100];
int[] playerScores = new int [100];
int numPlayers = 0;
double averageScore;
DisplayData(playerNames);
}
static void InputData(string[] playerNames, int[] playerScores, ref int numPlayers)
{
string playerName;
do
{
int i = 0;
Console.WriteLine("Enter the name of the player...Enter \"Q to exit...");
playerName = Console.ReadLine();
if (playerName == "Q" || playerName == "q")
Console.WriteLine("No further user input needed...\n");
else
playerNames[i] = playerName;
Console.WriteLine("Enter the score of the player...");
int playerScore = Convert.ToInt32(Console.ReadLine());
playerScores[i] = playerScore;
numPlayers += i;
i++;
}
while (playerName != "Q");
}
static void CalculateAverageScore(int[] playerScores, ref int averageScore)
{
InputData(playerScores);
InputData(ref numPlayers);
int averageScores = 0;
averageScores = playerScores / numPlayers;
}
The biggest question I have is that I cannot seem to pass the array data. I am plagued by "No overload method for "Input Data" or whatever method I am using. So I'm curious as to how I can pass the array data to another method.
Since this is homework, I won't give you the full answer, but here is a way forward.
Instead of using the ref keyword, just pass the array into the method. Have the method return an int instead of void. Calculate the average within the method and have the final line of the method return the int that you've calculated
static int CalculateAverageScore(int[] playerScores)
{
// calculate average
return average; // the int you've calculated.
}
Call the method from the main, when you need to acquire the average.
Also, are you missing some braces { } for the 6 lines that come after your else statement?

Categories

Resources