Click here to Skip to main content
15,879,535 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have problems with the output of my code - I call structure within a structure and it does not compile. I can't figure out my mistake (it definitely has to do with my not understanding tables in structures).

My code is below (I am having problems with the last line - I am trying to get the output for the "CourseName" and it does not compile).
I am very much a beginner.
Thank you!

What I have tried:

class Program
    {
        struct Class
        {
            public Student[] Array1;
        }
        struct Student
        {
            public string firstName;
            public string lastName;
            public int code;
            public CourseGrades[] Array2;
        }
        struct CourseGrades
        {
            public string CourseName;
            public double gradeMidterm;
            
        }

        static void Main(string[] args)
        {
            

                Class myClass;
                myClass.Array1 = new Student[2];

                for (int i = 0; i < myClass.Array1.Length; i++)
                {
                    Student myStudent = myClass.Array1[i];
                    Console.WriteLine("Enter first name");
                    myStudent.firstName = Console.ReadLine();
                    Console.WriteLine("Enter last name");
                    myStudent.lastName = Console.ReadLine();
                    Console.WriteLine("Enter code");
                    myStudent.code = Convert.ToInt32(Console.ReadLine());
                    myStudent.Array2 = new CourseGrades[2];

                    for (int j = 0; j < myStudent.Array2.Length; j++)
                    {
                        Console.WriteLine("Enter course name");
                        myStudent.Array2[j].CourseName = Console.ReadLine();
                        Console.WriteLine("Enter midterm grade");
                        myStudent.Array2[j].gradeMidterm = Convert.ToDouble(Console.ReadLine());
                    }
                }
                Console.WriteLine(myClass.Array1[0].Array2[0].CourseName);
            }
    }
}
Posted
Updated 29-Dec-20 20:37pm
Comments
Patrice T 29-Dec-20 22:02pm    
And you got an error message ?
Member 15033483 29-Dec-20 22:25pm    
Yes, the one below.

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
Patrice T 29-Dec-20 22:38pm    
Use Improve question to update your question.
So that everyone can pay attention to this information.
Maciej Los 31-Dec-20 2:18am    
There's nothing to improve. Take a deep look at His code and read OriginalGriff's answer ;)

First of all, please, read carefully, what OriginalGriff wrote. The most important statement is:
Quote:

Student myStudent = myClass.Array1[i];
//...

Creates a copy of the Student in the Array1 (...) that doesn't in any way affect the original version in the Array1.


What it means to you? You need to use that copy and pass it into original array. So, after second for() loop, you need to set the value to:
myClass.Array1[i] = myStudent;
 
Share this answer
 
This is one of the most common problems we get asked, and it's also the one we are least equipped to answer, but you are most equipped to answer yourself.

Let me just explain what the error means: You have tried to use a variable, property, or a method return value but it contains null - which means that there is no instance of a class in the variable.
It's a bit like a pocket: you have a pocket in your shirt, which you use to hold a pen. If you reach into the pocket and find there isn't a pen there, you can't sign your name on a piece of paper - and you will get very funny looks if you try! The empty pocket is giving you a null value (no pen here!) so you can't do anything that you would normally do once you retrieved your pen. Why is it empty? That's the question - it may be that you forgot to pick up your pen when you left the house this morning, or possibly you left the pen in the pocket of yesterday's shirt when you took it off last night.

We can't tell, because we weren't there, and even more importantly, we can't even see your shirt, much less what is in the pocket!

Back to computers, and you have done the same thing, somehow - and we can't see your code, much less run it and find out what contains null when it shouldn't.
But you can - and Visual Studio will help you here. Run your program in the debugger and when it fails, VS will show you the line it found the problem on. You can then start looking at the various parts of it to see what value is null and start looking back through your code to find out why. So put a breakpoint at the beginning of the method containing the error line, and run your program from the start again. This time, VS will stop before the error, and let you examine what is going on by stepping through the code looking at your values.

And here is where it gets complicated.
Basically, the problem is that you are using structs, which are value types while classes are reference types.

So when you use the value of any of your structs, you copy the value rather than taking a reference. So this code:
C#
Student myStudent = myClass.Array1[i];
Console.WriteLine("Enter first name");
myStudent.firstName = Console.ReadLine();
Creates a copy of the Student in the Array1, gets a a first name, and puts it into the copy - that doesn't in any way affect the original version in the Array1.
So when you use the Array version later there is nothing there; no information at all.

I'm not going to try and fix that for you - this is important and complicated, and you need to understand what is going on - so I'll suggest you have a look at this: Using struct and class - what's that all about?[^]
It gets a bit advanced for you, but it hopefully covers what you are doing and why it's failing so badly when it looks so right!

And do yourself a couple of favours:

Don't call anything "Class" as it's too close to class the keyword, and definitely don't call a struct "Class"!

Use sensible names for things: Student is fine, firstname is fine. But Array1? Array2? If you call them Students and Courses your code becomes a lot more readable!

Don't worry too much about this right now, but remember it: never use Convert methods on user input because users make mistakes, and the Convert methods cause your app to fail when that happens - and users like nothing less than typing a list of names and courses and grades only to have the app crash because they accidentally typed a comma instead of a full stop ...
When you have a little more experience, look at the TryParse methods instead: Int32.TryParse Method (System) | Microsoft Docs[^], Double.TryParse Method (System) | Microsoft Docs[^], DateTime.TryParse Method (System) | Microsoft Docs[^] - they allow you to check and convert user input without making your app fail!
 
Share this answer
 
Comments
Member 15033483 30-Dec-20 16:57pm    
I appreciate that you took time to write an answer (which unfortunately did not help one tiny bit to solve the problem). I DID ultimately find a solution - with the same code (which by the way does not fail at all - if you think that the three lines you mentioned above fail at the end - they don't, and when I use them later on, they compile perfectly:). The solution was not complicated at all - just one extra line of code put at the right place. And I didn't even have to switch to classes, everything worked well with the structures in the original code.
Maciej Los 31-Dec-20 2:20am    
As i mentioned in my answer, please read carefully what OriginalGriff wrote.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900