Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Вебмастеру (http://forum.oszone.net/forumdisplay.php?f=22)
-   -   вопрос по Perl (http://forum.oszone.net/showthread.php?t=41579)

mrcnn 25-11-2004 12:17 275254

вопрос по Perl
 
Почему Perl заменяет символ \x0a на \x0d\x0a ?

Например, в таком случае

open (READ, "<wuaucpl.cpl");
open (WRITE, ">write.cpl");
while(<READ>){
print WRITE $_;}
close READ;
close WRITE;


Размер нового файла увеличился на несколько байт, хотя этого ни в коем случае не должно происходить. Как этого избежать?

hasherfrog 25-11-2004 12:21 275256

Вопросы по Perl'у быстрее решаются у нас Вебмастерами.

Vlad Drakula 25-11-2004 12:35 275261

mrcnn
наверно \x0a == \n
тогжа это прописано в настройках
и это правильно иначе неправильно будет отобразаться текст!

mrcnn 25-11-2004 12:59 275267

\n в виндозе == \x0d\x0a
В Unixe действительно \n==\x0a

Как все-таки сделать так, чтобы размеры файлов wuaucpl.cpl и write.cpl и их содержимое полностью совпадали??

Vlad Drakula 25-11-2004 15:33 275319

mrcnn
линукс прекрастно поримает и \x0d\x0a в качестве перевод астроки!

а почему тебе просто не скопировать файл?

mrcnn 25-11-2004 15:49 275326

Vlad Dracula:
Я привел упрощенный пример.
На самом деле задача несколько другая, которая простым копированием не решается.
Нужно открыть бинарный файл и заменить строку другой строкой; при этом размер файла не должен меняться. (У меня стоит Windows.)
Заменять вручную очень-очень долго, потому что строка может встречаться несколько тысяч раз

Vlad Drakula 25-11-2004 15:52 275328

mrcnn
а как ты определяешь какую строчку тебе надо заменить?

mrcnn 25-11-2004 16:00 275333

Строки которые нужно заменить и на что заменить заранее известны, причем строки бинарные.

mrcnn 25-11-2004 16:03 275334

Например: \x43\x00\x3a\x00\x5c

mar 25-11-2004 16:33 275345

Цитата:

Нужно открыть бинарный файл
а Вы с ним обращаетесь, как с текстовым :), и в результате Perl резвится с концами строк согласно купленным билетам (то есть операционке). На Самом деле, может быть и зря этот топик сюда перенесли - помнится на те же грабли я наступала когда-то давно, переписывая файлы под C++ Builder

Vlad Drakula 25-11-2004 16:36 275348

mrcnn
ну так и работай через бинарные функции, ато у тебя и не это может произойти!

mrcnn 25-11-2004 16:38 275349

mar

Я понял свою ошибку!!!!Я забыл, что к тому файлу, в который мы записываем тоже надо binmode. Хотя к считываемому файлу я binmode применил. ;-)

Итого получилось следующее:


$msg ="File for reading: ";print $msg;
chomp ($read=<STDIN>);
$msg ="File for writing: ";print $msg;
chomp ($write=<STDIN>);

open (READ, "$read") || die "Can't open READ: $!\n";
open (WRITE, ">$write") || die "Can't open WRITE: $!\n";

binmode(READ);
binmode(WRITE);

$sz_file=(-s "$read");
$sz_read=0;

while (<READ>){
$sz_read+=length($_);
$procent_read=($sz_read/$sz_file)*100;
printf ("%.2f%\r", $procent_read);

$_=~s/\x43\x3a\x5c/\x52\x3a\x5c/g;
$_=~s/\x63\x3a\x5c/\x52\x3a\x5c/g;
$_=~s/\x43\x00\x3a\x00\x5c/\x52\x00\x3a\x00\x5c/g;

print WRITE $_;
}

close (READ);
close (WRITE);

mrcnn 30-11-2004 08:06 276616

Можно еще задать вопрос ?
Сам нижеприведенный скрипт уже почти готовый, однако меня интересует, какие ошибки, в том числе стилистические и алгоритмические допущены и пути улучшения?

Код:

#Задача: принять арифметическое выражение и вычислить его значение. Возможны следующие арифм. операции : сложение, умножение, деление, вычитание, возведение в степень, вычисление факториала. Допускается вложенность скобок любого уровня и работа с  отрицательными числами, заключение в скобки отрицательных чисел необязательно. Поддерживаются числа с плавающей точкой: напр. 8.23 5.9001

#TODO: проверка правильности скобок т е соответствия правых и левых скобок
#TODO: более тщательный разбор входящей строки

#Примеры использования:
#2+3*6-(-7)^(3!)
#((3*6)+5)^(2!+5)-5!
# 8!-7!*6

$msg="Разбор арифметических выражений.
Выйти - Ctrl+Z или Ctrl+C
Приоритет операций: () ! ^ * / + -
Приоритет операциям / и * надо задавать явно
\n";
 
