Liens rapides pour usage courant: (Accès à la liste des squelettes) (Polycopié)

Manuel hypertexte des langages C, C++ et sC++

Comment utiliser cet hypertext

Liste des mots-clés (pointent sur le polycopié)

{ } [ ] break case char default do else float for goto if int label main short struct switch typedef void while

objet instanciation surcharge constructeur destructeur inline offline public private protected héritage initialisation virtuel friend polymorphisme sous-typage templates surcharge-opérateurs

Extensions de Synchronous C++: active @corps accept select

Squelettes et explications

C C++ sC++

Comment créer un programme complet

Voici une marche à suivre pour créer un programme simple et l'exécuter. Si vous avez des problèmes, reportez-vous à cette liste.

Structure générale d'un programme C

explications

Ci-dessous sont donnés 4 exemples de squelettes de programmes:

#include <stdio.h>                    /* programme C simple */
fonct ()   {    }
main () 
{
}
----------------------------------
#include <stdio.h>                    /* programme C recuperant les parametres*/
#include <stdlib.h>
                                      /* de la ligne de commande */
main (int argc, char **argv) 
{
  int i;
  for (i=0; i<argc; i++)
     printf("%s\n", argv[i]);
     exit(0);                         /* utilise stdlib  */
}
-------------------------------------------------------------------------------------
#include <scxx.h>            // programme sC++ contenant un objet actif
#include <stdio.h> 

int setRealTimeMode=SetRealTimeMode();  // initialisation du noyau avant le main

active class ActObj {
public:
  void sign() {};
private:
  @ActObj() {
    printf("Bonjour\n");
    select { 
      accept sign;
    ||
      accept ~ActObj;
    }
  }
}Obj;

void main()  {}      // Le main attend que les objets se terminent
                     // ou acceptent leur destruction
---------------------------------------------------------------------------------------

#include <scxx.h> // programme sC++ qui utilise une #include <stdio.h> // fenetre simple XTerm dans le main #include <GUI.h> #include <XTerm.h> #include <CharString.h> main (int argc, char **argv) { GUI gui (argc, argv); XTerm xTerm(gui, "Ma fenetre"); CharString sStr; char str[80]; int i; xTerm.WriteString("Bonjour, tapez fin de ligne\n"); xTerm.ReadString(sStr); sscanf(sStr.Buffer(), "%d", &i); // conversion ASCII entier sprintf(str,"Valeur = %d\n",i); xTerm.WriteString(str); waituntil (now() + 100); }

description des interfaces à fenêtres / autres exemples avec fenêtres / fichiers.h

Commandes d'édition

xemacs &
lancer l'éditeur
menu File/Open File...
charger un fichier (ctrl est la touche contrôle); créer un nouveau fichier s'il n'y en a pas encore. Lorque l'on frappe la barre d'espacement, le système complète le nom, s'il est unique.
menu File/Save Buffer
sauver le fichier, à faire avant chaque compilation
bouton gauche de la souris --- flèches de déplacement
permet de se déplacer dans le texte
ctrl l
centrer le curseur sur le milieu de l'écran (ctrl = touche contrôle)
del
effacer le dernier caractère
ctrl k
efface jusqu'à la fin de la ligne
ctrl y
réinsère les derniers ctrl k à l'endroit du curseur (si l'on tape ctrl y après plusieurs fois ctrl k, sans bouger le curseur, on restaure le texte)
F11 x c-mode
met l'éditeur en mode C. Dans ce mode, on peut utiliser le tabulateur pour indenter la ligne sur laquelle se trouve le curseur
ctrl x u
annule la dernière modification (utile si l'on s'est trompé)
ctrl g
annule la commande en cours (utile si l'on s'est trompé, car il y a de nombreuses commandes)

Commandes de compilation

cc -o out filename.c                               programme C
cxx -o out filename.cxx                            programme C++
SC++ -o out filename.cxx                           programme sC++
SC++ -o out filename.cxx -lSockets                 au cas ou l'on utilise les sockets

Fonctions

explications
type  nom ( type nom1, type * nom2 , type & nom2 ) {
  instructions;
  return expr;
}

nom ( type nom1, type * nom2 , type & nom2 ) { instructions; return int_expr; }

void nom ( type nom1, type * nom2 , type & nom2 ) { instructions; return; }

type  nom ( nom1, nom2 )
    type1  nom1;
    type2  * nom2;
{
     ....  ;
     return expr;
}

Déclaration de variables

explications

int   nom,  * nom;
int   nom [ constante ];
int nom = 0;
void ;
char ;
short  ;
int   ;
long ;
unsigned, unsigned int  ;
unsigned short ;
unsigned long ;
float  ;
double, long float ;
enum xxx {aa, bb,cc};      // definition de type
enum {aaa,bbb,ccc} yyy;    // definition de variable
----------------------------------
struct  nom_de_type_optionnel {

} nom_de_variable_optionnel ;
----------------------------------
typedef struct indifferent {

} nom_de_type;

Instructions de boucles

explications

while () ;
----------------------------------
while () {
}
----------------------------------
do {

}
while ();
----------------------------------
for (i=0;i<10;i++) {
}
----------------------------------
for (;;);
----------------------------------
for (;;)  {
}

Instruction IF

explications

if () 
;
else
;
----------------------------------
if ()
;
else if ()
;
else
;
----------------------------------
if () {
}
else if () {
}
else {
}

Instruction de cas

explications

switch (VAR)  {
case XXX :  ;
      break;
case YYY :   {
      break;  }
default:  ;
}

Instruction de sauts

explications

label:

goto label;
----------------------------------
break;
----------------------------------
continue;

Affectation, opérateurs, expressions

explications

Les priorités décroissent de la première ligne à la dernière.

[]  ()  {}  .   ->
*  &   -  !  ++  --  sizeof( )
*  /  %
<<   >> <   <=   >   >=
==   !=
&
!
|
&&
||
condition ? vrai : faux;
=  *=  /=  %=  +=  -=  <<=  >>=  &=  ^=  |=
,

Pointeurs

explications explications
typedef struct enreg {  char a; } enreg ;

enreg *point;
char * ptr, caractere;
char array[10];

array[0] = 'a';
ptr = array; 
caractere = * ptr;
point = (enreg*)malloc(sizeof(enreg));
point->a = caractere;
free(point);

Voir aussi les pointeurs sur les classes. En C++ on utilise new et delete pour les classes et les struct.

Lecture, affichage de textes et de variables

explications

#include "stdio.h"

scanf("%d%f", &variable1, &variable2);

%d  %i  %u  %f  %e  %g (==%f ou %e)  %c  %s  %o  %x  %%

%0d  %5.2f  %-6d  %ld

\n  \32  \"  \'  \t

Affichage

explications

#include "stdio.h"

printf("texte%dtexte%f\n", variable1, variable2);

Classe simple

explications
class A   {
  public:
    int x;
    void f()  {    }
    int g();
};
A obj;  
obj.x = 0; 
obj.f();

Pointeur sur une classe

explications
A * ptr;            // définition
ptr = new A;        // instanciation
A * ptr1 = new A;   // définition et instanciation
ptr -> x = 0;       // affectation à un champ
ptr -> f();         // appel d'une methode

Initialisation / destruction d'une classe

explications
class XXX {
       method ( ... ) { ..... }
  public:
      XXX ( int i ) { .... }
     ~XXX  ( ) { ..... }
};

XXX * Z;

Z = new XXX (19); 

delete Z;

Code "inline"

explications

class XXX {
         method ( ... ) { ..... }
     public:
         XXX ( int i ) { .... }
         ~XXX  ( ) { ..... }
};

Code commun réentrant

explications
class XXX {
         method ( ... );
      public:
         XXX ( ... ); 
          ~XXX  ( );
};
XXX::method ( ... ) { ........ }
XXX::XXX ( ... ) { ........ }
XXX::~XXX ( ... ) { .......... }

Héritage de classes

explications
class D: A, private B, public C {
       A ma;
};

Initialisation de membres emboîtés

explications
class XXX (int) { ... };          // XXX a des parametres d'initialisation
class A: XXX {                    // pas de parametres possibles ici
      XXX a;                      // ni ici
   public:
      A ( ... ): XXX(12), a(34);  // placer les parametres apres le constructeur
};

