我的程序(C#.NET)存在多个问题,并且不知道导致它们的原因。
该程序旨在按名字,姓氏和生日按升序和降序对名称和生日(格式为first name,last name,DD/MM/YYYY
)的列表进行排序。它还有其他尚未实现的功能。
第一个问题出在quikSortStr
方法中。程序在第一个if
块中崩溃,说明j
超出了数组的范围。无论是否mode == "asc"
,都会发生这种情况。
第二个也是更令人困惑的问题是,当从文本文件加载值时,first
和last
的每个奇数索引值都将为空,而每个奇数索引值为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 :(得分:1)
您必须在quikSortStr
循环内的if (i <= j)
方法中更改以下代码
DateTime holdoverBeta = bDay[i];
bDay[i] = bDay[j];
bDay[j] = holdoverBeta;
i++;
j--;//was: j++;
这将解决问题。
答案 1 :(得分: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();
通过消除所有现在的null类型值来缩短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)
可以完全避免。在原始代码中,我将替换
StreamReader file = new StreamReader(name);
lines = file.ReadToEnd().Split('\n');
与
lines = File.ReadAllLines(name);
并添加using System.IO;
。