您的位置:首页 > 编程语言 > C#

c#中索引器实验案例及相关算法和类型设计的思考

2012-06-08 12:38 323 查看
案例是要实现一个对文档文本进行字符处理,并能筛选分离出文档中的单词,且可以以序列索引来对其中的单词进行访问和修改

完整代码

View Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 索引2
{
class Program
{
static void Main(string[] args)
{
Document mydoc = new Document("Hello,I am a Coder!");
for (int i = 0; i < mydoc.Words.Count; i++)
Console.Write(mydoc.Words[i]+" ");
}
}

class Document
{
private char[] TextArray;//声明一个char[]数组,用于存储数据
public WordCollection Words;//声明一个内部WordCollection类型的字段,作为索引属性
public Document(string initialStr)//构造函数
{
TextArray = initialStr.ToCharArray();
Words = new WordCollection(this);//以当前实例对象初始化改对象的字段属性
}

public class WordCollection//用于获得文档中单词集合的类
{
readonly Document document;
internal WordCollection(Document d)
{
document = d;
}
private bool Getword(char[] text,int begin,int wordcount,out int start,out int length)
{
int end = text.Length;
int count = 0;//初始化符号或空格个数为0
int inword = -1;//初始化inword为-1,作用是提供单词首字母的指针和空格或数字的判别
start = length = 0;//初始化单词位置和长度为0
for (int i = begin; i <= end; ++i)//由外部参数begin开始,遍历字符数组
{
bool isLetter = i < end && Char.IsLetterOrDigit(text[i]);//如果非末尾或为字母或数字,则返回true

if (inword >= 0)//判读inword是否重置,可以用于跳过空格或符号
{
if (!isLetter)//如果为空格或者符号,且前一个字符为单词的末尾
{
//与索引器的index值(wordcount)进行判断,这里count遇到空格或符号时才会叠加,
//而wordcount则表示单词的索引值,则表示未达到指定位置单词是不会返回的,PS:之所以可以比较,是因为索引值是从0开始计算的
if (count++ == wordcount)
{
start = inword;//获取inword为单词的起始值位置
length = i - inword;//以当前符号或空格位置减去单词起始位置得到单词长度
return true;//返回true并退出
}
//当遇到空格或符号时,又不是指定的单词索引处,则将inword重置为-1
inword = -1;
}
}
else//这里只有为初始状态或当前一个字符为空格或数字才执行
{
if (isLetter)//如果为字母或者数字
inword = i;//如果inword为默认值-1或被重置,且当前为字符,即将字符的索引值赋予inword
}
}
return false;//指定位置不存在单词,返回false
}
public string this[int index]//索引器
{
get
{
int start, length;
if (Getword(document.TextArray, 0, index, out start, out length))
{
return new string(document.TextArray, start, length);
}
else
throw new IndexOutOfRangeException();
}
set
{
int start, length;
if (Getword(document.TextArray, 0, index, out start, out length))
{
if (length == value.Length)
{
Array.Copy(value.ToCharArray(), 0, document.TextArray, start, length);
}
else
{
char[] newText=new char[document.TextArray.Length+value.Length-length];
Array.Copy(document.TextArray, 0, newText, 0, start);
Array.Copy(value.ToCharArray(),0,newText,start,value.Length);
Array.Copy(document.TextArray, start + length, newText, start + value.Length, document.TextArray.Length - start - length);
document.TextArray = newText;
}
}
else
{
throw new IndexOutOfRangeException();
}
}
}

public int Count
{
get
{
int count = 0, start = 0, length = 0;
while (Getword(document.TextArray, start + length, 0, out start, out length))//利用(start+length)定位到前一个单词之后一个字符所在的位置
++count;//累加所找到的单词的数目
return count;
}
}

}

}
}


知识整理

1.索引器的使用适合于具有序列数组性质的数据类型,并要在类型中声明一个可以储存序列数组的字段,例如:

class Document
{
private char[] TextArray;//声明一个char[]数组,用于存储数据
/*...*/
}


2.索引器返回的数据类型与本身的数据类型无关,可以自定义返回类型

class Document
{
public string this[int index]//索引器,返回string类型数据
{
get
{/*...*/}
}
}


3.主类中声明的内部类型,可以作为主类的字段或属性来使用

class Document
{
private char[] TextArray;//声明一个char[]数组,用于存储数据
public WordCollection Words;//声明一个内部WordCollection类型的字段,作为索引属性
public Document(string initialStr)//构造函数
{
TextArray = initialStr.ToCharArray();
Words = new WordCollection(this);//以当前实例对象初始化改对象的字段属性
}

public class WordCollection//用于获得文档中单词集合的类
{
/*....*/
}
}


4.利用out进行传址引用的方式传递参数时,可以帮助外部参数初始化,并且可以继续给其他的方法函数继续调用

public string this[int index]//索引器
{
get
{
int start, length;//声明2个参数
if (Getword(document.TextArray, 0, index, out start, out length))//利用getword判断是否含有单词,并返回start和length的值
{
return new string(document.TextArray, start, length);//将start和length的值代入string方法中,并返回值
}
else
throw new IndexOutOfRangeException();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: