Автор Тема: проблемы с substr()  (Прочитано 4143 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Forza

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 288
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« : 05 Августа 2004, 19:14:10 »
Имеются непонятные проблемы с функцией substr(), предназначенной в том числе и для вставки текста в строку.
Например, я хочу вставить текст, "раздвинув" символы вокруг. Я пишу:
substr ($lines[$i], $pos, 0) = \'a\'
   or die ("length: " . length($lines[$i]) . ", pos: " . $pos)

Без die() Апач выдаёт следующую ошибку: substr outside of string at.... С die() он пишет то, что я и просил: length: 151, pos: 105 at....
Вопрос в том, как же substr может быть outside of string, если альтернативное сообщение об ошибке показывает, что позиция намного меньше длины строки.

С меньшими значениями $pos работает нормально.

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #1 : 05 Августа 2004, 19:55:36 »
perldoc perldiag
Цитировать
  substr outside of string
           (W substr),(F) You tried to reference a substr() that
           pointed outside of a string.  That is, the absolute
           value of the offset was larger than the length of the
           string.  See "substr" in perlfunc.  This warning is
           fatal if substr is used in an lvalue context (as the
           left hand side of an assignment or as a subroutine
           argument for example).
The documentations is your friend

Оффлайн Forza

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 288
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #2 : 05 Августа 2004, 23:41:06 »
NeoNox, я сразу понял, что Perl считает, что я с substr() "вылез" за границы строки.
Но я же привёл пример, что он в die() выводит то, что изменяемая позиция на ~50 символов меньше, чем размер строки!!!  
Почему? :insane:

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #3 : 06 Августа 2004, 00:16:47 »
Forza какой у тебя Perl? или приведи свои данные переменных.
  DB<1$lines[$i] = \'abcd\'

  DB<2> $pos = 1

  DB<3> substr ($lines[$i], $pos, 0) = \'a\'

  DB<4> print  $lines[$i]
aabcd
The documentations is your friend

Оффлайн Forza

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 288
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #4 : 06 Августа 2004, 15:21:53 »
Цитировать
NeoNox:
какой у тебя Perl?

Active Perl 5.8.
Цитировать
NeoNox:
приведи свои данные переменных

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

my 
@lines;
#пример строки из исходного текстового файла
push (@lines"1    Абдряшевская СОШ   453630, д. Абдряшево   
1        да              Зайнуллин      нач.        (34772)"
);

my @array;
/*Анализ файла убираем, сразу пишу те позиции столбцов, которые должны быть. Использую массив хешей, т.к. на самом деле помимо позиций столбцов надо хранить ещё другую информацию*/
push (@array, {pos=>0},  {pos=>5}, {pos=>24}, {pos=>47}, {pos=>56}, {pos=>72}, {pos=>87}, {pos=>99});

#массив цветов
my @colors = (\'green\',\'white\');

#перебираем все строки исходного файла
foreach $i (0..$#lines)
{
  #перебираем все столбцы
  foreach $j (0..$#array) {

   #если это первый столбец, открываем тег <span>
     substr ($lines[$i], $array[$j]->{pos}, 0) = \'<span style="background-color:\'.$colors[$j%2].\'">\'
           if $j==0;

/*Если столбец не первый, надо закрыть предыдущий тег <span> и открыть новый. К позиции столбца в текстовом файле надо добавить 37 (длина открывающего тега <span>) для предыдущего столбца и 44 (длина открывающего и закрывающего тегов <span>) для всех обработанных столбцов кроме предыдушего*/

     my $pos = 37 + $array[$j]->{pos} + 44*($j-1);
     my $old_line = $lines[$i];
     substr ($lines[$i], $pos, 0, \'</span><span style="background-color:\'.$colors[$j%2].\'">\')
         or die ("length: ".length($lines[$i]).", pos: ".$pos.", : ".$j. "\\nline: \'".$lines[$i]."\'" ."\\nold_line: \'".$old_line."\', old_length: ".length($old_line))
	
  if $j>=1;
    }
    $lines[$i] .= "</span>";
#замену пробелов на   пока уберём
    $page .= tt($lines[$i]) . br();
}

print $page;

exit(0);


Как видно die() выводит отладочную информацию такую как содержимое и длина строки до и после substr(), а также позиция, на которую вставляется новый текст. Программа вылетает при $j=1, но при этом die() выдаёт, что строка с тегами была добавлена в исходную строку, т.е. $old_line отличается от $line[$i], а именно:
length187pos42j1
line
: \'<span style="background-color:green">1    </span><span style="background-color:white">Абдряшевская СОШ   453630, д. Абдряшево   1        да              Зайнуллин      нач.        (34772)\'
old_line: \'<span style="background-color:green">1    Абдряшевская СОШ   453630, д. Абдряшево   1        да
Зайнуллин      нач.        (34772)\', old_length: 143 at a.pl line 14.


Как ещё можно "окружить" тегами часть строки, если я знаю значение начальной и конечной позиции? s/// не предлагать, т.к. значения столбцов не уникальны для строки.

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #5 : 06 Августа 2004, 15:32:12 »
у меня этот код работает на.
я бы тебе посоветовал вывести в отладку переменные
$array[$j]->{pos}
$pos
вероятно на твоих реальных данных результат может быть иным.
The documentations is your friend

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #6 : 06 Августа 2004, 15:36:03 »
код:
#!/usr/bin/perl

my @lines;
#пример строки из исходного текстового файла
push (@lines"1    Абдряшевская СОШ   453630, д. Абдряшево
1        да              Зайнуллин      нач.        (34772)"
);

my @array;
push (@array, {pos=>0},  {pos=>5}, {pos=>24}, {pos=>47}, {pos=>56}, {pos=>72}, {pos=>87}, {pos=>99});

#массив цветов
my @colors = (\'green\',\'white\');

#перебираем все строки исходного файла
foreach $i (0..$#lines)
{
  #перебираем все столбцы
  foreach $j (0..$#array) {

   #если это первый столбец, открываем тег <span>
     substr ($lines[$i], $array[$j]->{pos}, 0) = \'<span style="background-color:\'.$colors[$j%2].\'">\'
           if $j==0;

     my $pos = 37 + $array[$j]->{pos} + 44*($j-1);
     my $old_line = $lines[$i];
     substr ($lines[$i], $pos, 0, \'</span><span style="background-color:\'.$colors[$j%2].\'">\') if $j>=1;
    }
    $lines[$i] .= "</span>";
#замену пробелов на   пока уберём
    $page .= $lines[$i];
}

print $page;

exit(0);


результат:
<span style="background-color:green">1    </span><span style="background-color:white">Абдряшевская СОШ   </span><span style="background-color:green">453630дАбдряшево   </span><span style="background-color:white">
1       </span><span style="background-color:green"да             </span><span style="background-color:white"Зайнуллин     </span><span style="background-color:green"нач.       </span><span style="background-color:white"> (34772)</span>
The documentations is your friend

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #7 : 06 Августа 2004, 15:37:02 »
perl -v

This is perl, v5.8.0 built for i686-linux
The documentations is your friend

Оффлайн Forza

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 288
  • +0/-0
  • 0
    • Просмотр профиля
проблемы с substr()
« Ответ #8 : 06 Августа 2004, 15:41:25 »
Цитировать
NeoNox:
я бы тебе посоветовал вывести в отладку переменные
$array[$j]->{pos}
$pos


$pos и так есть в отладке. См. первую строку: length: 187, pos: 42, j: 1.
А $array[$j]->{pos} не нужен, т.к. на его основе высчитывается $pos, который в дальнейшем используется и показывается в отладке.

Цитировать
NeoNox:
вероятно на твоих реальных данных результат может быть иным.

Дело в том, что у меня и с этой одной строкой, которую я привёл в примере, ничего не получается. :-(
Как раз сообщение об ошибке от die(), которое я указал внизу предыдущей мессаги, и относится именно к этому примеру.

Мда, странно всё.
Попробую тогда по-иному: доставать из $lines[$i] куски строки, обрамлять их тегами и результат сразу же записывать в $page.

Оффлайн vladsu

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 271
  • +0/-0
  • 0
    • Просмотр профиля
    • http://vladislavsurguchev.eu/
проблемы с substr()
« Ответ #9 : 07 Августа 2004, 03:48:13 »
Если я правильно понял задачу, то все делается значительно проще


use strict;

my $format = \'a5a19a23a9a16a15a12a7\';

my @colors = (\'green\',\'white\');
my $i = 0;

while ( ) {
        print map { \'\'.$_->[1]."\\n" }
              map { [$_ =~ s/ +$//g,$_]}
              unpack($format, $_);
}

__DATA__
1    Абдряшевская СОШ   453630, д. Абдряшево   1        да              Зайнуллин      нач.        (34772)
----------------------------------------------
Мой сайт чёрно-белых фотографий из разных уголков мира тут

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28