我目前正在做一项大学作业,在将文本文件解析为对象实例时遇到问题。我正在开发的程序的简单解释是外卖店装载机。人员输入具有设定格式的文本文件,然后将其解析为对象的实例,以创建一个简单的外卖店,供用户订购和编辑其订单。以下是如何格式化文本文件以与代码一起使用的示例:
Name:JustNom FastFood
Toppings:[<cheese,80>,<pepperoni,120>,<tomato sauce,40>,<ham,150>,<mushroom,80>]
Garnishes:[<cheese,100>,<fried onions, 80>,<bacon,150>]
Pizza:<Name:Margherita,Toppings:[tomato sauce, cheese],Price:500>
Pizza:<Name:Ham and Mushroom,Toppings:[tomato sauce, ham, mushroom, cheese],Price:650>
Burger:<Name:Plain Burger,Garnishes:[],Price:350>
Burger:<Name:Cheese Burger,Garnishes:[cheese],Price:450>
这里的代码读取每一行代码,从本质上删除不必要的符号和单词,并将其放入各自的类中。我的代码实际上可以解析文本文件,但它只对第一部分进行解析。例如,奶酪和价格会被解析,但不会解析其余的配料。
namespace JustNom.Logic
{
//The file reader menu that created a menu in which it opens and filters a specific file.
internal class FileReaderMenu : MenuItem
{
private FileReader _reader;
public string menuName { get; set; }
public FileReaderMenu(FileReader reader)
{
_reader = reader;
}
public override string MenuText()
{
return "Select a File.";
}
public override void Select()
{
StringBuilder sb = new StringBuilder($"{MenuText()}{Environment.NewLine}");
int i = 1;
foreach (string file in _reader.paths)
{
sb.AppendLine($"{i}. {file}");
i++;
}
Console.WriteLine(sb.ToString());
int selectedIndex = ConsoleHelpers.GetIntegerInRange(1, _reader.paths.Count, MenuText()) - 1;
string[] result = File.ReadAllLines(_reader.paths[selectedIndex]);
if (result.Length == 0)
{
Console.WriteLine("Cannot open file - No data found");
}
else if (result.Length > 0)
{
var splitedStringList = new List<List<String>>();
Menu menu = new Menu(menuName);
foreach (string file in result)
{
if (file.StartsWith("Name:"))
{
menuName = file.Substring("Name:".Length);
}
string token = file.Substring(0, file.IndexOf(':'));
switch (token)
{
case "Toppings":
Topping topping = LoadToppings(file);
menu.AddToppings(topping);
break;
case "Garnishes":
Garnish garnish = LoadGarnishes(file);
menu.AddGarnish(garnish);
break;
case "Pizza":
Pizza pizza = LoadPizzas(file);
menu.AddPizza(pizza);
break;
case "Burger":
Burger burger = LoadBurgers(file);
menu.AddBurger(burger);
break;
}
static Topping LoadToppings(string toppings)
{
int startIndex = toppings.IndexOf('<') + 1;
int endIndex = toppings.IndexOf(',');
int length = endIndex - startIndex;
string name = toppings.Substring(startIndex, length);
startIndex = endIndex + 1;
endIndex = toppings.IndexOf('>');
length = endIndex - startIndex;
string price = toppings.Substring(startIndex, length);
return new Topping(name, price);
}
static Garnish LoadGarnishes(string garnishes)
{
int startIndex = garnishes.IndexOf('<') + 1;
int endIndex = garnishes.IndexOf(',');
int length = endIndex - startIndex;
string name = garnishes.Substring(startIndex, length);
startIndex = endIndex + 1;
endIndex = garnishes.IndexOf('>');
length = endIndex - startIndex;
string price = garnishes.Substring(startIndex, length);
return new Garnish(name, price);
}
static Pizza LoadPizzas(string pizza)
{
int startIndex = pizza.IndexOf(':') + 7;
int endIndex = pizza.IndexOf(',');
int length = endIndex - startIndex;
string name = pizza.Substring(startIndex, length);
startIndex = endIndex + 11;
endIndex = pizza.IndexOf("]");
length = endIndex - startIndex;
string toppings = pizza.Substring(startIndex, length);
startIndex = endIndex + 1;
endIndex = pizza.IndexOf(">");
length = endIndex - startIndex;
string price = pizza.Substring(startIndex, length);
return new Pizza(name,toppings, price);
}
static Burger LoadBurgers(string burger)
{
int startIndex = burger.IndexOf(":") + 7;
int endIndex = burger.IndexOf(",");
int length = endIndex - startIndex;
string name = burger.Substring(startIndex, length);
startIndex = burger.IndexOf('[');
endIndex = burger.IndexOf("]");
length = endIndex - startIndex;
string garnish = burger.Substring(startIndex, length);
startIndex = burger.IndexOf(':');
endIndex = burger.IndexOf(">");
length = endIndex - startIndex;
string price = burger.Substring(startIndex, length);
return new Burger(name,garnish, price);
}
}
OrderMenuItem OrderMenu = new OrderMenuItem(menu);
OrderMenu.MenuText();
}
}
}
}
namespace JustNom.JustNom
{
internal class Menu
{
public string Name { get; private set; }
private List<Burger> _burgers;
private List<Pizza> _pizzas;
private List<Garnish> _garnish;
private List<Topping> _topping;
public IEnumerable<Burger> Burgers { get { return _burgers; } }
public IEnumerable<Pizza> Pizzas { get { return _pizzas; } }
public IEnumerable<Garnish> Garnish { get { return _garnish; } }
public IEnumerable<Topping> Toppings { get { return _topping; } }
public Menu(string name)
{
Name = name;
_burgers = new List<Burger>();
_pizzas = new List<Pizza>();
_topping = new List<Topping>();
_garnish = new List<Garnish>();
}
public void AddBurger(Burger burger)
{
_burgers.Add(burger);
}
public void AddPizza(Pizza pizza)
{
_pizzas.Add(pizza);
}
public void AddGarnish(Garnish garnish)
{
_garnish.Add(garnish);
}
public void AddToppings(Topping topping)
{
_topping.Add(topping);
}
}
}
这个类包含所有包含所有解析对象的对象。很抱歉冗长的描述,我正在尝试添加尽可能多的描述,因为这个项目中有很多代码。如果您想看其他课程以帮助您更多地理解我的问题,请告诉我!
我尝试循环 Load() 方法,但这并没有真正起作用。
看看你提到的第一个问题,你已经编写了
LoadToppings
方法来仅处理第一个配料。我将在这里举一个例子来说明解决此问题的一种方法。
我修改了
LoadToppings
的返回值以返回 List<Topping>
而不是单个配料,这样我们就可以一次处理所有配料。
首先,我们可以抓取
[
和 ]
字符之间的字符串,其中包含所有顶部对(名称和价格)。
接下来,我们可以在
<
和 >
字符上拆分该字符串,因此我们最终得到一个字符串列表,每个字符串仅包含内部对的配料名称和价格。
然后我们可以用逗号分割每个,并使用它们创建一个
Topping
,我们将其添加到 List<Toppings>
,并在最后返回:
List<Topping> LoadToppings(string input)
{
var toppings = new List<Topping>();
if (input == null) return toppings;
if (input.Contains("["))
{
int start = input.IndexOf("[") + 1;
int end = input.IndexOf("]", start);
if (start < end)
{
var toppingStrings = input.Substring(start, end - start);
// Now split on "<>" to get the individual topping
// items, like: "cheese,80", "pepperoni,120", etc.
var toppingPairs = toppingStrings.Split(new[] { '<', '>' },
StringSplitOptions.RemoveEmptyEntries);
foreach(var toppingPair in toppingPairs)
{
var parts = toppingPair.Split(',',
StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0) continue;
Topping topping = new Topping { Name = parts[0] };
if (parts.Length > 1 && decimal.TryParse(parts[1], out decimal price))
{
topping.Price = price;
}
toppings.Add(topping);
}
}
}
return toppings;
}