在列表对象中查找制表符时出错
本文关键字:制表符 出错 查找 列表 对象 | 更新日期: 2024-10-30 06:45:47
我正在使用C#,winforms应用程序。
我正在读取一个文本文件,其中每行都有按制表符划分的字段:
我将每一行放在名为 tic_string
的列表中。从这里开始,我尝试搜索每个列表对象,找到选项卡,并将每个字段放在自己的数组中。所以会有一个数组用于column a
、column b
、column c
...等。
问题是当我尝试在列表对象中查找选项卡时,它什么也找不到。 这是我的代码:
string[] tic_num = new string[row_counter];
string[] tic_title = new string[row_counter];
string[] tic_owner = new string[row_counter];
string[] tic_open_date = new string[row_counter];
int last_tab = 0;
int char_counter = 0;
int feild_counter = 1;
int feild_char_count = 1;
int current_row=0;
string temp_feild = "";
char temp_char;
char tab_char = ''t';
foreach (string tic_string_value in tic_string)
{
temp_char = tic_string_value[char_counter];
if (temp_char == tab_char)
{
Console.WriteLine("tab_found");
if (feild_char_count == 1)
{
temp_feild = "";
}
else
{
temp_feild = tic_string_value.Substring(last_tab, feild_char_count);
}
last_tab = char_counter;
feild_char_count = 0;
switch (feild_counter)
{
case 1:
tic_num[current_row] = temp_feild;
break;
case 2:
tic_title[current_row] = temp_feild;
break;
case 3:
tic_owner[current_row] = temp_feild;
break;
case 4:
tic_open_date[current_row] = temp_feild;
break;
}
}
current_row++;
feild_char_count++;
char_counter++;
if (feild_counter == 5)
feild_counter = 1;
}
对于如此简单的任务来说,您的代码似乎太复杂了。不要逐个字符解析每一行字符,只需使用String.Split
等辅助函数:
foreach (string tic_string_value in tic_string)
{
var parts = tic_string_value.Split(new [] { ''t' },
StringSplitOptions.RemoveEmptyEntries);
tic_num[current_row] = parts[0];
tic_title[current_row] = parts[1];
tic_owner[current_row] = parts[2];
tic_open_date[current_row] = parts[3];
current_row++;
}
首先,我从您的代码风格推断您可能熟悉 C/C++并且不熟悉 C#,因为这段代码具有特别"C++"的味道。它让我想起了我第一次自己跳转时自己的 C# 代码。
我很高兴您描述了您试图解决的问题,而不是简单地发布代码并询问在哪里可以找到错误,因为我认为您实际上可以更轻松地解决问题。
考虑以下代码(这假设您正在迭代此代码之外的每一行,并且我省略了您已经指定的一些变量声明):
int field_counter = 0;
foreach (var field in tic_string.Split(''t')) {
switch (field_counter++) {
case 0:
tic_num[current_row] = field;
break;
case 1:
tic_title[current_row] = field;
break;
case 2:
tic_owner[current_row] = field;
break;
case 3:
tic_open_date[current_row] = field;
break;
}
}
这利用了 C# 的简洁性并删除了相当多的代码行,这总是好的。String.Split 方法将为您处理大部分字符串拆分,因此无需手动完成所有操作并跟踪字符。
注意:我保留了某些字段名称的原始命名,尽管通常最好在 C# 代码中使用 CamelCase。
现在我从您的原始代码中注意到,您的数据中可能没有实际意义上的"行"(即由换行符拆分),而是您可能将数据完全分隔为制表符,并使用每行有固定数量的列来拆分行。
如果是这种情况,我是否可以建议以下代码块可以帮助您:
int i = 0;
foreach (var group in tic_string.GroupBy(x => i++ % 4)) {
int current_row = 0;
foreach (var field in group) {
switch (group.Key) {
case 0:
tic_num[current_row] = field;
break;
case 1:
tic_title[current_row] = field;
break;
case 2:
tic_owner[current_row] = field;
break;
case 3:
tic_open_date[current_row] = field;
break;
}
current_row++;
}
}
当然,现在您可能需要使这些块适应您的代码,而不是逐字使用它。我希望他们至少表现出对这个问题的不同思考方式。特别是,学习使用各种 LINQ 扩展方法和 LINQ 查询也将非常有帮助 - 它们是使 C# 代码如此快速且易于开发的一部分。
祝您好运解决您的问题!
您也可以使用列表而不是 4 个字符串数组:
public class ObjectToBeUsed
{
public Person(int num, string title, string owner, string opendate)
{
this.Num = num;
this.Title = title;
this.Owner = owner;
this.OpenDate = opendate;
}
private int _num;
public int Num
{
get { return _num; }
set { _num = value; }
}
private string _title;
public string Title
{
get { return _title; }
set { _title = value; }
}
private string _owner;
public string Owner
{
get { return _owner; }
set { _owner = value; }
}
private string _opendate;
public string OpenDate
{
get { return _opendate; }
set { _opendate = value; }
}
}
这是描述文本文件中每一行的类。
System.IO.StreamReader file = new System.IO.StreamReader("test.txt");
string currentLine = null;
List<ObjectToBeUsed> peopleList = new List<ObjectToBeUsed>();
while ((currentLine = file.ReadLine()) != null)
{
string[] tokens = Regex.Split(currentLine, @"'t");
peopleList.Add(new ObjectToBeUsed(Convert.ToInt32(tokens[0]), tokens[1], tokens[2], tokens[3]));
}
代码非常不言自明,但如果您需要任何进一步的解释,请继续。