Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
[C] S'éxecute mal avec GCC, mais pas avec MINGW (Résolu)
View unanswered posts
View posts from last 24 hours

Goto page 1, 2  Next  
Reply to topic    Gentoo Forums Forum Index French
View previous topic :: View next topic  
Author Message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Tue Feb 05, 2008 9:24 pm    Post subject: [C] S'éxecute mal avec GCC, mais pas avec MINGW (Résolu) Reply with quote

Salut à tous !!

J'essaye de créer un identifiant à partir de la première lettre du prénom et du reste du nom (7 caractères max).
Les 7 caractères n'est pas le souci pour l'instant. En fait, une fois la procédure exécutée, il me modifie ma liste chainée nom, alors que je n'y touche pas !
Cela se produit uniquement avec GCC. S'agit-il d'un bug, ou de mon code ?

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
 
void identifiant (const char p[], const char n[], char id[]);
 
int
main (void)
{
 
  const int max = 30;
  char nom[max], prenom[max], id[8];
  int lp, ln;
 
  // On saisie le prénom
  printf ("Entrez le prénom (maximum %d caractères): ", max);
  fgets (prenom, max, stdin);
  // Et le nom
  printf ("et le nom : ");
  fgets (nom, max, stdin);
 
  // Après le dernier caractère, on met \0
  lp = strlen (prenom);
  ln = strlen (nom);
  prenom[lp - 1] = '\0';
  nom[ln - 1] = '\0';
 
  // On s'assure qu'il y ai un prénom et un nom
  if (prenom[0] != '\0' && nom[0] != '\0')
    {
 
      printf ("Données :\tPrénom = %s\t--\tNom = %s\n", prenom, nom); // Affichage du résultat
 
      identifiant (prenom, nom, id);
      printf ("Identifiant :\t%s\n", id);       // Affichage du résultat
      printf ("Test de nom :%s\n",nom);
 
    }
    else printf("Merci d'écrire un prénom et un nom.");
 
  return EXIT_SUCCESS;
}
 
void
identifiant(const char p[], const char n[], char id[])
{
  int i, j;
        id[0] = p[0];
        i=1;j=0;
        while (i < 8)
        {
        id[i] = n[j];
        i++;j++;
        }
        id[i] = '\0';
}


Je n'ai aucune erreur, mais regardez le résultat :

Code:
Entrez le prénom : Jean-François XYZ
et le nom : Jeannette Andrée
Données :        Prénom = Jean-François XYZ        --        Nom = Jeanne Andrée
Identifiant :        JJeannet
Test de nom : (*des caractères spéciaux ici, je ne peux pas les copier, bug avec le forum*)


Il renvoi un nom différent, alors qu'il devrait m'afficher la même chose que dans Données.
Comment cela se fait-il, sachant qu'avec Mingw je n'ai pas ce soucis ?

Merci


Last edited by Animatrix on Sat Feb 09, 2008 8:43 pm; edited 1 time in total
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Tue Feb 05, 2008 9:50 pm    Post subject: Reply with quote

Ça marche chez moi (gcc 4.2.2)
Code:

% ./a.out
Entrez le prénom (maximum 30 caractères): Jean-François XYZ
et le nom : Jeannette Andrée
Données :       Prénom = Jean-François XYZ      --      Nom = Jeannette Andrée
Identifiant :   JJeannet
Test de nom :
[kraft:pts/1] [maxime] [/home/maxime]
% ./a.out
Entrez le prénom (maximum 30 caractères): Marie
et le nom : De Magdala
Données :       Prénom = Marie  --      Nom = De Magdala
Identifiant :   MDe Magd
Test de nom :
[kraft:pts/1] [maxime] [/home/maxime]
Back to top
View user's profile Send private message
sno35
Guru
Guru


Joined: 15 May 2004
Posts: 334
Location: Paris, France

PostPosted: Tue Feb 05, 2008 9:52 pm    Post subject: Reply with quote

Ouch, en gcc 4.2.2 sur ppc, ça passe tranquille, malgré les maladresses de C. ;-)
Notamment, strlen calcule la longueur justement en cherchant le premier '\0', donc pas besoin de le rajouter à cet endroit là (man fgets).
Mais si vraiment ton gcc produit un résultat comme tu le relates avec le code que tu nous montres, tu es bon pour le chopper en binaire, à moins de disposer d'une version qui montre de meilleures dispositions.
Eqça.

Edit: et le
Code:
id[i] = '\0';
à la fin est un dépassement (bénin, mais bon, quand les bornes sont dépassées ...)
car i == 8 à ce moment là.


Last edited by sno35 on Tue Feb 05, 2008 10:23 pm; edited 1 time in total
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Tue Feb 05, 2008 9:56 pm    Post subject: Reply with quote

Je vais voir ca pour le strlen.
Je viens de tester avec gcc-3.3.6 et magique ca marche !

Ne s'agirait-il pas d'un de mes USE ?
Code:
(fortran gcj gtk mudflap nls openmp -altivec -bootstrap -build -doc -hardened -ip28 -ip32r10k -multilib -multislot -n32 -n64 -nocxx -objc -objc++ -objc-gc -test -vanilla)


Edit : Question en C (je suis nouveau :) )

Code:
void
fonction (const char p[], const char n[], char mail[])
{
  int i;
   char pbis[30], nbis[30];
  /* Optionnel : écriture du prénom sous la forme Prénom
  (via une chaîne locale, car on ne peut pas écrire sur p) */
  sprintf(pbis, presentation(p));
  /* Optionnel : écriture du nom sous la forme Nom
  (via une chaîne locale, car on ne peut pas écrire sur n) */
  sprintf(nbis, presentation(n));

[...]
}

void
presentation (char t[])
{
  int i;
  t[0] = toupper (t[0]);
  for (i = 1; t[i]; i++)
    t[i] = tolower (t[i]);
}

J'aimerias copier p dans pbis et n dans nbis, mais j'ai cette erreur :

Quote:
attention : passing argument 1 of ‘presentation’ discards qualifiers from pointer target type
erreur: utilisation invalide d'expression void
attention : passing argument 1 of ‘presentation’ discards qualifiers from pointer target type
erreur: utilisation invalide d'expression void
Back to top
View user's profile Send private message
xaviermiller
Bodhisattva
Bodhisattva


Joined: 23 Jul 2004
Posts: 8708
Location: ~Brussels - Belgique

PostPosted: Tue Feb 05, 2008 10:02 pm    Post subject: Reply with quote

salut,

les USE et CFLAGS ne sont utilisés que par Portage ;)
_________________
Kind regards,
Xavier Miller
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Tue Feb 05, 2008 10:13 pm    Post subject: Reply with quote

XavierMiller wrote:
salut,

les USE et CFLAGS ne sont utilisés que par Portage ;)
Je le sais, mais est-ce que je n'aurais pas emergé GCC avec un mauvais USE ou j'en aurais oublié un, c'est ce que je voulais dire :)
Back to top
View user's profile Send private message
sno35
Guru
Guru


Joined: 15 May 2004
Posts: 334
Location: Paris, France

PostPosted: Tue Feb 05, 2008 10:18 pm    Post subject: Reply with quote

Euh, on va dire que c'est une histoire de goût de ma part, mais quand il y a des pointeurs en jeux, ça ne sert qu'à aller dans le mur de se les masquer. Les paramètres formels tu devrais les passer sous forme 'pointeur' :
Code:
const char *p

au lieu de
Code:
const char[]

sinon, strdup est plus économique que sprint pour ce que tu veux faire.
Et tu annonces que presentation renvoie void et tu essaies de passer ça à sprint. Le compilo te dit à juste titre que ce n'est pas ce type qu'il attendait comme 2ème argument à sprintf.
Déjà le premier avril ?? /o\

Edit : ceci doit ressembler à ce que tu voulais, non ? :
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
 
void identifiant (const char p[], const char n[], char id[]);
 
int main (void)
{

   const int max = 30;
   char nom[max], prenom[max], id[9];
   int lp, ln;

   // On saisie le prénom
   printf ("Entrez le prénom (maximum %d caractères): ", max);
   fgets (prenom, max, stdin);
   // Et le nom
   printf ("et le nom : ");
   fgets (nom, max, stdin);

   // On s'assure qu'il y ai un prénom et un nom
   if (prenom[0] != '\0' && nom[0] != '\0')
   {
      printf("n:%p, %p, %p,%p\n", nom, &nom, id, &id);
      printf ("Données :\tPrénom = %s\t--\tNom = %s\n", prenom, nom); // Affichage du résultat

      identifiant (prenom, nom, id);
      printf ("Identifiant :\t%s\n", id);       // Affichage du résultat
      printf ("Test de nom :%s\n",nom);

   }
   else printf("Merci d'écrire un prénom et un nom.");

   return EXIT_SUCCESS;
}
 
void
identifiant(const char p[], const char n[], char id[])
{
   int i;
   id[0] = toupper(p[0]);
   i = 1;
   while (i < 8)
   {
      /* la lisibilité est meilleure en gardant i-1 plutôt que
       * de manipuler une variable en parallèle. Et pas moins efficace.
       * Et quand bien même laisse faire le compilo. Si jamais il se trompe,
       * tu y reviendra et le règlera plus tard ;-) */
      id[i] = tolower(n[i-1]);
      i++;
   }
   id[i] = '\0';
}

Back to top
View user's profile Send private message
Magic Banana
Veteran
Veteran


Joined: 13 Dec 2005
Posts: 1912
Location: Belo Horizonte, Minas Gerais, Brasil

PostPosted: Wed Feb 06, 2008 1:05 pm    Post subject: Reply with quote

Lorsque tu as des problèmes de portabilité il est bon de rendre gcc plus exigeant et de regarder de près chaque avertissement :
Code:
$ gcc -Wall -Wextra -ansi -pedantic main.c
Back to top
View user's profile Send private message
Temet
Advocate
Advocate


Joined: 14 Mar 2006
Posts: 2586
Location: 92

PostPosted: Wed Feb 06, 2008 1:38 pm    Post subject: Reply with quote

Mouais, rien que revoir des chaines de caractères surdimensionnées, je me dis que le C c'est pas la panaC.

... si vous me cherchez : :arrow:
_________________
Full Gentoo powered.
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Wed Feb 06, 2008 2:46 pm    Post subject: Reply with quote

Merci beaucoup.
Pour l'utilisation des deux variables, je suis obligé.
Par ex : si il y a un tiret dans une chaine, je dois avancer sur l'une et non sur l'autre.

Même avec la commande donné, rien d'anormal (certes il gueule pour tout), il me dit même que c'est de type void.
Back to top
View user's profile Send private message
xaviermiller
Bodhisattva
Bodhisattva


Joined: 23 Jul 2004
Posts: 8708
Location: ~Brussels - Belgique

PostPosted: Wed Feb 06, 2008 2:57 pm    Post subject: Reply with quote

Animatrix wrote:
rien d'anormal (certes il gueule pour tout)


8O
_________________
Kind regards,
Xavier Miller
Back to top
View user's profile Send private message
Magic Banana
Veteran
Veteran


Joined: 13 Dec 2005
Posts: 1912
Location: Belo Horizonte, Minas Gerais, Brasil

PostPosted: Wed Feb 06, 2008 4:35 pm    Post subject: Reply with quote

XavierMiller wrote:
Animatrix wrote:
rien d'anormal (certes il gueule pour tout)


8O


8O 8O

Tu peux peut-être nous donner tous ces avertissements (j'ai pas trop envie de jouer au compilateur aujourd'hui :lol: ).
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Wed Feb 06, 2008 4:55 pm    Post subject: Reply with quote

Magic Banana wrote:
XavierMiller wrote:
Animatrix wrote:
rien d'anormal (certes il gueule pour tout)


8O


8O 8O

Tu peux peut-être nous donner tous ces avertissements (j'ai pas trop envie de jouer au compilateur aujourd'hui :lol: ).
QUand je dis ca, par exemple c'est pour un commentaire (//) si je met : il me met un msg d'erreur, alors que ce n'en ai pas un et vu que j'ai bcp de comms...
Back to top
View user's profile Send private message
GentooUser@Clubic
l33t
l33t


Joined: 01 Nov 2004
Posts: 829

PostPosted: Wed Feb 06, 2008 6:04 pm    Post subject: Reply with quote

Le C n'accepte que la forme /* ... */ pour les commentaires !
A moins que ça ai changé.
Back to top
View user's profile Send private message
YetiBarBar
Guru
Guru


Joined: 23 Dec 2005
Posts: 532

PostPosted: Wed Feb 06, 2008 6:09 pm    Post subject: Reply with quote

GentooUser@Clubic wrote:
Le C n'accepte que la forme /* ... */ pour les commentaires !
A moins que ça ai changé.


Ca a changé !

Plus exactement, le C99 tel que préconisé par l'ISO accepte // (en autres trucs ...)

mais pour celà, il faut dire à GCC que tu fais du C dans cette norme (-std=c99 en paramètre ou quelquechose du genre, pas envie de me faire mon petit man gcc non plus ...)

EDIT : en fait, GCC accepte les commentaires en // depuis un bail, sauf si tu forces le C ANSI (avec un -ansi)
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Thu Feb 07, 2008 9:08 pm    Post subject: Reply with quote

Voila ce que sa donne sans ainsi.

Code:
courriel.c:21:32: attention : Les commentaires à la C++ ne sont pas permis en C89 ISO
courriel.c:21:32: attention : (ceci sera rapporté une seule fois seulement par fichier d'entrée)
courriel.c: In function ‘main’:
courriel.c:29: attention : ISO C90 forbids variable-size array ‘nom’
courriel.c:29: attention : ISO C90 forbids variable-size array ‘prenom’
courriel.c:29: attention : ISO C90 forbids variable-size array ‘mail’

Donc rien d'annormal :'([/quote]
Back to top
View user's profile Send private message
xaviermiller
Bodhisattva
Bodhisattva


Joined: 23 Jul 2004
Posts: 8708
Location: ~Brussels - Belgique

PostPosted: Fri Feb 08, 2008 7:50 am    Post subject: Reply with quote

Essaie de remplacer ta constante par un #define : rien ne dit que toutes les implémentations supportent C99.
Et change les commentaires : tu fais du C, pas du C++

Ou alors, force la compilation en C99 !

A moins que tu ne refuses de faire du code portable ;)
_________________
Kind regards,
Xavier Miller
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Fri Feb 08, 2008 8:44 am    Post subject: Reply with quote

Alors, j'ai remplacé tous les commentaires et même utilisé un -std=c99 et aucune erreur de la part de gcc.
Code:
gcc -Wall -Wextra -ansi -pedantic -std=c99 main.c -o main


Le problème persiste, alors qu'avec les versions précédentes de ce même compilateur ca marche :(


Last edited by Animatrix on Fri Feb 08, 2008 8:46 am; edited 1 time in total
Back to top
View user's profile Send private message
xaviermiller
Bodhisattva
Bodhisattva


Joined: 23 Jul 2004
Posts: 8708
Location: ~Brussels - Belgique

PostPosted: Fri Feb 08, 2008 8:45 am    Post subject: Reply with quote

et à l'exécution ?

J'ai pas trop le temps de regarder ça maintenant (à la bourre au boulot et à la maison), mais peut-être dimanche ;)
_________________
Kind regards,
Xavier Miller
Back to top
View user's profile Send private message
YetiBarBar
Guru
Guru


Joined: 23 Dec 2005
Posts: 532

PostPosted: Fri Feb 08, 2008 3:55 pm    Post subject: Reply with quote

Animatrix wrote:
Alors, j'ai remplacé tous les commentaires et même utilisé un -std=c99 et aucune erreur de la part de gcc.
Code:
gcc -Wall -Wextra -ansi -pedantic -std=c99 main.c -o main


Le problème persiste, alors qu'avec les versions précédentes de ce même compilateur ca marche :(


Tu passes 2 paramètres auto-exclusifs à gcc :
-ansi (strictement identique à -std=c89 ou -std=c90, à voir avec man gcc)
-std=c99

Je ne sais pas trop comment gcc fait sa sauce en interne, mais je pense qu'une fois défini ...

En relisant le man, j'ai vérifie que le mode C "par défaut" de gcc est gnu90 (enfin un numéro du genre) : du C ansi avec des extensions extraites du C99

PS : +1 avec XavierMiller pour les commentaires, le // est vraiment rarement indispensable

EDIT : pour ton problème, en C ANSI, tu es bien obligé de définir des constantes avec un #define si tu veux déclarer des tableaux de cet taille (comme ça a été dit), le compilateur considérant qu'utiliser un int (même constant) ne lui fournit pas la taille des données à allouer. C'est très con (et il me semble que le C99 ne le tolère pas non plus, mais je t'avoue avoir travaillé vraiment trop peu avec ...)
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Fri Feb 08, 2008 9:30 pm    Post subject: Reply with quote

Je me suis trompé en copiant, je n'ai bien sûr pas fait de -ansi et de -std=c99 à la fois.

Pour les define, on m'a vraiment déconseillé de les utiliser car c'était une méthode "bourrin".

Mais l'étrang"ité" de la chose est que d'autres versions de gcc sur une même machine marchent.
Je ne devrais pas faire un rapport de bug ?
Back to top
View user's profile Send private message
guilc
Bodhisattva
Bodhisattva


Joined: 15 Nov 2003
Posts: 3326
Location: Paris - France

PostPosted: Fri Feb 08, 2008 10:03 pm    Post subject: Reply with quote

Animatrix wrote:
Mais l'étrang"ité" de la chose est que d'autres versions de gcc sur une même machine marchent.
Je ne devrais pas faire un rapport de bug ?

Heu, c'est pas pour être méchant, mais avant de faire un rapport de bug, il faudrait peut-être à faire du C non ?
Surtout pour des bugs de "base" comme ça, y a carrément peu de chance que le problème vienne de GCC... La ton code est bourré de débordements de buffers potentiels ou effectifs, donc à partir de la, le comportement sera hératique suivant les compilos et les version de compilos, au grès des différents écrasements de pile et compagnie...

Voici un exemple de code qui marche sans bug et sans débordements de buffers, et quelques allocations dynamiques (les tableaux statique sont à TOTALEMENT proscrire : de telles allocations se font sur la pile, qui est de taille TRES limitée, contrairement aux allocations dynamiques qui se font en RAM).
Attention, j'ai fait l'impasse sur les tests qui pourraient vérifier que les allocations se sont faites correctement par exemple (il faut les faire pour éviter les bugs potentiels lors d'échecs d'allocations)

Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

#define MAX_STRING 1024

void identifiant (char *p, char *n, char **id);

int main (void)
{
    char *nom = NULL, *prenom = NULL, *id = NULL;
    int lp, ln;

    // On saisie le prénom
    prenom = (char *)malloc ((MAX_STRING + 1) * sizeof (char));
    printf ("Entrez le prénom (maximum %d caractères): ", MAX_STRING);
    fgets (prenom, MAX_STRING, stdin);
    prenom = (char *)realloc (prenom, (strlen (prenom) + 1) * sizeof (char));
    // Et le nom
    nom = (char *)malloc ((MAX_STRING + 1) * sizeof (char));
    printf ("et le nom : ");
    fgets (nom, MAX_STRING, stdin);
    nom = (char *)realloc (nom, (strlen (nom) + 1) * sizeof (char));

    // On s'assure qu'il y ai un prénom et un nom
    if (*prenom != '\0' && *nom != '\0')
    {
        printf ("Données :\tPrénom = %s\t--\tNom = %s\n", prenom, nom); // Affichage du résultat
        identifiant (prenom, nom, &id);
        printf ("Identifiant :\t%s\n", id);       // Affichage du résultat
        printf ("Test de nom :%s\n", nom);
    }
    else
    {
        printf("Merci d'écrire un prénom et un nom.");
    }
    if (nom)
        free (nom);
    nom = NULL;
    if (prenom)
        free (prenom);
    prenom = NULL;
    if (id)
        free (id);
    id = NULL;

    return EXIT_SUCCESS;
}

void identifiant (char *p, char *n, char **id)
{
    int i, j;
    int max = strlen (n);
    *id = (char *)malloc (9 * sizeof (char));
    (*id)[0] = p[0];
    i = 1;
    j = 0;
    while (i < 8 && j < max)
    {
        (*id)[i++] = n[j++];
    }
    (*id)[i] = '\0';
    *id = (char *)realloc (*id, (strlen (*id) + 1) * sizeof (char));
}

_________________
Merci de respecter les règles du forum.

Mon site perso : https://www.xwing.info
Mon PORTDIR_OVERLAY : https://gentoo.xwing.info ou layman -a xwing
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Sat Feb 09, 2008 12:10 am    Post subject: Reply with quote

En effet plus de problème :)

