SDL2 Afficher l'heure

Fermé
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 - Modifié par poparnassus le 29/08/2016 à 21:56
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 - 30 août 2016 à 18:14
Bonjour,

Pour la librairie SDL2 sous Win7?

Je souahite afficher l'heure et un chronometre dans 2 surfaces distincte. Mon probleme reside dans la soustraction des chaines. Je sais qu'avec
    difftime (&chrono,&tm_now); 
je peux calculer la difference de temps mais je n'arrive pas a l'afficher

Je recupere le temps de lancement du programme
    //DEpart Chrono
    time_t chrono = time(NULL);
    struct tm tm_chrono = *localtime (&chrono);
    strftime (chronox, sizeof chronox, "%H:%M:%S", &tm_chrono);


Ici la fonction qui me sert d'horloge:
    //Fonction Temps
    time_t now = time (NULL);
    struct tm tm_now = *localtime (&now);
    strftime (xtime, sizeof xtime, "%H:%M:%S", &tm_now);


//J'affiche la variable xtime de type char
 sprintf(xtime, "%s",xtime);

  
//Le chronox doit m'afficher le temps depuis le lancement du programme mais je sais pas comment manipuler la fonction difftime()  
sprintf(chronox, "%s",chronox);

2 réponses

mamiemando Messages postés 33367 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 19 novembre 2024 7 801
30 août 2016 à 09:53
Bonjour,

Je suppose que xtime est de type char *, pas char.

Ensuite si tu veux calculer une différence de temps (et manipuler plus généralement un temps), passer par des chaînes est une mauvaise idée, car les fonctions qui servent à manipuler du temps sont basées sur des valeurs numériques.

Il faut donc représenter le temps dans ton programme des valeurs numériques, ...
https://stackoverflow.com/questions/16275444/how-to-print-time-difference-in-accuracy-of-milliseconds-and-nanoseconds-from-c

... et uniquement passer vers les chaînes de caractères au moment de l'afficher dans ton interface graphique.
https://stackoverflow.com/questions/3673226/how-to-print-time-in-format-2009-08-10-181754-811

Bonne chance
1
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
Modifié par poparnassus le 30/08/2016 à 11:56
Honnetement je tourne en rond, j'ai du mal ^^ Je suis novice cest pour ca.
A savoir aussi que je maitrise mal les pointeurs...

Dans mon interface, jai une surface "heure actuelle" et "une surface "chronometre"

Proto.h


time_t now, chrono;

struct tm *tm_now;
char xtime [sizeof "HH:MM:SS"];

struct tm *tm_chrono;
char chronox [sizeof "HH:MM:SS"];

double seconds;


main.c


//DEpart Chrono
time_t chrono = time(NULL);
tm_chrono = localtime (&chrono);
strftime (chronox, sizeof chronox, "%H:%M:%S", tm_chrono);
//Si je copie la ligne au dessus, dans affichage.c au dessus de la ligne 17 je me retrouve avec deux horloge. Comprends pas


     while (!input.quitter)
    { 
        chargement_image(Mes parametre);
    }


affichage.c

//Ici la varible xtime me permet d'afficher l"heure et chrnox mon chron , l'heure fonctionne le chrono non, j'ai seulement l'heure à laquelle le programme est demarrer.
void chargement_image()
{
        sprintf(xtime, "%s",xtime);
        menu_gauche->Stime = TTF_RenderText_Blended(ecran->police, xtime ,ecran->couleurRouge);
        menu_gauche->Ttime = SDL_CreateTextureFromSurface(ecran->renderer1, menu_gauche->Stime);
        SDL_QueryTexture(menu_gauche->Ttime, NULL, NULL, &w, &h);
        SDL_RenderCopy(ecran->renderer1, menu_gauche->Ttime, NULL, &menu_gauche->Rtime);
        //Affichage chrono
        sprintf(chronox, "%s",chronox);
        menu_gauche->Schrono = TTF_RenderText_Blended(ecran->police, chronox ,ecran->couleurRouge);
        menu_gauche->Tchrono = SDL_CreateTextureFromSurface(ecran->renderer1, menu_gauche->Schrono);
        SDL_QueryTexture(menu_gauche->Tchrono, NULL, NULL, &w, &h);
        SDL_RenderCopy(ecran->renderer1, menu_gauche->Tchrono, NULL, &menu_gauche->Rchrono);

}


pilotage.c

//Fonction Temps
    time_t now = time (NULL);
    tm_now = localtime (&now);
    strftime (xtime, sizeof xtime, "%H:%M:%S", tm_now);

    seconds = difftime (&chrono,&now);
   //J'arrive pas a manipuler la fonction , je veux transmettre le resultat de diffftime à "chronox"



0
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
30 août 2016 à 14:18
bon je progresse,

    //Fonction Temps
    now = time (NULL);
    tm_now = localtime (&now);
    seconds = difftime (now,chrono);
    heure = seconds / 3600;
    
//je passe ma variable seconde de type double, a chronx de type char
    sprintf(chronox, "%.f",seconds);


je souhaiterez que chronox est la forme "HH:MM:SS" , quelqun a une idee ?
0
mamiemando Messages postés 33367 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 19 novembre 2024 7 801
30 août 2016 à 16:33
Bonjour

Voici une manière de faire :

#include <stdio.h>  // fputs
#include <stdlib.h> // time
#include <unistd.h> // sleep
#include <time.h>   // strftime, difftime

void fprintf_tm(FILE * stream, const char * format, const struct tm * tm_info) {
    const unsigned buffer_size = 100;
    char buffer[buffer_size];
    strftime(buffer, buffer_size, format, tm_info);
    fputs(buffer, stream);
}

void fprintf_time(FILE * stream, const char * format, const time_t * t) {
    fprintf_tm(stream, format, localtime(t));
}

void printf_time(const time_t * t) {
    fprintf_time(stdout, "%Y:%m:%d %H:%M:%S", t);
}

int main() {
    time_t t1, t2;

    // Measure t1, wait 2s, measure t2.
    t1 = time(NULL);
    sleep(2);
    t2 = time(NULL);

    // Print results
    printf("t1 = ");
    printf_time(&t1);
    printf(" t2 = ");
    printf_time(&t2);
    printf(" delta = %lf\n", difftime(t2, t1));

    return EXIT_SUCCESS;
}


Résultat :

(mando@aldur) (~) $ gcc toto.c && ./a.out
t1 = 2016:08:30 15:15:33 t2 = 2016:08:30 15:15:35 delta = 2.000000


Maintenant regardons un peu plus en détail "l'idée".

time_t
est le type que l'on mesure. On peut facilement faire la différence entre deux
time_t
.

struct tm
sert principalement à faire le "rendu". On va donc masquer cette complexité dans
print_time
. Il faut convertir le
time_t
en
struct tm
pour enfin pouvoir exploiter
strftime
.

Malheureusement cette fonction requiert un buffer. On va une fois encore cacher ce détail d'implémentation dans notre fonction dédiée à l'affiche d'un
struct tm
, la fonction que j'ai appelée
fprintf_tm
.

On voit que celle-ci laisse le choix du flux dans lequel on écrit (fichier, sortie standard, etc...) et dans le format, donc autant laisser cette flexibilité. Flexibilité que je répercute dans
fprintf_time
. Maintenant en pratique on va utiliser toujours le même flux (
stdout
) et le même format, et la fonction print_tm va me permettre de masquer tout ceci.

À ce stade on a le design (les paramètres et les fonctions) du programme et on voit comment emboîter les fonctions. Reste à gérer les pointeurs. Ici toutes mes fonctions prennent des pointeurs. Il suffit donc que dans le main je passe des pointeurs. Le mot clé
const
permet de préciser ce qui ne sera pas modifié par la fonction (il est donc mieux de les mettre, ça améliore la lisibilité du programme, sa rigueur, et surtout c'est plus générique).

Les pointeurs

Les pointeurs ensuite ce n'est pas très compliqué. Une adresse indique o quelque chose se trouve. Moralement, c'est un entier, donc quelque soit l'adresse dont on parle elle fait toujours la taille d'un entier (32 bits sur un système 32 bits, 64 sur un système 4 bits). Une adresse générique se note
void *
et donne un accès en lecture et écriture à cet endroit. Un
const void *
ne donne qu'un accès en lecture.

Le "problème", c'est qu'on peut parler de l'adresse de choses qui ne font pas la même taille. Un
uint32_t
ou
char
ne font pas la même taille par exemple.

Pour spécifier la taille de l'objet pointé, on type le pointeur pour indiquer ce qu'on est sensé y trouver. Par exemple un
uint32_t *
signifie qu'on pointe à priori sur quelque chose qui fait la taille d'un uint32_t (soit 32 bits).

Ensuite la syntaxe est simple : ce qui est l'adresse p (comme pointeur) est atteint par
*p
. À ce stade, le programme tentera de lire
sizeof(*p)
octets à l'adresse
p
. Si p n'est pas une adresse correctement initialisée tu auras une erreur de segmentation (erreur mémoire). Ce genre d'erreur se débogue typiquement avec
gdb
. A contrario, l'adresse un objet o s'obtient avec
&o
.

On retrouve en outre que parler de
*p
si p est de type
void *
n'aura pas de sens (on ne sait pas quelle taille lire). L'opérateur * n'est donc défini que sur des pointeurs typés.

On peut une fois la taille d'une case (de l'objet pointé) définir un décalage avec l'opérateur +. Par exemple si p est de type uint32_t, p + i revient à se décaler de i*sizeof(uint32_t) = 32*i bits par rapport à p. Pour accéder à la ième case d'un tableau, il suffit donc de connaître l'adresse de sa première case et de se décaler de i cases. Avec cette syntaxe, si on renomme p en tab, cela donnerait
uint32_t x = *(tab + i)
. Mais cette syntaxe est un peu lourde donc on définit l'opérateur
[ ]
:
tab[i]
correspond exactement à
*(tab+i)
. En particulier si i = 0, on retrouve le fait que la première case du tableau est stockée à l'adresse
tab
, donc tout est cohérent.

Vu qu'
*
requiert un pointeur typé, il en est mécaniquement de même pour
[ ]
. Par ailleurs, rien ne garantit que si on parle de tab[1000], ceci tombe à une adresse "réservée" par le programme. Si ce n'est pas le cas et que tu y accèdes, tu auras probablement une erreur mémoire. Ou pire, si ça tombe sur de la mémoire utilisée par ailleurs par ton programme, tu risques d'écraser ou de lire des choses qui n'ont rien à voir avec ton tableau. Ce genre d'erreur se débogue avec un outil comme
valgrind
.

Quoiqu'il en soit, les opérateurs définis sur les pointeurs permettent de faire "comme si" on manipulait un tableau (sous réserve qu'il soit alloué en mémoire). C'est pourquoi il n'y a pas de type "tableau" à proprement parler en C.

Reste à traiter le fait de réserver et relâcher une zone mémoire. C'est respectivement fait par
malloc
(ou
calloc
) et par
free
. Le schéma typique est :

uint32_t * block = malloc(1000*sizeof(uint32_t));
if (block) {
  // Je peux accéder à bloc[0]...bloc[999]
  // Quand j'ai fini :
  free(block);
} else {
  // Plus assez de mémoire
}


Après si tu veux aller plus loin sur les pointeurs, tu peux regarder comment faire des liste chaînes, des arbres, des matrices à n dimensions, etc...

Bonne chance
1
poparnassus Messages postés 426 Date d'inscription vendredi 28 mars 2014 Statut Membre Dernière intervention 25 décembre 2019 30
30 août 2016 à 18:14
ok c'est super sympa de prendre du temps pour moi ;-) , je vais aller voir les listes chaines, matrice etc, ca va m'aider je pense.

J'ai du mal a saisir, comment sait on si on doit allouée de la memoire ou non ? Exemple dans la SDL il y a beaucoup de fonction tel que SDL_loadbmp() qui alloue la memoire automatique et qui est liberer dés qu'on ferme la SDL avec sDL_quit() avec SDL_FreeSurface().
Autre cas j'utilise enormement les structures, je trouve que c'est tres pratique, mais a aucun moment de mon programme j'utilise malloc() dans les variables des structures, alors du coup je sais pas si je fais bien les choses ou non ...

J'ai une autre question, il y a t'il un nombre maximal de paramètre pour une fonction void ou int ?

Autre chose que je suis pas arriver a faire, j'ai un tableau qui es construit dans une fonction void, et je souhaite que les elements tu tableau soit accessible depuis nimporte quel fonction, donc je me suis dis il faut mettre ce tableau dans une structure mais honnetement je me suis un peu perdu ^^, je voulais te montre le code, mais j'ai tout effacer vu que je n'y arriver pas, mon tableau se crée comme ca:
data_send[9]={menu_haut->statueCAM, menu_droit->lumiere,input->mode_pilotage,input->BOUTTON_A,input->BOUTTON_B,input->BOUTTON_X,input->BOUTTON_Y,input->PRoueG, input->PRoueD}


En faite, je code une interface pour piloter un buggy tout terrain via le wifi, la j'ai quasiment terminer la partie interface, dans limmediat se qui me fait un peux peur cest le reseau... je sens que ca va pas etre de la tarte ^^
Encore une autre question, j'arrive pas a me decider sur la maniere dont je vais afficher les image de ma camera, (je prends des photos depuis un raspberry donc lui es coder en python) la technique que j'avais essyer consister a prendre des photos, par ex 10 photos a la seconde les renomée dune maniere a pouvoir les retrouvé par ordre chronologique, les uploader dans un fichier partager, et depuis mon interface je charger les images avec SDL_LoadBMP() et je les coller, Methode absolument pas performante du coup j'ai abandonné celle ci. Alors du coup je me demande, existe t-il des librairies pour ca, ou seul la matière grise est notre ami :-)

Derniere question, sur le site CCM ou autre est il possible de cree un projet de devellopement, de maniere a ce que tout mes code source soit accessible a tout le monde, parce que j'imagine que je ne dois pas etre le seul a apprendre derriere son pc avec l'aide de personne comme toi. Mise a part le site openclassroum et devellopez, ya pas grand chose, j'ai essayer de chercher des projets un peu comme moi, mais a part Mathéo sur openclassroom j'ai franchement rien trouver.

Je te remercie en tout cas.
0