C в Delphi/Pascal

Мне нужно перевести часть кода C в код Delphi/Pascal, однако я не могу понять пару строк.

Код С:

static char* get_boundary(apr_pool_t* p, const char* ctype) {
  char* ret = NULL ;
  if ( ctype ) {
    char* lctype = lccopy(p, ctype) ;
    char* bdy = strstr(lctype, "boundary") ;
    if ( bdy ) {
      char* ptr = strchr(bdy, '=') ;
      if ( ptr ) {
    // what is the following line supposed to do?
    bdy = (char*) ctype + ( ptr - lctype ) + 1;
    // and this? I understand it's a loop, but *ptr and ++ptr is ugly!
    for ( ptr = bdy; *ptr; ++ptr )
      if ( *ptr == ';' || isspace(*ptr) )
        *ptr = 0 ;
    ret = apr_pstrdup(p, bdy) ;
      }
    }
  }
  return ret ;
}   

Мой текущий перевод:

function get_boundary(p: Papr_pool_t; const ctype: PChar): PChar;
var
  LCType: PChar;
  LBody: PChar;
begin
  Result := NIL;
  LCType := lccopy(p, ctype);
  LBody := strpos(LCType, 'boundary');
  if LBody <> NIL then begin
    // now what? (:
  end; // if LBody <> NIL then begin
end;

lccopy создает копию параметра ctype и переводит его в нижний регистр.

Некоторые детали перевода приветствуются, например, 'bdy = (char*) ctype + ( ptr - lctype ) + 1;' и цикл for.

К вашему сведению, я перевожу mod_upload.c.


person Community    schedule 06.02.2012    source источник
comment
Возможно, вы могли бы написать какой-нибудь связующий код для вызова вашего кода C из Pascal!   -  person Basile Starynkevitch    schedule 06.02.2012
comment
@BasileStarynkevitch Я предпочитаю не использовать утиную ленту повсюду, кроме того, это поможет мне немного лучше понять C.   -  person    schedule 06.02.2012
comment
1. Используйте string, а не PChar. C не имеет строкового объекта. Не позволяйте возможностям C управлять вашим дизайном Delphi. 2. strchr и strstr служат той же цели, что и Pos в Delphi.   -  person David Heffernan    schedule 06.02.2012
comment
@DavidHeffernan спасибо, не знал!   -  person    schedule 06.02.2012
comment
Дорин, мне нравится твое написание слова "утиная лента" ;-)   -  person Jan Doggen    schedule 07.02.2012
comment
о боже, устал как черт, я имел в виду изоленту ((:   -  person    schedule 07.02.2012


Ответы (2)


        bdy = (char*) ctype + ( ptr - lctype ) + 1;

Итак... ( ptr - lctype ) - это арифметика указателя, чтобы определить, как далеко в lctype ptr точек. Это разница между адресами, содержащимися в указателях, деленная на размер типа данных, на который они указывают (в данном случае char, так что размер равен всего 1).

Таким образом, bdy = (char*) ctype + ( ptr - lctype ) + 1; указывает bdy на символ, следующий за найденным ранее '=', но в исходной строке ctype вместо строчной копии lctype.

        for ( ptr = bdy; *ptr; ++ptr )

Это не очень странный способ перебора строки в C. ptr указывает на каждый символ при переборе, а *ptr дает символ; поэтому *ptr будет проверяться как FALSE, когда будет достигнут завершающий нулевой байт для завершения цикла. ++ptr - это больше арифметика указателя для перехода к указателю на следующий символ. Даже если это кажется беспорядочным, это довольно естественный способ сделать это в C.

Таким образом, цикл проходит через каждый символ строки, на которую указывает bdy, и во время каждой итерации *ptr обращается к текущему символу.

          if ( *ptr == ';' || isspace(*ptr) )
            *ptr = 0 ;

Похоже, что цель цикла состояла в том, чтобы завершить строку (путем размещения более раннего нулевого ограничителя) на следующем найденном символе точки с запятой или пробеле.


Существует достаточно различий между Delphi и C, когда дело доходит до манипулирования строками, поэтому вам может быть лучше просто выяснить, что функция делает, а затем написать эквивалент Delphi с нуля, а не пытаться перевести его напрямую. нравится.

Похоже, что функция ищет «границу» (без учета регистра) в ctype, затем пропускает следующий найденный «=» и возвращает копию всего оттуда до следующей точки с запятой или пробела. Вы можете легко сделать то же самое в Delphi со строками и функциями Delphi, используя совсем другой код, если вы хотите сначала преобразовать строки...

Кроме того, если это имеет значение, похоже, что исходный код C игнорирует все, что находится между «границей» и «=», поэтому он примет, скажем, «boundary asdf jidlsah;lkdsf =Value», а также «boundary=Value»

person Dmitri    schedule 06.02.2012
comment
+1 100% согласен, лучше просто выяснить, что делает функция, а затем написать эквивалент Delphi с нуля, а не пытаться перевести его напрямую - person PA.; 06.02.2012
comment
+1 и принято, спасибо Дмитрий за отличный ответ, еще одна вещь, *ptr похож на разыменование? - person ; 06.02.2012
comment
Да, это именно то, что есть — ptr — это указатель, а *ptr разыменовывает его, чтобы получить доступ к тому, на что он указывает. - person Dmitri; 06.02.2012

// what is the following line supposed to do?
bdy = (char*) ctype + ( ptr - lctype ) + 1;

ptr — это расположение знака "=", следующего за "границей" в пределах lctype, следовательно, ptr - lctype — это расстояние от начала lctype до этого конкретного знака "=". Таким образом, ctype + (ptr-lctype) + 1 — это расположение первого символа после этого знака "=" в исходной строке.

Вероятно, это сделано для того, чтобы искать подстроки, игнорируя регистр символов. Простой strncasecmp() мог добиться того же эффекта.

// and this? I understand it's a loop, but *ptr and ++ptr is ugly!
for ( ptr = bdy; *ptr; ++ptr )

Это действительно цикл, но вместо использования индексной переменной и доступа к строке по bdy[i] используется временный указатель ptr. Этот указатель перебирает строку, на которую указывает bdy. Он начинается с первого символа, продолжается до тех пор, пока не будет достигнут конец строки (то есть, если *ptr оценивается как 0 (в C строки заканчиваются нулем)), и увеличивает указатель цикла на 1 после каждой итерации.

Использование указателя вместо индексной переменной является распространенной идиомой в C, и многие предпочитают ее наивному for (i=0; i < strlen(bdy); i++), поскольку он сохраняет вызов strlen().

К сожалению для вас, я перестал программировать на Паскале 15 лет назад, поэтому не могу вам помочь с переводом. Однако это не должно быть проблемой, теперь, когда вы знаете, что означают эти две строки.

person Philip    schedule 06.02.2012
comment
+1 спасибо, Филипп, очень хороший ответ, к сожалению, ответ Дмитрия был таким же и на 1 час быстрее, но вы подошли очень близко! - person ; 06.02.2012