Le tout est que j'apprends le C actuellement, et que les sizeof, malloc, je n'ai pas encore vu.
Définir des char tableau[] sont imposés par le sujet, je ne peux pas faire autrement (quoi que maintenant je sais :))
Back to top
View user's profile Send private message
xaviermiller
Bodhisattva
Bodhisattva


Joined: 23 Jul 2004
Posts: 8708
Location: ~Brussels - Belgique

PostPosted: Sat Feb 09, 2008 8:17 pm    Post subject: Reply with quote

Animatrix wrote:
Pour les define, on m'a vraiment déconseillé de les utiliser car c'était une méthode "bourrin".


Qui t'a dit ça ? un chipoteur C++ ?

même les gourous C++ disent que les #define ont du sens.
_________________
Kind regards,
Xavier Miller
Back to top
View user's profile Send private message
Animatrix
Guru
Guru


Joined: 13 May 2006
Posts: 480
Location: France - Gard (30)

PostPosted: Sat Feb 09, 2008 8:36 pm    Post subject: Reply with quote

XavierMiller wrote:
Animatrix wrote:
Pour les define, on m'a vraiment déconseillé de les utiliser car c'était une méthode "bourrin".


Qui t'a dit ça ? un chipoteur C++ ?

même les gourous C++ disent que les #define ont du sens.

Tout au moins, apprenant le C depuis très peu de temps, je pense que le prof préfère utiliser l'autre méthode, pour ensuite venir au define :)

En tout cas, merci pour votre aide.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index French All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum