2013-05-05 44 views
1

我遇到了多个与我的程序(C#.NET)有关的问题,不知道是什么导致了它们。快速搜索超出数组范围和令人困惑的数组行为

该程序旨在按名称,姓氏和生日的升序和降序排列名称和生日的列表(格式为first name,last name,DD/MM/YYYY)。还有其他尚未实施的功能。

第一个问题是在quikSortStr方法中。该程序在第一个if块中崩溃,说明j超出了数组的范围。无论是否mode == "asc"都会发生这种情况。

第二,和更混乱的问题是,当所述值从文本文件加载的firstlast每奇数索引值将是零,而bDay每个奇数索引值将是1/1/0001

我已经包括下面的完整程序供参考,快速排序方法和使用并行数组是必需的。我对缺乏评论表示歉意。

在此先感谢您的帮助。我完全被难住了。

namespace Names_Arrays 
{ 
public partial class frmNamArrays : Form 
{ 
    System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-CA"); 
    string[] first; 
    string[] last; 
    DateTime[] bDay; 
    string order = "asc"; 
    string format = "d/M/yyyy"; 

    public frmNamArrays() 
    { 
     InitializeComponent(); 
    } 
    private void write() 
    { 
     string[] lines = new string[first.Length]; 

     for (int i = 0; i < lines.Length; i++) 
      lines[i] = first[i] + ',' + last[i] + ',' + bDay[i].ToString(format); 

     txtbxNames.Clear(); 
     txtbxNames.Lines = lines; 
    } 

    private void load() 
    { 
     string[] lines = txtbxNames.Lines; 

     first = new string[lines.Length]; 
     last = new string[lines.Length]; 
     bDay = new DateTime[lines.Length]; 

     int i = 0; 
     foreach (string line in lines) 
     { 
      string[] data = line.Split(','); 

      //There aren't any lines that split to a string[] of length less than three, 
      //but for some reason the program kept believing there are. 
      //patched that leak. 

      if (data.Length == 3) 
      { 
       first[i] = data[0]; 
       last[i] = data[1]; 
       bDay[i] = Convert.ToDateTime(data[2], culture); 
      } 
      i++; 
     } 
    } 
    public DateTime[] quikSortTim(DateTime[] primary, string mode, int left, int right) 
    { 
     if (primary.Length > 1) 
     { 
      int i = left, j = right; 
      DateTime pivot = primary[left + (right - left)/2]; 

      while (i <= j) 
      { 
       if (mode == "asc") 
       { 
        while (DateTime.Compare(primary[i], pivot) < 0) 
         i++; 
        while (DateTime.Compare(primary[j], pivot) > 0) 
         j--; 
       } 
       else 
       { 
        while (DateTime.Compare(primary[i], pivot) > 0) 
         i++; 
        while (DateTime.Compare(primary[j], pivot) < 0) 
         j--; 
       } 
       if (i <= j) 
       { 
        DateTime holdoverB = primary[i]; 
        primary[i++] = primary[j]; 
        primary[j--] = holdoverB; 

        string holdover = last[i - 1]; 
        last[i] = last[j + 1]; 
        last[j] = holdover; 

        holdover = first[i - 1]; 
        first[i] = first[j + 1]; 
        first[j] = holdover; 

       } 
      } 
      if (j > left) 
       primary = quikSortTim(primary, mode, left, j); 
      if (i < right) 
       primary = quikSortTim(primary, mode, i, right); 
     } 
     return primary; 
    } 

    public string[] quikSortStr(string[] primary, string type, string mode, int left, int right) 
    { 
     if (primary.Length > 1) 
     { 
      int i = left, j = right; 
      string pivot = primary[left + (right - left)/2]; 

      while (i <= j) 
      { 
       if (mode == "asc") 
       { 
        while (String.Compare(primary[i], pivot) < 0) 
         i++; 
        while (String.Compare(primary[j], pivot) > 0) 
         j--; 
       } 
       else 
       { 
        while (String.Compare(primary[i], pivot) > 0) 
         i++; 
        while (String.Compare(primary[j], pivot) < 0) 
         j--; 
       } 
       if (i <= j) 
       { 
        string holdover = primary[i]; 
        primary[i] = primary[j]; 
        primary[j] = holdover; 
        if (type == "first") 
        { 
         holdover = last[i]; 
         last[i] = last[j]; 
         last[j] = holdover; 
        } 
        else 
        { 
         holdover = first[i]; 
         first[i] = first[j]; 
         first[j] = holdover; 
        } 
        DateTime holdoverBeta = bDay[i]; 
        bDay[i] = bDay[j]; 
        bDay[j] = holdoverBeta; 
        i++; 
        j++; 
       } 
      } 
      if (j > left) 
       primary = quikSortStr(primary, type, mode, left, j); 
      if (i < right) 
       primary = quikSortStr(primary, type, mode, i, right); 
     } 
     return primary; 
    } 

    private void frmNamArrays_SizeChanged(object sender, EventArgs e) 
    { 
     txtbxNames.Width = this.Width - 40; 
     txtbxNames.Height = this.Height - 157; 
    } 

    private void btnSort_Click(object sender, EventArgs e) 
    { 
     load(); 

     switch (cbobxCategory.Text) 
     { 
      case ("First Name"): 
       first = quikSortStr(first, "first", order, 0, first.Length - 1); 
       break; 
      case ("Last Name"): 
       last = quikSortStr(last, "last", order, 0, last.Length - 1); 
       break; 
      case ("Birthday"): 
       bDay = quikSortTim(bDay, order, 0, bDay.Length - 1); 
       break; 
      default: 
       break; 
     } 

     write(); 
    } 

    private void cbobxOrder_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     if (cbobxOrder.Text == "Ascending") 
      order = "asc"; 
     else 
      order = "desc"; 
    } 

    private void displayfile(string name) 
    { 
     StreamReader fileData = new StreamReader(name); 

     txtbxNames.Lines = fileData.ReadToEnd().Split('\n'); 

    } 

    private void mnuOpen_Click(object sender, EventArgs e) 
    { 
     OpenFileDialog open = new OpenFileDialog(); 
     open.Filter = "Text Files|*.txt"; 
     open.Title = "Select a text file..."; 

     if (open.ShowDialog() == DialogResult.OK && open.FileName != "") 
      displayfile(open.FileName); 
    } 

    private void mnuExit_Click(object sender, EventArgs e) 
    { 
     this.Close(); 
    } 
} 
} 
+0

