Je suis un pdf pour étudier la récursivité et la manipulation de chaînes et je suis tombé dessus. J'ai généralement une compréhension du comportement d'une fonction récursive (toujours pas si bon) mais je ne peux pas le comprendre. Cela inverse la chaîne. Eh bien, l'imprime à l'envers.
void reverse(const char *const sptr);
int main()
{
char sentence[80];
printf("Enter a line of text:\n");
gets(sentence);
printf("\nThe reversed version:\n");
reverse(sentence);
puts("");
return 0;
}
void reverse(const char *const sptr)
{
if(sptr[0] == '\0')
{
return;
}
else{
reverse(&sptr[1]);
putchar(sptr[0]);
}
}
Je ne comprends pas vraiment comment putchar fonctionne à cette occasion. Quelqu'un peut-il me l'expliquer? J'imagine que ce n'est pas seulement pour putchar, comment se comporte la fonction lorsqu'une autre ligne de commande est écrite "après" le rappel de la fonction?
4 Réponses :
cela fonctionne à cause de cela:
putchar(sptr[0]); reverse(&sptr[1]);
vous appelez d'abord les caractères suivants puis vous imprimez le premier, donc
& sptr [1] équivaut à sptr + 1 donc cela pointe vers l'adresse du caractère suivant
si vous inversez les lignes et faites cela:
reverse(&sptr[1]); putchar(sptr[0]);
vous imprimez les caractères dans l'ordre initial
Lorsque vous ne comprenez pas, exécutez simplement le programme dans un débogueur étape par étape
C'est très simple.
Vous appelez récursivement la fonction avec la chaîne comme paramètre. Chaque appel de la chaîne a un caractère plus court (lorsque vous passez le pointeur sur le deuxième char de la chaîne. Lorsqu'elle est de longueur nulle, le premier retour se produit. La chaîne a une longueur de 1 et elle est seulement le dernier caractère de la chaîne. Vous l'imprimez (au fur et à mesure que vous imprimez le premier caractère), puis vous revenez à l'instance où la chaîne faisait 2 caractères de long - vous imprimez le premier caractère qui est le second à partir de la fin. Ensuite, vous retournez et la chaîne est longue de 3 caractères, vous imprimez à nouveau le premier caractère et cela se répète jusqu'à ce que vous imprimiez tous les caractères de la chaîne dans l'ordre inverse.
Vous n'avez pas du tout besoin de l'instruction else comme si la condition était rencontré le contrôle n'atteindra jamais ces déclarations
void reverse(const char *const sptr)
{
if(!sptr && sptr[0] == '\0') return;
reverse(&sptr[1]);
putchar(sptr[0]);
}
Vous pouvez également ajouter la vérification si le paramètre n'est pas NULL
void reverse(const char *const sptr)
{
if(!sptr[0]) return;
reverse(&sptr[1]);
putchar(sptr[0]);
}
int main()
{
reverse("Hello World");
return 0;
}
p >
Cela n'a rien à voir avec putchar, cela a tout à voir avec la récursivité.
Disons que vous lui donnez la chaîne "1234" - ou appelons-la ['1' , '2', '3', '4', '\ 0']
La première fois que reverse est appelé, il est appelé avec l'argument sptr pointant vers ['1', '2', '3', '4', '\ 0'] ;
L'exécution atteint l'appel récursif pour inverser et cette fois utilise l'offset 1, donc l'argument devient ['2', '3', '4', '\ 0'] p >
Le processus est répété jusqu'à ce qu'un '\ 0' soit trouvé et maintenant la fonction retourne à l'appelant précédent qui imprime le dernier caractère, revient à l'appelant précédent, qui imprime le 2: nd dernier caractère et ainsi de suite jusqu'à ce que l'appel inversé en haut soit atteint qui imprime le premier caractère, puis existe.
Peut-être que l'impression d'informations de débogage supplémentaires facilitera la compréhension.
The reversed version: reverse entered, recursion level:1 , sptr:1234 reverse entered, recursion level:2 , sptr:234 reverse entered, recursion level:3 , sptr:34 reverse entered, recursion level:4 , sptr:4 reverse entered, recursion level:5 , sptr: 4 reverse exits, recursion level:4 , 3 reverse exits, recursion level:3 , 2 reverse exits, recursion level:2 , 1 reverse exits, recursion level:1 ,
Comme tous les autres le disent, c'est simple.
Mais la meilleure chose à expliquer est de voir comment cela fonctionne en ajoutant du journal dans votre code C.
putchar( p ); putchar( l ); putchar( e ); putchar( h );
Lorsque vous exécutez ce programme en entrant "help", vous obtiendrez les lignes suivantes dans le fichier reverse.log .
>> reverse()
{
>> reverse()
{
>> reverse()
{
>> reverse()
{
>> reverse()
{
>> reverse()
{
end of string
}
putchar( \0 )
}
putchar( p )
}
putchar( l )
}
putchar( e )
}
putchar( h )
}
Si maintenant, vous extrayez l'appel putchar () sans changer l'ordre d'exécution, vous obtiendrez
#include "pch.h"
#include <stdio.h>
#include <stdlib.h>
void reverse(const char *const sptr);
void openTraceFile();
void closeTraceFile();
void enterFunction();
void exitFunction();
void writeMessage(const char* s);
int main()
{
char sentence[80];
printf("Enter a line of text:\n");
//gets(sentence);
fgets(sentence, 80, stdin);
openTraceFile();
printf("\nThe reversed version:\n");
reverse(sentence);
puts("");
closeTraceFile();
return 0;
}
static FILE* logfile;
static int iNrSpaces = 0;
void reverse(const char *const sptr)
{
enterFunction();
if (sptr[0] == '\0')
{
writeMessage("end of string");
exitFunction();
return;
}
reverse(&sptr[1]);
putchar(sptr[0]);
char s[80];
sprintf(s,"putchar( %c )", sptr[0]);
writeMessage(s);
exitFunction();
}
void openTraceFile()
{
logfile = fopen("reverse.log", "w");
if (logfile == NULL)
{
printf("Error! Could not open file\n");
exit(-1);
}
void closeTraceFile()
{
fclose(logfile);
}
void enterFunction()
{
writeMessage(">> reverse()");
iNrSpaces += 4;
writeMessage("{");
}
void exitFunction()
{
writeMessage("}");
iNrSpaces -= 4;
}
void writeMessage(const char* s)
{
for (int i = 0; i < iNrSpaces; i++)
{
fputc(' ',logfile);
}
fprintf(logfile, s);
fputc('\n', logfile);
}
qui est la chaîne inversée!
J'espère que cette explication en utilisant LOG vous a aidé à comprendre ce problème.
Petite remarque: \ 0 le caractère est retourné en premier dans votre exemple!
à mon humble avis, c'est beaucoup plus facile à comprendre sans la syntaxe du tableau, plutôt en utilisant uniquement l'arithmétique du pointeur et l'opérateur de déréférence. Dans
reverse, en changeant tous lessptr [0]en* sptret l'argument d'appel récursif ensptr + 1, peut (ne pas dire volonté; peut) aider