想要实现以下目标: 1.将richtextbox中的字符串以定长字节进行拆分并按数组保存.
比如说定长为4字节 则 "ABCDEF"拆分为"ABCD"和"EF"
包含中文时 "我爱北京"拆分为 "我爱"和"北京"
这些倒比较好解决,但是当字符串中包含换行符的时候应该怎么处理?
求好的建议 2.当单击richtextbox的时候,以光标所在位置自动定位上面拆分的数组.
该如何实现?
比如说定长为4字节 则 "ABCDEF"拆分为"ABCD"和"EF"
包含中文时 "我爱北京"拆分为 "我爱"和"北京"
这些倒比较好解决,但是当字符串中包含换行符的时候应该怎么处理?
求好的建议 2.当单击richtextbox的时候,以光标所在位置自动定位上面拆分的数组.
该如何实现?
比如说 "AB\nCDEF"就拆分成 "AB"和"CDEF"
另外
“ABC哈哈”怎么拆?
“A哈B哈C”怎么拆?
比如说LS朋友举的例子"ABC哈哈"=>"ABC"和"哈哈"
"A哈B哈C"=>"A哈"和"B哈"和"C哈"抱歉啊诸位 问题提的不仔细 呵呵
string[] lines = richTextBox1.Lines;
得到行的数组暂时可以把问题简化为对单行数据的处理还有个问题,是只有字母和汉字,还是说什么字符都可以有,如果有标点符号,是否全角和半角都可能有吗
刚刚没考虑那么多 就把问题提出来了
现在考虑假设包含所有字符吧
应该都好解决 只是不明白各种转义字符该怎么操作还有,第二个问题有没有思路~?
只要点在拆分元素之间,则选择前一个元素..我考虑是用一个结构,其中包含字符在richtextbox中的位置 尝试中..
{
char c;
int count = 0;
int len = 0; List<string> list = new List<string>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < src.Length; i++)
{
c = src[i];
len = Encoding.Default.GetBytes(new char[] { c }).Length; if (count == 0)
{
sb.Append(c);
count += len;
}
else if (count == 1)
{
sb.Append(c);
count += len;
}
else if (count == 2)
{
sb.Append(c);
count += len;
}
else if (count == 3)
{
if (len == 1)
{
sb.Append(c);
list.Add(sb.ToString());
sb = new StringBuilder();
count = 0;
}
else if (len == 2)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = 2;
}
}
else if (count == 4)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = len;
} if (i == src.Length - 1 && sb.ToString().Length > 0)
list.Add(sb.ToString());
}
return list;
}
调用:
string yourStr = "ABCDEF我爱北京G我爱H北I京J";
List<string> list = SplitByFour(yourStr);
foreach (string s in list)
{
richTextBox2.Text += s + "\n";
}
输出:
ABCD
EF我
爱北
京G
我爱
H北I
京J
{
int index = richTextBox1.SelectionStart;
int start = -1;
int end = -1; string[] lines = richTextBox1.Lines; int lineNum = richTextBox1.GetLineFromCharIndex(index); string yourStr = string.Empty;
if (lineNum < lines.Length)
{
yourStr = lines[lineNum];
} int preCount = 0;
for (int i = 0; i < lineNum; i++)
{
preCount += lines[i].Length + 1;
} List<int> location = new List<int>();
List<string> list = SplitByFour(yourStr, ref location); int lineIndex = index - preCount;
for (int i = 0; i < location.Count; i++)
{
if (location[i] < lineIndex)
continue;
else if (location[i] == lineIndex)
{
if (i == 0)
{
start = end = 0;
break;
}
else
{
start = location[i - 1];
end = location[i];
break;
}
}
else if (location[i] > lineIndex)
{
start = location[i - 1];
end = location[i];
break;
}
} start += preCount;
end += preCount; if (start != -1 && end != -1)
{
richTextBox1.Select(start, end - start);
}
}分割的方法也要做下改动private List<string> SplitByFour(string src, ref List<int> location)
{
char c;
int count = 0;
int len = 0; List<string> list = new List<string>();
location = new List<int>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < src.Length; i++)
{
c = src[i];
len = Encoding.Default.GetBytes(new char[] { c }).Length; if (count == 0)
{
sb.Append(c);
count += len;
location.Add(i);
}
else if (count == 1)
{
sb.Append(c);
count += len;
}
else if (count == 2)
{
sb.Append(c);
count += len;
}
else if (count == 3)
{
if (len == 1)
{
sb.Append(c);
list.Add(sb.ToString());
sb = new StringBuilder();
count = 0;
}
else if (len == 2)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = 2;
location.Add(i);
}
}
else if (count == 4)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = len;
location.Add(i);
} if (i == src.Length - 1 && sb.ToString().Length > 0)
{
list.Add(sb.ToString());
location.Add(src.Length);
}
}
return list;
}
当然,
string[] lines = richTextBox1.Lines;
这一行代码不应该放在
richTextBox1_Click
事件内的,否则每点一次都要去生成一次数组,太浪费资源了,至于应该放在哪里,要根据你的实际需求来定,太晚了,这里就没有处理另外就是通过鼠标点击位置,查找应该选中的内容的算法,应该有更好的算法,只是我的算法基础基本上相当于0,呵呵,楼主或是有对这方面感兴趣的朋友,给优化一下吧
int lineNum = richTextBox1.GetLineFromCharIndex(index);
是按照视觉上的行来取行号的,也就是超过richTextBox的宽度折行,但没有到\n的,它算做多行了楼主说下你的实际应用情况,如果说按“\n”分割的行,宽度不会达到richTextBox1的宽度,那么用上面的代码即可,否则还需要再改下睡了,白天再来改...
我爱北
京G我爱
H北I京J此时比如鼠标点在第一行的EF之间,应如何选中,是选中“EF我”,还是“EF”
不知道是不是我理解错误,我上面的做法是当鼠标当击时,自动选中鼠标所在范围的词,如果仅仅是找出分割后数组中对应的这个词,而不需要选中它,那就很简单了
tempStr=tempStr.Replace("\n","");把换行符过滤掉
因richTextBox的实际宽度,显示为 ABCDEF
我爱北
京G我爱
H北I京J如鼠标点在第一行的EF之间,应如何选中,是选中“EF我”,只按定长字节来选择数组中对应的词
加入richtextbox中输入字符的字节数刚好是4的倍数,比如说
"1234567890123456"的时候,最后4个字符"3456"无法选择,正在检查
{
if(i!=location.Count-1)
{
continue;
}
else
{
start = location[i];
end = yourStr.Length;
break;
}
}
{
int index = richTextBox1.SelectionStart; //光标所在位置索引
int start = -1; //应选中元素起始索引
int end = -1; //应选中元素结束索引 string[] lines = richTextBox1.Lines; //得到所有按“\n”分割行数组,不应放在此事件中 int lineNum = 0; //光标所在行的行索引,向前搜索找到“\n”即加1
for (int i = index; i > 0; i--)
{
if (richTextBox1.Text[i-1] == '\n')
lineNum++;
} int preCount = 0; //光标所在行开始位置索引,向前搜索,遇到第一个“\n”退出循环
for (int i = index; i >0 ; i--)
{
if (richTextBox1.Text[i - 1] == '\n')
{
preCount = i;
break;
}
} string yourStr = string.Empty; //光标所在行字符串
if (lineNum < lines.Length)
{
yourStr = lines[lineNum];
} List<int> location = new List<int>(); //分割后各元素起始及结束位置过引
List<string> list = SplitByFour(yourStr, ref location); //分割后元素集合 int lineIndex = index - preCount; //由于用location来计算,此处理到光标所在行光标的索引 for (int i = 0; i < location.Count; i++) //计算光标所在位置的元素起始和结束索引,此算法应该可以优化
{
if (location[i] < lineIndex)
continue;
else if (location[i] == lineIndex)
{
if (i == 0)
{
start = end = 0;
break;
}
else
{
start = location[i - 1];
end = location[i];
break;
}
}
else if (location[i] > lineIndex)
{
start = location[i - 1];
end = location[i];
break;
}
} start += preCount; //得到应选中元素在整个字符串中的起始索引
end += preCount; //得到应选中元素在整个字符串中的结束索引 if (start != -1 && end != -1)
{
richTextBox1.Select(start, end - start); //选中该元素
}
}
//分割方法
private List<string> SplitByFour(string src, ref List<int> location)
{
char c;
int count = 0;
int len = 0; List<string> list = new List<string>();
location = new List<int>(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < src.Length; i++)
{
c = src[i];
len = Encoding.Default.GetBytes(new char[] { c }).Length; if (count == 0)
{
sb.Append(c);
count += len;
location.Add(i);
}
else if (count == 1)
{
sb.Append(c);
count += len;
}
else if (count == 2)
{
sb.Append(c);
count += len;
}
else if (count == 3)
{
if (len == 1)
{
sb.Append(c);
list.Add(sb.ToString());
sb = new StringBuilder();
count = 0;
}
else if (len == 2)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = 2;
location.Add(i);
}
}
else if (count == 4)
{
list.Add(sb.ToString());
sb = new StringBuilder();
sb.Append(c);
count = len;
location.Add(i);
} if (i == src.Length - 1) //排除bug改动的代码,原来整除时不进入此分支
{
if (sb.ToString().Length > 0)
list.Add(sb.ToString());
location.Add(src.Length);
}
}
return list;
}
这里现在存在的问题一是
string[] lines = richTextBox1.Lines;
这个得到行数组的代码不应放在richTextBox1_Click事件里,至于应该放在哪里,视你的具体情况而定二是计算该选中元素起始和结束索引的算法,应该是可以优化的,我的算法太差,留给楼主或是感兴趣的朋友优化吧
--------------
离高手差着十万八千里呢不过现在思想基本上转变过来了,看到一些问题,首先想到的不再是正则,而是有限状态机了^o^这个帖里,分割时用到了有限状态机的思想,不过做的也不是很地道,哈有限状态机有人教了,算法上没人教,只能自己摸索,这个帖里用到的算法,自己感觉并不好,但目前也只能做到这种程度了
测试成功,散分~