&print($msg);

for (;$expression  ne "\cZ";){

 $msg="Введите выражение: ";
 &print($msg);
 $expression=<STDIN>;
 chomp($expression);
 $expression=~s/ //g;
 $expression=skob($expression);
 print "Result = $expression\n";
}

sub skob() {
# функция вычисляет выражения стоящее в скобках и записывает это значение вместо скобки

my $result;
my $flag;
my $counter;
my $lent;
my $newstr;
my $startposition;

#проверяем, есть ли вообще в выражении скобки
if ( $_[0] =~/\(/ || $_[0]=~/\)/ ) {
  $flag=0;
  for ($counter=0; $counter < length ($_[0]); $counter++){
      if ( (substr ($_[0], $counter,1)) eq '('){ #определяем начало скобки
        $flag+=1;
        #увеличиваем значение флаговой переменной, и если увеличение произошло в первый раз,                 
        #заносим в переменную $startposition номер символа подстроки, в котором находится скобка
        if ($flag==1){
            $startposition=$counter;
            }
        }
      elsif ( (substr ($_[0], $counter,1)) eq ')'){#определяем конец скобки
        $flag-=1; #уменьшаем значение флаговой переменной
        if ($flag==0){ # когда в этом месте флаг превратится в ноль, т.е. закончится скобка             
            $lent = length ($newstr) + 2;
            $newstr = skob ($newstr); #рекурсивно вызываем функцию заново,
                                      #чтобы проверить, есть ли в считанной скобке другие скобки
                                      #возвращаемое значение - результат вычисления скобки
            substr ($_[0], $startposition, $lent) = $newstr; #замена скобки на ее значение           
            $counter-=$lent; #уменьшение счетчика на длину скобки,
                            #т.к. в выражении могут присутствовать
                            #2 рядом стоящие скобки
                            #поэтому нужно считать строку до конца
            $newstr=undef; #?     
            } 
        }
         
      # если мы внутри скобки (т.е. $flag>0) И $startposition< счетчика,
      # то заносим в переменную $newstr содержимое скобки
      if ($flag>0  && $startposition <$counter){
          $newstr .=substr ($_[0], $counter,1)}
  }
}

$result=vichislenie($_[0]); #вычисление значения скобки
return $result;
}


sub vichislenie(){
  @znaki=();#знаки выражения
  @cyfers=(); # цифры

#чтение полученного выражения
for ($counter=0, $arraycnt=0, $currentposition=0; $counter <length($_[0]);$counter++){
  # $_[0] - выражение, которое нужно вычислить
  # $counter - счетчик массива $_[0]
  # $arraycnt - счетчик массива  @znaki
  # $currentposition - текущая позиция в массиве $_[0]
 
  #если встретили символ арифметичсекой операции 
  if (substr($_[0],$counter,1) eq '+' ||
  (substr($_[0],$counter,1) eq '-'&&
  substr($_[0],$counter-1,1) ne '-' &&
  substr($_[0],$counter-1,1) ne '+' &&
  substr($_[0],$counter-1,1) ne '*'&&
  substr($_[0],$counter-1,1) ne '/' &&
  substr($_[0],$counter-1,1) ne '^') ||
  substr($_[0],$counter,1) eq '*'||
  substr($_[0],$counter,1) eq '/' ||
  substr($_[0],$counter,1) eq '^')
    {
      #заносим в массив знак. арифм. операции
      $znaki[$arraycnt]=substr($_[0],$counter,1);

      #заносим в массив цифру (т.е. содержимое строки между знаками)
      #вместе с цифрой заносится и отрицательный знак, если он есть
      for ($i=$currentposition; $i<$counter;$i++){
        $cyfers[$arraycnt].=substr($_[0],$i,1);}
   
      #вычисление факториала     
      if ($cyfers[$arraycnt]=~/(.*)!/){
        $cyfers[$arraycnt]=factorial($1);
      }
      $currentposition=$counter+1;
      $arraycnt++;
    }
}


for ($i=$currentposition; $i<length($_[0]);$i++){
#чтобы не потерять последнюю цифру
  $cyfers[$arraycnt].=substr($_[0],$i,1);

#вычисление факториала
  if ($cyfers[$arraycnt]=~/(.*)!/){
  $cyfers[$arraycnt]=factorial($1);
  }
}

#выполнение арифметических операций
operation("\^");
operation("\*");
operation("\/");
operation("\+");
operation("\-");

#возвращение результата вычислений
return ($cyfers[0]);
}

sub print($msg){
 my $msg=$_[0];
 wintodos($msg); #перекодировка строки из win в dos, чтобы русские буквы нормально показывались в терминале
 printf ("%s", $msg);
}

