繁体   English   中英

indexof和substring的问题

[英]Issue with indexof and substring

现在,在我通过帮助解决之后,在一个小文本文件中从两个标签之间获取文本,我创建的文本仅用于测试4行。 现在我想创建一个新的文本文件,其中包含原始文件的内容,但是在每个我发现标签之间的文本的地方,我想看空格空字符串。 因此,如果原始文本文件现在看起来像这样:

daniel<Text>THISISOUTisthere</Text>
<Text>hellobye</Text>
<Text>danielTHISishereandnotthere</Text>
danie <Text> is THIS here and not THERE</Text>

所以新文件应该如下所示:

daniel<Text>                </Text>
<Text>        </Text>
<Text>                            </Text>
danie <Text>                           </Text>

这是现在不起作用的代码。 我使用了一些帮助变量,但是在线上运行此代码时出现错误:

string hh = f.Substring(lastIndex, currentIndex);

错误说:索引和长度必须引用字符串中的位置。 参数名称:长度

这是完整的代码,现在不起作用:

private void test()
        {
            w = new StreamWriter(@"d:\testFile.txt");
            int currentLength;
            int currentIndex;
            int lastIndex = 0;
            string startTag = "<Text>";
            string endTag = "</Text>";
            int startTagWidth = startTag.Length;
            //int endTagWidth = endTag.Length;
            index = 0;
            while (true)
            {
                index = f.IndexOf(startTag, index);
                if (index == -1)
                {
                    break;
                }
                // else more to do - index now is positioned at first character of startTag    
                int start = index + startTagWidth;
                currentIndex = start;
                index = f.IndexOf(endTag, start+1);
                if (index == -1)
                {
                    break;
                }
                // found the endTag    
                string g = f.Substring(start, index - start - 1);
                currentLength = index - start - 1;
                string hh = f.Substring(lastIndex, currentIndex);
                w.WriteLine(hh);
                lastIndex = currentIndex + currentLength;
                listBox1.Items.Add(g);
            } 
        }

请帮我这个代码。

substring将length作为其第二个参数而不是索引位置,因此它应该是

string hh = f.Substring(lastIndex, currentIndex-lastIndex); 

另外你要砍掉太多的字符,你想改变currentLength = index - start -1 to currentLength = index - start

最后使用Writeline将puttin Writeline行,使用Write代替。

有趣的替代方案是,您可以使用正则表达式为您进行替换:

string input = "daniel<Text>THISISOUTisthere</Text>\n<Text>hellobye</Text>\n<Text>danielTHISishereandnotthere</Text>\ndanie <Text> is THIS here and not THERE</Text>";
Regex re = new Regex("(?<=<Text>).*?(?=</Text>)");
string output = re.Replace(input, m => new string(' ', m.Length));

Console.WriteLine(input);
Console.WriteLine();
Console.WriteLine(output);

节目输出:

daniel<Text>THISISOUTisthere</Text>
<Text>hellobye</Text>
<Text>danielTHISishereandnotthere</Text>
danie <Text> is THIS here and not THERE</Text>

daniel<Text>                </Text>
<Text>        </Text>
<Text>                           </Text>
danie <Text>                           </Text>

另一个有趣的选择,因为我觉得我想尝试让它工作:一个小的自己动手解析器。

注意:到目前为止,这不是真正的HTML或XML解析器! 它只会侵入一个标签(例如<Text> )并且只有任何属性......

那么,解析器需要什么? 对,一个标记器。 干得好:

static IEnumerable<Token> Tokenize(string input, string tag)
{
    int index = 0;
    int lastIndex = 0;

    // Define the start and end tag and their common first character
    char tagChar = '<';
    string startTag = tag + '>';
    string endTag = '/' + tag + '>';

    while (true)
    {
        Token token = null;

        // Search for any new tag token
        index = input.IndexOf(tagChar, index) + 1;
        if (index <= 0)
            break;

        // Starttag or endtag token found
        if (input.Substring(index, startTag.Length) == startTag)
            token = new Token { Start = index - 1, Length = startTag.Length + 1, TypeOfToken = Token.TokenType.StartTag };
        else if (input.Substring(index, endTag.Length) == endTag)
            token = new Token { Start = index - 1, Length = endTag.Length + 1, TypeOfToken = Token.TokenType.EndTag };

        // Yield the text right before the tag and the tag itself
        if (token != null)
        {
            yield return new Token { Start = lastIndex, Length = index - lastIndex - 1, TypeOfToken = Token.TokenType.Text };
            yield return token;
            lastIndex = index + token.Length - 1;
        }
    }

    // Yield last text token
    yield return new Token { Start = lastIndex, Length = input.Length - lastIndex, TypeOfToken = Token.TokenType.Text };
}

class Token
{
    public int Start { get; set; }
    public int Length { get; set; }
    public TokenType TypeOfToken { get; set; }

    public enum TokenType
    {
        Text,
        StartTag,
        EndTag
    }
}

它甚至有所优化,因为它只搜索<并检查它是否是之后的开始或结束标记。

将字符串标记化后,其余处理非常简单:

static string ProcessString(string input, string tag)
{
    var sb = new StringBuilder();

    int depth = 0;
    foreach (var token in Tokenize(input, tag))
    {
        // Append all tags, but only text tokens with depth level 0
        if (token.TypeOfToken != Token.TokenType.Text || 
            (token.TypeOfToken == Token.TokenType.Text && depth == 0))
            sb.Append(input.Substring(token.Start, token.Length));
        else
            sb.Append(new string(' ', token.Length));

        // Increment for each starttag, decrement for each endtag, never smaller than 0
        depth = Math.Max(0, depth + (token.TypeOfToken == Token.TokenType.StartTag ? 1 :
                                    (token.TypeOfToken == Token.TokenType.EndTag ? -1 : 0)));
    }

    return sb.ToString();
}

这比正则表达式解决方案更灵活,因为你可以赋予它更多的语义含义,比如深度。 例如调用这个:

ProcessString("level0<Tag>level1<Tag>level2</Tag>level1again</Tag>level0again", "Tag");

将被处理为:

"level0<Tag>      <Tag>      </Tag>           </Tag>level0again"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM