2009-07-23 2 views
0

Я работаю над довольно неэффективным кодом на C#, который хочет удалить пробелы. Он делает это:Как заменить бесконечный цикл?

 
      string b; 
... 
      while (b.IndexOf("\n\n") >= 0) 
       b = b.Replace ("\n\n", "\n"); 

Один заменить не справиться с (например) \ N \ N \ N на входе, так что требуется цикл. Я думаю, что он должен работать, и это обычно происходит.

Но иногда ему удается попасть в бесконечный цикл, и я не понимаю, как это сделать. На каждой итерации число \ n должно уменьшаться, поэтому в конечном итоге оно должно заканчиваться.

Любые идеи?

+2

У вас есть пример строки, где он не останавливается? Когда-либо ворвался с отладчиком? –

+0

Мой ответ показывает один случай, который заставит это бежать бесконечно –

+0

Вот как я получаю неприятную строку, которая вызывает бесконечный цикл: \t \t \t \t System.IO.StreamReader AFile = System.IO.File.OpenText (@ "C: \ XFER \ s.tab"); \t \t \t \t string b = aFile.ReadToEnd(); \t \t \t \t aFile.Close(); Файл s.tab содержит эти 18 шестнадцатеричных байт: FF FE 41 00 0D 0A 00 00 0D 0A 0D 0A 00 42 00 здесь выход из моей программы: b.Length = 8 петли N = 1, i = 3, b = A ?? ?? B застрял в i = 3, b (i) = 10 2573 3328 ... сделано n = 1, i = 3, b = A ?? ?? B Так что это как-то связано с недействительным юникодом. Но я до сих пор не думаю, что это должно произойти. – Rob625

ответ

6

ли эта работа:

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

Почему дополнительный \ n? Ответ, который я написал ниже, должен позаботиться об этом только с помощью \ n +. –

+0

Да, это должно сработать. Дополнительный \ n необходим для повышения эффективности. Таким образом, заменяются двойные и тройные (и более) последовательные линии. Но однострочный канал остается один. Кроме того, используя этот метод, вам больше не нужен цикл. В этом случае регулярные выражения просто лучше. –

+0

Это преждевременная оптимизация, чтобы предотвратить регулярное соответствие Regex, чтобы заменить «\ n» на «\ n», который является NOOP. – notnoop

0

Можете ли вы привести пример строки, для которых это попадает в бесконечный цикл? Также для отладки вашей программы вы можете попробовать ее заменить:

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

и посмотреть, что он выводит.

+0

К сожалению, мой пример - строка из 13000 символов. Я добавил несколько Console.Writes, которые подтверждают, что IndexOf возвращает одно и то же значение при последовательных итерациях. Использование Visual Studio 2003, я не вижу, как смотреть в строку и видеть непечатаемые символы. Полагаю, я мог бы добавить больше Writes. – Rob625

6

У меня нет объяснения для вашего необъяснимого бесконечного цикла (вы НЕ ОПРЕДЕЛЯете его бесконечно? Вы проверили, изменилась ли строка?), Но вы можете сделать это намного проще и быстрее с регулярным выражением:

+0

Это лучший подход, ИМО. –

0

Я просто помещаю этот ответ здесь, чтобы прояснить точку на случай, если кто-то еще появится, и предположим, что код, выложенный выше, будет бесконечно циклическим, если b - пустая строка. Это неверно:

String b = String.Empty; 

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

// output: -1 

В documentation говорится, что IndexOf будет возвращать 0, если значение параметра переданной ей пусто, нет, если строка сами (б в данном случае) пусто.

0

Я поставил проблему на неприятную строку, которую я получаю, читая файл (полный код ниже).

Файл 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 

Так это как-то связано с неправильным юникодом. Я напечатал десятичные значения символов строки b, начиная с i = 3 = IndexOf ("\ n \ n"). Кажется, что IndexOf видит 10 в качестве новой строки (ОК), а затем 2573 (то есть 0D 0A) как другой (не ОК?). Тогда Replace не соглашается.

Очевидно, что что-то не так с данными в файле. Но я до сих пор не думаю, что это должно произойти. IndexOf и Replace должны согласиться.

Я реализую решение msaeed. Большое спасибо.

код Debug:

 { 
      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); 
     } 

 Смежные вопросы

  • Нет связанных вопросов^_^