所以我正在为一个班级制作电子表格。在下面的代码中有单元测试,电子表格类,单元类,依赖图类。我正在尝试调试我的程序,并观察我的电子表格类中的setCellContents方法会发生什么。我开始调试并创建一个工作表对象并向其中添加单元格。一切都很好,直到我尝试在小局部变量菜单中查看工作表内的单元格变量。一旦我点击小下拉箭头查看单元格对象中的内容,程序就会停止调试并崩溃说:
由于执行过程意外退出,因此中止了活动的测试运行。检查执行过程日志以获取更多信息。
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SS;
using Dependencies;
using Formulas;
namespace SpreadSheetTests
{
[TestClass]
public class SpreadSheetTests
{
/// <summary>
/// Tests the addition of two cells and whether the
/// dependency graph of the sheet graph works properly
/// </summary>
[TestMethod()]
public void getCellNamesTest()
{
AbstractSpreadsheet sheet = new SpreadSheet();
sheet.SetCellContents("A1", 4);
//SetCellContents will create a cell in the spreadsheet.cs class and will
//add the cell to the dictionary and the dependency graph possibly
Formula formula = new Formula("A1 + 5");
sheet.SetCellContents("A2", formula);
//The name of the cell in the contents of A2 matches the name of A1
//So A2 depends on A1
Formula form1 = new Formula("A1 + A2");
sheet.SetCellContents("A3", form1);
//MORE WORK TO BE DONE ON THIS ONE TO GET IT WORKING
Assert.AreEqual(9, sheet.GetCellContents("A3"));
}
}
}
THIS IS THE SPREADSHEET CLASS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dependencies;
using Formulas;
using System.Text.RegularExpressions;
namespace SS
{
public class SpreadSheet : AbstractSpreadsheet
{
//Private data members of the Spreadsheet class
private Dictionary<string, Cell> sheet;
private DependencyGraph graph;
/// <summary>
/// Spreadsheet Constructor
/// Creates an empty spreadsheet
/// </summary>
public SpreadSheet()
{
sheet = new Dictionary<string, Cell>();
graph = new DependencyGraph();
}
/// <summary>
/// Enumerates the names of all the non-empty cells in the spreadsheet.
/// </summary>
public override IEnumerable<String> GetNamesOfAllNonemptyCells()
{
HashSet<string> cellNames = new HashSet<string>();
for (int i = 0; i < sheet.Count; i++ )
{/*
if(sheet[i].CellContents)
{
}*/
}
return cellNames;
}
/// <summary>
/// If name is null or invalid, throws an InvalidNameException.
///
/// Otherwise, returns the contents (as opposed to the value) of the named cell. The return
/// value should be either a string, a double, or a Formula.
public override object GetCellContents(String name)
{
if (!Regex.IsMatch(name, @"[a-zA-Z]+[1-9][0-9]*") || name == null)
{
throw new InvalidNameException();
}
else
{
if (sheet[name] != null)
{
return sheet[name].CellContents;
}
else
{
return null;//don't know if this will work. test
}
}
}
/// <summary>
/// If name is null or invalid, throws an InvalidNameException.
///
/// Otherwise, the contents of the named cell becomes number. The method returns a
/// set consisting of name plus the names of all other cells whose value depends,
/// directly or indirectly, on the named cell.
///
/// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
/// set {A1, B1, C1} is returned.
/// </summary>
public override ISet<String> SetCellContents(String name, double number)
{
HashSet<string> dependentSet = new HashSet<string>();
//Check to see if the cell name is valid
// A string is a cell name if and only if it consists of one or more letters,
// followed by a non-zero digit, followed by zero or more digits.
if(!Regex.IsMatch(name, @"[a-zA-Z]+[1-9][0-9]*") || name == null)
{
throw new InvalidNameException();
}
else
{
//Name is valid and the cell is created
Cell cell = new Cell(name, number);
//Now the cell is put into the dictionary for quick reference
sheet.Add(cell.CellName, cell);
//Check to see if the cell is dependant on any other cells
//If it is return a set of the name of the cell and all the other
//cells that it is dependant on
if(graph.HasDependents(cell.CellName))
{
dependentSet.Add(cell.CellName);
foreach(string value in graph.GetDependents(cell.CellName))
{
dependentSet.Add(value);
}
}
else
{
dependentSet.Add(cell.CellName);
}
}
return dependentSet;
}
/// <summary>
/// If text is null, throws an ArgumentNullException.
///
/// Otherwise, if name is null or invalid, throws an InvalidNameException.
///
/// Otherwise, the contents of the named cell becomes text. The method returns a
/// set consisting of name plus the names of all other cells whose value depends,
/// directly or indirectly, on the named cell.
///
/// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
/// set {A1, B1, C1} is returned.
/// </summary>
public override ISet<String> SetCellContents(String name, String text)
{
if(text == null)
{
throw new ArgumentNullException();
}
HashSet<string> dependentSet = new HashSet<string>();
//Check to see if the cell name is valid
// A string is a cell name if and only if it consists of one or more letters,
// followed by a non-zero digit, followed by zero or more digits.
if (!Regex.IsMatch(name, @"[a-zA-Z]+[1-9][0-9]*") || name == null)
{
throw new InvalidNameException();
}
else
{
//Name is valid and the cell is created
Cell cell = new Cell(name, text);
//Now the cell is put into the dictionary for quick reference
sheet.Add(cell.CellName, cell);
//Check to see if the cell is dependant on any other cells
//If it is return a set of the name of the cell and all the other
//cells that it is dependant on
if (graph.HasDependents(cell.CellName))
{
dependentSet.Add(cell.CellName);
foreach (string value in graph.GetDependents(cell.CellName))
{
dependentSet.Add(value);
}
}
else
{
dependentSet.Add(cell.CellName);
}
}
return dependentSet;
}
/// <summary>
/// If formula parameter is null, throws an ArgumentNullException.
///
/// Otherwise, if name is null or invalid, throws an InvalidNameException.
///
/// Otherwise, if changing the contents of the named cell to be the formula would cause a
/// circular dependency, throws a CircularException.
///
/// Otherwise, the contents of the named cell becomes formula. The method returns a
/// Set consisting of name plus the names of all other cells whose value depends,
/// directly or indirectly, on the named cell.
///
/// For example, if name is A1, B1 contains A1*2, and C1 contains B1+A1, the
/// set {A1, B1, C1} is returned.
/// </summary>
public override ISet<String> SetCellContents(String name, Formula formula)
{
HashSet<string> dependentSet = new HashSet<string>();
//NEED TO ADD THE CIRCULAR DEPENDENCY EXCEPTION CHECK!!!!!!!!!!!!
//---------------------------------------------------------------
//---------------------------------------------------------------
/*if(forula makes a circular dependancy)
{
throw new CircularException();
}*/
if(formula == null)
{
throw new ArgumentNullException();
}
//Check to see if the cell name is valid
// A string is a cell name if and only if it consists of one or more letters,
// followed by a non-zero digit, followed by zero or more digits.
if (!Regex.IsMatch(name, @"[a-zA-Z]+[1-9][0-9]*") || name == null)
{
throw new InvalidNameException();
}
else
{
//Name is valid and the cell is created
Cell cell = new Cell(name, formula);
//Now the cell is put into the dictionary for quick reference
sheet.Add(cell.CellName, cell);
Regex regex = new Regex(@"\s");
string[] cellString = regex.Split(cell.CellContents.ToString());
//ONLY HAS DEPENDANTS IF THERE IS A FORMULA
//Check to see if the cell depends on any othere cells by checking
//for any matching regular expressions in the cells contents
foreach(string match in cellString)
{
if (Regex.IsMatch(match, @"[a-zA-Z]+[1-9][0-9]*"))
{
graph.AddDependency(name, match);
}
}
//NOT SURE IF THIS IS RIGHT TEST IT
//---------------------------------
//Check to see if the cell is dependant on any other cells
//If it is return a set of the name of the cell and all the other
//cells that it is dependant on
if (graph.HasDependents(cell.CellName))
{
dependentSet.Add(cell.CellName);
foreach (string value in graph.GetDependents(cell.CellName))
{
dependentSet.Add(value);
}
}
else
{
dependentSet.Add(cell.CellName);
}
}
return dependentSet;
}
/// <summary>
/// If name is null, throws an ArgumentNullException.
///
/// Otherwise, if name isn't a valid cell name, throws an InvalidNameException.
///
/// Otherwise, returns an enumeration, without duplicates, of the names of all cells whose
/// values depend directly on the value of the named cell. In other words, returns
/// an enumeration, without duplicates, of the names of all cells that contain
/// formulas containing name.
///
/// For example, suppose that
/// A1 contains 3
/// B1 contains the formula A1 * A1
/// C1 contains the formula B1 + A1
/// D1 contains the formula B1 - C1
/// The direct dependents of A1 are B1 and C1
/// </summary>
protected override IEnumerable<String> GetDirectDependents(String name)
{
HashSet<string> dependants = new HashSet<string>();
if(name == null)
{
throw new ArgumentNullException();
}
if(!(Regex.IsMatch(name, @"[a-zA-Z]+[1-9][0-9]*")))
{
throw new InvalidNameException();
}
foreach(string cellName in graph.GetDependents(name))
{
dependants.Add(cellName);
}
return dependants;
}
}
}
THIS IS THE CELL CLASS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Formulas;
namespace SS
{
public class Cell
{
//Private data members of the cell class
private string cellName;
private object cellContents;
private object cellValue;
/// <summary>
/// Cell Constructor
/// Creates a Cell with a string in it
/// </summary>
/// <param name="cellName"></param>
/// <param name="word"></param>
public Cell(string cellName, string word)
{
this.cellName = cellName;
this.cellContents = word;
this.cellValue = word;
}
/// <summary>
/// Cell Constructor
/// Creates a cell with a number in it
/// </summary>
/// <param name="cellName"></param>
/// <param name="cellNum"></param>
public Cell(string cellName, double cellNumber)
{
this.cellName = cellName;
this.cellValue = cellNumber;
this.cellContents = cellNumber;
}
/// <summary>
/// Cell Constructor
/// Creates a cell with a formula in it
/// </summary>
/// <param name="cellName"></param>
/// <param name="cellFormula"></param>
/// type object holds double, formula, string
public Cell(string _cellName, Formula formula)
{
cellName = _cellName;
cellContents = formula;
//this.cellValue = this will be a calculated double in future assignements
}
/// <summary>
/// Gets or Sets the cell name
/// </summary>
public string CellName
{
get{ return cellName; }
set { cellName = value; }
}
/// <summary>
/// Gets or Sets the cell word
/// </summary>
public string CellWord
{
get { return CellWord; }
set { CellWord = value; }
}
/// <summary>
/// Gets or Sets the cell number
/// </summary>
public object CellContents
{
get { return cellContents; }
set { cellContents = value; }
}
/// <summary>
/// Gets or Sets the cell formula
/// </summary>
public object CellValue
{
get { return cellValue; }
set { cellValue = value; }
}
}
}