7
votes

Comment déclarer une variable entre crochets de la déclaration de si?

Je veux déclarer une variable locale entre parenthèses d'une déclaration IF. Par exemple.

char c = getc(stdin);
if(c == 0x01)
{
    bla...
}


9 commentaires

Vous pouvez abuser du pour boucle.


S'il s'agit de la pollution, vous pouvez toujours utiliser une nouvelle portée ou la boucle pour la boucle.


La solution la plus succincte (stupide) est probablement si (int c = getc (stdin) - 1); sinon nongetc (C + 1); .


Pourquoi cette limitation de ne pas soulever la définition variable et l'initialisation de la condition?


@Gmannickg Feng Shui?


@Slaks: Cela doit être le plus gros abus que j'ai entendu depuis un moment, ce qui est néanmoins une idée aussi fraîche que je suis presque tentée de trouver un endroit pour l'utiliser. pour (char c = getc (stdin); c == 0x01;) {...} - Pas précisément print-de-de-lafusion, mais génial :-) Sauf ... comment Est-ce qu'il quitte, jamais?


@Damon remplir la dernière partie: pour (char c = getc (stdin); c == 0x01; c = 42)


@Potatoswatter: ah droite, bien sûr :-)


duplicaté possible de Comment est-ce que l'on déclare une variable à l'intérieur d'un si () déclaration?


3 Réponses :


10
votes

Je ne savais pas comment créer une variable et tester sa valeur avec un si code> jusqu'à ce que certaines des solutions affichées. Cependant, vous pouvez utiliser le commutateur code>. Cela vous permettrait de réagir aux valeurs supplémentaires (peut-être eof code>): xxx pré>

Vous pouvez toujours placer la relève si code> dans une fonction inlined Au lieu de cela, et le code sera un peu plus propre. Si vous voulez vraiment le code source juste à cet endroit, mais sans créer de nouvelle portée autour d'un si code> avec une nouvelle variable, alors peut-être une Lambda serait acceptable pour vous. P>

template <typename T>
class SetAndTest {
    const T test_;
    T set_;
public:
    SetAndTest (T s = T(), T t = T()) : set_(s), test_(t) {}
    operator bool () { return set_ == test_; }
    operator bool () const { return set_ == test_; }
    operator T & () { return set_; }
    operator T () const { return set_; }
};

//...
if (auto c = SetAndTest<int>(getc(stdin), 0x01)) {
    ungetc(c, stdin); //or bla...
}


2 commentaires

Wow, n'a jamais pensé à cela.


Pourquoi vous répétez-vous surcharge de l'opérateur?



17
votes

Si c'est la pollution des espaces de noms, vous vous inquiétez de vous pouvez toujours définir le si instruction dans un bloc: xxx

de sorte que c durera seulement jusqu'à la fin du bloc d'être atteint.


3 commentaires

Bien que je n'ai pas répondu à la question, cette façon de rédiger le code est simple, claire et efficace. Merci.


@ QLB1234 Parfois, une question, comme dans votre cas, demande efficacement "comment est-ce que je préfère écrire un mauvais code". Ces questions ne sont pas censées être répondues avec "Voici comment vous écrivez un mauvais code", mais avec "N'écrivez pas de mauvais code, faites cela à la place." :-)


@Nikosc.: L'appel de cette réponse est sa simplicité, mais je trouve rarement de telles constructions acceptables dans un examen de code. Lorsque je vois un bloc d'instruction autonome comme celui-ci, je pense toujours que le code doit être dans une fonction distincte.



8
votes

peut em> définir la variable à l'intérieur du si code> déclaration très bien. Par exemple, cela devrait compiler:

if (char ch = 1 && ...


16 commentaires

Ne pouviez-vous pas aussi utiliser une virgule?


@ SJE397: Curieusement, non - non autorisé dans ce cas.


Que fait le 0 || ? Il ressemble à ch = true arrivera inévitablement après ch = getchar () .


Wikipedia note ceci comme cas d'utilisation pour l'opérateur de la virgule dans des exemples / conditions ici: en.wikipedia.org/wiki / Comma_Operator . Mais ils ont dit une fois que le grand mur était composé de figurines d'action Star Wars ...


@ SJE397: Chaque compilateur J'ai rejeté le code si vous essayez d'utiliser une virgule (et je pense que la norme les oblige à le faire).


@Potatoswatter: OOPS - Besoin d'un autre ensemble de parens à droite. Merci de le pointer.


@JerryCoffin -1 , peu importe le nombre de parens que vous avez mis là un booléen finira toujours dans ch . c'est à dire. Char Ch = 0 || ((ch = getchar ()) == 42) n'aura jamais ch == 42 à l'intérieur du corps de la if-énoncé .


@RefP: Quand tout est dit et fait, oui - mais ce n'est pas ce qu'il a demandé, n'est-ce pas? Lorsque la valeur est testée, la valeur est venue de getchar () , ce qu'il semble se soucier.


@Jerrycoffin et vous pensez que cela a du sens? il veut utiliser ch (c.-à-d. la valeur de getchar () ) à l'intérieur de la if-énoncé s'il voulait juste tester la valeur de getchar () getchar () == ... serait suffisant. Votre réponse implique que la valeur de getchar () sera stockée dans ch et restera à l'intérieur de la if-énoncé ; quelque chose qui n'est pas vrai. Devis de OP : "Pour le dire couramment, je veux utiliser la variable (char c) à la fois dans la ligne de si et le corps de si, mais pas en dehors du si." / i>


@RefP: Je pense que vous inférez quelque chose qui n'est pas vraiment impliqué n'importe où. Il ne me semble pas beaucoup de sens de toute façon - il teste spécifiquement l'égalité à 1, la seule valeur qu'il peut avoir à l'intérieur de la déclaration si est une toute de toute façon (sinon, rien à l'intérieur du < code> si l'instruction peut exécuter).


@JerryCoffin sûr, mais vous devriez également mentionner que ce que vous faites est équivalent à si (getchar () == 0x1) {/ * Il suffit d'utiliser "true" au lieu de ch ici * /}


@Refp Ouais, c'est vrai. Le niveau de logique ou ( || ) est supérieur à celui de l'affectation ( = ). Si écrit comme ci-dessus mentionné, ch n'abalte jamais à getchar () et le corps de si ne connaîtra jamais la valeur de getchar () . Si oui, pourquoi cette question serait-elle exsite? J'ai presque accepté cette réponse pour une erreur, mais ce qu'il pense est toujours intelligent.


"Cela vous permet d'obtenir la création et l'initialisation du CH fait, puis [...]" en fait, le côté droit du || fait toujours partie de l'expression d'initialisation. La syntaxe de la condition si est une expression ou une seule déclaration; Il n'y a pas de «déclaration suivie d'expression» et votre code est donc structuré de sorte que l'expression soit cachée dans l'initialisateur d'une déclaration.


De plus, votre code ne fait pas la chose prévue, comme vous dites ch est réaffecté à 1 ou 0, et ne conserve pas la valeur souhaitée résultant de getchar () .


N.b. Ce code est uniquement bien défini car char n'a pas de constructeur non trivial, si vous avez essayé si (nontridialinit p = 0 || (((P = quelque chose ()) == x )) Il serait indéfini car p est affecté avant d'avoir été initialisé. De mauvaises choses vont arriver.


@Jerrycoffin Je ne suis pas sûr de voir la raison de la double affectation dans si (char ch = 0 || ((ch = getchar ()) == 0x1)) . si (char ch = 0 || (getchar () == 0x1)) soit équivalent? Et pendant que nous sommes à elle ... si (char ch = (getchar () == 0x1)) est toujours la même logique, seulement plus lisible ;-)