web-dev-qa-db-fra.com

Existe-t-il une fonction d'attente décente en C ++?

L’une des premières choses que j’ai apprises en C++ est que

#include <iostream>
int main()
{
    std::cout<<"Hello, World!\n";
    return 0;
}

serait simplement apparaître et disparaître extrêmement rapidement sans pause. Pour éviter cela, je devais aller au bloc-notes et enregistrer

helloworld.exe
pause

ase

helloworld.bat

Cela est devenu fastidieux lorsque j'ai eu besoin de créer un ensemble de petits programmes de test, et finalement, j'ai simplement mis while(true); à la fin de la plupart de mes programmes de test, juste pour que je puisse voir les résultats. Existe-t-il une meilleure fonction d'attente que je peux utiliser?

46
user98188

vous pouvez demander à l'utilisateur d'appuyer sur entrée avant de fermer le programme ... quelque chose comme cela fonctionne.

#include <iostream>
int main()
{
  std::cout << "Hello, World\n";
  std::cin.ignore();
  return 0;
}

Cin lit en entrée utilisateur, et la fonction .ignore () de cin indique au programme de simplement ignorer l'entrée. Le programme continuera une fois que l'utilisateur cliquera.

Lien

63
DeadHead

Beaucoup de gens ont suggéré POSIX sleep, Windows Sleep, Windows system("pause"), C++ cin.get()… il y a même un DOS getch() là-bas, à partir de la fin des années 1920 environ.

S'il vous plaît ne faites aucune de ces choses.

Aucune de ces solutions ne passera l'examen de code dans mon équipe. Cela signifie que si vous soumettiez ce code à l'inclusion dans nos produits, votre commit serait bloqué et on vous dirait d'aller chercher une autre solution. (On pourrait dire que les choses ne sont pas si graves quand on est juste un amateur, mais je propose que développer de bonnes habitudes dans les projets de votre animal de compagnie est ce qui fera de vous un professionnel précieux dans une entreprise et vous maintiendra embauché. )

Garder la fenêtre de la console ouverte afin que vous puissiez lire la sortie de votre programme n’est pas la responsabilité de votre programme! Lorsque vous ajoutez un délai d'attente/sommeil/blocage à la fin de votre programme, vous enfreignez le principe de responsabilité unique, créez une fuite d'abstraction massive et effacez la possibilité de réutilisation/chaînabilité de votre programme. Il ne prend plus d’entrée et donne une sortie - il se bloque pour des raisons d’utilisation transitoire. C'est vraiment pas bon.

Au lieu de cela, vous devez configurer votre environnement pour que l'invite reste ouverte une fois que votre programme a terminé son travail. Votre encapsuleur de script Batch est une bonne approche! Je peux voir à quel point il serait ennuyeux de devoir mettre à jour manuellement les mises à jour, et vous ne pouvez pas l'invoquer à partir de votre IDE. Vous pouvez faire en sorte que le script prenne le chemin du programme à exécuter en tant que paramètre et configurez votre IDE pour l'invoquer à la place de votre programme directement.

Une approche provisoire à démarrage rapide consisterait à changer la commande d'exécution de votre IDE de cmd.exe <myprogram> ou <myprogram>, à cmd.exe /K <myprogram>. Le /K basculer vers cmd.exefait que l'invite reste ouverte après la fin du programme dans le chemin donné. Cela va être légèrement plus gênant que votre solution de script Batch, car vous devez maintenant taper exit ou cliquer sur le "X" rouge lorsque vous avez fini de lire la sortie de votre programme, plutôt que de simplement figer l'espace. bar.


J'assume l'utilisation d'un IDE, car sinon, vous appelez déjà à partir d'une invite de commande, ce qui ne poserait pas de problème. De plus, je suppose que l’utilisation de Windows (sur la base des détails donnés dans la question), mais cette réponse s’applique à n’importe quelle plate-forme… ce qui, incidemment, est la moitié du problème.

Veuillez noter que le code ci-dessus a été testé sur Code :: Blocks 12.11 et Visual Studio 2012.
sous Windows 7.

Pour forcer votre programme à arrêter ou à attendre, vous avez plusieurs options:


  • sleep (unsigned int)

La valeur doit être un entier positif en millisecondes. Cela signifie que si vous souhaitez que votre programme attende 2 secondes, entrez 2000.

Voici un exemple:

#include <iostream>     //for using cout
#include <stdlib.h>     //for using the function sleep

using namespace std;    //for using cout

int main(void)         
{
   cout << "test" << endl;
   sleep(5000);         //make the programme waiting for 5 seconds
   cout << "test" << endl;
   sleep(2000);         // wait for 2 seconds before closing

   return 0;
}

Si vous attendez trop longtemps, cela signifie probablement que le paramètre est en secondes. Alors changez le en ceci:

sleep(5);

Pour ceux qui obtiennent un message d'erreur ou un problème en utilisant sleep, essayez de le remplacer par _sleep ou Sleep, en particulier sur Code :: Bloks.
Et si vous rencontrez toujours des problèmes, essayez d’ajouter une de ces bibliothèques au début du code.

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <dos.h>
#include <windows.h>

  • système ("PAUSE")

Un simple programme "Hello world" sur une application de console Windows se fermerait probablement avant que vous puissiez voir quoi que ce soit. C'est le cas où vous pouvez utiliser le système ("Pause").

#include <iostream>    

using namespace std;   

int main(void)         
{
    cout << "Hello world!" << endl;

    system("PAUSE");

    return 0;
}

Si vous obtenez le message "erreur: 'système' n'a pas été déclaré dans cette portée", ajoutez simplement la ligne suivante à la fin du code:

#include <cstdlib>

  • cin.ignore ()

Le même résultat peut être atteint en utilisant cin.ignore ():

#include <iostream>     

using namespace std;    

int main(void)         
{
    cout << "Hello world!" << endl;

    cin.ignore();

    return 0;
}

  • cin.get ()

exemple :

#include <iostream>     

using namespace std;    

int main(void)         
{
    cout << "Hello world!" << endl;

    cin.get();

    return 0;
}

  • getch ()

N'oubliez pas d'ajouter la bibliothèque conio.h:

#include <iostream>     
#include <conio.h>    //for using the function getch()

using namespace std;    

int main(void)
{

    cout << "Hello world!" << endl;

    getch();

    return 0;
}

Vous pouvez avoir un message vous disant d'utiliser _getch () au lieu de getch

44
borderless

L'apparition et la disparition d'une fenêtre d'affichage de texte est une caractéristique de la façon dont vous exécutez le programme, pas de C++.

Exécutez-le dans un environnement de ligne de commande persistant, ou incluez un support de fenêtrage in votre programme, ou utilisez sleep ou attendez une entrée, comme indiqué dans les autres réponses.

20
dmckee

l'équivalent du programme batch serait

#include<iostream>
int main()
{
    std::cout<<"Hello, World!\n";
    std::cin.get();
    return 0;
}

La ligne supplémentaire fait exactement ce que PAUSE fait, attend une entrée de caractère unique

En réalité, contrairement aux autres réponses, je pense que la solution d’OP est la plus élégante.

Voici ce que vous gagnez en utilisant un wrapper externe .bat:

  1. L’application attend évidemment les entrées de l’utilisateur, elle fait donc déjà ce que vous voulez.
  2. Vous n'encombrez pas le code avec des appels maladroits. Qui devrait attendre? main()?
  3. Vous n'avez pas besoin de traiter des problèmes multi-plateformes - voyez combien de personnes ont suggéré system("pause") ici.
  4. Sans cela, pour tester votre exécutable de manière automatique dans un modèle de test de boîte noire, vous devez simuler la pression de touche enter (sauf si vous faites les choses mentionnées dans la note de bas de page).
  5. Le plus important est peut-être que si un utilisateur souhaite exécuter votre application via un terminal (cmd.exe Sur la plate-forme Windows), il ne le fait pas veut attendre, car il verra de toute façon la sortie. Avec la technique de wrapper .bat, Ils peuvent décider d’exécuter le wrapper .bat (Ou .sh) Ou d’exécuter directement l’exécutable.

En se concentrant sur les deux derniers points - avec toute autre technique, le programme devrait proposer au moins le commutateur --no-wait De sorte que, en tant qu'utilisateur, je puisse utiliser l'application avec toutes sortes d'opérations telles que sortie, chaînage avec d’autres programmes, etc. Cela fait partie du flux de travail CLI normal, et l’attente à la fin lorsque vous êtes déjà dans un terminal vous gêne et détruit l’expérience utilisateur.

Pour ces raisons, la solution IMO .bat Est la plus agréable ici.

7
rr-

Il y a une manière de faire C++ 11. C'est assez simple et je pense que c'est portable. Bien sûr, comme Lightness Races in Orbit a souligné, vous ne devriez pas le faire pour pouvoir voir un Hello World dans votre terminal, mais il existe de bonnes raisons d'utiliser une fonction d'attente. Sans plus tarder,

#include <chrono> // std::chrono::microseconds
#include <thread> // std::this_thread::sleep_for
std::this_thread::sleep_for(std::chrono::microseconds{});

Plus de détails sont disponibles ici . Voir aussi sleep_until .

6
Kevin

Ce que vous avez peut être écrit plus facilement. Au lieu de:

#include<iostream>
int main()
{
    std::cout<<"Hello, World!\n";
    return 0;
}

écrire

#include<iostream>
int main()
{
    std::cout<<"Hello, World!\n";
    system("PAUSE");
    return 0;
}

La fonction système exécute tout ce que vous lui donnez comme s’il était écrit dans la commande Invite. Il suspend l'exécution de votre programme pendant l'exécution de la commande afin que vous puissiez tout faire, vous pouvez même compiler des programmes à partir de votre programme cpp.

4
poliklosio

Syntaxe:

vide sommeil (secondes non signées);

sleep () suspend l'exécution pendant un intervalle (secondes). Avec un appel en veille, l'exécution du programme en cours est suspendue pendant le nombre de secondes spécifié par l'argument secondes. L’intervalle n’est précis qu’au centième de seconde près ou à la précision de l’horloge du système d’exploitation, selon ce qui est le moins précis.

Cet exemple devrait préciser:

#include <dos.h>
#include <stdio.h>
#include <conio.h>

int main()
{
   printf("Message 1\n");
   sleep(2); //Parameter in sleep is in seconds
   printf("Message 2 a two seconds after Message 1");
   return 0;
}

N'oubliez pas que vous devez inclure # dos.h

EDIT:

Vous pouvez également utiliser winAPI.

VOID WINAPI Sleep(
DWORD dwMilliseconds
);

fonction de veille (Windows)

Juste une remarque, le paramètre de la fonction fournie par winapi est exprimé en millisecondes. La ligne de veille située dans l’extrait de code ci-dessus se présentera ainsi: "Sleep (2000);"

2
Ivan Prodanov