Propriété private sélective

explications
class A  {
     public:        int x;
     protected:  int y;
};
class B : private A  {
     public:        A :: x;               
     protected:   A :: y;             
};

Exportation de types

explications
class A {
  public:
     enum colors {blue, red, yellow=100,green};
     typedef int tt;
     struct B { int m;  char c; };
};

void main(  )   {
   A::tt x;                 /* types définis dans la classe A */
   A::colors c = A::red;
   A::B bstruc;
}

Tout le programme est "friend"

explications
class X {  int a; 
    friend void f ( X * ) ;         // tout le monde peut définir f() };
    void f (X * p)  {               // dans f() on peut atteindre 
        p -> a = 0;                 // les membres de X 
    };

void main () { 
    X * ptr = new X;                // on peut mettre l'objet en
    f (ptr);                        // paramètre et éviter la 
}                                   // forme  d'appel d'objet

Classe "friend"

explications
class B;                            // annonce de définition future de B
class A {  
      private: int a;
             f ();
      friend B;                     // autorisation en faveur de B
};
class B {                           // B peut atteindre les membres de A 
                                    // des façons suivantes 
    void g () {   A :: a = 0;    A :: f ();  }
    void h (A* p)  {    p->a = 0;    p->f();   }
};

Membre "friend"

explications
class B;
class A {  
    private: int a;
    friend void B :: f();           // autorisation en faveur de la 
};                                  // fonction B :: f() seulement
class B  {
    void f () { A::a = 0; }         // la définition de f() peut
};                                  // utiliser les membres de A

Héritage multiple de classes virtuelles

explications
class X  {  public:  int x;      };
class A: virtual public X {   };
class B: virtual public X {   };
class C: public A, public B {  x=0; };

void main () {
      C  objectC;
      objectC . x = 0;
}

Membre virtuel non surchargés

explications
class A  {
    public:
       virtual void  f()  { ........ }  };
class B: public A {        };                // non surchargé
B  bb;


bb . f();             

bb . A :: f ();

Surcharge de membres virtuels

explications
class A  {
    public:
       virtual void  f()  { ........ }  };
class C: public  A  {
    public:
       void  f();                            // surchargé
};

C  cc;

cc . f();                                    // accède C::f()

cc . A :: f ();  

Surcharge avec différents types

explications
class A  {
    public:
       virtual void  f ( )  { ........ };
};
class B: public  A   {
    public:
       void  f ( int );     };                // surchargé avec un autre
                                              // type de paramètre
B  bb;
bb . f ( i );                                 // accède B::f()
bb . f ( );                                   // accède A::f()

Template

explications
template<class T, int N> class Clas {      // definition
public:
  T arr[N];
  T f(T*,int);
  Clas(T var);
};

template<class T, int N>   // constructeur
    Clas<T,N>::Clas(T var) {
      for (int i=0;i<N;i++)
        arr[i]=var;
    }

template<class T, int N>       // methode
    T Clas::f(T *var, int j) {
      T temp;
      temp = arr[j];
      arr[j] = *var;
      return (temp);
    }

Clas<int,10> Obj(1);     // instanciation

Syntaxe d'un objet actif sC++

explications ,
active class XXX {
public:
      method ( ... ) { ..... }                // methode
      XXX  ( ) { ..... }                      // constructeur
      ~XXX  ( ) { ..... }                     // destructeur

      @XXX ( ... )                            // corps (programme interne)
        {  for (;;)     {
              accept method;
           } 
        }
};

Instruction de sélection

explications
select     {
        accept Receive; 
||
        call O2->Send ( );
|| 
        waituntil (now()+ T1);
|| 
        default;
}


select     {
   when   (FreeStoreAvailable)
         accept Receive; 
||
    when  ( ! Empty (B2)) 
        call O2->Send ( );
|| 
    waituntil (now()+ T1);
|| 
    when   (TimerActive)
         waituntil (TimeoutStart + T1);
|| 
    when   (InAHurry)
        default;
}

Fenêtre simple (placée dans le main)

explications

#include <scxx.h>       // programme sC++ qui utilise une
#include <stdio.h>      // fenetre active dans le programme main
#include <GUI.h>
#include <XTerm.h>
#include <CharString.h>

main (int argc, char *argv[])
{
  GUI gui(argc, argv);    // manager des fenetres, avant tout objet de fenetrage
  XTerm xterm (gui,"HELLO",10,30,100,100);

  int i;
  CharString msg;
  char txt[80];

  xterm.WriteString("Type a number:");
  xterm.ReadString(msg);
  sscanf(msg.Buffer(),"%d", &i);
  sprintf(txt,"Number is '%d'",i);
  xterm.WriteString(txt);
  waituntil(now()+100);
}

Boutons et textes dans une fenêtre (dans le main)

explications fichiers.h

La fenêtre ci-dessus est créée par le programme ci-dessous. Elle est composée d'une colonne (RowColumn) qui englobe trois éléments. Notez que (RowColumn) peut aussi créer des lignes, grâce à un paramètre, comme l'indique l'exemple qui suit celui qui est donné ci-dessous. La commande base.Realize provoque l'affichage de la fenêtre. Pour lire ou écrire dans les fenêtres, on utilise les commandes illustrées dans la deuxième partie du programme.

#include <scxx.h>                     // programme sC++ qui utilise une
#include <stdio.h>                    // fenetre active dans le programme main
#include <GUI.h>
#include <RowColumn.h>
#include <TextField.h>
#include <PushButton.h>
#include <Text.h>
#include <CharString.h>

main (int argc, char *argv[])
{
  GUI gui(argc, argv);                // manager des fenetres, avant tout objet de fenetrage
  RowColumn         base ( gui, "RootWindow" );
  Text              texte ( base, 4);
  TextField         ligne ( base );
  PushButton        quit ( base, "QUITTER" );

  base.Realize();    // affiche la fenetre

  CharString msg;

  ligne.ReadText(msg);    // Bloquant: evenement == enter
  ligne.GetText(msg);     // Non bloquant
  texte.ReadText(msg);    // Bloquant: evenement == crtl-enter
  texte.GetText(msg);     // Non bloquant
  texte.AppendText(msg);  // impression a la fin du texte
  texte.AppendText("hello\n");
  quit.Pressed();
}

Autre exemple: interface GUI avant le main

Dans l'exemple suivant on a placé une interface GUI avant le main et avant l'objet qui les utilise. Remarque: les RowColumn sont emboîtables les uns dans les autres.

#include <scxx.h>
#include <GUI.h>
#include <RowColumn.h>
#include <TextField.h>
#include <PushButton.h>
#include <Text.h>
#include <CharString.h>

int setRealTimeMode = SetRealTimeMode();  // parce qu'il y a des objets avant main
GUI               gui;                    // parce qu'il y a des objets gui avant main

RowColumn         base ( gui, "RootWindow" );
RowColumn         groupe ( base, 1, GUIOrientation::HORIZONTAL);
Text              texte ( base, 10);
TextField         ligne ( base );
PushButton        quit ( base, "QUITTER" );
PushButton        bouton1 ( groupe, "Bouton1" );
PushButton        bouton2 ( groupe, "Bouton2" );
PushButton        bouton3 ( groupe, "Bouton3" );
GUIRealizer       baseRealizer(base);

active class Obj  {
   @Obj ()  {                       // corps de l'objet (processus)
      CharString msg;
      for (;;) {
        select {
          ligne.ReadText(msg);    // pret avec enter
        ||
          texte.ReadText(msg);    // pret avec crtl-enter
        ||
          quit.Pressed();
          accept ~Obj;            // accepte sa propre destruction
        }
      }
   }
};
Obj O1;

void main (  )  { }

Autre exemple: interface GUI dans un objet

Dans l'exemple suivant on a placé l'interface GUI dans un objet. Observer l'initialisation !

#include <scxx.h>
#include <GUI.h>
#include <RowColumn.h>
#include <TextField.h>
#include <PushButton.h>
#include <Text.h>
#include <CharString.h>

int setRealTimeMode = SetRealTimeMode();  // parce qu'il y a des objets avant main
GUI               gui;                    // parce qu'il y a des objets gui avant main


active class Obj  {
   RowColumn         base;         // Les membres d'un objet doivent etre initialises 
   RowColumn         groupe;       // apres les parametres du constructeur
   Text              texte;
   TextField         ligne;
   PushButton        bouton1;
   PushButton        quit;
   GUIRealizer       baseRealizer;

public:
   Obj(): base ( gui, "RootWindow" ),
          groupe ( base, 1, GUIOrientation::HORIZONTAL),
          texte ( base, 10),
          ligne ( base ),
          quit ( base, "QUITTER" ),
          bouton1 ( groupe, "Bouton1" ),
          baseRealizer(base)              {}

private:
   @Obj ()  {                       // corps de l'objet (processus)
      waituntil (now() + 100);
   }
};
Obj O1;

void main (  )  { }
       // le programme attend de pouvoir effacer l'objet actif, ce qui n'est
       // possible que lorsqu'il accepte explicitement sa destruction.

Création et utilisation d'un socket TCP serveur

explications
#include  <TCPSocket.h>
int result;
char msg[100];

              // déclaration et initialisation du socket-démon  (OK: result=0)
TCPSocketDaemon * sd = new TCPSocketDaemon (result, 5000);

              // déclaration socket de données
TCPSocket * ns;

              // attente de la génération d'un nouveau socket correspondant 
              // à un nouveau client
ns = sd -> SocketCreated ();   

              // émission d'un message sur le socket créé (OK: result=nbre de bytes)
result = ns -> Send (msg, sizeof(msg), 0);                (connection fermée: result==0)

              // réception d'un message du socket créé    (erreur: result<0)
result = ns -> Recv (msg, sizeof(msg), 0);

              // ferme un socket
delete ns;

Création et utilisation d'un socket TCP client

explications
#include  <TCPSocket.h>
int result;
char msg[100];

              // déclaration et initialisation du socket         (OK: result=0)
TCPSocket * sd = new TCPSocket (result, "host", 5000);

              // émission d'un message sur le socket créé (OK: result=nbre de bytes)
result = sd -> Send (msg, sizeof(msg), 0); (connection fermée: result==0)

              // réception d'un message du socket créé    (erreur: result<0)
result = sd -> Recv (msg, sizeof(msg), 0);


Création et utilisation d'un socket UDP serveur

Les sockets UDP décrits ci-dessous sont tels qu'il sont définis dans UNIX. Ils sont suivis de sockets proches de ceux de TCP, en ce sens qu'ils définissent également un canal.
#include  <UDPConn.h>
int result;
char msg[100];

              // déclaration et initialisation du socket-démon    (OK: result=1)
UDPConnDaemon * sd = new UDPSocketDaemon (&result, 5000);

              // déclaration socket de données
UDPConn * ns;

              // attente de la génération d'un nouveau socket correspondant 
              // à un nouveau client
ns = sd -> SocketCreated ();   

              // émission d'un message sur le socket créé    (OK: result=nbre de bytes)
result = ns -> Send (msg, sizeof(msg), 0);                   (connection fermée: result==0)
 
              // réception d'un message du socket créé       (erreur: result<0)
result = ns -> Recv (msg, sizeof(msg), 0);

Les sockets UDP décrits ci-dessous se comportent comme les sockets TCP, quant à l'ouverture et aux ports, mais ils envoient des datagrammes non fiables.

Création et utilisation d'un socket UDP client

explications
#include  <UDPSocket.h>     // connection oriented (il y a aussi un socketTCP pour gérer l'ouverture et la fermeture !)
int result;
char msg[100];

              // déclaration et initialisation du socket            (OK: result=1)
UDPSocket * sd = new UDPsocket ("host",5000,&result);

              // émission d'un message sur le socket créé     (OK: result=nbre de bytes)
result = sd -> Send (msg, sizeof(msg), 0);                    (connection fermée: result==0)

              // réception d'un message du socket créé        (erreur: result< 0)
result = sd -> Recv (msg, sizeof(msg), 0);

Machine à états finie

explications
Etat1:  select  {
                 accept Send;
                 goto Etat2;
            ||
                 call Oa->Connect ( paramx );
                 goto Etat1;
            }

Etat2:  select  {
               . . .
            }
Manuel hypertexte de C, C++ et sC++ / EPFL / petitpierre@lti.di.epfl.ch