Модераторы: korob2001, ginnie
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Зависание скрипта при проходе по массиву, в чем причина, понять не могу 
:(
    Опции темы
Chuck
Дата 15.9.2008, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Сушня
**


Профиль
Группа: Эксперт
Сообщений: 442
Регистрация: 12.12.2003
Где: Узбекистан, Ташке нт

Репутация: нет
Всего: 9



Доброго времени суток, друзья.

Есть в БД таблица
sections
---------------------
section_id
section_parent
section_name

Которая содержит данные о секциях в древовидной структуре (каждый элемент, кроме головных, имеет ID родительской секции).
Задача состоит в том, чтобы написать функцию, которая бы вытаскивала из этого списка только те секции, section_parent которых равен определенному значению.

Был написан вот такой вот тестовый скрипт:
Код

#!C:\perl\bin\perl -w

use CGI;
use CGI::Carp 'fatalsToBrowser';
use DBI;
use strict;
use utf8;
use warnings;

# Dirs ...
our $root_dir = 'E:/work/current/freelance/ndvakt.uz';
our $tempales_dir = $root_dir . '/cgi-bin/templates';

my @sections = ();

sub get {
    my $parent = shift;
    foreach my $section (@sections) {
        if ($parent eq $section->{section_parent}) {
            my $sid = $section->{section_id};
            my $s = $sections[$sid];
            print %{$s};
            get($sid);
        }
    }
}


# Connect to database ...
our $dbc = DBI->connect('DBI:mysql:ndvakt:localhost:3306', 'root', 'psw123');
$dbc->do('SET NAMES utf8');

print "Content-type: text/html;charset=utf-8\n\n";
my $res = $dbc->prepare('SELECT * FROM sections');
$res->execute();
while (my $section = $res->fetchrow_hashref()) {
    my $sid = $section->{'section_id'};    
    $sections[$sid] = $section;
}
$res->finish();

get(20);


Однако, при выполнении данного кода перл-интерпретатор просто зависает. 

Пожалуйста, подскажите, в чем причина и как правильно реализовать задачу.
PM MAIL WWW GTalk   Вверх
nitr
Дата 16.9.2008, 01:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 12
Всего: 84



Chuck, считаю что зависание в вашем рекурсив.обходе - sub get.


--------------------
PM   Вверх
Chuck
Дата 24.9.2008, 09:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Сушня
**


Профиль
Группа: Эксперт
Сообщений: 442
Регистрация: 12.12.2003
Где: Узбекистан, Ташке нт

Репутация: нет
Всего: 9



Простите, не понял. Я понимаю, что зависает именно в этой функции, однако, как этого избежать?
PM MAIL WWW GTalk   Вверх
nitr
Дата 24.9.2008, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 12
Всего: 84



покажите здесь
Код
...
use Data::Dumper 'Dumper';

...
print Dumper(@sections);
#get(20);



--------------------
PM   Вверх
Chuck
Дата 3.10.2008, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Сушня
**


Профиль
Группа: Эксперт
Сообщений: 442
Регистрация: 12.12.2003
Где: Узбекистан, Ташке нт

Репутация: нет
Всего: 9



Извиняюсь, что пропал, была командировка. 

Дампер вывел вполне адекватные результаты, на мой взгляд.

На что я должен обратить внимание?

Код

$VAR1 = undef;
$VAR2 = {
          'template' => 'admin:mainpage',
          'section_alias' => 'admin',
          'section_order' => '0',
          'section' => 'Админ панель',
          'section_id' => '1',
          'show_menu' => '1',
          'default_section' => '0',
          'section_parent' => '0',
          'section_level' => '1'
        };
$VAR3 = {
          'template' => 'admin:users',
          'section_alias' => 'users',
          'section_order' => '0',
          'section' => 'Пользователи',
          'section_id' => '2',
          'show_menu' => '1',
          'default_section' => '0',
          'section_parent' => '1',
          'section_level' => '2'
        };
$VAR4 = {
          'template' => 'admin:sections',
          'section_alias' => 'sections',
          'section_order' => '0',
          'section' => 'Секции',
          'section_id' => '3',
          'show_menu' => '1',
          'default_section' => '0',
          'section_parent' => '1',
          'section_level' => '2'
        };
$VAR5 = {
          'template' => 'admin:content',
          'section_alias' => 'content',
          'section_order' => '0',
          'section' => 'Контент',
          'section_id' => '4',
          'show_menu' => '1',
          'default_section' => '0',
          'section_parent' => '1',
          'section_level' => '2'
        };
$VAR6 = undef;
$VAR7 = undef;
$VAR8 = undef;
$VAR9 = undef;
$VAR10 = undef;
$VAR11 = undef;
$VAR12 = undef;
$VAR13 = undef;
$VAR14 = undef;
$VAR15 = undef;
$VAR16 = undef;
$VAR17 = undef;
$VAR18 = undef;
$VAR19 = undef;
$VAR20 = undef;

PM MAIL WWW GTalk   Вверх
ginnie
Дата 4.10.2008, 09:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 4
Всего: 49



Chuck, мне кажется, что с такими данными у Вас в строке

Код

if ($parent eq $section->{section_parent}) {


должно быть сообщение об ошибке, про невозможность использования undef в качестве ссылки на хэш.
Кроме того, в этой строке правильнее использовать == вместо eq, т.к. сравниваются числовые значения.


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
nitr
Дата 4.10.2008, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 12
Всего: 84



Chuck, тогда объясните, что должна делать данная функция smile ?
Например, из вашего скрипта видно, что необходимо вернуть "секции", у которых в "родителях" section_parent=20.
Но зачем тут "на первый взгляд" рекурсия?

Если всё же верно:
Цитата(Chuck @  15.9.2008,  20:21 Найти цитируемый пост)
Задача состоит в том, чтобы написать функцию, которая бы вытаскивала из этого списка только те секции, section_parent которых равен определенному значению.

ТО:
  Из sub get уберите get($sid);.

Добавлено через 3 минуты и 37 секунд
А если все секции и внутри веток, то:
 У вас неверно создается древовидная структура!

Добавлено через 6 минут и 13 секунд
Я всегда привожу примерную структуру, на которой можно выявлять некоторые ошибки...
Вот как пример (сильно не бить за стиль... утро smile) ):
Код
#!/usr/bin/perl
use strict;
use warnings;

my @sections = (
    {
        'section_parent' => '0', 
        'section_id' => '0',
        'section' => 'Parent',
    },
    {
        'section_parent' => '0', 
        'section_id' => '1',
        'section' => 'Menu',
    },
    {
        'section_parent' => '1', 
        'section_id' => '2',
        'section' => 'Sub Menu1',
    },
    {
        'section_parent' => '2', 
        'section_id' => '3',
        'section' => 'Sub Menu1_1',
    },
    {
        'section_parent' => '2', 
        'section_id' => '4',
        'section' => 'Sub Menu1_2',
    },
    {
        'section_parent' => '4', 
        'section_id' => '5',
        'section' => 'Menu',
    },
    {
        'section_parent' => '4', 
        'section_id' => '6',
        'section' => 'Sub Menu1_1_2',
    },
    {
        'section_parent' => '6', 
        'section_id' => '7',
        'section' => 'Sub Menu1_1_1_2',
    },
    {
        'section_parent' => '7', 
        'section_id' => '8',
        'section' => 'Menu',
    },
    {
        'section_parent' => '6', 
        'section_id' => '9',
        'section' => 'Sub Menu2_1_1_2',
    },
    {
        'section_parent' => '9', 
        'section_id' => '10',
        'section' => 'Menu',
    },
);

sub get {
    my $parent = shift;
    foreach my $section (@sections) {
        if ( $parent == $section->{section_parent} ) {
            my $sid = $section->{section_id};
            my $s = $sections[$sid];
            print %{$s}, "\n";
            get($sid);
        }
    }
}

get(1);



--------------------
PM   Вверх
Chuck
Дата 4.10.2008, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Сушня
**


Профиль
Группа: Эксперт
Сообщений: 442
Регистрация: 12.12.2003
Где: Узбекистан, Ташке нт

Репутация: нет
Всего: 9



ginnie, вы правы, но скрипт все равно зависает.

Мне кажется, это потому что я использую fetchrow_hashref();
И не правильно работаю со ссылками. Но вот как тут разобраться - не понимаю.

nitr, ваш скрипт работает, и сопоставив функции get() мою и вашу, я понял, что проблема не в ней, а в том, что я храню в массиве ссылки.
PM MAIL WWW GTalk   Вверх
nitr
Дата 4.10.2008, 13:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 12
Всего: 84



Chuck, я склоняюсь к формированию структуры!
Если немного измените мой скрипт, он сразу же зависнет smile (где менять - даю вам подумать)

Добавлено через 53 секунды
Подскажу - в структуре, а точнее @sections

Добавлено через 1 минуту и 32 секунды
Цитата(Chuck @  4.10.2008,  13:02 Найти цитируемый пост)
а в том, что я храню в массиве ссылки.

это нормально, что вы там ещё хранить хотели ;) ?


--------------------
PM   Вверх
Chuck
Дата 6.10.2008, 07:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Сушня
**


Профиль
Группа: Эксперт
Сообщений: 442
Регистрация: 12.12.2003
Где: Узбекистан, Ташке нт

Репутация: нет
Всего: 9



Доброе утро, на ум приходит только одно: элементы массива реализовать ссылками на хеши.
PM MAIL WWW GTalk   Вверх
unicross
Дата 6.10.2008, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 422
Регистрация: 15.6.2008

Репутация: 2
Всего: 53



Добавьте одну строку в функцию get()

Код

       next if ($section == undef);



Код

sub get {
    my $parent = shift;
    foreach my $section (@sections) {
        next if ($section == undef);
        if ( $parent == $section->{section_parent} ) {
            my $sid = $section->{section_id};
            my $s = $sections[$sid];
            print %{$s}, "\n";
            get($sid);
        }
    }
}

PM MAIL WWW   Вверх
ginnie
Дата 6.10.2008, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Комодератор
Сообщений: 1287
Регистрация: 6.1.2008
Где: Москва

Репутация: 4
Всего: 49



unicross, это где же Вас такому научили?

Код

next if ($section == undef);


у нас все пишут

Код

next if (!defined $section);


или

Код

next unless (defined $section);


Это сообщение отредактировал(а) ginnie - 6.10.2008, 13:04


--------------------
Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям. (Мартин Фаулер. Рефакторинг)
PM MAIL Skype Jabber   Вверх
unicross
Дата 6.10.2008, 14:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 422
Регистрация: 15.6.2008

Репутация: 2
Всего: 53



Да. Так будет правильнее

Код

next if (!defined $section);


Sorry. Еще не проснулся...
PM MAIL WWW   Вверх
nitr
Дата 6.10.2008, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2543
Регистрация: 10.2.2006
Где: Россия :)

Репутация: 12
Всего: 84



Цитата(Chuck @  6.10.2008,  07:47 Найти цитируемый пост)
Доброе утро, на ум приходит только одно: элементы массива реализовать ссылками на хеши. 

у вас иначе? smile "тыкните пальцем" где не так уже...

У вас формирование имхо неверное, там совсем маааленькая ошибка. которая ведет к такой большой.
Возможно у вас первые три элемента зацикливают...

Цитата(nitr @  4.10.2008,  11:42 Найти цитируемый пост)
Из sub get уберите get($sid);.

что вам это дает? Проверьте.


--------------------
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: CGI программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к CGI программированию
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", качать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: разработка для Web | Следующая тема »


 




[ Время генерации скрипта: 0.0892 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.