FAQ Qt
FAQ QtConsultez toutes les FAQ
Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021
- Faut-il utiliser les pointeurs avec QString ?
- Comment transformer un QString en std::string et réciproquement ?
- Comment convertir un QString en chaîne C (char *) ?
- Comment formater du texte avec QString ?
- Comment convertir un nombre en chaîne de caractères ?
- Comment formater les nombres entiers ?
- Comment convertir un QString en un nombre ?
- Comment formater les nombres réels ?
- Comment tester si une chaîne de caractères est vide ?
- Comment QString gère l'encodage des chaînes de caractères ?
- Comment découper les mots d'une chaîne de caractères ?
Ce n'est pas nécessaire. QString utilise un pointeur partagé pour stocker les caractères. Les opérations de copie et d'affectation sont aussi performantes qu'en manipulant des pointeurs.
QString
texte =
"Developpez!"
;
// la copie est rapide
QString
copie =
texte;
QString
secondeCopie;
// l'affectation est rapide
secondeCopie =
copie;
// utiliser QString en argument est efficace
uneFonction(texte);
Pour transformer un std::string en QString, utilisez la fonction statique QString::fromStdString().
Pour l'opération inverse, transformer un QString en std::string, utilisez la fonction membre toStdString().
Pour convertir un objet QString en chaîne de 8 bits, il faut utiliser les méthodes toAscii(), toLatin1(), toUtf8(), toLocal8Bit(). Ces méthodes retournent un objet QByteArray, qui permet de gérer la mémoire. QByteArray fournit les méthodes constData() et data() pour accéder à un pointeur sur un tableau de char. Ce pointeur est valide aussi longtemps que l'objet n'est pas modifié ou détruit.
QString
adresseIp("127.0.0.1"
);
QByteArray
adresseIpEncodee =
adresseIp.toUtf8();
printf(adresseIpEncodee.constData());
Avec des chaînes de type C, il faut être attentif à la mémoire. Par exemple, le code suivant provoquera des problèmes de mémoire.
QStringList
list;
list <<
"C"
<<
"C++"
<<
"Qt"
;
QList
<
const
char
*>
ipListEnChar;
foreach
(const
QString
&
ip, list)
{
QByteArray
adresseIpEncodee =
ip.toUtf8();
ipListEnChar <<
adresseIpEncodee.constData(); // le pointeur sera invalide
}
foreach
(const
char
*
str, ipListEnChar)
{
printf(str); // le résultat est imprévisible
}
Il faut revenir aux vieilles habitudes de C et gérer les allocations à la main. Il suffit dans l'exemple de s'assurer que les objets QByteArray ne soient pas détruits.
QStringList
list;
list <<
"C"
<<
"C++"
<<
"Qt"
;
QList
<
QByteArray
>
ipListEnCharData;
QList
<
const
char
*>
ipListEnChar;
foreach
(const
QString
&
ip, list)
{
QByteArray
adresseIpEncodee =
ip.toUtf8();
ipListEnChar <<
adresseIpEncodee.constData();
ipListEnCharData <<
adresseIpEncodee;
}
foreach
(const
char
*
str, ipListEnChar)
{
printf(str);
}
Dans un problème réel, le tableau de char * serait caché dans les fonctions C utilisées, et il faut rester attentif à la gestion de la mémoire.
Remarque : QString permet aussi une conversion vers les formats std::string et std::wstring fournis par la STL.
Lien : Comment transformer un QString en std::string et réciproquement ?
QString implémente un équivalent au printf() et boost::format pour faire du formatage de chaîne. Pour cela, QString utilise des formateurs sous la forme %n (où n est un nombre) et les fonctions arg.
Chaque fonction arg retourne une nouvelle chaîne où les %n sont placés par ordre croissant. La fonction arg possède énormément de versions différentes qui vont permettre de remplacer un formateur par un nombre ou une chaîne. De plus, si plusieurs formateurs ont le même nombre, ils seront remplacés par la même valeur.
QString
s =
"%2 et %1 ou %1 et %3"
;
// On remplace le plus petit formateur contenu dans s
// tous les %1 sont remplacés par le nombre 42
// s1 == "%3 et 42 ou 42 et %2"
// s n'est pas modifié
QString
s1 =
s.arg(42
);
// On remplace plusieurs formateurs contenus dans s1 dans l'ordre croissant
// %2 est remplacé par hello
// %3 est remplacé par salut
// s2 == "salut et 42 ou 42 et hello"
// s1 n'est pas modifié
QString
s2 =
s1.arg("hello"
,"salut"
);
Cet outil est d'autant plus puissant que l'on peut faire du formatage récursif : l'on peut ajouter des formateurs lors du remplacement d'un formateur.
QString
s =
"%1"
;
//%1 est remplacé par "formatage récursif : %1 %2"
// s1 == "formatage récursif : %1 %2"
// s1 est composé par deux nouveaux formateurs.
QString
s1 =
s.arg("formatage récursif : %1 %2"
);
QString fournit la méthode statique number() pour convertir des nombres.
QString
cinquante =
QString
::
number(50
);
QString
unTiers =
QString
::
number(0.33333
);
Avec QString::number(), il est aussi possible de spécifier la base pour les entiers, et le format et la précision pour les réels. La méthode statique QString::number() possède un équivalent pour convertir un nombre dans un objet existant : QString::setNum().
QString
cinquante("Ce texte sera supprimé"
);
cinquante.setNum(50
); // cinquante vaut "50"
Pour insérer un nombre dans une chaîne de caractères, il est plus simple d'utiliser les fonctionnalités de formatage de QString.
Lien : Comment formater du texte avec QString ?
Lien : Comment formater les nombres entiers ?
Qt à l'aide de la classe QString peut formater des chaînes de caractères. Cela est possible grâce à la méthode sprintf() qui permet de formater les chaînes, comme en C, ou à la méthode arg(), plus propre à Qt.
Exemple : on souhaite formater une chaîne sous la forme Image_00032.
QString
str;
int
val=
32
;
str =
str.sprintf("Image_%05d"
, val ); // str == "Image_00032"
QString
str =
"Image_%1"
;
int
val=
32
;
str =
str.arg(val, 5
, 10
, QChar
('0'
) ); // str == "Image_00032"
La classe QString implémente directement des méthodes pour transformer une chaîne de caractères en variable numérique. De plus ces méthodes possèdent des paramètres optionnels :
- comme la conversion peut être impossible, un pointeur vers un booléen permet de récupérer le résultat de la conversion ;
- pour la conversion vers un des types entiers, il est possible de spécifier la base (2 à 36).
Utilisation sans paramètre.
QString
str=
"123.36969577"
;
double
number =
str.toDouble();//number == 123.36969577
Utilisation avec paramètre qui permet la vérification de la conversion.
QString
str1=
"128"
;
QString
str2=
"Qt128"
;
bool
ok; // Permet de vérifier si la conversion a réussi ou non.
int
num1 =
str1.toInt(&
ok); // ok == true et conversion réussie : num1 ==128
int
num2 =
str2.toInt(&
ok); // ok == false et conversion échouée : num2 == 0
Conversion d'une chaîne dans une base particulière (hexadécimal, octal…).
QString
str =
"FFFF"
;
bool
ok; // Toujours utile à la vérification de la conversion
int
num =
str .toInt(&
ok,16
); // ok == true et num == 65535
str ==
"0xFFFF"
; // Les conventions standards du C, par exemple, ici, "0x" pour une chaîne hexadécimale, sont reconnues.
num =
str.toInt(&
ok,16
); // ok == true et num == 65535
Remarque : Le même principe de conversion existe pour les autres types de variables numériques.
La méthode statique QString::number() prend des arguments facultatifs qui permettent de formater les nombres réels.
Le premier argument est un caractère qui précise le format, les formats possibles sont :
- 'e' : format scientifique avec un e minuscule, comme 2.997925e+08 ;
- 'E' : format scientifique avec un e majuscule, comme 2.997925E+08 ;
- 'f' : format classique pour les réels, comme 299792458.0 ;
- 'g' : choisir automatiquement le plus concis entre e et f, c'est le mode par défaut ;
- 'G' : choisir automatiquement le plus concis entre E et f.
// vaut "2.997925e+08"
QString
::
number(299792458.0
, 'e'
);
// vaut "299792458.000000", voir plus loin pour comprendre pourquoi
QString
::
number(299792458.0
, 'f'
);
Le second argument permet de spécifier la précision utilisée. Par défaut, Qt utilise une précision de 6, ce qui explique le résultat de l'exemple précédent.
// vaut "299792458.0"
QString
::
number(299792458.0
, 'f'
, 1
);
Il est suggéré de toujours préciser le format lorsque l'on veut convertir des réels (que ce soit avec Qt ou autre). Dans le cas contraire, un affichage inattendu peut apparaître lorsque les nombres deviennent très petits ou très grands, ce qui n'apparaît généralement pas dans les tests lors du développement.
Pour insérer un réel dans une chaîne de caractères, il est plus simple d'utiliser la fonctionnalité de formatage de QString
Lien : Comment formater du texte avec QString ?
Lien : Comment convertir un QString en un nombre ?
QString fournit la méthode isEmpty() pour savoir si une chaîne est vide.
if
(texte.isEmpty()){
...
}
Il est possible de comparer QString avec un tableau de char, ce qui permet aussi de tester si une chaîne est vide.
// mauvaise idée
if
(texte ==
""
){
...
}
Cela fonctionne, mais il y a une conversion implicite de "" en QLatin1String, ce qui est inutile pour une chaîne vide et est légèrement moins performant que l'exemple précédent.
En interne, QString stocke les caractères en Unicode 4.0 sur 16 bits, ce qui permet des opérations rapides quel que soit le type de caractère utilisé.
Pour convertir un chaîne sur 8 bits en QString, il est possible de l'encoder grâce aux méthodes statiques fromAscii(), fromLatin1(), fromUtf8(), et fromLocal8Bit().
QString
infini =
QString
::
fromUtf8("∞"
);
Par défaut, QString interprète une chaîne C avec l'encodage Latin 1 (ISO 8859-1). Il est possible de changer ce comportement de façon globale grâce à la méthode statique QTextCodec::setCodecForCStrings().
Pour convertir un objet QString en tableau de char, il faut utiliser une des méthodes toAscii(), toLatin1(), toUtf8() ou toLocal8Bit(). Si d'autres encodages sont nécessaires, il suffit d'utiliser QTextCodec, qui permet d'encoder à peu près n'importe quoi.
Pour découper les mots d'une QString, on utilise la méthode QString::split() et une des possibilités suivantes :
- découper en fonction d'un caractère séparateur ;
- découper en fonction d'une chaîne de caractères en guise de séparateur ;
- découper en fonction d'une expression régulière en guise de séparateur.
Voici quelques exemples :
//La phrase à découper
QString
phrase =
"Bonjour, voici une phrase à découper !"
;
//1) Découper en fonction du caractère ','
QStringList
mots1 =
phrase.split(','
, QString
::
SkipEmptyParts);
//mots1 = ["Bonjour" ," voici une phrase à découper !"]
//2) Découper en fonction du mot "une"
QStringList
mots2 =
phrase.split("une"
, QString
::
SkipEmptyParts);
//mots2 = ["Bonjour, voici " ," phrase à découper !"]
//3) Découper en fonction des espaces
QStringList
mots3 =
phrase.split(QRegExp
("
\\
s+"
), QString
::
SkipEmptyParts);
//mots3 = ["Bonjour," , "voici" , "une" , "phrase" , "à" , "découper" , "!"]
//3) Découper en fonction des espaces en retirant la ponctuation
QStringList
mots4 =
phrase.split(QRegExp
("
\\
W+"
), QString
::
SkipEmptyParts);
//mots4 = ["Bonjour" , "voici" , "une" , "phrase" , "à" , "découper"]
QString::SkipEmptyParts permet de ne pas récupérer dans le résultat de split() les chaînes de caractères vides.
Exemple :
QString
phrase =
"Bonjour,, ça va ?"
;
QStringList
mots1 =
phrase.split(","
);
// mots1 = [ "Bonjour", "", " ça va ?"]
QStringList
mots2 =
phrase.split(","
, QString
::
SkipEmptyParts);
// mots2 = [ "Bonjour", " ça va ?" ]