在另一个列表中使用字符串列表时出现问题

本文关键字:列表 字符串 问题 另一个 | 更新日期: 2023-09-27 18:21:34

基本上,我要做的是将一本书的文本文件加载到一个字符串数组中,然后将各个页面以及书中每个页面的其他属性分解为单独的页面。当我试图将一个新项目添加到页面列表中时,在我调用temp.pageText.Clear()后,它不会保留dailypages.pageText值。我对C#和面向对象编程非常陌生,所以我可能在这里做错了不止一件事:)

abstract class Book
{
  abstract internal void loadPages();
  protected string[] bookText { get; set; }  // Load entire book text into
  /// Other generic book properties
  public Book(string filename)  // Load the book
  {
    bookText = File.ReadAllLines(filename);
  }
  protected abstract class Page  // Generic page properties
  {
    internal int pageNum { get; set; }
    internal List<string> pageText{ get; set; }  // Single page from the book
    public Page()    // Init list of strings
    {
      pageText = new List<string>();
    }
  }
}
class DailyReflections : Book
{
  List<dailyPage> dailypages = new List<dailyPage>();  // Init list of Pages
  override internal void loadPages()  // Split dailypages from bookText
  {
    DateTime date = new DateTime();
    DateTime date2 = new DateTime();
    dailyPage temp = new dailyPage();
    for (int bookline = 0; bookline < bookText.LongLength; bookline++)
    {
      if (DateTime.TryParse(this.bookText[bookline], out date))
      {
        bookline++;
        while (!DateTime.TryParse(bookText[bookline], out date2))
        {
          temp.pageText.Add(bookText[bookline]);
          if (++bookline >= bookText.LongLength) break;
        }
        bookline--;
      }
      temp.dailyDate = date;
      dailypages.Add(temp);
      temp.pageText.Clear();
      this.totalPages++;
    }
  Console.WriteLine(dailypages[0].pageText[0]); 
//    ^^^ This line I get an out of range error, this should be line 1 of the 
//    first page. Same error with any index used. If I take out the line
//    temp.pageText.Clear(); (used to clear the text to fill it with the next
//    page, maybe I am using it wrong). Without the .Clear() dailypages[0]
//    contains page 1, [1] contains page 1 and page 2, [2] pages 1,2,3 since.
//    it continues adding to the end of temp.pageText without clearing the 
//    last page.
  }
  protected class dailyPage : Page  // Page with values unique to the book
  {
    internal DateTime dailyDate { get; set: }  // Date on the page
    internal string pageTitle { get; set; }  // Title of the page
  }
}

在另一个列表中使用字符串列表时出现问题

将整本书加载到一个数组中,然后将该数组分解并添加到单独的页面中,这可能是一种效率低下的方法,因为您实际上在内存中存储了两次书,并处理了两次,一次加载,一次解析页面。

很难判断接口还是抽象方法是最好的方法,但由于您是在具体类中加载页面,因此接口可能更简单。

以下是一个不完整的例子,说明如何在一次通行证中阅读和处理这本书:

public interface IBook
{
    // List might be too specific, IEnumerable might work fine
    List<IPage> Pages { get; set; }
    // ctor loading is ok, but harder to unit test and define via interface
    void LoadPages(string fileName); 
}
public interface IPage
{
    int Number { get; set; }
    string Text { get; set; }
}
public class DailyReflections : IBook
{
    List<IPage> Pages { get; set; }
    public void LoadPages(string fileName)
    {            
        // Read one line at time, perhaps by appending line to StringBuilder
        // Attempt to parse date on this line, then when your date parses, 
        // create new DailyPage from StringBuilder text and date, then add to Pages.
        // Then clear your StringBuilder and continue until all lines are read.
        // e.g. https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline(v=vs.110).aspx
    }
}
public class DailyPage : IPage
{
    public int Number { get; set; }
    public string Text { get; set; }
    public DateTime Date { get; set; }
}

你可以将其进一步分解,例如通过拥有BookReader类,或者创建接口IDailyReflections和IDailyPage,但除非你在其他地方需要它们,否则这可能不值得。

我还建议设置单元测试,以验证您的方法是否有效,边缘案例是否得到处理(例如,第一页|最后一页没有日期)。然后,您可能会发现,最好将流传递给LoadPages,而不是文件名,从而避免了书籍始终是文件的假设,并使单元测试更容易实现(内存流与磁盘上的文件),使书籍阅读更灵活(从文件加载、从web加载等)

祝你好运!

经过一些实验,我发现了代码无法正常工作的主要原因。我把pageText变成了一个字符串,以使事情变得更简单(现在它不再是列表中的列表)并消除潜在的问题。主要问题是在我试图将新页面添加到页面列表的行上。问题不一定是清单中的清单。我在给日刊打电话。Add(temp);这并不是在列表的末尾创建一个新的日画实例,而是简单地指向内存中temp的位置。当我调用temp.pageText.Clear()时,它也会有效地清除并使dailypages.pageText为null,因为它们都引用了同一个内存块。

因此,这个问题通过替换日画而被消除了。添加(temp)与dailypages。Add(new dailyPage),它保留特定于dailyPage类型的新内存块。如果我要将dailypages.pageText作为一个列表,我需要为每个为dailypages创建的新列表项添加dailypage[totalPages-1]pageText.Add(新字符串),以使我的列表在列表中工作。我会发布"修复"的代码,但由于我对C#还很陌生,我相信你们这些老手会发现许多新手错误:)我还远远没有完成这个代码,但我想我会发布我发现的解决方案来解决我之前的问题。我从帖子中得到了一些有用的信息。

using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
namespace Books
{
    abstract class Book // Class prototype for a book from a text file
    {
        public string bookTitle { get; set; } // the title
        public string bookSubTitle { get; set; } // subtitle
        public string bookAuthor { get; set; }  // author
        protected string[] bookText { get; set; } // book's text
        protected int totalPages { get; set; } // Total number of pages
        public Boolean loadError = false;     // file not found marker
        abstract internal void loadPages(); // seperates pages
        // Generic class constructor
        public Book(string filename)
        {
            if (File.Exists(filename)) // does text file book exist?
                bookText = File.ReadAllLines(filename); //load bookText
            else
            {
                loadError = true;// File was not found
                ErrorMessage("File '"" + filename + "'" is missing.                             
                  'nClosing program.");
            }
        }
        // Displays an error message
        private static void ErrorMessage(string str)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(str);
            Console.ResetColor();
        }
        // Prototype class for a page
        protected abstract class Page
        {
            internal int pageNum { get; set; }
            internal string pageText { get; set;}
        }
    }
    // Class used specifically for the "Daily Reflections" book
    class DailyReflections : Book
    {
        List<dailyPage> dailypages = new List<dailyPage>();
        private DateTime today = DateTime.Now;
        // Organizes pages from bookText[] into dailypages list
        internal void loadPages()
        {
            DateTime date = new DateTime();
            DateTime date2 = new DateTime();
            string temptitle;
            StringBuilder str = new StringBuilder();
            for (int bookline = 0; bookline < bookText.LongLength;                    
              bookline++)
            {
                if (DateTime.TryParse(bookText[bookline], out date))
                {
                    bookline++;
                    temptitle = bookText[bookline].Trim();
                    while (!DateTime.TryParse(bookText[bookline], out                         
                      date2))
                    {
                        str.AppendLine(bookText[bookline]);
                        if (++bookline >= bookText.LongLength) break;
                    }
                    bookline--;
                    dailypages.Add(new dailyPage());
                    dailypages[totalPages].pageDate = date;
                    dailypages[totalPages].pageText = str.ToString();
                    dailypages[totalPages].pageNum = totalPages + 1;
                    dailypages[totalPages].pageTitle = temptitle;
                    str.Clear();
                    totalPages++;
                }
            }
        }
        // Class constructor unique to DailyReflections
        public DailyReflections() : base("Daily Reflections.txt")
        {
            this.bookTitle = "Daily Reflections";
            this.bookSubTitle = "";
            this.bookAuthor = "";
            loadPages();
        }
        // Display all lines of bookText
        public void printText()
        {
            foreach (dailyPage txt in dailypages)
            {
                Console.WriteLine(txt);
            }
        }
        // Page[] unique to DailyReflections
        protected class dailyPage : Page
        {
            internal DateTime pageDate { get; set; }
            internal string pageTitle { get; set; }
        }
    }
}