【问题标题】:How can Replace infinite loop?如何替换无限循环?
【发布时间】:2009-07-23 17:20:28
【问题描述】:

我正在编写一些想要删除空白行的效率很低的 C# 代码。它这样做:

字符串 b; ... 而 ( b.IndexOf("\n\n") >= 0 ) b = b.替换("\n\n", "\n");

单个替换无法处理(例如)输入中的 \n\n\n,因此需要循环。我认为它应该起作用,而且通常会起作用。

但有时它会设法进入无限循环,我不明白如何。在每次迭代中,\n 的数量都应该减少,所以它应该最终终止。

有什么想法吗?

【问题讨论】:

  • 你有没有停止的示例行?曾经使用过调试器吗?
  • 我的回答显示了一种情况会迫使它无限运行
  • 这是我如何得到一个导致无限循环的讨厌字符串: System.IO.StreamReader aFile = System.IO.File.OpenText(@"c:\xfer\s.tab");字符串 b = aFile.ReadToEnd(); aFile.Close();文件 s.tab 包含这 18 个十六进制字节: FF FE 41 00 0D 0A 00 0D 0A 00 0D 0A 00 42 00 这是我的程序的输出: b.Length=8 loop n=1, i=3, b=A ?? ?? B 停留在 i=3, b(i)=10 2573 3328... 完成 n=1, i=3, b=A?? ?? B 所以这与无效的unicode有关。但我仍然认为它不应该发生。

标签: c# string replace infinite-loop


【解决方案1】:

这行得通吗:

String c = Regex.Replace(b, "\n\n+", "\n");

【讨论】:

  • 为什么要额外的\n?我在下面发布的答案应该只需 \n+ 即可解决。
  • 是的,这应该可以。额外的 \n 是提高效率所必需的。这样,双倍和三倍(以及更多)连续换行符将被替换。但是一个换行符被单独留下。此外,通过使用此方法,您不再需要循环。在这种情况下,正则表达式会更好。
  • 这是一个过早的优化,以防止 Regex 浪费匹配将 '\n' 替换为 '\n' 这是一个 NOOP。
  • 我完全同意你的观点。我正要写完全相同的代码,但你打败了我。
  • 所以我们现在有了一个可以接受的答案,但仍然没有解释最初问题的原因......
【解决方案2】:

我没有解释你莫名其妙的无限循环(你确定它是无限的吗?你检查过字符串是否改变了吗?),但你可以用正则表达式更容易和更快地做到这一点:

b = System.Text.RegularExpressions.Regex.Replace(b, "\n+", "\n")

【讨论】:

  • 这是最好的方法,IMO。
【解决方案3】:

你能举一个字符串的例子,它会进入一个无限循环吗?另外要调试您的程序,您可以尝试将其替换为:

while(b.IndexOf("\n\n")>=0)
{
     Console.Write(b)
     Console.Write(b.IndexOf("\n\n").ToString())
     b = b.Replace("\n\n", "\n");
}

看看它输出了什么。

【讨论】:

  • 不幸的是,我的示例是一个 13000 个字符的字符串。我添加了一些 Console.Writes 来确认 IndexOf 在连续迭代中返回相同的值。使用 Visual Studio 2003,我看不到如何查看字符串并查看非打印字符。我想我可以添加更多的 Writes。
【解决方案4】:

我只是将这个答案放在这里以澄清一点,以防其他人出现并建议如果 b 是空字符串,上面发布的代码将无限循环。这是不正确的:

String b = String.Empty;

Console.WriteLine(b.IndexOf("\n\n"));

// output: -1

documentation 声明IndexOf 将在传递给它的 参数 值为空而不是字符串本身(在本例中为 b)为空时返回 0。

【讨论】:

    【解决方案5】:

    我已经将问题归结为我通过读取文件得到的一个讨厌的字符串(下面的完整代码)。

    文件 s.tab 包含这 18 个十六进制字节:FF FE 41 00 0D 0A 00 0D 0A 00 0D 0A 00 42 00

    这是我的程序的调试输出:

    b.Length=8 loop n=1, i=3, b=A?? 
    ?? B 
    stuck at i=3, b(i)=10 2573 3328... 
    done n=1, i=3, b=A?? 
    ?? B 
    

    所以这与无效的 unicode 有关。我已经打印出字符串 b 的字符的十进制值,从 i = 3 = IndexOf("\n\n") 开始。 IndexOf 似乎将 10 视为换行符(OK),然后将 2573(即 0D 0A)视为另一个(不是 OK?)。然后 Replace 不同意。

    显然文件中的数据有问题。但我仍然认为这不应该发生。 IndexOf 和 Replace 应该是一致的。

    我正在实施 msaeed 的解决方案。非常感谢。

    调试代码:

            {
                System.IO.StreamReader aFile = System.IO.File.OpenText( @"c:\xfer\s.tab");
                string a = aFile.ReadToEnd();
                aFile.Close();
    
                int nn=0, ii;
                Console.WriteLine ("a.Length={0}", a.Length);
                while ( (ii=a.IndexOf("\n\n")) >= 0 )
                {
                    nn++;
                    Console.WriteLine("loop n={0}, i={1}, a={2}"
                        , nn
                        , ii
                        , a);
                    if (ii == a.IndexOf("\n\n"))
                    {
                        Console.WriteLine ("stuck at i={0}, a(i)={1} {2} {3}..."
                            , ii
                            , (int)(a.ToCharArray()[ii])
                            , (int)(a.ToCharArray()[ii+1])
                            , (int)(a.ToCharArray()[ii+2])
                            );
                        break;
                    }
                    a = a.Replace ("\n\n", "\n");
                }
                Console.WriteLine("done n={0}, i={1}, a={2}", nn, ii, a);
            }
    

    【讨论】:

      猜你喜欢
      • 2016-12-21
      • 1970-01-01
      • 2011-01-06
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 2016-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多