Un équivalent graphique de std::cout et de printf pour Casio
Posté le 23/03/2025 19:06
Hello les gens !
Pour simplifier le debugging de mes projets casio, j’ai conçu un flux de sortie graphique inspiré de std::cout, appelé casio::dout, et je vais vous le partager.
J'ai aussi ajouté un équivalent de printf.
Équivalent de std::cout pour C++
Il gère :
-La composition de flux avec <<
-Les retours à la ligne \n
-Les fins de lignes avec casio::end
-Les types string, int, float, etc.
Exemple d’utilisation
casio::dout(10, 20, C_WHITE) << "Valeur : " << 42 << casio::end;
casio::dout(10, 60, C_WHITE) << "Pi ~ " << 3.14159f << "\nApproximatif" << casio::end;
Comment ça marche ?
Le système repose sur une classe DoutStream qui encapsule :
-Les coordonnées (x, y) initiales
-La couleur du texte
-Un curseur de position mis à jour dynamiquement
Le texte est découpé ligne par ligne, chaque mot est affiché avec dtext(), et les sauts de ligne sont simulés en ajustant les coordonnées via dsize().
Intégration
Incluez simplement le fichier dout.hpp dans votre projet, et utilisez casio::dout() comme un flux standard.
Code :
#ifndef DOUSTREAM_HPP
#define DOUSTREAM_HPP
#include <gint/gint.h>
#include <gint/display.h>
#include <string>
#include <sstream>
#include <iostream>
namespace casio
{
struct DoutEnd {};
inline DoutEnd end;
class DoutStream {
public:
DoutStream(int x, int y, int color)
: startX(x), curX(x), curY(y), color(color) {}
template<typename T>
DoutStream& operator<<(const T& value) {
std::ostringstream oss;
oss << value;
processText(oss.str());
return *this;
}
DoutStream& operator<<(DoutEnd) {
// Force une nouvelle ligne
newline();
return *this;
}
private:
int startX;
int curX;
int curY;
int color;
void processText(const std::string& text) {
std::string line;
for (char ch : text) {
if (ch == '\n') {
if (!line.empty()) draw(line);
newline();
line.clear();
} else {
line += ch;
}
}
if (!line.empty()) draw(line);
}
void draw(const std::string& text) {
dtext(curX, curY, color, text.c_str());
int w = 0, h = 0;
dsize(text.c_str(), dfont_default(), &w, &h);
curX += w; // Avancer horizontalement
}
void newline() {
curX = startX;
int h = 0;
dsize("A", dfont_default(), nullptr, &h); // Hauteur de ligne
curY += h + 1;
}
};
// Interface comme std::cout
struct dout_creator {
DoutStream operator()(int x, int y, int color) {
return DoutStream(x, y, color);
}
};
inline dout_creator dout;
inline void formatFloat(float val, char* out) {
int sign = val < 0 ? -1 : 1;
val = val < 0 ? -val : val;
int int_part = static_cast<int>(val);
int dec_part = static_cast<int>((val - int_part) * 1000 + 0.5f); // arrondi
sprintf(out, "%s%d.%03d", (sign < 0 ? "-" : ""), int_part, dec_part);
}
inline DoutStream& operator<<(casio::DoutStream& out, float val) {
char buf[32];
formatFloat(val, buf);
return out << buf;
}
inline DoutStream& operator<<(casio::DoutStream& out, double val) {
char buf[32];
formatFloat(static_cast<float>(val), buf);
return out << buf;
}
}
#endif
Équivalent de printf pour C
dprint est une réimplémentation simplifiée de printf
Ce n’est pas un printf complet :
-Pas de gestion des drapeaux (-, +, 0, etc.)
-Pas d’alignement ou largeur (%5d, %05d, etc.)
-Pas de support Unicode ou internationalisation
Fonctionnalités prises en charge
-Position (x, y) initiale personnalisable
-Couleur personnalisée via int color
-Gestion des \n comme retour à la ligne visuel
-Reconnaissance et rendu des formats :
▬► %d / %i → int
▬► %u / %lu / %ld → unsigned int, long, unsigned long
▬► %zu → size_t
▬► %f / %.Nf → float ou double avec précision personnalisée
▬► %x → hexadécimal (minuscule)
▬► %p → pointeur
▬► %s → chaîne de caractères
▬► %b → booléen (true/false)
▬► %% → pour afficher un %
(Le format %b n’existe pas dans printf, mais dprint le supporte)
Exemple d’utilisation
dprint(10, 10, C_WHITE, "Bonjour\ntout le monde !");
dprint(10, 30, C_WHITE, "Nom: %s Score: %d", "Alice", 42);
dprint(10, 50, C_WHITE, "Pi ≈ %.3f", 3.14159f);
dprint(10, 70, C_WHITE, "Taille: %zu octets", (size_t)512);
dprint(10, 90, C_WHITE, "État: %b", true);
dprint(10, 110, C_WHITE, "Adresse: %p", (void*)0x12345678);
dprint(10, 130, C_WHITE, "Hex: %x", 255);
dprint(10, 150, C_WHITE, "Progression: 100%%");
Code :
#ifndef DPRINT_H
#define DPRINT_H
#include <gint/gint.h>
#include <gint/display.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
inline void formatFloat(float val, char* out, int precision)
{
int sign = val < 0 ? -1 : 1;
val = val < 0 ? -val : val;
int int_part = (int)val;
int dec_part = (int)((val - int_part) * pow(10,precision) + 0.5f); // arrondi
sprintf(out, "%s%d.%03d", (sign < 0 ? "-" : ""), int_part, dec_part);
}
void dprint(int x, int y, int color, const char* fmt, ...)
{
char buffer[256] = {0};
int cx = x;
int cy = y;
va_list args;
va_start(args, fmt);
while (*fmt) {
if (*fmt == '%') {
fmt++;
int precision = -1;
if (*fmt == '.') {
fmt++;
precision = 0;
while (*fmt >= '0' && *fmt <= '9') {
precision = precision * 10 + (*fmt - '0');
fmt++;
}
}
char temp[64] = {0};
switch (*fmt) {
case 'd':
case 'i':
sprintf(temp, "%d", va_arg(args, int));
break;
case 'u':
sprintf(temp, "%u", va_arg(args, unsigned int));
break;
case 'x':
sprintf(temp, "%x", va_arg(args, unsigned int));
break;
case 'l':
fmt++;
if (*fmt == 'd')
sprintf(temp, "%ld", va_arg(args, long));
else if (*fmt == 'u')
sprintf(temp, "%lu", va_arg(args, unsigned long));
break;
case 'z':
fmt++;
if (*fmt == 'u')
sprintf(temp, "%zu", va_arg(args, size_t));
break;
case 'f': {
double f = va_arg(args, double);
if (precision == -1)
precision = 3;
formatFloat(f, temp, precision);
break;
}
case 's':
snprintf(temp, sizeof(temp), "%s", va_arg(args, char*));
break;
case 'p':
sprintf(temp, "%p", va_arg(args, void*));
break;
case 'b':
snprintf(temp, sizeof(temp), "%s", va_arg(args, int) ? "true" : "false");
break;
case 'c':
snprintf(temp, sizeof(temp), "%c", va_arg(args, int));
break;
case '%':
strcpy(temp, "%");
break;
default:
snprintf(temp, sizeof(temp), "%%%c", *fmt); // Unknown format
break;
}
dtext(cx, cy, color, temp);
int w = 0, h = 0;
dsize(temp, dfont_default(), &w, &h);
cx += w;
} else if (*fmt == '\n') {
int h;
dsize("A", dfont_default(), NULL, &h);
cx = x;
cy += h;
} else {
buffer[0] = *fmt;
buffer[1] = '\0';
dtext(cx, cy, color, buffer);
int w = 0, h = 0;
dsize(buffer, dfont_default(), &w, &h);
cx += w;
}
fmt++;
}
va_end(args);
}
#endif
Citer : Posté le 23/03/2025 19:47 | #
Merci Fahri, c'est le genre de chose qui peuvent en effet bien servir quand on veut faire un petit programme rapidement.
Juste pour préciser, c'est pour du C++ only, ça ne fonctionne pas en C.
Donc il faut que votre programme casio soit compilé comme du C++.
Citer : Posté le 24/03/2025 02:34 | #
De rien
Update topic
Du coup j'ai rajouté dprint pour ceux qui en veulent une version C
Albert Einstein