sub operation(){
 my $counter;
 my $result;
 for ($counter=0; $counter<@znaki;){
  if($znaki[$counter] eq $_[0]){
  $result=$cyfers[$counter]**$cyfers[$counter+1] if ( $_[0] eq "\^");
  $result=$cyfers[$counter]*$cyfers[$counter+1] if ( $_[0] eq "\*");
  $result=$cyfers[$counter]/$cyfers[$counter+1] if ( $_[0] eq "\/");
  $result=$cyfers[$counter]+$cyfers[$counter+1] if ( $_[0] eq "\+");
  $result=$cyfers[$counter]-$cyfers[$counter+1] if ( $_[0] eq "\-");
  $cyfers[$counter]=$result;
   
  #уничтожение одного элемента массива
  @cyfers=sdvig (@cyfers,$counter+1);
  @znaki=sdvig (@znaki,$counter);
  }
 else {
    $counter++;}
 }
}

sub sdvig(){
  my $lent=length(@_);
  my $counter= $_[-1];
  my @array=@_;
  $#array--;
  for ($tmp=$counter; defined($array[$tmp+1]);$tmp++){
      $array[$tmp]=$array[$tmp+1];
  }
  $#array--;
  return @array;

  }

sub factorial {
  my $result;
  my @b;
  my $i;

  $result=1;
  @b =(1 .. $_[0]);
  for($i=1;$i<$_[0];$i++) {
      $result= ($b[$i])* $result;
  }
  return $result;
}

sub wintodos {
      $_[0]=~s/\xe0/\xa0/g;
      $_[0]=~s/\xe1/\xa1/g;
      $_[0]=~s/\xe2/\xa2/g;
      $_[0]=~s/\xe3/\xa3/g;
      $_[0]=~s/\xe4/\xa4/g;
      $_[0]=~s/\xe5/\xa5/g;
      $_[0]=~s/\xe6/\xa6/g;
      $_[0]=~s/\xe7/\xa7/g;
      $_[0]=~s/\xe8/\xa8/g;
      $_[0]=~s/\xe9/\xa9/g;
      $_[0]=~s/\xea/\xaa/g;
      $_[0]=~s/\xeb/\xab/g;
      $_[0]=~s/\xec/\xac/g;
      $_[0]=~s/\xed/\xad/g;
      $_[0]=~s/\xee/\xae/g;
      $_[0]=~s/\xef/\xaf/g;
      $_[0]=~s/\xf0/\xe0/g;
      $_[0]=~s/\xf1/\xe1/g;
      $_[0]=~s/\xf2/\xe2/g;
      $_[0]=~s/\xf3/\xe3/g;
      $_[0]=~s/\xf4/\xe4/g;
      $_[0]=~s/\xf5/\xe5/g;
      $_[0]=~s/\xf6/\xe6/g;
      $_[0]=~s/\xf7/\xe7/g;
      $_[0]=~s/\xf8/\xe8/g;
      $_[0]=~s/\xf9/\xe9/g;
      $_[0]=~s/\xfa/\xea/g;
      $_[0]=~s/\xfb/\xeb/g;
      $_[0]=~s/\xfc/\xec/g;
      $_[0]=~s/\xfd/\xed/g;
      $_[0]=~s/\xfe/\xee/g;
      $_[0]=~s/\xff/\xef/g;

      $_[0]=~s/\xc0/\x80/g;
      $_[0]=~s/\xc1/\x81/g;
      $_[0]=~s/\xc2/\x82/g;
      $_[0]=~s/\xc3/\x83/g;
      $_[0]=~s/\xc4/\x84/g;
      $_[0]=~s/\xc5/\x85/g;
      $_[0]=~s/\xc6/\x86/g;
      $_[0]=~s/\xc7/\x87/g;
      $_[0]=~s/\xc8/\x88/g;
      $_[0]=~s/\xc9/\x89/g;
      $_[0]=~s/\xca/\x8a/g;
      $_[0]=~s/\xcb/\x8b/g;
      $_[0]=~s/\xcc/\x8c/g;
      $_[0]=~s/\xcd/\x8d/g;
      $_[0]=~s/\xce/\x8e/g;
      $_[0]=~s/\xcf/\x8f/g;
      $_[0]=~s/\xd0/\x90/g;
      $_[0]=~s/\xd1/\x91/g;
      $_[0]=~s/\xd2/\x92/g;
      $_[0]=~s/\xd3/\x93/g;
      $_[0]=~s/\xd4/\x94/g;
      $_[0]=~s/\xd5/\x95/g;
      $_[0]=~s/\xd6/\x96/g;
      $_[0]=~s/\xd7/\x97/g;
      $_[0]=~s/\xd8/\x98/g;
      $_[0]=~s/\xd9/\x99/g;
      $_[0]=~s/\xda/\x9a/g;
      $_[0]=~s/\xdb/\x9b/g;
      $_[0]=~s/\xdc/\x9c/g;
      $_[0]=~s/\xdd/\x9d/g;
      $_[0]=~s/\xde/\x9e/g;
      $_[0]=~s/\xdf/\x9f/g;
      }



Время: 19:09.

Время: 19:09.
© OSzone.net 2001-