Необходимо сделать, чтобы переменная, используемая в рекурсивной функции (при каждом первом вызове последней принимала одно и то же значение)

Модератор: Модераторы разделов

promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Я вижу 2 пути:

1) Объявляем переменную (допустим "c") внешней, инициализируем её нужным значением. Затем делаем вызов рекурсивной функции a (), в которой и используем эту переменную с нужным уcтановленным значением. Этот способ мне неудобен, ибо если придётся скопировать куда-нибудь текст функции a (), в это же место придётся скопировать и объявление внешней переменной "c". Нельзя ли обойтись без "перетаскивания" переменной "c" за функцией "a"?

2)Объявляем функцию a () как принимающую аргумент: a (int c). Первый вызов будет выглядеть так: a (<необходимое значение>) Этот способ был бы удобен, если бы не одно "но": я предполагаю, что разрабатываемая мной функция a () при первом вызове будет использовать всегда одно и то же значение "с". И это значение равно 0. Не один, не два, а именно 0 И мне при каждом первом вызове a () (она может вызываться в разных программах). Необходимо будет вручную писать одно и то же значение аргумента 0. Вот так: a (0)

Как обойтись без такого прописывания? Или третьего способа не дано? Заранее спасибо.

P. S. Объявить в функции а () переменную "c" и инициализировать её нужным мне значением я тоже не могу, ибо предполагается, что при каждом новом рекурсивном вызове функции a () переменная "c" должна быть разной (должна увеличиваться на 1)
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Burnout
Сообщения: 88
ОС: Gentoo Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение Burnout »

А чем не вариант указать 0 умолчальным аргументом при объявлении рекурсивной ф-ции?
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Вариант! Чувствую, что вариант! Вот нечто подобное я и мыслил! Только... как указывать-то? Я прямо в растерянности- даже упоминания об этом не мелькало нигде в книгах. Вот, к примеру, K&R. Судя по полезности Вашего предложения я давно должен был о нём прочесть. Не могу найти.
Язык C
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
Voice
Сообщения: 1073
Статус: столлманист
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение Voice »

Вот это Вы хотели?

Код: Выделить всё

#include <stdio.h>

void foo()
{
    static int c = 0;
    c++;

    printf("%d\n", c);

    if(c < 10)
        foo();
}

int main()
{
    foo();

    return 0;
}
"И может собственных Платонов и быстрых разумом Невтонов российская земля рождать."
М. В. Ломоносов
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Да! Но как это может быть? (При задавании вопроса я, естественно, имел ключевое слово "static" ввиду. Но мне и в голову не приходило с ним эксперементировать) ибо : (цитата из K&R)

"Объявление static применимо и к внутренним переменным. Внутренние статические переменные являются локальными по отношению к конкретной функции, как и автоматические. Но, в отличиеот автоматических статические переменные продолжают существовать непрерывно, а не создаются и уничтожаются при вызове и завершении функции. Получается, что внутренние статические переменные являются средством постоянного хранения скрытой информации внутри одной функции"

Я не прочёл здесь, что объявление статической функции действительно один раз, а остальные объявления игнорируются компилятором... Или это ускользнуло от моего внимания?:

"Это является ключевой концецией статических переменных- они не создаются и не исчезают при вызове и окончании работы функции. Значения таких переменных остаются такими, какими они были при последнеи вызове функции, и не изменяются до следующего вызова" (Стефан Кочан)

Меж тем примеров с рекурсией в книге нет. Иначе и вопроса бы не возникло. Ну, не написано нигде, что эти правила распространяются и на рекурсивные вызовы. Странно, конечно. Надо будет найти, где это прописано явно, а не косвенно.

Большое спасибо.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение KiWi »

ВЕЗДЕ написано явно:
Но, в отличиеот автоматических статические переменные продолжают существовать непрерывно, а не создаются и уничтожаются при вызове и завершении функции.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Да! Я понял, что мне мешало применить "static" и что держит меня в недоумении! То, что значения этих переменных постоянны, это да. Но они постоянны всегда! Переменная "c", инициализированная значением 0, должна всегда оставаться 0! Ибо вот:

"Значения таких переменных остаются такими, какими они были при последнем вызове функции, и не изменяются до следующего вызова" (Стефан Кочан)

Имеем вызов функции foo, в нём объявлена стачиеская переменная "c равная 0. И она должна остаться такой какой была до следующего вызова! Почему она вдруг инкременируется? Cтановится вдруг равной 1? Написано же: "Значения таких переменных остаются такими, какими они были при последнем вызове функции, и не изменяются до следующего вызова" (Стефан Кочан) Я уже повторяюсь, извините.

Ну, понятно, что если переменная объявлена со static то всякое обращение к такой переменной есть обращение к одной и той же области памяти. Так? Так. Но я прочёл, помимо этого, что в этой области памяти должно быть представлено одно и только одно значение!
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
azrael
Сообщения: 73
ОС: KUbuntu 8.04 Hardy Heron

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение azrael »

promov, цитата в вашем последнем посте, очевидно, взята из описания какого-то конкретного примера, где это действительно так. В общем случае это неверно.
Статические переменные - это, как ни странно, все же переменные, а не константы.
Спасибо сказали:
Аватара пользователя
Shura
Сообщения: 1537
Статус: Оказывается и без KDE есть жизнь
ОС: FreeBSD 8.0-RC2

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение Shura »

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

Код: Выделить всё

void foo(int c=0);

Тогда при первом ее вызове аргумент можно не указывать, а внутри этой функции вызывать её же с нужным аргументом.
Rock'n'roll мертв © БГ
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение wzrd »

promov писал(а):
28.02.2008 21:30
Да! Я понял, что мне мешало применить "static" и что держит меня в недоумении! То, что значения этих переменных постоянны, это да. Но они постоянны всегда! Переменная "c", инициализированная значением 0, должна всегда оставаться 0! Ибо вот:

"Значения таких переменных остаются такими, какими они были при последнем вызове функции, и не изменяются до следующего вызова" (Стефан Кочан)

Имеем вызов функции foo, в нём объявлена стачиеская переменная "c равная 0. И она должна остаться такой какой была до следующего вызова! Почему она вдруг инкременируется? Cтановится вдруг равной 1? Написано же: "Значения таких переменных остаются такими, какими они были при последнем вызове функции, и не изменяются до следующего вызова" (Стефан Кочан) Я уже повторяюсь, извините.

Ну, понятно, что если переменная объявлена со static то всякое обращение к такой переменной есть обращение к одной и той же области памяти. Так? Так. Но я прочёл, помимо этого, что в этой области памяти должно быть представлено одно и только одно значение!

блин. вы сами своим словам противоречите.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Нет. Имеем рекурсивную функцию a ()

void a () {
static int c= 0;
c++;
a ();
}

Самый первый вызов функции даёт нам с=0, потом с станвится равной единице. Хотя она не имеет права такой становиться! Она, пока функция а снова не вызовется не должна изменяться! "не изменяются до следующего вызова" (Стефан Кочан)

Вы поймите меня правильно, я принял на веру то, что мне предложили и так сейчас делаю. И делал бы дальше. Но раз уж Вы снова к этому вопросу возвращаетесь- давайте уж добьём его тогда, что ли.

Ну да, переменная "с" не константа. Но дело-то ведь не в том, как её назвать, дело в том, как она будет себя вести, согласно этому называнию. По мне (и по цитатам тоже) получается, что именно как константа и должна себя вести
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
Uncle_Theodore
Сообщения: 3339
ОС: Slackware 12.2, ArchLinux 64

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение Uncle_Theodore »

<Передумал>
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение wzrd »

promov писал(а):
01.03.2008 17:42
Нет. Имеем рекурсивную функцию a ()

void a () {
static int c= 0;
c++;
a ();
}

Самый первый вызов функции даёт нам с=0, потом с станвится равной единице. Хотя она не имеет права такой становиться! Она, пока функция а снова не вызовется не должна изменяться! "не изменяются до следующего вызова" (Стефан Кочан)

Вы поймите меня правильно, я принял на веру то, что мне предложили и так сейчас делаю. И делал бы дальше. Но раз уж Вы снова к этому вопросу возвращаетесь- давайте уж добьём его тогда, что ли.

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

где в вашей цитате говорится что эта переменная константа??? там говорится что по завершению функции память, выделенная как статическая (static), cохраняется, а не затирается и это не значит что её ничего нельзя присваивать во время выполнения функции. не будем больше спорить.
Спасибо сказали:
Аватара пользователя
azrael
Сообщения: 73
ОС: KUbuntu 8.04 Hardy Heron

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение azrael »

promov, когда сомневаетесь в ответе на подобные вопросы, попробуйте себе ответить на другой простой вопрос: чем отличается константный указатель от указателя на константу? Ответ придет сам собой.
А утверждение Стефана Кочана, еще раз повторяю, следует читать в контексте, а не само по себе. И не надо верить в то, что написано в книжке, как в абсолютную истину :)
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

А сейчас нужно доразбираться с этим и закрыть тему.
Shura писал(а):
01.03.2008 16:05
Думаю, что можно обойтись и без использования static.
Для этого необходимо определить функцию как

Код: Выделить всё

void foo(int c=0);

Тогда при первом ее вызове аргумент можно не указывать, а внутри этой функции вызывать её же с нужным аргументом.

Ваше предложение не работает. Имеем исполняемый файл <имя файла>

Код: Выделить всё

#include <stdio.h>

    void a (int c= 0) {
     printf ("c= %d\n", c);
     c++;
     if (c< 5){
      a ();
     }
    }

    int main () {
     void a (int c);
     a ();
     return 0;
    }

Команда сс <имя файла> Вывод

Код: Выделить всё

po.c:3: error: expected ';', ',' or ')' before '=' token
    po.c: In function 'main':
    po.c:13: error: too few arguments to function 'a'

Синтаксис не тот, как видим. Нельзя в определении функции писать void a (int c= 0), а нужно всё-таки писать void a (int c)
Честно говоря, я рад- но не тому, что Вы оказались неправы (это побочное явление) а тому, что хоть одной неоговорённой допустимостью в языке C стало меньше.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение v04bvs »

promov писал(а):
02.03.2008 16:22
А сейчас нужно доразбираться с этим и закрыть тему.
Ваше предложение не работает. Имеем исполняемый файл <имя файла>

Код: Выделить всё

#include <stdio.h>

     void a (int c= 0) {
      printf ("c= %d\n", c);
      c++;
      if (c< 5){
       a ();
      }
     }

     int main () {
      void a (int c);
      a ();
      return 0;
     }

Команда сс <имя файла> Вывод

Код: Выделить всё

po.c:3: error: expected ';', ',' or ')' before '=' token
     po.c: In function 'main':
     po.c:13: error: too few arguments to function 'a'

Синтаксис не тот, как видим. Нельзя в определении функции писать void a (int c= 0), а нужно всё-таки писать void a (int c)
Честно говоря, я рад- но не тому, что Вы оказались неправы (это побочное явление) а тому, что хоть одной неоговорённой допустимостью в языке C стало меньше.


Так можно писать в С++, но не в С.
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение wzrd »

может так?

Код: Выделить всё

void foo ( c )
int c = 0;
{

}
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Не надо гадать. Нужно попробовать у себя на компьютере и в случае удачи предложить.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали:
Аватара пользователя
wzrd
Сообщения: 323
ОС: Debian Lenny

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение wzrd »

promov писал(а):
02.03.2008 17:33
Не надо гадать. Нужно попробовать у себя на компьютере и в случае удачи предложить.

ну попробуйте. я не дома и у меня нет компилятора. и при том у вас код не правильный: функция a() вызывается без аргументов, а надо a ©.
Спасибо сказали:
promov
Сообщения: 384
Статус: Участник
ОС: Debian GNU/Linux

Re: Необходимо сделать, чтобы переменная, используемая в рекурсивной функции

Сообщение promov »

Не помогает. Да и не должно помочь- всё равно выдаётся ошибка в синтаксисе при определении аргументов функции. Впрочем, уже выяснено, что предложенный мне вариант для C++, а я на С пишу.
Зачем хорёк пошел в ларёк, зачем барсук полез на сук...
Мораль легко уразуметь: зачем на бал пришёл медведь?
Спасибо сказали: