OVH Cloud OVH Cloud

(je suis débutant en c) je ne vois d'instruction pour boucler

156 réponses
Avatar
bpascal123
Bjr,sr,
Voici une fonction tr=E8s simple qui r=E9agit comme s'il y avait une
boucle alors qu'en apparence il n'y en a pas :

#include <stdio.h>

void f2(int b);
void f1(int a);

int main(void)
{
f1(30);

return 0;
}

void f1(int a)
{
if( a )
f2( a - 1 );
printf("%d ", a);
}

void f2(int b)
{
printf(" . ");
if(b)
f1( b - 1 );
}

http://www.java2s.com/Code/C/Function/Functioncalleachother.htm

Merci,
Pascal

10 réponses

Avatar
bpascal123
On Nov 29, 3:24 am, candide wrote:
a écrit :

>> void f(int n)
>> {
>>   if (n > 0)
>>     {
>>       f(n - 1);
>>       printf("%d ", (n - 1) * (n - 1));
>>     }

>> }

> Qu'est-ce qui se produit après "f(n-1)" ?La séquence "rembobine"???

Oui

> càd après void f(10) ;

Euh non, void f(10) ne veut rien dire.

Bon pour simplifier les explications, supposons que le code soit

#include <stdio.h>

void f(int n)
{
  if (n > 0)
    {
      f(n-1)
      printf("%d ", (n - 1) * (n - 1));
    }

}

int main(void)
{
  f(3);
  printf("n");
  return 0;

}

et qui affiche :

0 1 4

Au premier appel f(3), immédiatement f est relancée par l'appel f(2) qui
lui même est relancé par f(1) qui à nouveau appelle f(0). C'est
l'empilement des appels. Donc pour chacun de ces appels, l'exécution de
la fonction f s'est arrêté à la ligne suivante :

      f(n - 1);

Maintenant, à cause de la ligne

if (n > 0)

f(0) se termine dans rien faire et c'est là que vient le point capital :
on revient à la fonction appelante (/return to the caller/) qui était f
bien sûr avec le paramètre n=1. Donc le programme continue après la ligne

      f(n - 1);

et donc avec l'instruction

printf("%d ", (n - 1) * (n - 1));

où n=1 ce qui affiche 0. Vu le code de f, l'exécution de f(1) se te rmine
et comme f(1) avait été appelé par f(2), on continue le programme l à où
il était resté, le printf est exécuté. Bon, et ainsi de suite jus qu'au
premier appel (n=3) et qui va afficher 4 puis se terminer. La fonction
qui avait appelée f(3) est main() donc on revient à main, ce qui clot le
programme.

Le fait que la fonction soit récursive ne change en fait
fondamentalement rien à la façon dont les appels sont effectués et achevés.

> void f(9) au second appel )à cause de f
> (n-1), ...void f(8) ... où  printf est inclus avant que la séquen ce
> rembobine dans ce cas, 81 64 42 ...devrait être affichés ?

Non, justement. Modifie le code en plaçant le f(n-1) après le printf( )
et tu verras ce qu'il se passe.



merci
Avatar
Wykaaa
candide a écrit :
Wykaaa a écrit :

Alors je comprends que tu n'aime pas la récursivité.



Au contraire, j'adore pratiquer la récursivité et je peux passer des
heures à épurer un code récursif.

Je ne vois pas ce qui te laisse dire ça. Tout ce dont tu as parlé
précédemment n'a rien à voir avec le C me semble-t-il et je ne vois pas
en quoi ça m'aiderait à mieux coder en C.



Non, tout ce que j'ai dis a à voir avec la récursivité et ça s'applique
à tous les langages où la récursivité peut être mise en oeuvre.


Oui la suite de Fibonacci écrite de cette manière n'est pas optimisée
car les mêmes évaluations se font à plusieurs endroits.
ce qui une fois de plus montre qu'il y a une distance entre le concept
souvent simple voire trivial, et l'implémentation. Bref, ne confondons
pas récursivité de salon et récursivité de codeur.


Ce n'est pas à moi que tu vas tenir ce discours. J'ai trempé pendant 10
ans dans les compilateurs et il y avait de la récursion à tous les
étages...



La question n'était pas là, tu m'as dit qu'un algorithme récursif devait
suivre "au plus près" la définition mathématique. Mon exemple ci-dessus
prouve le contraire et d'autres exemples pourraient montrer que la
récursivité est plus compliquée à comprendre que ce que dit Richard
Delorme.



Je suis d'accord avec Richard Delorme. La récursivité n'est pas dure à
comprendre, du moins pour la récursion directe (une fonction qui
s'appelle elle-même) car, dans ce cas, il suffit de dire que l'appel
récursif doit être tel que l'on est certain, qu'à un moment donné, la
condition d'arrêt sera rencontrée.
Avatar
bpascal123
> Au premier appel f(3), immédiatement f est relancée par l'appel f(2) qui
lui même est relancé par f(1) qui à nouveau appelle f(0). C'est
l'empilement des appels. Donc pour chacun de ces appels, l'exécution de
la fonction f s'est arrêté à la ligne suivante :



Bonjour,
J'ai pu comprendre le concept de récursivité avec votre explication.
Je comprends également que pour comprendre des récursions plus
"sophistiquées", une compréhension de ce qui se passe en compilation/
assembleur est nécessaire. Je pense à l'accès des données en mémo ire.
Je ne suis pas encore là, je souhaiterais sortir de ce livre sur
l'architecture des ordinateurs pour passer à la pratique mais si je
vais trop vite, je pense que je devrais retourner à ce livre (et
puisl'inconvénient d'etre autodidacte; il y a aussi le manque de
motivation). Mais selon ce qui est dit dans cette discussion,
comprendre la récursivité permet de comprendre for et while ...
Ce livre n'est pas à coté maintenant mais j'ai en mémoire d'un
pointeur IP ou quelque chose comme ca qui "empile" le résultat des
fonctions dans le stack ou heap je crois et retourne à l'adresse d'une
données dans un buffer selon les instructions du séquenceur ou de
l'unité de commande...
Je pensais que IP n'était employé que pour les fonctions vers les
pointeurs. Et c'est pourquoi je n'ai pas fait le lien en
premier'depuis le début de cette discussion et votre réponse) avec les
fonctions de récursivité qui ne sont pas des fonctions vers les
pointeurs.
Peut-être c'est un autre sujet, mais une fonction vers un pointeur
pourrait rendre l'appel d'une fonction récursive plus rapide?
Merci,
Pascal
Avatar
Senhon
a écrit dans le message de groupe de discussion
:

Au premier appel f(3), immédiatement f est relancée par l'appel f(2) qui
lui même est relancé par f(1) qui à nouveau appelle f(0). C'est
l'empilement des appels. Donc pour chacun de ces appels, l'exécution de
la fonction f s'est arrêté à la ligne suivante :



Bonjour,
J'ai pu comprendre le concept de récursivité avec votre explication.
Je comprends également que pour comprendre des récursions plus
"sophistiquées", une compréhension de ce qui se passe en compilation/
assembleur est nécessaire. Je pense à l'accès des données en mémoire.
Je ne suis pas encore là, je souhaiterais sortir de ce livre sur
l'architecture des ordinateurs pour passer à la pratique mais si je
vais trop vite, je pense que je devrais retourner à ce livre (et
puisl'inconvénient d'etre autodidacte; il y a aussi le manque de
motivation). Mais selon ce qui est dit dans cette discussion,
comprendre la récursivité permet de comprendre for et while ...
Ce livre n'est pas à coté maintenant mais j'ai en mémoire d'un
pointeur IP ou quelque chose comme ca qui "empile" le résultat des
fonctions dans le stack ou heap je crois et retourne à l'adresse d'une
données dans un buffer selon les instructions du séquenceur ou de
l'unité de commande...
Je pensais que IP n'était employé que pour les fonctions vers les
pointeurs. Et c'est pourquoi je n'ai pas fait le lien en
premier'depuis le début de cette discussion et votre réponse) avec les
fonctions de récursivité qui ne sont pas des fonctions vers les
pointeurs.
Peut-être c'est un autre sujet, mais une fonction vers un pointeur
pourrait rendre l'appel d'une fonction récursive plus rapide?
Merci,
Pascal



Houlala, tu embrouilles tout.
Avatar
Senhon
a écrit dans le message de groupe de discussion
:

Au premier appel f(3), immédiatement f est relancée par l'appel f(2) qui
lui même est relancé par f(1) qui à nouveau appelle f(0). C'est
l'empilement des appels. Donc pour chacun de ces appels, l'exécution de
la fonction f s'est arrêté à la ligne suivante :



Bonjour,
J'ai pu comprendre le concept de récursivité avec votre explication.
Je comprends également que pour comprendre des récursions plus
"sophistiquées", une compréhension de ce qui se passe en compilation/
assembleur est nécessaire. Je pense à l'accès des données en mémoire.
Je ne suis pas encore là, je souhaiterais sortir de ce livre sur
l'architecture des ordinateurs pour passer à la pratique mais si je
vais trop vite, je pense que je devrais retourner à ce livre (et
puisl'inconvénient d'etre autodidacte; il y a aussi le manque de
motivation). Mais selon ce qui est dit dans cette discussion,
comprendre la récursivité permet de comprendre for et while ...
Ce livre n'est pas à coté maintenant mais j'ai en mémoire d'un
pointeur IP ou quelque chose comme ca qui "empile" le résultat des
fonctions dans le stack ou heap je crois et retourne à l'adresse d'une
données dans un buffer selon les instructions du séquenceur ou de
l'unité de commande...
Je pensais que IP n'était employé que pour les fonctions vers les
pointeurs. Et c'est pourquoi je n'ai pas fait le lien en
premier'depuis le début de cette discussion et votre réponse) avec les
fonctions de récursivité qui ne sont pas des fonctions vers les
pointeurs.
Peut-être c'est un autre sujet, mais une fonction vers un pointeur
pourrait rendre l'appel d'une fonction récursive plus rapide?
Merci,
Pascal



Houlala, tu embrouilles tout, le hard, l'asm, le C.
Suis les recommandations de Candide parce que là tu semble très mal
embringué.
Avatar
Senhon
"Marc Espie" a écrit dans le message de groupe de
discussion : hettah$25et$
In article <4b127610$0$21957$,
candide wrote:



Tu m'emmerdes. Va chercher dans la biblio. J'emploie des termes precis. Tu


...
M'a echappe ? mais va te faire foutre ! C'est pas parce que tu veux


...
Le code plus ou moins standard du pgcd récursif est :


"plus ou moins". c'est juste une autre facon d'ecrire la meme chose.
Tu l'as recopie de quelque part, pour dire que c'est standard ? ou tu
arrives
encore a inventer trois lignes de code sans les repiquer ailleurs ?


...
La j'avoue, la coupe est pleine. J'en ai plus que marre de tes frasques.


...
A force de jouer au "candide" qui reprend tout et tout le monde en jouant
ta mouche du coche, et en voulant imposer aux gens ta vision etriquee du
monde, tu as finalement reussi a m'enerver un peu.


...
M'en fous, a troll, troll-et-demi. J'ai la peau plus solide que toi. Si tu
cherches la bagarre...



Candide explique au moins. Toi, noyé dans l'agressivité, il y a aussi des
explications, mais au final on n'en retient que la vulgarité ( au sens
péjoratif ) de tes propos.
Avatar
Marc Boyer
Bon, mon passé d'enseignant me fait bondir quand je lit tout ça.

Le 28-11-2009, a écrit :

J'interviens su r ce forum de manière irrégulière, pour l'instant je
concentre mes efforts vers les algorithmes. Je me concentre vers le
langage assembleur. Je ne veux pas approfondir. Avant d'aller plus
loin dans la programmation, je veux comprendre ce qui se passe dans la
machine tant que c'est à "porter de mains".



1) Pour apprendre l'algorithmique, le C est un bien mauvais outil.
Les analogies ont toutes leurs limites, alors disons pour simplifier
que C a ses raisons d'être pour les pros, mais que débuter avec ça
en 2009, c'est chercher les complications.

2) L'assembleur, ce n'est justement pas "à portée de main"
A moins que les ASM ne se soient simplifiés depuis 10 ans,
pleins de pb von se poser au débutant.
Ca va commencer avec les opérations signées, non signées,
8,16,32,64 bits, extensions de signes qui feraient presque
aimer celles du C.
On va ajouter les jolis pb d'instructions après le branchement
qui sont quand même exécutés à cause du pipe-line.
Les E/S à base d'interuptions, ça va être une jolie affaire,
surtout que les OS modernes vont surement pas laisser n'importe
quel code accéder comme ça aux périphériques.
On doit pouvoir s'en passer en liant l'ASM à des biblios
d'E/S en C, mais pour le débutant, ça risque d'être pas mal.
Je ne suis pas sur que la gestion des segments mémoire soit
très facile elle aussi....

En fait, je ne viens pas sur ce forum pour savoir ce qui serait bien
pour les intestins ou le foi. J'ai quand même du mal à imaginer que le
langage C est inutile.



Le C n'est pas inutile. Mais apprendre à programmer en autodidacte
en C, c'est un peut comme apprendre à nager dans la rade de Brest
un jour de grand vent... On passe son temps à se noyer (sauf que
dans la natation on se noie qu'une fois).

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?article1&id_mot0
Avatar
Marc Boyer
Le 29-11-2009, Benoit Izac a écrit :
Bonjour,
Ceci dit, pour quelqu'un qui n'est pas informaticien (comme moi) et
qui ne pratique pas la programmation de manière régulière, il ne faut
pas s'attendre à pouvoir programmer en C correctement avant plusieurs
années (pratiquement dix ans dans mon cas mais je suis une
feignasse ;-) ).



Il faut savoir mettre les choses en balance. En gros, en IUT, il
faut 2 ans pour faire un programeur pro débutant.
En 100-200 heures, on peut apprendre des bases correctes de
programmation pour des petits projets (<10.000 lignes).

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?article1&id_mot0
Avatar
Marc Boyer
Le 29-11-2009, Wykaaa a écrit :
candide a écrit :
Il y a plein de programmeurs C (C ou autre) qui n'ont jamais rien
compris à la récursivité donc te crois pas obligé de passer par ce
pensum (qui est aussi une belle tarte à la crème).



La "tarte à la crème" c'est de faire croire qu'on peut se dispenser de
comprendre la récursivité quand on est programmeur. Ceci est totalement
faux.



Ca dépend de la définition de "programmeur".

Tout algorithme qui requiert un automate à pile est souvent beaucoup
plus facile à coder de façon récursive (exemple : la reconnaissance
syntaxique des expressions arithmétiques).
Et puis nombre d'algorithmes sur les arbres, voire les listes, sont bien
plus faciles à programmer de façon récursive.



Mais dans la vraie vie, ils ont été empaquetté dans un truc qui va
s'appeller std::map, java.util.TreeSet, lex/yak ou un truc du genre.

La récursivité est un concept clé de la programmation (et de
l'informatique et des mathématiques en général).



Oui, la notion de calculabilité aussi, et le typage aussi,
et Turing aussi... Est-ce bien nécessaire pour faire un site
de e-commerce ?

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?article1&id_mot0
Avatar
Marc Boyer
Le 29-11-2009, Samuel Devulder a écrit :
Dernier point: en embarque la vitesse n'est pas le problème. Les mhz
sont souvent là plus que nécéssaire (80Mhz pour traiter des trucs qui
arrivent à une freq de 5khz ca le fait les doigts dans le nez), mais ce
qui coince c'est la ROM et la RAM. Elles sont toutes petites en
embarqué, et on préfère de loin, mais vraiment de loin, optimiser en
taille (rom/ram) qu'en vitesse.



Je pense qu'il y a différents mondes "embarqués". Chez les avioneurs,
on réduit aussi le nombre de CPU (pour diminuer l'alim), et on a
tendance à charger la CPU le plus qu'on puisse (en restant déterministe).

Il existe des calculateurs qui sont vraiment très chargés.

Marc Boyer
--
En prenant aux 10% des francais les plus riches 12% de leurs revenus,
on pourrait doubler les revenus des 10% les plus pauvres.
http://www.inegalites.fr/spip.php?article1&id_mot0