Voir la version complète : [Debutant]Tableaux à String
CocoChef
08/08/2005, 12h22
:00000005: Bonjour,
J'aimerais savoir comment afficher les valeurs d'un tableau :00000010:
J'ai essayé ça :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
string MyArray[5]=("Un","Deux","Trois","Quatre");
for (int i=0;i<5,i++)
{
cout << " Valeur du tableau, numéro " << i << " : " << MyArray[i] << endl;
}
system("PAUSE");
return 0;
}
Mais ca ne marche pas, pourquoi ?
Merci d'avance
il faudrai pa que tu remplace string par char ?
J'ai jamais vu un tableau avec string comme declaration, je sais meme pas si ça existe string :s
deathangel
08/08/2005, 12h42
euh, juste, tu as 4 éléments dans ton tableau, et tu déclares un tableau de taille 5, et tu parcours 5 éléments...
si tu as une erreur à l'éxecution, ca peut venir de là
Mais ca ne marche pas
Ca c'est en général une réplique à éviter, surtout lorsqu'on parle de programmation.
Donc pour les membres qui ne sont pas devins, merci d'indiquer :
1- Si c'est une erreur de compilation, d'édition de liens, d'execution ou simplement des résultats erronés.
2- Le message d'erreur qui va avec
3- Le plus d'infos supplémentaires possibles selon le cas (infos de debugging, contexte, ce que tu as déjà essayé, ......)
Ce sera plus simple pour nous tu ne penses pas ? ;)
ZeBlueCow
08/08/2005, 13h09
...Erreurs de compilations:
1- L'initialisation d'un tableau se fait avec des accolades, pas avec des parenthèses:
string MyArray[5] = {"Un","Deux","Trois","Quatre"};
2- Il y a une erreur de syntaxe dans la déclaration de ton for (l'erreur est tellement simple que je te laisse le plaisir de la trouver...)
Après, ça compile et ça "marche" (testé sous vc6, tant que i est strictement inférieur à la taille du tableau, pas de pb).
CocoChef
08/08/2005, 13h22
Merci @ tous !
Loulou > ok je ferais ça aux prochaines questions ! merci
ZeBlueCow > MERCIIIIII !!! Pour l'erreur de FOR j'ai trouvé et pour le tableau... :00000032: ... ca a marché ! Merci !
Voila le bon code ( un peu rectifié ) :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
string MyArray[5]={"Un","Deux","Trois","Quatre","Cinq"};
for (int i=0;i<5;i++)
{
cout << " Valeur du tableau, numéro " << i << " : " << MyArray[i] << endl;
}
system("PAUSE");
return 0;
}
Aussi, les variables de type CHAR ne peuvent que contenir Qu'un caractère, et pas toute une chaine de caractères, je ne me trompe pas ?
MERCI ET @+
Tu ne te trompes pas mais tu peux utiliser char* ou char[] pour stocker des chaines de caractères. Perso c'est ce que je fais mais je crois que c'est juste un vieux relant de C et qu'en C++ il est plus propre d'utiliser string
Flamaros
08/08/2005, 17h46
Oui mais tu peux faire un tableau de CHAR et la tu as une chaine de caracteres.
Et tu peux faire un tableau de ca.
Ca donne :
char dtab[20][100]; // 20 chaines de 100 caracteres (ou 100 de 20)
char *dtab[20]; // 20 char * (chaine de caractere de taille non fixe)
char **dtab; // tableau de chaines de caracteres dynamique
PS : lis les messages de log de la compilation, les erreurs de syntaxes sont les plus simple a raisoudre (y a meme la ligne et le pb).
CocoChef
08/08/2005, 21h54
Merci @ vous deux !
Vous m'avez bien aidé !
Pour Flamero :
Merci je vient de comprendre quelque chose : les tableaux de tableaux, que j'ai appliqué simplement sur des tableaux ( de tableaux ^^ ).
:00000025:
Ca donne :
char dtab[20][100]; // 20 chaines de 100 caracteres (ou 100 de 20)
char *dtab[20]; // 20 char * (chaine de caractere de taille non fixe)
char **dtab; // tableau de chaines de caracteres dynamique
:00000014:
Mais pourquoi ce code :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
char *MyArray[2]={{"B","o","n","j","o","u","r"},{"T","o","i"}};
for (int i=0;i<7;i++)
{
cout << *MyArray[i];
}
system("PAUSE");
return 0;
}
Me donne une erreur de compilation ( brace-enclosed initializer used to initialize `char*' ) ? Pourquoi ?
Et pourquoi ce code :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
char MyArray[2][7]={{"B","o","n","j","o","u","r"},{"T","o","i"}};
for (int a=0;a<2;a++)
{
for (int i=0;i<7;i++)
{
cout << " Valeur du tableau " << a << ", numero " << i << " : " << MyArray[a][i] << endl;
}
}
system("PAUSE");
return 0;
}
Me donne une erreur de compilation ( invalid conversion from `const char*' to `char' ) ??
Et quelle est la différence entre char *dtab[20]; et char **dtab; ? Je ne comprend pas là...
Merci et @+
:00000025:
Concernant ton exemple 1, tu devrais plutot faire, je n'explique pas pourquoi tu comprendra dans n'importe quel livre de C++ :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
char *MyArray[2]={"Bonjour", "Toi"};
for (int i=0;i<2;i++) {
cout << MyArray[i];
}
system("PAUSE");
return 0;
}Pour ton exemple 2, les chaines s'encadrent de "", et les caractères, de '', ce qui donne : #include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
char MyArray[2][7]={{'B','o','n','j','o','u','r'},{'T','o','i'}};
for (int a=0;a<2;a++)
{
for (int i=0;i<7;i++)
{
cout << " Valeur du tableau " << a << ", numero " << i << " : " << MyArray[a][i] << endl;
}
}
system("PAUSE");
return 0;
}Tu peux aussi te dispenser de donner une limite à la première dimension de tableaux lorsque tu les initialises en même temps que tu les déclares.
Flamaros
08/08/2005, 22h47
Fais tres attention a la syntaxe.
Les doubles cotes " sont utilise pour les char *. Alors que les single cotes ' sont utilisees pour les char.
En gros la tu declares un char **, alors que tu l'utilises comme un char ***.
ecrit plutot l'une des deux choses suivantes :
char *MyArray[2]={{"Bonjour"},{"Toi"}};
char *MyArray[2]={{'B','o','n','j','o','u','r'},{'T','o','i'}};
Les pointeurs est la notion la plus complexe du C pour les debutants, mais apres elle est vraiment un atout.
Aussi fais tres attention dans ton cas tu n'as pas alloue la memoire avant de mettre des donnees. Quand tu utilises un pointeur tu dois obligatoirement faire l'allocation (dite dynamique) ou etre faite par une autre fonction (pour certaine lib par ex). Quand tu declares un pointeur le systeme ne reserve pas de place en memoire, justement il te sers a retrouver les donnees sur lesquelles il va pointer lorsque tu ferra l'allocation. Il faut aussi liberer la memoire apres.
Dans ton deuxieme expemple le probleme de gestion de memoire ne se pose pas.
PS : Si tu n'alloue pas la memoire alors que tu devrais ton programme a quand meme de grande chance de tourner surtout si tu n'utilises pas beaucoup de memoire. Seulement l'OS ne sachant pas ou tu as ecris (puisque tu n'as pas reserve une zone), il peut tres bien laisser un autre programme ecrire la ou tu as mis tes donnees et la il va sans dire que ton prog crash sur un bon segfault (lecture sur une zone memoire interdite). Et en plus il y a une grosse faille de securite dans se cas.
Flamaros
08/08/2005, 22h48
Mais heu NewbiZ tu me concurences la, lol je plaisante.
Marrant la facon qu'on a d'expliquer les choses (pas du tout de la meme facon).
Flamaros > la différence c'est que toi tu as expliqué, alors que j'ai juste corrigé ce qu'il fallait pour que ca tourne ;)
Flamaros
09/08/2005, 02h21
J'espere que c'est comprehensible aussi de la facon dont j'explique, car c'est pas toujours evidante d'expliquer un truc qu'on maitrise a quelqu'un qui ne comprend rien.
C'est quoi l'interret d'utiliser des char[] en C++ ? :00000005:
Vous utilisez les mallocs aussi?
Euh, quand tu es passé par quelques années de C avant le C++ tu perds pas tes petites habitudes comme ca :) Chacun a sa façon de coder, ses petites manies ...
Bref quand on aborde les préférences individuelles il ne faut pas s'étonner si on sort du cadre de la logique.
Flamaros
09/08/2005, 05h47
Moi perso en C++ je me force a utiliser les string et tout le reste.
Mais bon comme je n'ai fait qu'un seul proj en C++, je me raporte plus facilement a ce que je fais quand je code en C, et pi j'adore vraiment les pointeurs.
J'ai du faire tellement de fonction sur le traitement de chaines de caracteres (char *) que ca ne me prend pas forcment plus de temps pour certain truc (a recoder) que d'utiliser les methodes de la class string.
CocoChef
09/08/2005, 12h04
Merci @ tous pour vous réponses !
Mais.. dans ce code :
#include <string>
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
char *MyArray[2]={{'B','o','n','j','o','u','r'},{'T','o','i'}};
for (int i=0;i<7;i++)
{
cout << *MyArray[i];
}
system("PAUSE");
return 0;
}
Pourquoi ça me met une erreur de compilation ( brace-enclosed... ) ? Faut-il " allouer " la mémoire ? Si oui, comment l'allouer ?
Mais quand je déclare une variable << char *variable[2] >>, c'est une variable pointeur si je me trompe pas, et les pointeurs sont là pour .. donner l'adresse mémoire d'une autre variable ! :00000020: Alors pourquoi dans l'exemple que tu me donne ( flamencos ), pourquoi << char* variable[2] >> déclare un tableau de 2 CHAINES DE CARACTERES ?
Et aussi... ( personnellement ) je ne vois pas pourquoi ( trop ) se compliquer la vie en utilisant des CHAR* au lieu de STRING..
Merci d'avance !
:00000025:
En fait, on conseille souvent aux débutants de ne pas utiliser
char *Chaine;
Mais plutot
char* Chaine;
Vois-tu où je veux en venir ? si tu ne comprends pas, essayes de faire comme si (char*) était un type en lui même, comme string.
Flamaros
09/08/2005, 16h28
Mon pseudo a une legere tendance a changer tout le temps.
Mais quand je déclare une variable << char *variable[2] >>, c'est une variable pointeur si je me trompe pas, et les pointeurs sont là pour .. donner l'adresse mémoire d'une autre variable !
Oui mais ton autre variable n'est pas declaree, donc pas allouee, voila pourquoi c'est a toi de le faire.
En C tu utilises la fonction malloc() pour l'allocation et en C++ l'operateur new.
Pour ce qui est du message d'erreur j'ai jamais vu ca tu utilises quel compilo (ou IDE)?
Pour l'allocation ca dois donner :
int main()
{
char *MyArray[2];
MyArray[0] = new char[7];
MyArray[1] = new char[3];
MyArray[0] = "Bonjour";
MyArray[1] = "Toi";
for (int i=0;i<7;i++)
{
cout << *MyArray[i];
}
delete MyArray[0];
delete MyArray[1];
system("PAUSE");
return 0;
}
char *MyArray[2]={{'B','o','n','j','o','u','r'},{'T','o','i'}};
MyArray[0] = new char[7];
MyArray[1] = new char[3];
MyArray[0] = "Bonjour";
MyArray[1] = "Toi";
...
delete MyArray[0];
delete MyArray[1];
Hum... Dans ce code tu as un crash, deux fuites mémoire et deux comportements indéterminés.
-> Le crash : tu initialises les éléments de MyArray avant de lui allouer la mémoire. A moins que ce soit une simple erreur de copié / collé.
-> Les fuites mémoire : juste après avoir obtenu 2 pointeurs vers de la mémoire allouée, tu réaffectes les éléments de MyArray vers des chaînes constantes. La mémoire que tu venais d'allouer est perdue. D'autant plus que ce vers quoi pointent maintenant tes MyArray[i] sont des chaînes constantes, donc non modifiables par la suite. Pour la copie de chaîne, il faut utiliser strcpy et non une bête affectation.
-> Le comportement indeterminé 1 : tu alloues n caractères mais tu en stockes n + 1 (tu oublies le \0 terminal).
-> Le comportement indeterminé 2 : tu utilises delete avec new[] (il faut utiliser delete[]).
Mais pourquoi diable vous entêtez-vous à réécrire de la manière la plus sale et buggée possible un code qui est au départ si bon ? :00000003:
Flamaros
09/08/2005, 18h57
Effectivement pour l'initialisation c'est que j'ai fait un copier/coller et j'ai oublier de modifier la ligne.
Ensuite en C++ si je ne me trompe pas je peux affecter des chaines de caracteres directement car l'operateur = a ete surcharge a cet effet. Mais en C il faut faire une copy avec strdup() ou strcpy() (un truc dans le genre).
Pas besoin du '\0' la boucle est basee sur la taille de la chaine et nous jusqu'a ce qu'on ne puisse plus la lire, mais effectivement je le mets toujours.
Et pour le delete je ne vois pas bien ou est le probleme.
Lightness1024!
09/08/2005, 19h35
le probleme est que tu utilises pas le bon opérateur.
delete truc;
ca ne supprime qu'un objet.
tu dois utiliser delete [] truc;
pour supprimer un tableau.
et puis au lieu de faire ces allocations à la main, faites les dans le constructeur et destructeur d'une classe chaine.
et surchargez les opérateurs.
c'est exactement ce qu'est la classe std::string
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector< string > mesChaines;
mesChaines[0] = "premiere chaine";
...
mesChaines[n] = "nieme chaine";
for (int i; i <= n; ++i)
cout << mesChaines[i] << endl;
return 0;
}
est parfaitement légal et ne cause pas de leaks ni overruns.
Ensuite en C++ si je ne me trompe pas je peux affecter des chaines de caracteres directement car l'operateur = a ete surcharge a cet effet. Mais en C il faut faire une copy avec strdup() ou strcpy() (un truc dans le genre).
Non... L'opérateur = entre deux pointeurs ne fera rien d'autre qu'affecter celui de droite à celui de gauche. On ne peut surcharger des opérateurs que pour des classes, en l'occurence ça l'est pour std::string.
Pas besoin du '\0' la boucle est basee sur la taille de la chaine et nous jusqu'a ce qu'on ne puisse plus la lire, mais effectivement je le mets toujours.
La boucle affiche les chaînes directement, et non caractère par caractère, c'est donc bien le '\0' final qui sera utilisé. D'ailleurs c'est une autre erreur que je n'avais pas vue : tu boucles sur 7 éléments alors que ton tableau n'en a que 2.
vector< string > mesChaines;
mesChaines[0] = "premiere chaine";
...
mesChaines[n] = "nieme chaine";
Là tu as tout de même un plantage, tu n'as pas alloué de place pour les éléments de ton vector. Il faut ajouter avec push_back, ou construire un vector directement dimensionné correctement.
for (int i; i <= n; ++i)
Il manque un "= 0" pour initialiser i :)
Conclusion de cette discution : lorsqu'on tente de faire en C des choses qui se font mieux en C++, on se gourre inexorablement...
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
const string mesChaines[] = {"Un", "Deux", "Trois"};
copy(mesChaines, mesChaines + sizeof(mesChaines) / sizeof(*mesChaines), ostream_iterator<string>(cout, "\n"));
return 0;
}
Là, difficile de faire une erreur.
Flamaros
09/08/2005, 22h29
J'avoue que la je me suis plante sur pas mal de chose.
Et pour que ce soit a ce point je ne dois pas etre bien reveille.
Par contre pour la surchage de l'operateur = je te remercie, je debute le C++.
Lightness1024!
09/08/2005, 23h30
Là tu as tout de même un plantage, tu n'as pas alloué de place pour les éléments de ton vector. Il faut ajouter avec push_back, ou construire un vector directement dimensionné correctement.
ah bon, j'avoue que je ne connais pas bien STL, dans le cas des maps si on fait ca, l'allocation des indices affectés est automatique.
je pensait que ca serait pareil pour les vector.
Il manque un "= 0" pour initialiser i
ah ben oui tiens. ( :D )
d'ailleurs ca me fait penser que j'ai lu qq part que la classe "int" avait un constructeur qui l'initialisait à zéro. cependant le constructeur par defaut dans les déclarations old-style C n'initialisait pas la valeur, curieux comme norme.
vBulletin® v.3.6.5, Copyright ©2000-2009, Jelsoft Enterprises Ltd. Tous droits réservés - Version française vbulletin-fr.org