Странное поведение IndexOf() с подстроками, содержащими escape-символы

Я пытаюсь найти все индексы строки "\r\n" (в основном перевод строки и возврат) в большой строке.

Мне нужно сделать это, так как я должен написать большую строку в файл PDF построчно (мне нужно вызвать API-интерфейс новой строки dll, который я использую после написания предыдущей строки).

Вот короткая версия кода: -

    string fileContents = "abc\r\n\r\ndef\r\nghi";

    int pos = -1; 

    int start = 0;

    while ((pos = fileContents.IndexOf("\r\n", start)) != -1)
    {
        //extract string
        //write string to PDF
        //call newline API

        start = pos + 1;

    }

Ожидаемые позиции «\r\n» в переменной fileContents — 3, 7 и 14. Однако при отладке кода значения в переменной pos — 3, 5 и 10.

Что не так с моим вызовом indexOf()?


person user720694    schedule 27.08.2013    source источник
comment
Я думаю, что ваши предположения неверны, можете ли вы уточнить, как вы пришли к 3, 7 и 14?   -  person Scott Chamberlain    schedule 27.08.2013
comment
\r и \n считаются за 1, а не за 2, поскольку '\n' - это символ   -  person sa_ddam213    schedule 27.08.2013


Ответы (5)


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

"abc\r\n\r\ndef\r\nghi"

 0 : a
 1 : b
 2 : c
 3 : \r
 4 : \n
 5 : \r
 6 : \n
 7 : d
 8 : e
 9 : f
 10: \r
 11: \n
 ...
person TecHunter    schedule 27.08.2013

Должно быть 3, 5 и 10.

\r и \n и т. д. считаются одним символом, а не двумя. Escape-символы — это один символ в коде, а не два, даже если они записываются с использованием двух символов в строке.

Вы считаете так:

a_b_c_\r_\n_\r_\n_d_e_f_\r_\n_g__h__i
0_1_2_3__4__5__6__7_8_9_10_11_12_13_14
person Automatico    schedule 27.08.2013

Оба символа \n или \r будут отображаться как одиночные символы, а не два. Это означает, что позиции, которые вы видите, верны. Просто посчитайте это так, чтобы каждый символ \x считался одним символом.

person TGH    schedule 27.08.2013

Ниже может быть лучшее решение вашей проблемы

    string s = "abc\r\n\r\ndef\r\nghi";
    List<String> lines = s.Split("\r\n".ToCharArray()).ToList();

    lines.RemoveAll(str => str == "");

    foreach (string l in lines)
        Response.Write(l + "<br/>");
person Ronak Patel    schedule 27.08.2013
comment
Да, кажется шустрым. Спасибо :) - person user720694; 27.08.2013

Попробуйте это, чтобы искать литералы так, как вы изначально хотели, в качестве альтернативы для остальных ответов.

Сначала преобразуйте свою строку, чтобы избежать всех литералов:

var writer = new StringWriter();
var provider = CodeDomProvider.CreateProvider("CSharp"));

provider.GenerateCodeFromExpression(new CodePrimitiveExpression(fileContents), writer, null);

string fileContents2 = writer.ToString();

И затем искать таким образом:

.IndexOf("\\r\\n", start)
person SysDragon    schedule 27.08.2013
comment
Ему также нужно будет экранировать исходную строку. - person Scott Chamberlain; 27.08.2013
comment
Они ищут символы возврата каретки и новой строки, а не управляющую последовательность, представляющую их. - person TheEvilPenguin; 27.08.2013