Je cherchais le code suivant dans lequel je suis tombé sur l'impression d'une chaîne dans l'ordre inverse en C Utilisation de la récursion: Je suis relativement nouveau à C et suis confus confus par la ligne 2. < Code> * STR CODE> de ma compréhension est la désérogation du pointeur et doit renvoyer la valeur de la chaîne dans la position actuelle. Mais comment cela est-il utilisé comme argument à une déclaration conditionnelle (qui devrait sauf un droit booléen?)? Dans la ligne 3, le pointeur sera toujours incrémenté au bloc suivant (4 octets depuis son int) ... Donc, ce code n'a donc pas pu échouer s'il s'agit d'être des données dans le prochain bloc de mémoire après la fin de la chaîne? P>
10 Réponses :
Ligne 2 vérifie pour voir si le caractère actuel est la terminaison nulle de la chaîne - puisque les chaînes C sont terminés nulle, et le caractère nul est considéré comme une valeur fausse, il va commencer à dérouler la récursion quand il arrive à la fin de la chaîne (au lieu d'essayer d'appeler StrReverse4 sur le caractère après la terminaison nul, ce qui serait au-delà des limites des données valides).
notez également que le pointeur est à un Exemple:. p> char code>, incrémenter ainsi le pointeur seulement par incréments de 1 octet (depuis char code> est un type à un seul octet) p> 0 1 2 3
+--+--+--+--+
|f |o |o |\0|
+--+--+--+--+
merci pour la réponse..mais comme mentionné dans ma mise à jour..Can vous élaborer sur ce que l'on entend par 'NULL est considéré comme une fausse valeur "car c n'a pas de type booléen?
Dans C, il n'y a pas de type booléen, correct - à la place, des instructions logiques traitent simplement tout ce qui évalue à 0 comme false code>, et tout ce qui évalue à non zéro comme vrai code>. Étant donné que le "caractère null" est en réalité un octet dont la valeur est 0, elle est considérée comme false code>.
Critique mineure - Le caractère ASCII 0 est généralement appelé "nul" (avec un L), tandis que le pointeur non valide est généralement appelé "null" (avec deux L). Je pense qu'il est important de faire une distinction ici, car il est facile de se perdre avec des pointeurs.
"NUL" est une forme abrégée, oui, toutefois, lorsque vous parlez de "Terminator NULL" ou "NULL PARTICULIER" Habituellement, l'orthographe correcte (avec deux L) est utilisée. Par exemple: EN.Wikipedia.org/wiki/Null_Character
Wikipedia, par nos termes propres (WP), ne doit pas être utilisé pour des références. Dans le cas de cet article Null_Caracter, il s'agit d'une source de désinformation. Utilisateur: Heathhunnicutt
Je n'ai rien vu sur Wikipedia qui indique que tel est plus que votre propre opinion, Heath.
@Heath - Wikipedia n'est pas d'accord avec vous: en.wikipedia.org/wiki/wikipedia_Talk:Citing_wikipediaIa
@Amber: En C, il y a un type booléen, _bool code>.
@DeMlax: seulement en C99 et plus tard.
@Amber: C99 est C, tout autant que C ++ 98 (ou peut-être même C ++ 03) est C ++.
@DeMlax: Oui, C99 est C, mais C n'est pas nécessairement C99.
à la fin d'une chaîne est typiquement un 0 octet - la ligne si (* str) code> vérifie l'existence de cet octet et d'arrêter quand il y arrivera. P>
Le type d'une chaîne C n'est rien d'autre qu'un pointeur à char. La convention est que ce que le pointeur pointe vers un tableau de caractères, terminé par un octet zéro em>. P>
Utilisation de * str code> est donc le premier caractère de la chaîne pointée par str code>. p>
* STR code> dans un état conditionnel est évalué vers FALSE code> si STR code> pointe vers l'octet NULL terminant dans la chaîne (vide). p>
à la fin de la chaîne, il y a un et De cette façon, cela fonctionnera. P> 0 code> - vous avez donc "test" => [0] 'T' [1] '[2]' [2] [3] 'T' [4] 0 code> p>
si (0) -> faux code> p>
dans la ligne 3, le pointeur sera toujours incrémenté au bloc suivant (4 octets depuis son int) ... p>
thats faux, c'est char *, il ne sera incrémenté que par 1. Parce que le caractère est de 1 octet seulement. P>
Mais comment cela est-il utilisé comme argument à une déclaration conditionnelle (qui devrait sauf un droit booléen?)? p> BlockQuote>
Vous pouvez utiliser n'importe quelle valeur si ($$) à $$, et il ne vérifiera que si son non-zéro ou non, Bool est également implémenté comme simple 1 = true et 0 = faux. P>
Dans un autre niveau supérieur, une langue fermement tapé, vous ne pouvez pas utiliser de telles choses si, mais en C, tout se résume à des chiffres. Et vous pouvez utiliser n'importe quoi. P>
if(1) // evaluates to true if("string") // evaluates to true if(0) // evaulates to false
Déclarations conditionnelles ( comme un de côté, si vous faites si code>, pour code>, tandis que code>, etc.) attend une expression booléenne. Si vous fournissez une valeur entière, l'évaluation revient à 0 == false code> ou non-0 == true code>. Comme mentionné déjà, le caractère de terminaison d'une chaîne C est un octet nul (valeur entière 0). Donc le si code> échouera à la fin de la chaîne (ou premier octet nul dans la chaîne). P>
* str code> sur un pointeur NULL, vous invoquez un comportement indéfini; Vous devez toujours vérifier qu'un pointeur est valide avant la déséroférance. p>
1.
pour ex: p> 2. P> L'expression est évaluée et si la valeur résultante est zéro ( str code> est un pointeur à un char. L'incrémentation str code> rendra le point de pointeur sur le second caractère de la chaîne (car il s'agit d'un tableau de caractères).
Remarque: L'incrémentation des pointeurs augmentera par le type de données que le pointeur pointe sur. P> null code>, \ 0 code>, 0 code>), les déclarations ne sont pas exécutés. Comme chaque chaîne se termine par \ 0 code> la récursion devra terminer un certain temps. P> p>
Toutes les chaînes ne sont pas garanties dans un octet nul. En effet, la plupart des temps c'est; Mais il n'y a rien qui nécessite que cela soit le cas.
Se mettre d'accord. Je viens de supposer cela dans ce cas.
@ezpz: une c-string est par définition i> une séquence de caractères terminée par un caractère null; S'il n'y a pas de null de terminaison, ce n'est tout simplement pas une c-string;)
c n'a pas de concept de valeurs booléennes: en C, chaque type scalaire (c.-à-d. Types d'arithmétique et de pointeur) peut être utilisé dans des contextes booléens où Comme les chaînes sont désormais terminées, le terminateur sera interprété comme 0 code> signifie false code> et non -zero true code>. faux code>, alors que tous les autres caractères (avec une valeur non nulle!) vrai code>. Cela signifie qu'il existe un moyen facile d'itération sur les caractères d'une chaîne: p> stréscript4 () code> fait la même chose, mais par récursivité à la place d'itération. p> p>
Essayez ce code, qui est aussi simple que celui que vous utilisez:
C'est une sorte de sujet hors sujet, mais quand j'ai vu la question que je me demandais immédiatement si cela était réellement plus rapide que de faire une linge et de faire partner à l'arrière.
Donc, j'ai fait un petit test. P>
#include <string.h>
void reverse1(const char* str)
{
int total = 0;
if (*str) {
reverse1(str+1);
total += *str;
}
}
void reverse2(const char* str)
{
int total = 0;
size_t t = strlen(str);
while (t > 0) {
total += str[--t];
}
}
int main()
{
const char* str = "here I put a very long string ...";
int i=99999;
while (--i > 0) reverseX(str);
}
C'est probablement parce que dans votre système i> la surcharge des appels de fonction récursive est grand par rapport au temps de la solution itérative, ce qui rend un appel de fonction à Strlen. Mon point principal consiste à faire des généralisations d'un test peut être dangereux, si vous êtes intéressant. Il vaut mieux écrire clairement le code maintenu et l'optimiser ultérieurement, uniquement lorsque les tests de performance réels révèlent des goulots d'étranglement.
Je suis d'accord. Bien que, comme Strlen scanne linéairement (je suppose) toute la chaîne, la comparaison doit être comprise entre une seule fonction (la récursion) et une itération de la mise en œuvre de SHLEN plus 1 / N de l'appel de la fonction Strlen. Mais encore une fois, je suis d'accord pour dire qu'il est préférable d'écrire clair, puis d'optimiser si nécessaire. Une question, dans votre système, il est plus rapide de la solution de récursion plutôt que la solution itérative?
Garçon, j'espère que ce n'était pas du code de production! :)
Je me demande combien de temps une chaîne devrait être avant d'exploser.
Probablement très long ... mais toujours.
À l'origine, la méthode s'appelait strations4, donc éventuellement qu'elle était destinée aux chaînes d'environ 4 caractères de longueur.