想要实现以下目标:    1.将richtextbox中的字符串以定长字节进行拆分并按数组保存.
     比如说定长为4字节  则  "ABCDEF"拆分为"ABCD"和"EF"
                    包含中文时  "我爱北京"拆分为 "我爱"和"北京"
     这些倒比较好解决,但是当字符串中包含换行符的时候应该怎么处理?
     求好的建议     2.当单击richtextbox的时候,以光标所在位置自动定位上面拆分的数组.
     该如何实现?

解决方案 »

  1.   

    如果包含换行符的话就直接截取
    比如说 "AB\nCDEF"就拆分成 "AB"和"CDEF"
      

  2.   

    先用s.Split(new char[] { '\r', '\n' });分成行在处理
    另外
    “ABC哈哈”怎么拆?
    “A哈B哈C”怎么拆?
      

  3.   

    如果超出4个字节就舍去~
    比如说LS朋友举的例子"ABC哈哈"=>"ABC"和"哈哈"
    "A哈B哈C"=>"A哈"和"B哈"和"C哈"抱歉啊诸位 问题提的不仔细 呵呵
      

  4.   

    可以用
    string[] lines = richTextBox1.Lines;
    得到行的数组暂时可以把问题简化为对单行数据的处理还有个问题,是只有字母和汉字,还是说什么字符都可以有,如果有标点符号,是否全角和半角都可能有吗
      

  5.   

    谢谢 lxcnn 关注 
    刚刚没考虑那么多 就把问题提出来了
    现在考虑假设包含所有字符吧
    应该都好解决 只是不明白各种转义字符该怎么操作还有,第二个问题有没有思路~?
      

  6.   

    呵呵 是比较怪的需求 最近做一个LCD写屏控制 需要这样..大家帮忙 谢谢
      

  7.   

    再细化一下  如lxcnn兄所问
    只要点在拆分元素之间,则选择前一个元素..我考虑是用一个结构,其中包含字符在richtextbox中的位置 尝试中..
      

  8.   

    处理单行的方法,处理多行循环或是写到方法内也可以private List<string> SplitByFour(string src)
    {
        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
      

  9.   

    对比了下  LXCNN兄的解决办法要方便得多了 佩服佩服~
      

  10.   

    总算是实现这一功能了,对我来说还真是一个不小的挑战private void richTextBox1_Click(object sender, EventArgs e)
    {
        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,呵呵,楼主或是有对这方面感兴趣的朋友,给优化一下吧
      

  11.   

    如有需要,明天再来做下注释吧,睡了zzzZZZ~~~
      

  12.   

    -_-#,又测了下,发现一个BUG,就是
    int lineNum = richTextBox1.GetLineFromCharIndex(index);
    是按照视觉上的行来取行号的,也就是超过richTextBox的宽度折行,但没有到\n的,它算做多行了楼主说下你的实际应用情况,如果说按“\n”分割的行,宽度不会达到richTextBox1的宽度,那么用上面的代码即可,否则还需要再改下睡了,白天再来改...
      

  13.   

    又看了下,这个问题还是需要楼主来明确的举例来说吧,以下是按“\n”定义的一行ABCDEF我爱北京G我爱H北I京J但因richTextBox的实际宽度,显示为ABCDEF
    我爱北
    京G我爱
    H北I京J此时比如鼠标点在第一行的EF之间,应如何选中,是选中“EF我”,还是“EF”
    不知道是不是我理解错误,我上面的做法是当鼠标当击时,自动选中鼠标所在范围的词,如果仅仅是找出分割后数组中对应的这个词,而不需要选中它,那就很简单了
      

  14.   

    这个问题可以利用lucene里面的一个分词类比较容易实现^_^
      

  15.   

    string tempStr=richtextbox.Text;
    tempStr=tempStr.Replace("\n","");把换行符过滤掉
      

  16.   

    老兄起的真早,这段时间眼睛刚做完手术,久看电脑实在受不了,昨晚早早休息去了...如lxcnn的问题, 
              因richTextBox的实际宽度,显示为           ABCDEF
               我爱北
               京G我爱
               H北I京J如鼠标点在第一行的EF之间,应如何选中,是选中“EF我”,只按定长字节来选择数组中对应的词
      

  17.   

    上面的代码发现了一个BUG  
    加入richtextbox中输入字符的字节数刚好是4的倍数,比如说
    "1234567890123456"的时候,最后4个字符"3456"无法选择,正在检查
      

  18.   

    尝试了下,将这段代码改动了下,显示正常if (location[i] < lineIndex)
                    {
                        if(i!=location.Count-1)
                        {
                            continue;
                        }
                        else
                        {
                            start = location[i];
                            end = yourStr.Length;
                            break;
                        }
                    }
      

  19.   

    搞定,这回应该是可以了,上面说的bug也排除了,不过不是用你这种方式,哈,是分割是一个逻辑问题,稍改下就好了,已经测试过,楼主再测下吧private void richTextBox1_Click(object sender, EventArgs e)
    {
        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事件里,至于应该放在哪里,视你的具体情况而定二是计算该选中元素起始和结束索引的算法,应该是可以优化的,我的算法太差,留给楼主或是感兴趣的朋友优化吧
      

  20.   

    过客按照iv思路,如期成为状态机高手中……
    --------------
    离高手差着十万八千里呢不过现在思想基本上转变过来了,看到一些问题,首先想到的不再是正则,而是有限状态机了^o^这个帖里,分割时用到了有限状态机的思想,不过做的也不是很地道,哈有限状态机有人教了,算法上没人教,只能自己摸索,这个帖里用到的算法,自己感觉并不好,但目前也只能做到这种程度了
      

  21.   

    感谢lxcnn兄及各位同仁~
    测试成功,散分~