What is simpliest way to get Line number from char position in String?

前端 未结 4 1476
旧巷少年郎
旧巷少年郎 2020-12-15 11:45

What is simpliest way to get Line number from char position in String in C#? (or get Position of line (first char in line) ) Is there any built-in function ? If there are n

4条回答
  •  孤城傲影
    2020-12-15 12:03

    If you are going to call the function many times on the same long string, this class can be usefull. It caches the new line positions, so that later it can perform O(log (line breaks in string)) lookup for GetLine and O(1) for GetOffset.

    public class LineBreakCounter
    {
        List lineBreaks_ = new List();
        int length_;
    
        public LineBreakCounter(string text)
        {
            if (text == null)
                throw new ArgumentNullException(nameof(text));
    
            length_ = text.Length;
            for (int i = 0; i < text.Length; i++)
            {
                if (text[i] == '\n')
                    lineBreaks_.Add(i);
    
                else if (text[i] == '\r' && i < text.Length - 1 && text[i + 1] == '\n')
                    lineBreaks_.Add(++i);
            }
        }
    
        public int GetLine(int offset)
        {
            if (offset < 0 || offset > length_)
                throw new ArgumentOutOfRangeException(nameof(offset));
    
            var result = lineBreaks_.BinarySearch(offset);
            if (result < 0)
                return ~result;
            else
                return result;
        }
    
        public int Lines => lineBreaks_.Count + 1;
    
        public int GetOffset(int line)
        {
            if (line < 0 || line >= Lines)
                throw new ArgumentOutOfRangeException(nameof(line));
    
            if (line == 0)
                return 0;
    
            return lineBreaks_[line - 1] + 1;
        }
    }
    

    Here is my test case:

    [TestMethod]
    public void LineBreakCounter_ShouldFindLineBreaks()
    {
        var text = "Hello\nWorld!\r\n";
        var counter = new LineBreakCounter(text);
    
        Assert.AreEqual(0, counter.GetLine(0));
        Assert.AreEqual(0, counter.GetLine(3));
        Assert.AreEqual(0, counter.GetLine(5));
        Assert.AreEqual(1, counter.GetLine(6));
        Assert.AreEqual(1, counter.GetLine(8));
        Assert.AreEqual(1, counter.GetLine(12));
        Assert.AreEqual(1, counter.GetLine(13));
        Assert.AreEqual(2, counter.GetLine(14));
    
        Assert.AreEqual(3, counter.Lines);
        Assert.AreEqual(0, counter.GetOffset(0));
        Assert.AreEqual(6, counter.GetOffset(1));
        Assert.AreEqual(14, counter.GetOffset(2));
    }
    

提交回复
热议问题