[C] Problèmes d'allocation dynamique ?

Problèmes d'allocation dynamique ? [C] - C++ - Programmation

Marsh Posté le 19-09-2002 à 18:05:47    

Bonjour tout le monde,
 
J'ai un petit soucis avec l'execution d'un programme (un petit parser de log). Des printf bien placé m'ont permis de déterminer à quel endroit ca coincait.
Voici tout d'abord le bout de code qui pose problème :  
 
 
 
 

Code :
  1. for(i=0;(strcmp(ptable[i]->name,"EOP" )!=0);i++)
  2.     {       
  3.         for(j=0;j<MAX_PLAYERS;j++)    //MAX_PLAYERS == 100  
  4.         {
  5.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  6.         ptable[i]->ktable[j]->name = (char*)malloc(50*sizeof(char));
  7.         ptable[i]->ktable[j]->id = 999; //id fantaisiste
  8.         fill_string(ptable[i]->ktable[j]->name,50);
  9.         ptable[i]->ktable[j]->kills = 0; //initialisation du nombre de kill pour le joueur considéré
  10.         }
  11.        
  12.     }


ptable est un tableau de pointeurs vers des structures joueurs :
 
 

Code :
  1. typedef struct player
  2. {
  3. char* name;
  4. int id;
  5. char* team;               
  6. int kills;
  7. kill* ktable[MAX_PLAYERS];
  8. int deaths;
  9. int suicides;
  10. int team_kill;
  11. }player;


 
ktable est un tableau de pointeurs vers des structures kill
 
 

Code :
  1. typedef struct kill
  2. {
  3. int id;
  4. char* name;
  5. int kills;
  6. }kill;


 
 
Voici le déroulement de la chose :
 
- Premier passage : on balaye le fichier de log et on extrait le nom de joueurs pour remplir mon tableau ptable. Le code n'apparait pas
mais la fonction fonctionne très bien, j'ai pu tester. Tout ca pour dire que j'alloue correctement (je pense) de la mémoire pour chaque  
case de mon tableau par un ptable[lacasequivabien] = (player*)malloc(sizeof(player));
 
- Une fois ce passage effectué, c'est le bout de code que je vous ai affiché qui entre en jeu : pour chaque joueurs détécté, il va  
initialiser son tableau ktable.  
 
 
Résultat, ca merdouille dans cette fonction. Si je place un printf dans le for comme ceci :
 

Code :
  1. for(i=0;(strcmp(ptable[i]->name,"EOP" )!=0);i++)
  2.     {
  3.        
  4.         for(j=0;j<MAX_PLAYERS;j++)
  5.         {
  6.         printf("ICI!" ); getchar();
  7.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  8.         ptable[i]->ktable[j]->name = (char*)malloc(50*sizeof(char));
  9.         ptable[i]->ktable[j]->id = 999;
  10.         fill_string(ptable[i]->ktable[j]->name,50);
  11.         ptable[i]->ktable[j]->kills = 0;
  12.         }
  13.        
  14.     }


 
Résultat : Ca se "bloque" au bout d'une centaine de ICI! et mon utilisation mémoire ne cesse d'augmenter jusqu'à faire exploser ma swap file  
et planter Windows (J'utilise actuellement devC++ sous Windows 2000, car je suis en vacances et que j'ai oublié les cds de ma debian, bref, ca changera rien je pense)
 
 
Je suis ensuite passé à une autre version de débuggage made in printf :
 
 

Code :
  1. for(j=0;j<MAX_PLAYERS;j++)
  2.         {
  3.         printf("ICI! i=%d j=%d",i,j); getchar();
  4.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  5.         ptable[i]->ktable[j]->name = (char*)malloc(50*sizeof(char));
  6.         ptable[i]->ktable[j]->id = 999;
  7.         fill_string(ptable[i]->ktable[j]->name,50);
  8.         ptable[i]->ktable[j]->kills = 0;
  9.         }


 
Résultat : ca "bloque" à i=1 et j = 90.
 
 
Bizarre, bizarre. J'ai tenté autre chose en "limitant" l'allocation dynamique de mémoire :
 
 

Code :
  1. for(j=0;j<MAX_PLAYERS;j++)
  2.         {
  3.         printf("ICI! i=%d j=%d",i,j); getchar();
  4.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  5.         //ptable[i]->ktable[j]->name = (char*)malloc(50*sizeof(char)); //plus d'allocation dynamique ici !
  6.         ptable[i]->ktable[j]->id = 999;
  7.         fill_string(ptable[i]->ktable[j]->name,50);
  8.         ptable[i]->ktable[j]->kills = 0;
  9.         }


 
Résultat : ca "bloque" très rapidement à i=0 et j=1. Je me suis dit : "Tu tiens une piste" J'ai continué en ce sens, c'est à dire en allouant de plus en plus de mémoire
à cette chaine de caracteres
 

Code :
  1. for(j=0;j<MAX_PLAYERS;j++)
  2.         {
  3.         printf("ICI! i=%d j=%d",i,j); getchar();
  4.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  5.         ptable[i]->ktable[j]->name = (char*)malloc(1*sizeof(char)); //on alloue un seul caracteres
  6.         ptable[i]->ktable[j]->id = 999;
  7.         fill_string(ptable[i]->ktable[j]->name,50);
  8.         ptable[i]->ktable[j]->kills = 0;
  9.         }


 
Résultat : ca "bloque" comme précédemment à i=0 et j=1.
 
 
Dernier essai pour me conforter dans mon début d'idée, j'alloue 1000 * 8 = 8ko à ma chaine de caractères :
 

Code :
  1. for(j=0;j<MAX_PLAYERS;j++)
  2.         {
  3.         printf("ICI! i=%d j=%d",i,j); getchar();
  4.         ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  5.         ptable[i]->ktable[j]->name = (char*)malloc(1000*sizeof(char));
  6.         ptable[i]->ktable[j]->id = 999;
  7.         fill_string(ptable[i]->ktable[j]->name,50);
  8.         ptable[i]->ktable[j]->kills = 0;
  9.         }


 
Résultat : ca "bloque" comme précédemment à i=0 et j=47, soit un peu plus loin. C'est là ou je suis largué :)
 
Avant d'avoir des problèmes, je me contentais de la structure player sans le tableau de pointeurs vers des structures kill et
l'ensemble du programme fonctionnait très bien. Il y a peut être un problème plus profond, mais que je n'arrive pas à voir.
 
 
Merci à tous ceux qui ont eu le courage de me lire !  
 
A+


Message édité par Evadream -jbd- le 19-09-2002 à 18:07:23
Reply

Marsh Posté le 19-09-2002 à 18:05:47   

Reply

Marsh Posté le 19-09-2002 à 18:08:48    

man malloc
man free

Reply

Marsh Posté le 19-09-2002 à 19:29:15    

Citation :


Code :
  1. for(i=0;(strcmp(ptable[i]->name,"EOP" )!=0);i++)
  2. {
  3. for(j=0;j<MAX_PLAYERS;j++) //MAX_PLAYERS == 100
  4. {
  5. ptable[i]->ktable[j] = (kill*)malloc(sizeof(kill));
  6. ptable[i]->ktable[j]->name = (char*)malloc(50*sizeof(char));
  7. ptable[i]->ktable[j]->id = 999; //id fantaisiste
  8. fill_string(ptable[i]->ktable[j]->name,50);
  9. ptable[i]->ktable[j]->kills = 0; //initialisation du nombre de kill pour le joueur considéré
  10. }
  11. }



 
 
ptable est il bien alloué avant tout ??? :
 

Code :
  1. for(i=0; i<MAX_PTABLE; i++) {
  2. ptable[i] = (player*)malloc(MAX_PTABLE*sizeof(player));
  3. }


 
ensuite, ton invariant de boucle est faux ! :
 

Code :
  1. for(i=0;strcmp(ptable[i]->name,"EOP" ) && i<MAX_PTABLE; i++)
  2. {
  3. for(j=0;j<MAX_PLAYERS;j++) //MAX_PLAYERS == 100
  4. {
  5. ...
  6. }
  7. }


 
Un conseil :
fais des procédures d'allocation/libération de tes structures et utilises les !


---------------
Get the Cooool... Get the cool shoe-shine !
Reply

Marsh Posté le 19-09-2002 à 20:32:54    

ptable est ok comme je l'ai dit dans mon premier post. Merci qd même. Mon invariant de boucle n'est pas faux vu le test (je me comprends, j'ai fais des tests, c ok). De toutes facons mes problemes ne semblent pas venir de là.
 
Voici le bout de code qu'il y a juste au dessus et qui fonctionne parfaitement :
 

Code :
  1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++)   //tant que l'on est pas à la fin du log
  2.     {                                              //premier passage pour détecter les joueurs
  3.              
  4.        if( strcmp(tab[i]->data2,"player" )==0 && strcmp(tab[i]->data3,"Connect" )==0 )
  5.        {
  6.        ptable[pn]= (player*)malloc(sizeof(player));
  7.        ptable[pn]->name = (char*)malloc(50*sizeof(char));     
  8.        ptable[pn]->team = (char*)malloc(15*sizeof(char));           
  9.               ptable[pn]->name = tab[i]->data4;  //le nom
  10.        ptable[pn]->team = tab[i+1]->data5; //la team...
  11.        ptable[pn]->id = atoi(tab[i]->data5); //l'id
  12.        ptable[pn]->kills = 0; //inialisation des stats du joueur
  13.        ptable[pn]->deaths = 0;
  14.        ptable[pn]->suicides = 0;
  15.        ptable[pn]->team_kill = 0;
  16.                                
  17.        //strcat(players,tab[i]->data4); // pour le retour
  18.        //strcat(players," " );
  19.        pn++;
  20.        }
  21.        ptable[pn]->name = "EOP";// on marque la fin


 
Pour lorill, si tu avais lu entierement mon post tu aurais vu que je n'ai pas de cd sous la main.
 
J'ai justement fait attention à faire un poste le plus détaillé possible pour éviter d'avoir ce genre de réponse :/ Enfin, y'a ptetre qqchose que je comprends pas.
 
A+


Message édité par Evadream -jbd- le 19-09-2002 à 20:42:15
Reply

Marsh Posté le 19-09-2002 à 20:45:43    

Un autre conseil : au lieu de faire des printf, utilise un debuger... C'est plus puissant, plus souple, plus rapide. Et en plus c'est fait pour.

Reply

Marsh Posté le 19-09-2002 à 21:58:35    

Evadream -jbd- a écrit a écrit :

 
Pour lorill, si tu avais lu entierement mon post tu aurais vu que je n'ai pas de cd sous la main.




 
J'ai juste lu les extraits de code, j'ai vu que tu allouais plein de mémoire, et que tu la libérait pas. Voila.

Reply

Marsh Posté le 19-09-2002 à 23:18:36    

Ok, escuse moi alors. Mais je ne vais pas libérer de la mémoire que j'ai pas encore utiliser. Bien sur qu'avant de quitter mon programme, je fais le grand nettoyage !
 
Mais les symptomes que j'ai pu mettre en avant me semblent mettre en avant un problème "profond" et non une erreur ds l'allocation de la mémoire. Je coince depuis 4 jours dessus et j'avance pas trop.
 
Je vais m'investir ds l'utilisation d'un débuggeur !
 
Merci, A+

Reply

Marsh Posté le 20-09-2002 à 06:11:11    

1) Ton post aurait pu être plus court et tout aussi informatif.
 
2) Tu enlèves/modifies le 'malloc' pour le test, mais tu laisse 'fill_string(...,50)'. Suspect.
 
3) '1000*sizeof(char))', c'est pas '1000 * 8'.
Par définition, sizeof(char) == 1.
 
4) Pourquoi allouer plusieurs copies des noms ?
Gardes-les en un seul endroit, et amènes tous les pointeurs dessus.
Ou alors 1 indice= 1 joueur, puisque tes tableaux sont de taille max.
 
5)

Citation :

"De toutes facons mes problemes ne semblent pas venir de là"


A 95%, le problème est un écrasement de la mémoire avant l'échec effectif.
Il te faut un débogeur pas-à-pas pour surveiller tes allocations.
On ne pourras pas beaucoup plus t'aider sans examiner TOUT ton code :-/
 
6) Il y a beaucoup de '->' et de 'malloc'. Ça doit être simplifiable.
 
7) Fais des fonctions dédiées à l'initialisation de structures:

Code :
  1. void player_init(player* pl, int id, ...){
  2. ptable[pn]->name = (char*)malloc(50*sizeof(char));


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 20-09-2002 à 09:14:53    

Evadream -jbd- a écrit a écrit :

ptable est ok comme je l'ai dit dans mon premier post. Merci qd même. Mon invariant de boucle n'est pas faux vu le test (je me comprends, j'ai fais des tests, c ok). De toutes facons mes problemes ne semblent pas venir de là.




 
Ca semble marcher... alors ça marche !!! :sarcastic:
C'est faux d'un point de vue algo, mais vu que tu me dis que ça semble marcher...
 

Evadream -jbd- a écrit a écrit :

Voici le bout de code qu'il y a juste au dessus et qui fonctionne parfaitement :
...




 
Montre nous le bout de code où tu déclares ptable, et où tu alloues chaque case de ptable.


Message édité par zi_ril_wanou le 20-09-2002 à 09:16:01

---------------
Get the Cooool... Get the cool shoe-shine !
Reply

Marsh Posté le 20-09-2002 à 11:21:24    

Merci pour toutes vos réponses, même si j'ai du mal à tout comprendre, notemment que c'est faux d'un point de vue algo, mais je vais chercher en cette voie !
 
Voici le morceau du code qui, pour moi, fonctionne parfaitement.
 

Code :
  1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++)  //tant que l'on est pas à la fin du log  
  2.       {                                             //premier passage pour détecter les joueurs  
  3.                  
  4.            if( strcmp(tab[i]->data2,"player" )==0 && strcmp(tab[i]->data3,"Connect" )==0 )
  5.            {
  6.              ptable[pn]= (player*)malloc(sizeof(player));
  7.      
  8.              ptable[pn]->name = (char*)malloc(50*sizeof(char));       
  9.              ptable[pn]->team = (char*)malloc(15*sizeof(char));             
  10.                     ptable[pn]->name = tab[i]->data4; //le nom  
  11.              ptable[pn]->team = tab[i+1]->data5;//la team...  
  12.              ptable[pn]->id = atoi(tab[i]->data5);//l'id  
  13.              ptable[pn]->kills = 0;//inialisation des stats du joueur  
  14.              ptable[pn]->deaths = 0;
  15.              ptable[pn]->suicides = 0;
  16.              ptable[pn]->team_kill = 0;
  17.                                      
  18.             //strcat(players,tab[i]->data4); // pour le retour  
  19.             //strcat(players," " );  
  20.              pn++;
  21.            }
  22.            ptable[pn]->name = "EOP"// on marque la fin


 
Voilà ! Merci à vous encore !
 
A+

Reply

Marsh Posté le 20-09-2002 à 11:21:24   

Reply

Marsh Posté le 20-09-2002 à 12:36:15    

Encore merci pour vos réponses. J'ai qqs questions par rapport à ce qui a été dit :
 
 
Pour Murasan :
 
1) Ok, ne postant pas énormément et n'ayant pas accès illimité au net j'ai voulu être le plus précis possible.
 
2)Tu enlèves/modifies le 'malloc' pour le test, mais tu laisse 'fill_string(...,50)'. Suspect
Exact, il s'agit d'une grossière erreur de ma part ! J'ai donc été cohérent en mettant en commentaire fill_string... et le programme "bloque"
à i = 3 et j = 94.
 
3)'1000*sizeof(char))', c'est pas '1000 * 8'. Par définition, sizeof(char) == 1.
Euhhhh 8000 Bits ? :D Oui j'ai parlé trop vite sorry.
 
   
5) Pourquoi allouer plusieurs copies des noms ?
 
Je ne vois pas de quoi tu parles. Tu parles ptable[pn]->name et ptable->ktable[j]->name ? Si c'est cà, ca ne représente pas le même nom
 
 
6) [i]Il y a beaucoup de '->' et de 'malloc'. Ça doit être simplifiable.

 
Je vais chercher en cette voie même si je saisis pas trop.
 
 
7) Fais des fonctions dédiées à l'initialisation de structures:

Code :
  1. Code :
  2.   void player_init(player* pl, int id, ...){
  3.      ptable[pn]->name = (char*)malloc(50*sizeof(char));

[/citation]  
 
Là, j'ai quelques doutes. Je viens de faire un essai tout simple
 

Code :
  1. void init_string(char* chaine,int size);
  2. void main()
  3. {
  4. char* str;
  5. init_string(str,100);
  6. gets(str);
  7. printf("\n%s",str);
  8. getchar();     
  9.      
  10. }     
  11. void init_string(char* chaine,int size)
  12. {
  13. chaine = (char*)malloc(size*sizeof(char));     
  14. }


 
 
Résultat : ca plante
 
 
Par contre
 

Code :
  1. char* init_string(char* chaine,int size);
  2. void main()
  3. {
  4. char* str;
  5. str=init_string(str,100);
  6. gets(str);
  7. printf("\n%s",str);
  8. getchar();     
  9.      
  10. }     
  11. char* init_string(char* chaine,int size)
  12. {
  13. return ( chaine = (char*)malloc(size*sizeof(char)) );     
  14. }


 
Résultat : ca fonctionne
 
 
Alors peut-être en passant par des pointeurs de pointeurs ?
 

Code :
  1. char* init_string(char** chaine,int size);
  2. void main()
  3. {
  4. char* str;
  5. init_string(&str,100);
  6. gets(str);
  7. printf("\n%s",str);
  8. getchar();     
  9.      
  10. }     
  11. char* init_string(char** chaine,int size)
  12. {
  13. return ( *chaine = (char*)malloc(size*sizeof(char)) );     
  14. }

     
 
 
Résultat : ca fonctionne. Donc tu me conseilles de tout regrouper dans une fonction pour rendre mon code plus propre ?
 
 
Voilà, encore merci de m'accorder un peu de votre temps !


Message édité par Evadream -jbd- le 20-09-2002 à 12:39:11
Reply

Marsh Posté le 20-09-2002 à 12:59:52    

Citation :

Code :
  1. char* init_string(char** chaine,int size);
  2. void main()
  3. {
  4. char* str;
  5. init_string(&str,100);
  6. gets(str);
  7. printf("\n%s",str);
  8. getchar();     
  9.      
  10. }     
  11. char* init_string(char** chaine,int size)
  12. {
  13. return ( *chaine = (char*)malloc(size*sizeof(char)) );     
  14. }


Dans ce cas il me semble que c'est inutile de faire un return...  ;)

Reply

Marsh Posté le 20-09-2002 à 15:41:52    

:D
 
Tout à fait ! Copier coller en folie !
 

Reply

Marsh Posté le 20-09-2002 à 16:38:43    

Quelques conseils supplémentaires :

  • Pour allouer tes chaines de caractères, préfère calloc() à malloc(). calloc() fait un malloc() puis remplit la zone mémoire de zéros. Ca évite certaines surprises plus tard...  
  • Normalement, le "for" ne devrait être utilisé que lorsqu'on connait à l'avance le nombre d'itérations à faire dans la boucle. Dans tous les autres cas, il est préférable d'utiliser un "while". Donc ta boucle :

    Code :
    1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++) {
    2.   ...
    3. }

    devrait être réécrite en :

    Code :
    1. i = 0;
    2. while (strcmp(tab[i]->data, "EOL" ) != 0)) {
    3.   ...
    4.   i++;
    5. }

Ces 2 structures de contrôles sont strictement équivalentes -- y compris du point de vue code généré par le compilateur -- mais la seconde est plus lisible et plus maintenable.

Reply

Marsh Posté le 20-09-2002 à 16:50:36    

Musaran a écrit a écrit :

3) '1000*sizeof(char))', c'est pas '1000 * 8'.
Par définition, sizeof(char) == 1.




Désolé de te contredire, mais c'est à cause de ce genre d'hypothèses malheureuses que l'immense majorité des programmes ne supportent pas autre chose que les caractères de l'alphabet anglais -- ce qui entre nous, est quand même un comble, avec la puissance des machines dont on dispose aujourd'hui. Même les programmes supposés modernes ont un mal de chien à supporter des caractères comme le "e dans l'o" (vous savez, la première lettre du mot "oeuf" ), ou les caractères propres aux langues des pays de l'Europe de l'Est. Sans parler des caractères d'autres alphabets, comme l'alphabet grec (PI, par exemple, est pourtant utilisé en France), ou des alphabets encore plus "exotiques", comme les alphabets arabes, hébreux, cyrilliques, ou même chinois...  :ouch:  :sarcastic:  
 
Non, il ne faut pas, surtout pas, supposer qu'un caractère tient sur un octet, même si en C, le type "naturel" pour manipuler les caractères est le type "char", et que ce type est représenté en mémoire sur un octet. Même si l'affirmation "un char=un octet" est vraie aujourd'hui, tu auras peut-être besoin que ce ne soit plus le cas dans une semaine.
 
Donc, Evadream, je t'encourage à continuer d'écrire " * sizeof(char)", parce qu'ainsi, tu ne présages pas de l'occupation mémoire d'un caractère.


Message édité par BifaceMcLeOD le 20-09-2002 à 16:53:03
Reply

Marsh Posté le 20-09-2002 à 20:45:22    

oui sauf qu'un char n'est pas comme semble l'indiquer son nom, un caractere mais un byte, c'est a dire selon la definition courante, la plus petite unite de bits adressable sur une machine. (il existe donc des char de 7 bits et de 9 bits, sauf qu'ils renvoient tous d'apres le standard sizeof(char) == 1)
 
Donc pour supporter les caracteres exotiques il ne faut donc pas se reposer sur un char de plus de 8 bits mais plutot utiliser les librairies specifiques au widechar (mfc, stl etc..)
a noter que stocker des caracteres sur deux octets, pose de nouveaux problemes lies a l'endianness.
 
LeGreg

Reply

Marsh Posté le 20-09-2002 à 22:57:31    

Merci BifaceMcLeOD pour, une nouvelle fois, tes précieux conseils. Merci aussi aux autres pour vos remarques.
 
Je vais pour l'instant réecrire proprement tout ce que j'ai déja fait, ca me semble indispensable pour avancer plus prudemment. Si vous voyez d'autre fautes de styles ou des fautes de bases dans l'utilisation des pointeurs, n'hésitez pas.
 
Je vais m'investir dans l'utilisation de gdb pour analyser mon problème.
 
Merci à tous et à bientôt !

Reply

Marsh Posté le 21-09-2002 à 01:34:29    

Citation :

Citation :

5) Pourquoi allouer plusieurs copies des noms ?

Je ne vois pas de quoi tu parles. Tu parles ptable[pn]->name et ptable->ktable[j]->name ? Si c'est cà, ca ne représente pas le même nom

J'avais cru.
 

Citation :

Citation :

6) Il y a beaucoup de '->' et de 'malloc'. Ça doit être simplifiable.


Je vais chercher en cette voie même si je saisis pas trop.

Le problème: il y a trop de choses enchaînées, on s'y perd, et on vois peut-être pas une grosse erreur.
Avec le point suivant, ce serait déjà plus lisible.
 

Citation :

Citation :

7) Fais des fonctions dédiées à l'initialisation de structures:

Là, j'ai quelques doutes. Je viens de faire un essai tout simple...

Je pensais au structures 'kill' et 'player'. Genre:

Code :
  1. ptable[i]->ktable[j]= mallockill(); //une ligne en remplace 5

Pour un truc ausi simple qu'une chaîne, ça perd de l'intérêt.
Quoique, une simple macro aiderait:

Code :
  1. #define typedmalloc(type,num) (type*)malloc(num*sizeof(type)) //type simple uniquement


 
Et la fonction 'fill_string', je la trouves suspecte. Ça mérite une enquête.
 
 
 

BifaceMcLeOD a écrit a écrit :

Normalement, le "for" ne devrait être utilisé que lorsqu'on connait à l'avance le [i]nombre d'itérations


Mon opinion est différente:
Utiliser 'for' quand on peut regroupper au moins deux des 3 étapes de contrôle de boucle: initialisation, test, progression.
Je dirais en plus, vu la lourdeur du test, qu'il vaudrais mieux les espacer, ou les séparer:

Code :
  1. for( i=0  ;  strcmp(tab[i]->data,"EOL" ) != 0  ;  i++) {
  2. for(i=0;
  3.     strcmp(tab[i]->data,"EOL" ) != 0;
  4.    i++){


 
Je parlais bien du type 'char' du C++, qui est bien définit comme synonyme de 'byte', utilisé comme unité de mesure de taille, et ça rique pas de changer (trop tard).
Pour les textes évolués, il y a 'wchar_t': Unicode 16 bits.
En passant, le mot français 'octet' implique 8, et n'est pas tout à fait synonyme de 'byte'. 'codet', ou 'multiplet' existent.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 21-09-2002 à 04:08:14    

Le code qui d'apres toi fonctionne parfaitement a des problemes:
 

Code :
  1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++)   //tant que l'on est pas à la fin du log
  2.     {                                              //premier passage pour détecter les joueurs
  3.              
  4.        if( strcmp(tab[i]->data2,"player" )==0 && strcmp(tab[i]->data3,"Connect" )==0 )
  5.        {
  6.        ptable[pn]= (player*)malloc(sizeof(player));
  7.        ptable[pn]->name = (char*)malloc(50*sizeof(char));       
  8.        ptable[pn]->team = (char*)malloc(15*sizeof(char));           
  9.        ptable[pn]->name = tab[i]->data4;  //le nom
  10.        ptable[pn]->team = tab[i+1]->data5; //la team...
  11.        ptable[pn]->id = atoi(tab[i]->data5); //l'id
  12.        ptable[pn]->kills = 0; //inialisation des stats du joueur
  13.        ptable[pn]->deaths = 0;
  14.        ptable[pn]->suicides = 0;
  15.        ptable[pn]->team_kill = 0;
  16.                                
  17.        //strcat(players,tab[i]->data4); // pour le retour
  18.        //strcat(players," " );
  19.        pn++;
  20.        }
  21.        ptable[pn]->name = "EOP";// on marque la fin


 
DEjà, ce code est assez bizzare:
Si tu alloues, pourquoi ne recopies tu pas la valeur dedans? Parce que là, tu perds les 50 octets alloués.
 
Alors, si par hasard, avant que tu utilises ptable[pn]->name, tu libere les données de tab[i], y'aura un bleme.
Donc soit tu fais:
ptable[pn]->name = (char*)malloc(50*sizeof(char));
strncpy(ptable[pn]->name, tab[i]->data4, 49);
soit tu fais un  
ptable[pn]->name = tab[i]->data4;
parce que tab[i]->data4 sera une zone memoire valide tout le temps de ton utilisation de  ptable[pn]->name, mais il faudrait choisir.
 
Passons au second probleme:

Code :
  1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++)  //tant que l'on est pas à la fin du log  
  2.       {                                             //premier passage pour détecter les joueurs  
  3.                  
  4.            if( strcmp(tab[i]->data2,"player" )==0 && strcmp(tab[i]->data3,"Connect" )==0 )
  5.            {
  6.              ptable[pn]= (player*)malloc(sizeof(player));
  7.      
  8.              ptable[pn]->name = (char*)malloc(50*sizeof(char));       
  9.              ptable[pn]->team = (char*)malloc(15*sizeof(char));             
  10.                     ptable[pn]->name = tab[i]->data4; //le nom  
  11.              ptable[pn]->team = tab[i+1]->data5;//la team...  
  12.              ptable[pn]->id = atoi(tab[i]->data5);//l'id  
  13.              ptable[pn]->kills = 0;//inialisation des stats du joueur  
  14.              ptable[pn]->deaths = 0;
  15.              ptable[pn]->suicides = 0;
  16.              ptable[pn]->team_kill = 0;
  17.                                      
  18.             //strcat(players,tab[i]->data4); // pour le retour  
  19.             //strcat(players," " );  
  20.              pn++;
  21.            }
  22.            ptable[pn]->name = "EOP"// on marque la fin


Je ne vois pas que ptable[pn]->name ait ete alloué quelque part; ni meme en fait, que ptable[pn]->name soit un pointeur valide a ce stade, car on a pas alloué la structure ptable[pn].
Et meme si c'etait le cas, si par hasard, la chaine temporaire dans laquelle a ete copiee "EOP" et sur laquelle pointe ptable[pn]->name , est liberee, il y aura bleme [et comme on a pas tout ton code, on ne peut pas savoir si ca se produit.]
Au fait, il manque un ; en fin de ligne:  
ptable[pn]->name = "EOP";
 
Dernier point, le ligne
ptable[pn]->team = tab[i+1]->data5;//la team...  
me semble dangereuse.  
Tu es a l'etape i. est tu sur que tab[i+1] existe?
Ou etait-ce ptable[pn]->team = tab[i]->data5;//la team...
ce que tu voulais taper?
 
Perso, un truc comme ceci me paraitrait plus propre:

Code :
  1. for(i=0;(strncmp(tab[i]->data,"EOL", 4)!=0);i++)  //tant que l'on est pas à la fin du log  
  2. {                                                 //premier passage pour détecter les joueurs  
  3.  if((strncmp(tab[i]->data2,"player", 7)==0) &&
  4.     (strncmp(tab[i]->data3,"Connect", 8)==0) )
  5.  {
  6.   ptable[pn]= (player*)calloc(1, sizeof(player));
  7.   ptable[pn]->name = (char*)calloc(50, sizeof(char));       
  8.   ptable[pn]->team = (char*)calloc(15, sizeof(char));           
  9.   strncpy(ptable[pn]->name, tab[i]->data4, 49); //le nom   
  10.   strncpy(ptable[pn]->team, tab[i+1]->data5, 14);//la team... (i+1???)
  11.   ptable[pn]->id = atoi(tab[i]->data5);//l'id  
  12.   pn++;
  13.  }
  14. }
  15. // On traite le pseudo dernier joueur
  16. ptable[pn]= (player*)calloc(1, sizeof(player));
  17. ptable[pn]->name = (char*)calloc(50, sizeof(char)); // 50 ou 4. je preferre 50 pour etre homogene  
  18. strcpy(ptable[pn]->name,"EOP" );// on marque la fin


Je vois pas ou pn est initialisé, je suppose que c'est fait avant le code que tu nous a donné.
A+,


Message édité par gilou le 21-09-2002 à 05:09:39

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 21-09-2002 à 12:08:30    

Merci Musaran pour tes nouvelles remarques et à gilou pour ton analyse, c'est sympa.
 
J'ai "reussi" à faire fonctionner le tout sans trop comprendre, sic, mais je vais repasser dessus apres les remarques pertinentes de gilou.
 
Voici ce que j'ai fait ds la nuit, selon le conseil de Musaram. Bien sur, il me reste à prendre en compte ce que m'a dit gilou.
 

Code :
  1. //***********************************************************************//
  2. // init_player                                                           //
  3. // initialisation et remplissage d'une structure joueur                  //
  4. //***********************************************************************//  
  5. void init_player(player** pl, log_line* line1, log_line* line2)
  6. {
  7. int i;
  8.      (*pl) = (player*)malloc(sizeof(player));   
  9.      init_string(&((*pl)->name),30); 
  10.      init_string(&((*pl)->team),15);
  11.      (*pl)->name = line1->data4; //le nom
  12.      (*pl)->team = (line2)->data5; //la team
  13.      (*pl)->id = atoi(line1->data5);
  14.      (*pl)->kills = 0;
  15.      (*pl)->deaths = 0;
  16.      (*pl)->suicides = 0;
  17.      (*pl)->team_kill = 0;
  18.          
  19.      for(i=0;i<MAX_PLAYERS;i++)
  20.      {
  21.      init_kplayer(&((*pl)->ktable[i]));
  22.      }
  23. }


 
Ces deux lignes m'ont d'ailleurs posées problème :
 

Code :
  1. (*pl)->name = line1->data4; //le nom
  2.      (*pl)->team = (line2)->data5; //la team


 
Je pensais pouvoir accéder à line2 en faisant juste un (line+1)->data5, mais ca ne fonctionnait pas, d'ou mon utilisation provisoire (?) du troisième paramètre de la fonction.
 
 

Code :
  1. //***********************************************************************//
  2. // init_kplayer                                                          //
  3. // initialisation de la table des kills des joueurs détéctés             //
  4. //***********************************************************************//
  5.                                                                          
  6. void init_kplayer(kill** kpl)
  7. {
  8.      (*kpl) = (kill*)malloc(sizeof(kill));
  9.      init_string(&((*kpl)->name), 30);
  10.      (*kpl)->id = 999; //id fictive pour détecter la fin
  11.      (*kpl)->kills = 0;
  12. }


 
Le code qui me posait problème devient alors le suivant
 

Code :
  1. for(i=0;(strcmp(tab[i]->data,"EOL" )!=0);i++)   //tant que l'on est pas à la fin du log
  2.     {                                              //premier passage pour détecter les joueurs     
  3.        if( strcmp(tab[i]->data2,"player" )==0 && strcmp(tab[i]->data3,"Connect" )==0 )
  4.        {             
  5.        init_player(&(ptable[pn]), tab[i], tab[i+1]);  //détection d'un joueur -> initialisation
  6.        pn++;                             //on se déplace d'une case ds le tableau des joueurs
  7.        }
  8.     }


 
 
Il reste encore des erreurs, notemment mon amalgame entre affectation d'adresse entre 2 pointeurs et recopie des contenus que gilou à mis en avant. J'y retourne dans les jours qui suivent et je vous tiens au courant !
 
Encore merci à tous ! A+


Message édité par Evadream -jbd- le 21-09-2002 à 12:11:48
Reply

Marsh Posté le 22-09-2002 à 03:14:59    

Bien vu gilou.
Le problème était simple, mais le code trop chargé pour que ça me saute au yeux.
 
Une remarque d'ailleurs: C'est mieux de regroupper l'initialisation au plus près de l'allocation correspondante.


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 22-09-2002 à 08:13:13    

En general, quand je lis ou entends ce genre de phrase:
Voici le bout de code qu'il y a juste au dessus et qui fonctionne parfaitement :
Je vais y voir en premier car bien souvent, c'est la qu'est la racine du probleme.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-09-2002 à 14:34:01    

Roo c l'arrogance des jeunes :]

Reply

Marsh Posté le 23-09-2002 à 12:24:12    

legreg a écrit a écrit :

oui sauf qu'un char n'est pas comme semble l'indiquer son nom, un caractere mais un byte, c'est a dire selon la definition courante, la plus petite unite de bits adressable sur une machine. (il existe donc des char de 7 bits et de 9 bits, sauf qu'ils renvoient tous d'apres le standard sizeof(char) == 1)
 
Donc pour supporter les caracteres exotiques il ne faut donc pas se reposer sur un char de plus de 8 bits mais plutot utiliser les librairies specifiques au widechar (mfc, stl etc..)
a noter que stocker des caracteres sur deux octets, pose de nouveaux problemes lies a l'endianness.
 
LeGreg




Tout dépend si l'on considère C comme un assembleur de haut niveau ou un véritable langage de programmation évolué. Les 2 approches sont valables -- je dirais même qu'historiquement C a été conçu avec la première approche. Le problème, c'est que C est utilisé majoritairement dans des problématiques qui requièrent un véritable langage de programmation évolué, et le programme d'Evadream en est une. Et c'est parce qu'on mélange les habitudes liés à l'assembleur de haut niveau et les problématiques vraiment haut niveau qu'on arrive à de gros problèmes, et qu'on observe autant de bugs dans la pratique.
 
Toutes tes remarques sont justes en elles-mêmes, legreg, mais à mon sens, elles ne sont pleinement justifiées que dans le cas où on a besoin d'un assembleur de haut niveau. Dans tous les autres cas, il faut éviter la majorité des raccourcis que C propose, car ils mènent à un code plus difficile à maintenir et surtout plus difficile à faire évoluer (choses qu'on nous demande avec de plus en plus d'insistance). Et quand un programmeur peut faire plus court aujourd'hui, même si ça implique un surcoût important demain, il fera toujours plus court (ou alors il faut être idéologue... comme moi ! :D ;) ).
 
Voilà au passage pourquoi je considère C comme un mauvais langage. Ce n'est pas qu'il soit mauvais en lui-même, mais c'est qu'on l'utilise dans des domaines où il est inapproprié et dangereux.


Message édité par BifaceMcLeOD le 23-09-2002 à 12:25:27
Reply

Marsh Posté le 23-09-2002 à 14:36:49    

Musaran a écrit a écrit :

 
...
Je parlais bien du type 'char' du C++, qui est bien définit comme synonyme de 'byte', utilisé comme unité de mesure de taille, et ça rique pas de changer (trop tard).
Pour les textes évolués, il y a 'wchar_t': Unicode 16 bits.
En passant, le mot français 'octet' implique 8, et n'est pas tout à fait synonyme de 'byte'. 'codet', ou 'multiplet' existent.




 
 :non:  
 
D'une part il y a le C qui definit le char comme un octet...
 
D'autre part il y a le C++ qui se garde bien de le definir autrement que comme 1<=sizeof(char)<=sizeof(short)...
 
ce qui n'est donc pas incompatible avec des chars de 32 bits...
 voir le BS.

Reply

Marsh Posté le 23-09-2002 à 17:00:32    

Le problème aussi, Musaran, c'est que combien de programmeurs utilisent le char* comme une string ? Quasiment tous. Combien utilisent le type 'wchar_t' ? Pratiquement aucun.
C'est bien qu'il y a confusion entre le type "char" et le type caractère chez l'immense majorité des programmeurs C.

Reply

Marsh Posté le 23-09-2002 à 22:12:05    

BifaceMcLeOD a écrit a écrit :

Le problème aussi, Musaran, c'est que combien de programmeurs utilisent le char* comme une string ? Quasiment tous. Combien utilisent le type 'wchar_t' ? Pratiquement aucun.
C'est bien qu'il y a confusion entre le type "char" et le type caractère chez l'immense majorité des programmeurs C.




Pis wchar_t*, c'est un type precis, pas necessairement adapté a ce qu'on manipule.
Si le soucis est unicode, je preferre nettement utiliser char* et des strings encodées en UTF8; ca bouffe moins de place memoire, et ca casse beaucoup moins de code "legacy".
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-09-2002 à 00:34:19    

BENB a écrit a écrit :

D'autre part il y a le C++ qui se garde bien de le definir autrement que comme 1<=sizeof(char)<=sizeof(short)...



Es-tu sûr ?
 

"Le Langage C++", Édition spéciale, par Bjarne Stroutsrup, Chapitre 4.6, page 84.
Il y est écrit très précisément: a écrit
:

 
La taille des objets C++ s'expriment sous la forme de multiple de la taille d'un char. Cette dernière est donc par définition 1.
...
De plus, il est garanti qu'un char soit constitué d'au moins 8 bits...


Ce qui est cohérent avec le fait que le seul moyen standard de déterminer le nombre de bits d'un type soit sizeof(type)*CHAR_BIT.
Ce qui n'est pas non plus incompatble avec des char de 32 bits.
 
Détail que j'oubliais: En C, sizeof(char)==sizeof(int), mais un seul 'byte' en est utilisé.
 

gilou a écrit a écrit :

je preferre nettement utiliser char* et des strings encodées en UTF8


Puisque tu as l'air de connaître, j'ai des questions:
1) Les 'multi-byte characters' sont introduits par quoi ? Une valeur spécifique, ou une gamme de valeur?
2) Est-ce qu'une fonction de traitement de chaîne classique peut foirer sur une chaîne UTF8/multi-byte ?


Message édité par Musaran le 24-09-2002 à 00:40:12

---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 24-09-2002 à 02:10:27    

Tu veux dire quoi par Les 'multi-byte characters' sont introduits par quoi?
Dans le cadre de l'UTF8, seul l'ascii a le meme encodage:
UTF8 ca s'encode comme suit:
Codepoint
Unicode      encodage UTF-8
------------------------------
0000-007F    0xxxxxxx pour encoder 00000000 0xxxxxxx
0080-07FF    110xxxx 10yyyyyy pour encoder 00000xxx xxyyyyyy
0800-FFFF    1110xxxx 10yyyyyy 10zzzzzz pour encoder xxxxyyyy yyzzzzzz  
100000-10FFFF 11110xxx 10yyyyyy 10zzzzzz 10uuuuuu pour encoder 000xxxyy yyyyzzzz zzuuuuuu
et pour la zones (speciale) suivante, dite des surrogates:
(D800-DBFF)*(DC00-DFFF) 11110xxx 10xxyyyy 10zzzzzz 10uuuuuu pour encoder 110110ww wwyyyyzz 110111zz zzuuuuuu ou xxxxx = wwww+1
 
L'interet, c'est que les fonctions usuelles de la librairie C marchent avec, puisque 1 caractere unicode --> 1, 2, 3 0u 4 chars. Donc, on peut utiliser strcpy, strcmp, etc etc tant que tout est en UTF-8.
   
>Est-ce qu'une fonction de traitement de chaîne classique peut foirer sur une chaîne UTF8/multi-byte ?
En principe non pour l'UTF-8.
A+,


Message édité par gilou le 24-09-2002 à 02:13:26

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-09-2002 à 10:34:31    

gilou a écrit a écrit :

 
Pis wchar_t*, c'est un type precis, pas necessairement adapté a ce qu'on manipule.
Si le soucis est unicode, je preferre nettement utiliser char* et des strings encodées en UTF8; ca bouffe moins de place memoire, et ca casse beaucoup moins de code "legacy".
A+,




Pour la place en mémoire, désolé, mais ça dépende ce que tu fais. Si tu ne manipules que des caractères ouest-européens, c'est sûr, mais de toute façon, dans ces cas-là, les gens préfèrent encore utiliser des char (donc sur un octet) et supposer qu'on est en iso-latin-1. Par contre, si tu te sais que tu as à peu près autant de chances de manipuler des caractères européens, hébreux, chinois, arabes, coréens, cyrilliques, ... (à ceux dont je n'ai pas cité l'alphabet et qui me comprennent, veuillez m'excuser ;) ), l'UTF-8 est plus gourmand. Et surtout, il est très pénible et souvent coûteux à manipuler caractère par caractère (va faire un calcul de longueur à la strlen(), par exemple ; c'est pas coûteux, ça ?).
Et puis entre nous, la place mémoire prise par les chaînes de caractères, ça fait quelques années qu'on s'en fout un peu...
 
Bref, à mon sens, UTF-8 est un format bâtard. Et il ne doit son existence qu'au fait qu'en C, qui est un langage répandu, les chaines de caractères sont implémentés par une suite d'octets qui se termine par un octet à zéro.
Si les normalisateurs de C avaient prévu un type "string" en standard, avec un tableau de caractères et un attribut longueur, comme en Pascal par exemple, on ne serait pas dans cette m...

Reply

Marsh Posté le 24-09-2002 à 13:32:00    

BifaceMcLeOD a écrit a écrit :

 
Pour la place en mémoire, désolé, mais ça dépende ce que tu fais. Si tu ne manipules que des caractères ouest-européens, c'est sûr, mais de toute façon, dans ces cas-là, les gens préfèrent encore utiliser des char (donc sur un octet) et supposer qu'on est en iso-latin-1. Par contre, si tu te sais que tu as à peu près autant de chances de manipuler des caractères européens, hébreux, chinois, arabes, coréens, cyrilliques, ... (à ceux dont je n'ai pas cité l'alphabet et qui me comprennent, veuillez m'excuser ;) ), l'UTF-8 est plus gourmand. Et surtout, il est très pénible et souvent coûteux à manipuler caractère par caractère (va faire un calcul de longueur à la strlen(), par exemple ; c'est pas coûteux, ça ?).
Et puis entre nous, la place mémoire prise par les chaînes de caractères, ça fait quelques années qu'on s'en fout un peu...
 
Bref, à mon sens, UTF-8 est un format bâtard. Et il ne doit son existence qu'au fait qu'en C, qui est un langage répandu, les chaines de caractères sont implémentés par une suite d'octets qui se termine par un octet à zéro.
Si les normalisateurs de C avaient prévu un type "string" en standard, avec un tableau de caractères et un attribut longueur, comme en Pascal par exemple, on ne serait pas dans cette m...




Non, l'argument de la strlen est tres souvent mis en avant, mais c'est faux probleme: quand j'utilise l'UTF-8, j'ai deja largement depassé le stade ou j'ai besoin de la longueur unicode de la chaine.
De plus, calculer unicode-strlen en UTF-8 est assez facile, etant donné l'encodage:  
bit de poids fort = 0 ==> 1 octet
Bit de poids fort 1 ==> le nb de bits de poids fort avant un zero donne le nb d'octets du caractere.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 24-09-2002 à 15:36:46    

OK, on peut arriver à optimiser beaucoup de fonctions par cette méthode.
Il n'empêche que l'hypothèse un caractère = un octet a conduit et continue à conduire à des contournements sordides (genre, les tables de caractères), qui continuent à polluer la majorité des logiciels qui sont écrits aujourd'hui.


Message édité par BifaceMcLeOD le 24-09-2002 à 15:36:59
Reply

Marsh Posté le 24-09-2002 à 21:18:23    

BifaceMcLeOD a écrit a écrit :

OK, on peut arriver à optimiser beaucoup de fonctions par cette méthode.
Il n'empêche que l'hypothèse un caractère = un octet a conduit et continue à conduire à des contournements sordides (genre, les tables de caractères), qui continuent à polluer la majorité des logiciels qui sont écrits aujourd'hui.




Certes, mais quand tu as 700 000 lignes de legacy code, c'est la seule solution envisageable, hors une reecriture totale.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 26-09-2002 à 02:03:33    

gilou:
OK, ils sont introduits par certains octets spéciaux.
 
Ce qui veut dire qu'on ne peut pas donner à une fonction mbcs une chaîne C 'single-byte' utilisant le jeu ANSI ou ASCII étendu.
Du coup je suis tout donfusionné: comment place-t'on un 'à' (ANSI) de code binaire 1110 000 dans une chaîne littérale ?
 
Faut-il appeler une fonction de conversion single-byte vers multibyte dans un tampon ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 26-09-2002 à 12:04:08    

Musaran a écrit a écrit :

gilou:
OK, ils sont introduits par certains octets spéciaux.
 
Ce qui veut dire qu'on ne peut pas donner à une fonction mbcs une chaîne C 'single-byte' utilisant le jeu ANSI ou ASCII étendu.
Du coup je suis tout donfusionné: comment place-t'on un 'à' (ANSI) de code binaire 1110 000 dans une chaîne littérale ?
 
Faut-il appeler une fonction de conversion single-byte vers multibyte dans un tampon ?




Tout n'est pas clair, mais là tu fais allusion a des codages types Shift Jis?
Ben c'est simple: le jeu de caracteres Shift-Jis ne comporte pas les caracteres ascii accentués.  
Le bouquin de reference sur ce genre de chosdes est celui de Ken Lunde chez O'Reilly, CJKV Information Processing (une nouvelle edition remaniee devrait etre publiée en octobre).http://www.oreilly.com/people/authors/lunde/blowfish-small.gif
Ken bosse dans ma boite, et utilise mon produit pour generer le PDF de son bouquin qu'il envoie a l'editeur. :)
A+,


Message édité par gilou le 26-09-2002 à 12:06:47

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 27-09-2002 à 04:42:54    

Je suis très loin du niveau professionnel.
 
On ne peut déclarer de chaîne littérale UTF8 en C/C++.
Une chaîne littérale (char) n'utilisant pas de caractères étendus (>127), est aussi une chaîne UTF8 valide.
 
J'ai bon, là ?


---------------
Bricocheap: Montage de ventilo sur paté de mastic silicone
Reply

Marsh Posté le 27-09-2002 à 05:34:03    

Je comprends pas tout.
 
Si tu veux coder "blablâ" en utf-8 tu vas avoir un tableau contenant: 'b', 'l', 'a', 'b', 'l', 'Ã', '¢', '\0'
Et ca se manipule comme une chaine normale.  
Il n'y a qu'au moment de l'affichage, qu'il va falloir faire attention a mapper correctement une eventuelle suite de caracteres vers une valeur unique pour ta fonte.
 
Sinon, une chaine ascii (non etendu) est une chaine UTF-8 valide en effet.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed