Array of Structs | Not passing values - c#

I am new to structs in C# and I am stuck and can not pass the values in a file back to struct and successfully read them again.
The initialisation values work fine, but the file will not load at all
This is what I have so far:
public struct Card
{
public char suit;//'C'- Clubs, 'D'-Diamonds,'H'- Hearts
//and 'S'- Spades
public int value;//2-14 – for 2-10, Jack, Queen, King, Ace
}
static void Main(string[] args)
{
const int CARDS_IN_HAND = 5;//number of cards in hand
Card[] hand = new Card[CARDS_IN_HAND];//array of cards
InitialiseArray(hand);
Console.WriteLine("-------------\n");
Console.WriteLine("Initialised Values in Array");
DisplayHandData(hand);
Console.ReadLine();
The issue seems to be below
LoadArray(hand);//load values into array for use
//check values loaded to array
Console.WriteLine("-------------\n");
Console.WriteLine("Actuals Values in Array from file");
DisplayHandData(hand);
Console.ReadLine();
}
public static void InitialiseArray(Card[] data)
{
for (int count = 0; count < data.Length; count++)
{
data[count].suit = 'C';
data[count].value = 0;
}
}
public static void LoadArray(Card[] data)
{
string fileName = "FullHouse.txt";//name of file for menu item 3
//data in file = C 13 H 13 D 13 C 10 H 10
string input = fileName;
List<Card> cards = new List<Card>();
//string input = fileName;
StreamReader inFile = new StreamReader(fileName);//open file
input = inFile.ReadLine();//priming read for array
string[] inputArray = input.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
//input loading data into array
for (int i = 0; i < 10; i += 2)
{
Card newCard = new Card();
newCard.suit = inputArray[i][0];
newCard.value = int.Parse(inputArray[i + 1]);
cards.Add(newCard);
}
inFile.Close();
}
public static void DisplayHandData(Card[] data)
{
Console.WriteLine();
//test values loaded into array in correct positions
for (int records = 0; records < data.Length; records++)
{
Console.WriteLine(data[records].suit);
Console.WriteLine(data[records].value);
}
Console.WriteLine("-------------\n");
Console.ReadLine();
}
Any help would be greatly appreciated.

Your LoadArray should work just fine. The problem is probably that you are filling in variable cards, which is a local List<Card>, but what you probably want to do is fill in the data parameter.
Here is my sugestion for altering the for-cycle in LoadArray method
for (int i = 0; i < data.Length; ++i)
{
Card newCard = new Card();
newCard.suit = inputArray[i * 2][0];
newCard.value = int.Parse(inputArray[i * 2 + 1]);
data[i] = newCard;
}
But be careful about this approach. It is quite fragile. If there will be a mismatch in the length of data and inputArray, you will get an exception (if inputArray will be shorter than expected). You should check the length before the for-cycle.

Your LoadArray() method isn't changing the contents of the array passed in to it.
I recommend using a List in your main method instead, and change LoadArray() to:
public static List<Card> LoadArray()
{
string fileName = "FullHouse.txt";//name of file for menu item 3
//data in file = C 13 H 13 D 13 C 10 H 10
string input = fileName;
List<Card> cards = new List<Card>();
//string input = fileName;
StreamReader inFile = new StreamReader(fileName);//open file
input = inFile.ReadLine();//priming read for array
string[] inputArray = input.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
//input loading data into array
for (int i = 0; i < 10; i += 2)
{
Card newCard = new Card();
newCard.suit = inputArray[i][0];
newCard.value = int.Parse(inputArray[i + 1]);
cards.Add(newCard);
}
inFile.Close();
return cards;
}
Then you shouldn't need the InitialiseArray() method at all.
Instead you can do:
var hand = LoadArray();
Of course, then you might want to rename LoadArray() to something like LoadHand().

You can check, the value using Console.WriteLine(hand.Count) this will give you the size, and you can display your data in hand some like this
foreach(var h in hand)
{
Console.WriteLine(h.suit);
Console.WriteLine(h.value);
}
if you wish you can try this too.
hand.ForEach(h=>
{
Console.WriteLine(h.suit);
Console.WriteLine(h.value);
});
Edited:
Sorry, Matthew; I should put this as a comment under your answer. :-)

Related

Reading a file and storing in 2d array on Form Load

I'm designing a simple Epos system as a project and I need to read my stock values in from a file at the beginning of the application in the form of a collection so I am trying to use a 2d int array but not having much luck.
The format of my txt file looks like this:
15,10,12,19,8
16,9,11,17,10
7,6,17,14,11
8,8,12,13,5
6,7,13,14,4
1,4,15,10,10
6,9,10,14,13
8,7,9,10,11
8,12,10,15,6
9,7,6,13,9
18,8,7,11,5
7,12,10,8,9
12,6,7,9,10
My code is as follows :
private void ReadToFileOpeningStock(int [,] Stock)
{
//create an array to hold data from file
string[] OneRowOfDataArray;
const int StockColumns = 13;
const int StockRows = 5;
int[,] STOCK_ITEMS = new int[StockColumns, StockRows];
try
{
// Declare a StreamReader variable.
StreamReader inputFile;
// Open the file and get a StreamReader object.
inputFile = File.OpenText("Opening StartingStock.txt");
while (!inputFile.EndOfStream)
{
OneRowOfDataArray = inputFile.ReadLine().Split(',');
for (int i = 0; i < StockColumns; i++)
{
//Here are the inner columns
for (int j = 0; j < StockRows; j++)
{
}
}
}
inputFile.Close();
}
catch
{
MessageBox.Show("Error");
}
I also have an empty array named Stock declared with the rest of thevariables that I have declared in the method name above.
int[,] Stock ;
How do I assign my text values to an array so that I can use it later in the application?
Sorry if I'm not being clear, I'm new to programming. Any help would be greatly appreciated. Thanks.
I changed it to use file.readallines as it is what I normally use. I've added an extra array to record all the lines, to then be separated with a split into OneRowOfDataArray.
I added outputs and the line to set the value to the STOCK_ITEMS. The only other thing I changed is I removed the spaces in between the rows on the txt file
static int[,] STOCK_ITEMS = new int[4, 3];
static void Main(string[] args)
{
//create an array to hold data from file
string[] RowsOfData;//contains rows of data
string[] OneRowOfDataArray;//will contain values seperated by the rows
const int StockColumns = 13;
const int StockRows = 5;
int[,] STOCK_ITEMS = new int[StockColumns, StockRows];
try
{
// Open the file and get a StreamReader object.
RowsOfData = File.ReadAllLines("Opening StartingStock.txt");//sets all lines and seperates them into ROWSOFDATA array
for (int i = 0; i < StockColumns; i++)
{
OneRowOfDataArray = RowsOfData[i].Split(',');//splits the values in each row seperate
Console.WriteLine();//new line when outputting the data
//Here are the inner columns
for (int j = 0; j < StockRows; j++)
{
STOCK_ITEMS[i, j] = Int32.Parse(OneRowOfDataArray[j]);//save to correct index in stock items
Console.Write("[" + STOCK_ITEMS[i, j] + "]");//output value from the row
}
}
}
catch
{
MessageBox.Show("Error");
}
}
txt file
15,10,12,19,8
16,9,11,17,10
7,6,17,14,11
8,8,12,13,5
6,7,13,14,4
1,4,15,10,10
6,9,10,14,13
8,7,9,10,11
8,12,10,15,6
9,7,6,13,9
18,8,7,11,5
7,12,10,8,9
12,6,7,9,10

How to efficiently declare objects [duplicate]

I was wondering whether there's a way in a "for" loop to assign a value to a string variable named according to its index number?
let's say I have 3 string variables called:
string message1 = null;
string message2 = null;
string message3 = null;
And I want the 'for' loop to do the something like the following code:
for (int i = 1; i <=3; i++)
{
messagei = "blabla" + i.ToString();
}
I don't want to use an "if" or a "switch" because it will make the code harder to follow.
Is there a way to do that?
You don't want 3 variables with the same name, you want an array of those variables.
string[] messages = new string[3]; // 3 item array
You can then store your items in the array elements
messages[0] = "Apple"; // array index starts at 0!
messages[1] = "Banana";
messages[2] = "Cherry";
Another way to create that array is an inline array initializer, saves some code
string[] messages = { "Apple", "Banana", "Cherry" };
(Note: there are more valid syntaxes for array initialization. Research on the various other methods is left as an exercise.)
And access them via a loop (foreach)
foreach (string fruit in messages)
{
Console.WriteLine("I'm eating a " + fruit);
}
Or for
for (int i = 0; i < messages.Length; i++)
{
Console.WriteLine("I'm eating a " + messages[i]); // reading the value
messages[i] = "blabla" + i.ToString(); // writing a value to the array
}
can you use an array? or list type?
string[] messages = new string[3];
for (int i = 1; i <=3; i++)
{
messages[i] = "blabla" + i.ToString();
}
You said you don't want to have a switch statement. I realize this does have a switch, but if you must have three different variables, you could encapsulate your switch inside a function call:
string message1 = null;
string message2 = null;
string message3 = null;
void SetMessage(int i, string value)
{
if(i == 1)
message1 = value;
etc
}
for (int i = 1; i <=3; i++)
{
SetMessage(i, "blabla" + i.ToString());
}
Not an optimal solution but if you MUST have separate variables it will hide the mess.
You can't do that (well, not sanely). Have you considered using an array of strings instead?
I think you should use an array for this kind of variables.
string[] message = new string[3];
for (int i = 1; i <=3; i++)
{
message[i] = "blabla" + i.ToString();
}
Usually instead of having N differents variables named 1, 2, ..., N the way is to store them in an array:
string message[3];
message[0] = null;
message[1] = null;
message[2] = null;
and then the loop:
for (int i = 0; i <=2; i++)
{
message[i] = "blabla" + i.ToString();
}
Note that, usually again, a set of indexed variables starts with value 0 ;)
I would go about it a little differently, maybe use a dictionary and store your messages. Something like this:
Dictionary<string, string> messages = new Dictionary<string, string>();
for(int i = 1; i <= 3; i++)
{
messages.Add("message" + i.ToString(), i.ToString());
}
You can also do it without the index:
string[] Messages = { "Tom", "Dick", "Harry" };
foreach (String Message in Messages)
{
Response.Write("Hello " + Message + "<br />");
}
If you declare your variable in a class as public variables, you can access them as follow;
public partial class _Default : System.Web.UI.Page
{
public string message1 = null;
public string message2 = null;
public string message3 = null;
public void setVars()
{
for (int i = 1; i <=3; i++)
{
this.GetType().GetField("message" + i.ToString()).SetValue(this, "blabla" + i.ToString());
}
}
}

Count the number of words within an Array or List

I need to count the number of words within an array or a list. The reason I say array or list is because I am not sure which would be the best to use in this situation. The data is static and in a .txt file (It's actually a book). I was able to create an array and break down words from the array but for the life of me I can not count! I have tried many different ways to do this and I'm thinking since it is a string it is unable to count. I have even teetered on the edge of just printing the whole book to a listbox and counting from the listbox but, that's ridiculous.
public partial class mainForm : Form
{
//------------------------
//GLOBAL VARIABLES:
//------------------------
List<string> countWords;
string[] fileWords;
string[] fileLines;
char[] delim = new char[] { ' ', ',','.','?','!' };
string path;
public mainForm()
{
InitializeComponent();
}
private void BookTitle() // TiTleAndAuthor Method will pull the Book Title and display it.
{
for (int i = 0; i < 1; i++)
{
bookTitleLabel.Text = fileLines[i];
}
}
private void BookAuthor() // TiTleAndAuthor Method will pull the Book Author and display it.
{
for (int i = 1; i < 2; i++)
{
bookAuthorLabel.Text = fileLines[i];
}
}
private void FirstLines() // FirstTenWords Method pulls the first ten words of any text file and prints the to a ListBox
{
for (int i = 0; i <= 499; i++)
{
wordsListBox.Items.Add(fileWords[i]);
}
}
private void WordCount() // Count all the words in the file.
{
}
private void openFileButton_Click(object sender, EventArgs e)
{
OpenFileDialog inputFile = new OpenFileDialog();
if (inputFile.ShowDialog() == DialogResult.OK) // check the file the user selected
{
path = inputFile.FileName; // save that path of the file to a string variable for later use
StreamReader fileRead = new StreamReader(path); // read a file at the path outlined in the path variable
fileWords = fileRead.ReadToEnd().Split(delim); // Breakdown the text into lines of text to call them at a later date
fileLines = File.ReadAllLines(path);
countWords = File.ReadLines(path).ToList();
wordsListBox.Items.Clear();
BookTitle();
BookAuthor();
FirstLines();
WordCount();
}
else
{
MessageBox.Show("Not a valid file, please select a text file");
}
}
}
Maybe this is useful:
static void Main(string[] args)
{
string[] lines = File_ReadAllLines();
List<string> words = new List<string>();
foreach(var line in lines)
{
words.AddRange(line.Split(' '));
}
Console.WriteLine(words.Count);
}
private static string[] File_ReadAllLines()
{
return new[] {
"The one book",
"written by gnarf",
"once upon a time ther werent any grammer",
"iso 1-12122-445",
"(c) 2012 under the hills"
};
}
Before I get to the answer, a quick observation on some of the loops:
for (int i = 1; i < 2; i++)
{
bookAuthorLabel.Text = fileLines[i];
}
This'll only run once, so it's pointless to have it in a loop (unless you intended this to actually loop through the whole list, in which case it's a bug). If this is the expected behavior, you might as well just do
bookAuthorLabel.Text = fileLines[1];
You have something similar here:
for (int i = 0; i < 1; i++)
{
bookTitleLabel.Text = fileLines[i];
}
Again, this is pointless.
Now for the answer itself. I'm not sure if you're trying to get total word count or count of individual words, so here's a code sample for doing both:
private static void CountWords()
{
const string fileName = "CountWords.txt";
// Create a dummy file
using (var sw = new StreamWriter(fileName))
{
sw.WriteLine("This is a short sentence");
sw.WriteLine("This is a long sentence");
}
string text = File.ReadAllText(fileName);
string[] result = text.Split(new[] { " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
// Total word count
Console.WriteLine("Total count: " + result.Count().ToString());
// Now to illustrate getting the count of individual words
var dictionary = new Dictionary<string, int>();
foreach (string word in result)
{
if (dictionary.ContainsKey(word))
{
dictionary[word]++;
}
else
{
dictionary[word] = 1;
}
}
foreach (string key in dictionary.Keys)
{
Console.WriteLine(key + ": " + dictionary[key].ToString());
}
}
This should be easy to adapt to your particular needs in this case.
Read text file line by line. split by empty character and remove unnecessary spaces. sum this count to total.
var totalWords = 0;
using (StreamReader sr = new StreamReader("abc.txt"))
{
while (!sr.EndOfStream)
{
int count = sr
.ReadLine()
.Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries).Count();
totalWords += count;
}
You can also use the below code:
totalWords = fileRead.ReadToEnd().Split(delim, StringSplitOptions.RemoveEmptyEntries).Length;

How To Read Data Into A List Structure in C#?

I am writing a program that uses a StudentStruct (structure) that consists of: studentID, studentName, and grades (which is a separate List). The program is supposed to read in a sequential text file and contains methods that allow the user to: Add Student, Add Grades (to a particular student), Change Student Name, and Delete Student. At the end of the program it is supposed to overwrite the previous file with the new changes made from the current program session.
My question is how do I read in data from the text file into the separate structure variables within the lists?
My text file looks like this:
00000,Mimzi Dagger,100,50,75,70,45,10,98,83
00001,Alexander Druaga,89,45,80,90,15,73,99,100,61
00002,Nicholas Zarcoffsky,100,50,80,50,75,100,100
00003,Kantmiss Evershot,50,100
Once the structure variables within the list are filled, how do I overwrite the file with the contents of the List structure in the same format as the above file?
Since I have multiple and varying amounts of grades, how would I achieve looping through and adding each grade to the grades list?
As you can maybe already tell, I am very new to c# and this is my first project. Any help would be greatly appreciated!
class Program
{
static string pathSource = #"C:\schoolfiles\StudentGrades.txt";
struct StudentStruct
{
public string studentID;
public string studentName;
public List<string> grades;
}
static void Main(string[] args)
{
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
student.grades = new List<string>();
}
UPDATE: Here is what I have come up with so far:
for (int i = 0; i < fileLines.Length; i++)
{
output = fileLines[i];
string[] outputArray = output.Split(',');
student.grades = new List<string>();
student.studentID = outputArray[0];
student.studentName = outputArray[1];
for (int j = 2; j < outputArray.Length; j++)
{
student.grades.Add(outputArray[j]);
}
myList.Add(student);
UPDATE: The code above worked out wonderfully. Here is the top part of my code involving this question:
static void Main(string[] args)
{
//Declare variables
string output;
//Read the File into an array
string[] fileLines = File.ReadAllLines(PathSource);
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
for (int i = 0; i < fileLines.Length; i++)
{
output = fileLines[i];
string[] outputArray = output.Split(',');
student.grades = new List<string>();
student.studentID = outputArray[0];
student.studentName = outputArray[1];
for (int j = 2; j < outputArray.Length; j++)
{
student.grades.Add(outputArray[j]);
}
myList.Add(student);
}
MainMenu(myList);
}
And then to add the list back to the file I did this:
static void ExitModule(List<StudentStruct> myList)
{
//Declare variables
string inputChoice = null;
string output = null;
System.IO.StreamWriter file = new System.IO.StreamWriter(PathSource);
Console.Clear();
Console.WriteLine("Are You Sure You Want To Exit The Program? Y/N");
inputChoice = Console.ReadLine();
if (inputChoice == "Y" || inputChoice == "y")
{
for (int i = 0; i < myList.Count; i++)
{
output = (myList[i].studentID + "," + myList[i].studentName);
for (int j = 0; j < myList[i].grades.Count; j++)
{
output += ("," + myList[i].grades[j]);
}
file.WriteLine(output);
}
file.Close();
Environment.Exit(0);
Since this is clearly homework, it may be a good time for you to learn about data structures. This will help you store the information you've read in from the text file efficiently, allowing you to write it out much more easily after modifying the records.
Here are a couple of other random pointers:
The System.IO.File.ReadLines(pathSource) method would be a good place to start reading each line of a text file
You should almost never be using a struct in C# (especially one that is mutable like in your example) unless you are well-versed in its semantics and purpose. Use a class instead
try this code. it's working for me
class Program
{
static string pathSource = #"C:\schoolfiles\StudentGrades.txt";
struct StudentStruct
{
public string studentID;
public string studentName;
public List<string> grades;
}
static void Main(string[] args)
{
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
student.grades = new List<string>();
// get all lines from text file
string[] allLinesFromFile = File.ReadAllLines(pathSource);
// iterate through each line and process it
foreach(string line in allLinesFromFile)
{
// split each line on ','
string[] sections = line.Split(',');
student.studentID = sections[0];
student.studentName = sections[1];
// use this loop to add numbers to list of grades
for(int i =2; i < sections.Length; i++)
{
student.grades.Add(sections[i]);
}
// add this student to list
myList.Add(student);
// create new object of student
student = new StudentStruct();
student.grades = new List<string>();
}
}
A few things.
(1) I am not sure why your teacher/professor would have you use a struct here. A class is much more appropriate. I actually cringed when I first saw the code
(2) having something as a const also implies that it is static "pathSource"
(3) Properties should be capitalized "pathSource" -> "PathSource"
(4) You should separate responsibilities... Try not to put everything in Main
(5) You shouldn't have to create an instance of grades outside of StudentStruct, this can lead to errors. i.e. NullPointerException... basically the struct should be self containing.
(6) Everything should compile. I haven't tested it. If you have any issues. let me know.
Program {
private const string PathSource = #"C:\schoolfiles\StudentGrades.txt";
private struct StudentStruct
{
public string StudentID;
public string StudentName;
private List<string> _gradeList;
public List<string> GradeList
{
// if _gradeList is null create a new instance
get { return _gradeList ?? (_gradeList = new List<string>()); }
private set { _gradeList = value; }
}
}
private static void Main( string[] args )
{
var studentFile = File.ReadAllLines( PathSource );
// If you haven't learned about delegates or extensions methods...
// You can just change it to a foreach statement
var myList = studentFile.Select( GetStudent ).ToList();
// make sure we have everything
foreach (var studentStruct in myList)
{
Console.WriteLine( "{0} {1}", studentStruct.studentName, studentStruct.studentID );
foreach (var grade in studentStruct.GradeList) { Console.Write( grade + " " ); }
Console.WriteLine();
}
}
private static StudentStruct GetStudent( string line )
{
var student = new StudentStruct();
var studentDelimited = line.Split( ',' );
student.studentID = studentDelimited[ 0 ];
student.studentName = studentDelimited[ 1 ];
for ( int i = 2; i < studentDelimited.Length; i++ ) { student.GradeList.Add( studentDelimited[ i ] ); }
return student;
}
}

How to implement C# code for Order id separated by commas and range separated by hyphens, and display all info of order

Ex: 1,4-90, 292,123
It needs to display the whole order information of
1
4,5,6....90
292
123.
Whats the gud approach to solve this.
It is similar to tracking in UPS or fedex if multiple orders are given in search box.
I meant if in a search box I giv 1,4-90, 292,123 this string the result that needs to come back is a grid representation of all the data which is corresponding to each of the order id respectively. I want to know how to parse the string into collection and send them to the database and show the information in the grid for...
1
4,5,6....90
292
123.
as a different row...from where I can generate reports too (alternative)
Please try.
static ArrayList list;
static void Main(string[] args)
{
string str = "1,4-90,292,123";
string[] arr = str.Split(',');
list = new ArrayList();
for (int i = 0; i < arr.Length; i++)
{
string tmp = arr[i];
if (tmp.IndexOf('-') != -1)
{
Range(tmp);
}
else list.Add(int.Parse(tmp));
}
list.Sort();
object[] intResult = list.ToArray();
//print the final result
for (int i = 0; i < intResult.Length; i++)
{
Console.WriteLine(intResult[i].ToString());
}
Console.Read();
}
static void Range(string range)
{
string[] tmpArr = range.Split('-');
int stInt = int.Parse(tmpArr[0]);
int edInt = int.Parse(tmpArr[1]);
int[] intArr = new int[(edInt - stInt) + 1];
for (int i = 0; stInt <= edInt; i++)
{
list.Add(stInt++);
}
}

Categories

Resources