您是否考虑编写单元测试?将你的排序逻辑分成它自己的类,然后用样本数据写一个测试。你有没有考虑过使用Person类? – 2013-05-05 04:09:02

回答

0

感谢saravanan指出我的第一个错误。超出范围的错误是由错误方向的意外增量j造成的。固定方法是

public DateTime[] quikSortTim(DateTime[] primary, string mode, int left, int right) 
    { 
     if (primary.Length > 1) 
     { 
      int i = left, j = right; 
      DateTime pivot = primary[left + (right - left)/2]; 

      while (i <= j) 
      { 
       if (mode == "asc") 
       { 
        while (DateTime.Compare(primary[i], pivot) < 0) 
         i++; 
        while (DateTime.Compare(primary[j], pivot) > 0) 
         j--; 
       } 
       else 
       { 
        while (DateTime.Compare(primary[i], pivot) > 0) 
         i++; 
        while (DateTime.Compare(primary[j], pivot) < 0) 
         j--; 
       } 
       if (i <= j) 
       { 
        DateTime holdoverB = primary[i]; 
        primary[i] = primary[j]; 
        primary[j] = holdoverB; 

        string holdover = last[i]; 
        last[i] = last[j]; 
        last[j] = holdover; 

        holdover = first[i]; 
        first[i] = first[j]; 
        first[j] = holdover; 

        i++; 
        j--; 
       } 
      } 
      if (j > left) 
       primary = quikSortTim(primary, mode, left, j); 
      if (i < right) 
       primary = quikSortTim(primary, mode, i, right); 
     } 
     return primary; 
    } 

    public string[] quikSortStr(string[] primary, string type, string mode, int left, int right) 
    { 
     if (primary.Length > 1) 
     { 
      int i = left, j = right; 
      string pivot = primary[left + (right - left)/2]; 

      while (i <= j) 
      { 
       if (mode == "asc") 
       { 
        while (String.Compare(primary[i], pivot) < 0) 
         i++; 
        while (String.Compare(primary[j], pivot) > 0) 
         j--; 
       } 
       else 
       { 
        while (String.Compare(primary[i], pivot) > 0) 
         i++; 
        while (String.Compare(primary[j], pivot) < 0) 
         j--; 
       } 
       if (i <= j) 
       { 
        string holdover = primary[i]; 
        primary[i] = primary[j]; 
        primary[j] = holdover; 
        if (type == "first") 
        { 
         holdover = last[i]; 
         last[i] = last[j]; 
         last[j] = holdover; 
        } 
        else 
        { 
         holdover = first[i]; 
         first[i] = first[j]; 
         first[j] = holdover; 
        } 
        DateTime holdoverBeta = bDay[i]; 
        bDay[i] = bDay[j]; 
        bDay[j] = holdoverBeta; 
        i++; 
        j--; 
       } 
      } 
      if (j > left) 
       primary = quikSortStr(primary, type, mode, left, j); 
      if (i < right) 
       primary = quikSortStr(primary, type, mode, i, right); 
     } 
     return primary; 
    } 

我没有找到第二个问题的解决方案本身。但是,我确实发现所有添加了",,1/1/0001"的元素都被添加了,并且没有替换任何名称。使用这个,我只在数组lines中加入了不包含"1/1/0001"的索引值。然后,我使用lines = lines.Where(s => s != null).ToArray();通过消除所有现在为空类型的值来缩短lines。修改后的功能如下。

private void write() 
    { 
     string[] lines = new string[first.Length]; 

     for (int i = 0; i < lines.Length; i++) 
      if (bDay[i].ToString(format) != "1/1/0001") 
       lines[i] = first[i] + ',' + last[i] + ',' + bDay[i].ToString(format); 

     lines = lines.Where(s => s != null).ToArray(); 

     txtbxNames.Clear(); 
     txtbxNames.Lines = lines; 
    } 

感谢您的帮助。我找到了我的解决方案资源here

编辑:这似乎是StreamReader.ReadToEnd()固有的问题。我不知道为什么,但可以通过使用System.IO.File.ReadAllLines(filepath)完全避免。在最初的代码中,我将与

lines = File.ReadAllLines(name); 

更换

StreamReader file = new StreamReader(name); 
lines = file.ReadToEnd().Split('\n'); 

,并添加using System.IO;

+0

对于您的实物信息,默认情况下,Sort API在内部使用.Net中的QuickSort。感谢您发布解决方案,供他人作为参考。 – Saravanan 2013-05-06 04:48:47

+0

这不是一个解决方案作为解决方法,但谢谢。不幸的是,我还需要从头开始编写我的排序算法,但是当我没有这些条件时,我会记住这一点。 – user1576628 2013-05-06 22:55:12

1

你要更改代码为下文quikSortStr方法if (i <= j)循环

DateTime holdoverBeta = bDay[i]; 
    bDay[i] = bDay[j]; 
    bDay[j] = holdoverBeta; 
    i++; 
    j--;//was: j++; 

内,这将解决这个问题。

+0

我不敢相信我做到了。 – user1576628 2013-05-05 15:59:08