【问题标题】:Finding text in array在数组中查找文本
【发布时间】:2017-12-19 05:07:31
【问题描述】:

我正在将例程从 C++ 移植到 C#,但很难理解移植失败的原因:

我有一个字符串数组,其中包含我正在尝试删除的内容。

    string[] aryLines = File.ReadAllLines(mstrFilename);

数组包含以下内容:

aryLines = new[]
{
    "<?xml version=\"1.0\" encoding=\"utf-8\"?>",
    "<!--",
    "",
    "  File:\t\tuif.xml, User Interface",
    "  Notes:\tThis file contains the application layout and includes",
    "\t\tfor other files defining the application look and functionality.",
    "",
    "  Node:\t\tuif, Root container node",
    "  Attributes:\tid\t\t: Unique node identifier",
    "\t\tcameras\t\t: Initial camera set-up",
    " \t\tcolor_bg\t: Application background colour:",
    "\t\t\t\t\tAlpha, Red, Green, Blue",
    "\t\theight\t\t: Height of the application container",
    "\t\twidth\t\t: Width of the appplication container\t\t",
    "",
    "  Node:\t\tinclude, Includes another XML file",
    "  Attributes:\tname\t\t: Encoded path to XML file to include",
    "",
    "  History:\t2017/09/11 Created by Simon Platten",
    "// -->"
};

我有一个方法应该删除 cmets,找到第一次出现的 &lt;!-- 和匹配的 --&gt;,然后它将删除中间的所有内容。问题是,虽然它找到了&lt;!--,但它没有找到--&gt;,我不明白为什么。

private static readonly string msrostrCmtClose = "-->";
private static readonly string msrostrCmtOpen = "<!--";

int intOpen = 0;
while((intOpen = Array.IndexOf(aryLines, msrostrCmtOpen, intOpen)) >= 0) 
{
    //Opening marker located, look for closing marker   
    int intClose = Array.IndexOf(aryLines, msrostrCmtClose, intOpen);

    if ( intClose < intOpen ) 
    {
        //Shouldn't get here!
        continue;
    }

    Console.WriteLine(intOpen);
}

上面的套路不完整,但是在调试器中看intClose总是-1,为什么?

【问题讨论】:

  • 由于 cmets 可以跨越多行,您可能应该将文件读入一个长字符串,而不是一系列独立的“行”。那么你的逻辑会更清晰。
  • 因为你在第 19 行有 // --> Array.IndexOf 不是 string.Contains
  • Array.IndexOf 对数组中的元素进行完全匹配。在您的情况下,它正在对字符串的全部内容进行完全匹配。您似乎希望它做的是每个字符串元素的部分匹配。
  • 您最好使用支持 DOM 的 XML 解析器。然后你可以只寻找评论节点并删除它们。 :P
  • @SPlatten:如果是 XML,那么 XML 解析器可以解析它。如果没有一些帮助,可能无法完全理解它,但 XML 解析器不会在格式良好的 XML 上窒息。

标签: c#


【解决方案1】:

这里的问题是Array.IndexOf 将每个元素与您要查找的内容进行比较,除了您要查找的内容实际上不在数组中。数组中的内容是 // --&gt; 而不仅仅是 --&gt;

你可以做一个像这样的简单函数:

private int IndexOfInArray(string[] array, string elemToFind, int startIndex = 0)
{
    for (int i = startIndex; i < array.Length; i++)
    {
        if (array[i].Contains(elemToFind))
            return i;
    }

    return -1;
}

然后像这样使用它:

int intOpen = 0;
while((intOpen = IndexOfInArray(aryLines, msrostrCmtOpen, intOpen)) >= 0 ) 
{
    //Opening marker located, look for closing marker   
    int intClose = IndexOfInArray(aryLines, msrostrCmtClose, intOpen);
    if (intClose < intOpen) 
    {
        //Shouldn't get here!
        continue;
    }

    Console.WriteLine(intOpen);
}

您可能必须将intOpen 设置为intClose 或只设置intOpen++ 才能永远得到相同的结果。

【讨论】:

    【解决方案2】:

    我现在已经解决了这个问题,感谢 cmets 中的建议,新的解析器看起来像这样:

        string strXML = File.ReadAllText(mstrFilename);
    
        int intOpen = 0;
        while( (intOpen = strXML.IndexOf(msrostrCmtOpen, intOpen)) >= 0 ) {
        //Opening marker located, look for closing marker   
                int intClose = strXML.IndexOf(msrostrCmtClose, intOpen);
    
                if ( intClose < intOpen ) {
        //Shouldn't get here!
                    continue;
                }
                Console.WriteLine(intOpen);
            }
    

    【讨论】:

    • @Rufus,仔细看看,原来是把数据读入一个字符串数组而不是一个字符串。
    • 是的,我明白...我是在提示您实际回答这个问题,以便其他人可以从中学习——例如,描述问题所在以及您是如何解决的。 :)
    • 不是很明显问题是因为我对索引的误解
    猜你喜欢
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多