I am trying to code for an assignment at school. When I call my addElement() method and input the data to pass that data to my constructor which is used to store the data in certain elements in the array it seems to work ok. However, when I try to print the elements of the array it crashes. Since there are predefined values for certain elements in the array it prints before I try to assign any values myself yet when I try to add any then print it crashes with the NullReferenceException error and I have no idea why. Can anybody help guide me to my mistake?
using System;
namespace StarterFiles
{
/// <summary>
/// This class serves as the 'User Interface', or UI, to
/// the PeriodicTable class.
/// </summary>
class PeriodicTableUI
{
PeriodicTable m_theTable;
private const int QUIT = 0;
private const int PRINTALL = 1;
private const int PRINTONE = 2;
private const int ADDELEMENT = 3;
private const int EDITELEMENT = 4;
/// <summary>
/// The constructor will create a single instance
/// of the PeriodicTable class
/// </summary>
public PeriodicTableUI()
{
m_theTable = new PeriodicTable();
}
public void RunProgram()
{
int userChoice;
Console.WriteLine("Welcome to the Periodic Table Program!\n\n");
do
{
Console.WriteLine("\nPlease select from the following menu of options:");
Console.WriteLine("0) Quit the program");
Console.WriteLine("1) Print all the elements");
Console.WriteLine("2) Print out a particular element");
Console.WriteLine("3) Add a new element");
Console.WriteLine("4) Edit an existing element");
userChoice = getValidUserInput(0, 4);
switch (userChoice)
{
case PRINTALL:
printAllElements();
break;
case PRINTONE:
printOneElement();
break;
case ADDELEMENT:
addElementGetInput();
break;
case EDITELEMENT:
editElement();
break;
case QUIT:
// empty, but prevents us from falling into the 'default' case
break;
default:
Console.WriteLine("ERROR: You've selected an option which isn't supported!");
break;
}
}
while (userChoice != QUIT);
Console.WriteLine("\nThank you for using the Periodic Table Program!");
Console.WriteLine("(Please press the <Enter> key to exit)");
Console.ReadLine();
}
private void printAllElements()
{
for (int atomicNum = 1; atomicNum <= m_theTable.MaxAtomicNumber; atomicNum++)
{
if (m_theTable.ElementHasData(atomicNum - 1))
m_theTable.getElement(atomicNum).Print();
else
{
Console.WriteLine("Cannot print data: Missing {0}", atomicNum);
}
}
// STUDENTS: IMPLEMENT THIS!!
}
private void printOneElement()
{
Console.WriteLine("What is the atomic number of the element you would like to print?");
Console.WriteLine("Valid atomic numbers range from 1 to {0}", m_theTable.MaxAtomicNumber);
int atomicNum = getValidUserInput(1, m_theTable.MaxAtomicNumber);
if (m_theTable.ElementHasData(atomicNum - 1))
{
m_theTable.getElement(atomicNum).Print();
}
else
{
Console.WriteLine("Cannot print data: Missing");
}
// STUDENTS: IMPLEMENT THIS!!
}
// These are provided for your use
private void addElementGetInput()
{
Console.WriteLine("What is the atomic number of the element you would like to add?");
Console.WriteLine("Note that you can't replace an existing element");
Console.WriteLine("Valid atomic numbers range from 1 to {0}", m_theTable.MaxAtomicNumber);
int atomicNum = getValidUserInput(1, m_theTable.MaxAtomicNumber);
addElement(atomicNum);
}
private void addElementIfUserWantsTo(int atomicNum)
{
Console.WriteLine("There is no data for that element!");
Console.WriteLine("Would you like to add it now? (type 'y' or 'Y' to do so!)");
char letter = (char)Console.Read();
Console.ReadLine(); // clear input buffer
if ('y' == letter || 'Y' == letter)
addElement(atomicNum);
}
private void addElement(int atomicNum)
{
atomicNum = atomicNum - 1;
string atomicName;
string atomicSym;
double atomicWeight;
Element e;
if (m_theTable.ElementHasData(atomicNum))
{
Console.WriteLine("This element has already been defined");
Console.WriteLine("Would you like to edit that element?");
}
else
{
Console.WriteLine("atomic num: {0}", atomicNum);
Console.WriteLine("What is the atomic name of the element you would like to add?");
atomicName = Console.ReadLine();
Console.WriteLine("What is the atomic symbol of that element?");
atomicSym = Console.ReadLine();
Console.WriteLine("What is the atomic weight of that element?");
atomicWeight = Double.Parse(Console.ReadLine());
e = new Element(atomicNum, atomicName, atomicSym, atomicWeight);
m_theTable.setElement(atomicNum, e);
}
}
private void editElement()
{
Console.WriteLine("What is the atomic number of the element you would like to edit?");
Console.WriteLine("Valid atomic numbers range from 1 to {0}", m_theTable.MaxAtomicNumber);
int atomicNum = getValidUserInput(1, m_theTable.MaxAtomicNumber);
if (m_theTable.ElementHasData(atomicNum))
{
}
// STUDENTS: IMPLEMENT THIS!!
}
private double getValidUserInputDouble(double min, double max)
{
double userChoice;
bool notANum;
while ((notANum = !Double.TryParse(Console.ReadLine(), out userChoice)) ||
userChoice < min ||
userChoice > max)
{
if (notANum)
Console.WriteLine("You need to type in a decimal number, no less than {0}, and no greater than {1}", min, max);
else if (userChoice < min)
Console.WriteLine("You chose {0}, which is less than the smallest allowed number ({1})", userChoice, min);
else if (userChoice > max)
Console.WriteLine("You chose {0}, which is larger than the largest allowed number ({1})", userChoice, max);
}
return userChoice;
}
// A perfect place for generics.... which we're avoiding, since
// we haven't covered them yet :)
private int getValidUserInput(int min, int max)
{
int userChoice;
bool notANum;
while ((notANum = !Int32.TryParse(Console.ReadLine(), out userChoice)) ||
userChoice < min ||
userChoice > max)
{
if (notANum)
Console.WriteLine("You need to type in a whole number, no less than {0}, and no greater than {1}", min, max);
else if (userChoice < min)
Console.WriteLine("You chose {0}, which is less than the smallest allowed number ({1})", userChoice, min);
else if (userChoice > max)
Console.WriteLine("You chose {0}, which is larger than the largest allowed number ({1})", userChoice, max);
}
return userChoice;
}
}
}
using System;
namespace StarterFiles
{
class PeriodicTable
{
Element[] m_theElements;
public PeriodicTable()
{
m_theElements = new Element[118]; // I think there are 113....changed to 118 to reflect more accurate periodic table
// create new elements here, as needed/desired:
m_theElements[0] = new Element(1, "Hydrogen", "H", 1.008);
m_theElements[26] = new Element(27, "Cobalt", "Co", 58.9332);
m_theElements[70] = new Element(71, "Lutetium", "Lu", 174.96);
m_theElements[89] = new Element(90, "Protactinium", "Pa", 231.0359);
// You'll need (at least) 6 more.
// Pick them so that you can test your program
// Don't worry about filling in more than 10, total, unless you
// need more to test the program.
}
/// <summary>
/// You might find this useful, since you're only required to fill
/// in 10 elements, and yet there are many more in table...
/// </summary>
/// <param name="atomicNum"></param>
/// <returns>
/// Return true if the table has data for a given element;
/// return false otherwise
/// </returns>
public bool ElementHasData(int atomicNum)
{
// STUDENTS: YOU NEED TO WRITE YOUR CODE BELOW:
if (m_theElements[atomicNum] != null)
return true;
else
return false;
// STUDENTS: YOU NEED TO WRITE YOUR CODE ABOVE:
}
public int MaxAtomicNumber
{
get
{
// STUDENTS: YOU NEED TO WRITE YOUR CODE BELOW:
return m_theElements.Length;
// STUDENTS: YOU NEED TO WRITE YOUR CODE ABOVE:
}
}
/// <summary>
/// This is an "indexer"
/// </summary>
/// <param name="atomicNum">The atomic number of the element that we're
/// accessing. Note that Hydrogen, the first element, is 1 (not zero).
/// This method will take care of any 're-mapping' that needs to happen</param>
/// <returns></returns>
public Element getElement(int atomicNum)
{
// STUDENTS: YOU NEED TO WRITE YOUR CODE BELOW:
foreach (Element e in m_theElements)
{
if (e != null)
{
if (e.getAtomicNumber() == atomicNum)
{
return e;
}
}
}
return null;
// STUDENTS: YOU NEED TO WRITE YOUR CODE ABOVE:
}
public void setElement(int atomicNum, Element e)
{
if(m_theElements[atomicNum] == null)
m_theElements[atomicNum] = e;
// STUDENTS: IMPLEMENT THIS!!
}
}
}
using System;
namespace StarterFiles
{
class Element
{
private int atomicNum;
private string atomicName;
private string atomicSymbol;
private double atomicWeight;
public Element(int num, string name, string sym, double w)
{
atomicNum = num;
atomicName = name;
atomicSymbol = sym;
atomicWeight = w;
}
// HINT: In terms of figuring out what's a transition metal, etc,
// you should do a web search for 'Periodic table', and then see what
// useful,scientifically relevant images you find. Your instructor can help you
// if you get stuck - keep in mind that while you may (or may not) find the
// programming-related aspects of this assignment challenging, you shouldn't be spending
// much time on the chemistry-specific stuff. So if you're confused about the chemistry,
// ask!!
public void Print()
{
Console.WriteLine("Name: {0}", atomicName);
Console.WriteLine("Symbol: {0}", atomicSymbol);
Console.WriteLine("Atomic weight: {0}", atomicWeight);
if ((atomicNum > 20 && atomicNum < 31) || (atomicNum > 38 && atomicNum < 49) ||
(atomicNum > 57 && atomicNum < 81) || (atomicNum > 88 && atomicNum < 113))
Console.WriteLine("This element is a transition metal.");
if (atomicNum > 57 && atomicNum < 81)
Console.WriteLine("This element is a lanthanoid metal.");
if (atomicNum > 88 && atomicNum < 113)
Console.WriteLine("This element is an actinoid metal.");
// STUDENTS - IMPLEMENT THIS!!
}
public int getAtomicNumber()
{
return atomicNum;
}
public double getWeight()
{
return atomicWeight;
}
public void setWeight(double weight)
{
atomicWeight = weight;
}
// Here is a great place to add any other methods that you'll need...
}
}