IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème de sprintf


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 35
    Par défaut Problème de sprintf
    Bonjour!

    pourquoi est ce quand je fais 2 sprintf à la suite sur deux char* différents, j'obtiens une concaténation des deux dans le même char * ?

    Voici une partie partielle de la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    char request[MAX_SIZE_REQUEST];/*250*/
    char select[MAX_SIZE_REQUEST];
     
    sprintf(request,"insert into %s values (NULL,'%s','%s','%s','%s')",tableName,values->pair[mapString_isset(*values,LABEL_GENRE)]->value, values->pair[mapString_isset(*values,LABEL_DIRECTOR)]->value, values->pair[mapString_isset(*values,LABEL_ACTOR)]->value, values->pair[mapString_isset(*values,LABEL_PRODUCER)]->value );
    sprintf(select,"select max(id_profile)+1 from %s",tableName);
    j'obtiens
    request :
    insert into profile values (NULL,'4,8.91;17,9.65;16,7.02;3,7.94;12,8.19;2,9.56;15,8.44;6,7.05','3630,0.1;3177,0.1;4016,0.77;3649,0.1;3871,4.28','12679,0.1;12680,0.1;11754,0.1;12681,0.1;12682,0.1;11074,0.1;11075,0.1;11076,0.1;11077,0.1;11078,0.1select max(id_profile)+1 from profile

    select :
    select max(id_profile)+1 from profile


    Voila merci!
    et au sinon un moyen de passer en dynamique request et select?
    j'avais essayé char ** request;
    request=malloc(sizeof (char*));
    sprintf(*request,[..]);
    mais ça me faisait une erreur de segmentation.

  2. #2
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Salut,

    En fait c'est parce que ton buffer est trop petit, il fait 250 alors que la chaine que tu nous montres fait 272.

    Comme tu le sais, chaque chaine de caractère est terminée par le caractère '\0', sprintf l'ajoute lui même à la fin.

    Tes deux buffers sont situés un à côté de l'autre, et dans ce cas, tu as alloué 500 caractères de mémoire contigües. Si tu n'avais pas déclaré le deuxième buffer juste après tu aurais pu avoir une segfault car tu accédais une mémoire que tu n'avais pas réservée.

    Ce qui se passe c'est que les 22 caractères en trop sont stockés dans le 2ème buffer, par conséquent lors du 2ème sprintf tu les écrases (légitimement) avec les nouvelles données. Le 2ème printf ajoute un '\0' qui sera le délimiteur pour le premier et deuxième buffer !!

    et au sinon un moyen de passer en dynamique request et select?
    j'avais essayé char ** request;
    request=malloc(sizeof (char*));
    sprintf(*request,[..]);
    mais ça me faisait une erreur de segmentation.
    C'est normal, dans ce code, tu réserves un pointeur sur char, autrement dit, une zone mémoire pouvant contenir une adresse. Donc faisant 8 octets.

    Je ne vais tout ré-expliquer ici, je te conseille d'aller voir les nombreux tutoriels sur les pointeurs. Néanmoins, si tu veux éviter une segfault une fois pour toute (dans cette exemple), il faudra que tu réserves assez de mémoire pour toute ta chaine, peu importe sa taille. Donc via l'allocation dynamique tu feras :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char* request; // simple pointeur suffisant
    request = malloc(strlen(chaine1) + strlen(chaine2) + ... + taille_chaine_statique + 1) ; // +1 pour le '\0'
    sprintf(request, ...);
    Ce que j'appelle chaine "statique" c'est ce que tu écris en "dur" dans le sprintf.

    Voila, j'espère que j'ai été assez clair

  3. #3
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 35
    Par défaut
    Merci! je vais essayer de faire ça

  4. #4
    Membre éprouvé Avatar de nowahn
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 84
    Par défaut
    Salut,

    Citation Envoyé par Kimly
    et au sinon un moyen de passer en dynamique request et select?
    j'avais essayé char ** request;
    request=malloc(sizeof (char*));
    sprintf(*request,[..]);
    mais ça me faisait une erreur de segmentation.
    Il y a asprintf pour ça, mais je ne sais pas si c'est standard ou une extension GNU/linux.

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Jolie fonction

    Sauf que :

    Citation Envoyé par http://man.developpez.com/man3/asprintf.3.php
    NOTES
    Ces fonctions sont des extensions GNU et sont absentes des standards C et POSIX. Elles sont également disponibles sous *BSD. L'implantation FreeBSD affecte à strp la valeur NULL en cas d'erreur.

  6. #6
    Membre averti
    Femme Profil pro
    Inscrit en
    Juin 2012
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Juin 2012
    Messages : 35
    Par défaut
    Bon j'en reviens à vous pour m'aider à résoudre mon problème!

    Voici mon code (très partiel) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    char * request;
    int sizeR2=1+strlen("insert into  (id_product, status, id_genres, title, id_countries, id_directors, id_actors, id_producers, duration, short_synopsis, long_synopsis, id_tags, date) values ('', '', '', '', '', '', '', '', '', '', '', '', '')")+strlen(tableName)+strlen(values->pair[idx_idProduct]->value)+strlen(values->pair[idx_status]->value)+strlen(values->pair[idx_genre]->value)+strlen(values->pair[idx_title]->value)+strlen( values->pair[idx_country]->value)+strlen(values->pair[idx_director]->value)+strlen(values->pair[idx_actor]->value)+ strlen(values->pair[idx_producer]->value)+strlen( values->pair[idx_duration]->value)+strlen(values->pair[idx_shortSynopsis]->value)+strlen(values->pair[idx_longSynopsis]->value)+strlen(values->pair[idx_tags]->value+strlen(values->pair[idx_date]->value));
    			request=malloc(sizeR2);
    			snprintf(request,sizeR2,"insert into %s (id_product, status, id_genres, title, id_countries, id_directors, id_actors, id_producers, duration, short_synopsis, long_synopsis, id_tags, date) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", tableName, values->pair[idx_idProduct]->value, values->pair[idx_status]->value, values->pair[idx_genre]->value, values->pair[idx_title]->value, values->pair[idx_country]->value, values->pair[idx_director]->value, values->pair[idx_actor]->value, values->pair[idx_producer]->value, values->pair[idx_duration]->value, values->pair[idx_shortSynopsis]->value, values->pair[idx_longSynopsis]->value, values->pair[idx_tags]->value, values->pair[idx_date]->value);
    Mon problème est que la taille sizeR retounée est trop petite. Un exemple :
    Pour une chaine de taille 300+1;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into kuest_product (id_product, status, id_genres, title, id_countries, id_directors, id_actors, id_producers, duration, short_synopsis, long_synopsis, id_tags, date) values ('1', 'available', '12,13,14', '', '', '2100,3649', '11000,11076,12681,13000', '250,342', '4', '', '', '', '2012/7/10')
    j'ai sizeR=292 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into kuest_product (id_product, status, id_genres, title, id_countries, id_directors, id_actors, id_producers, duration, short_synopsis, long_synopsis, id_tags, date) values ('1', 'available', '12,13,14', '', '', '2100,3649', '11000,11076,12681,13000', '250,342', '4', '', '', '', '20
    Donc je comprends que le problème vient du calcul de la taille mais je ne sais pas comment j'ai pu omettre quelquchose.

    Merci d'avance et désolé si c'est une erreur stupide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec sprintf
    Par latitude38 dans le forum Débuter
    Réponses: 23
    Dernier message: 16/04/2010, 11h19
  2. Problème avec sprintf
    Par snake264 dans le forum C++
    Réponses: 10
    Dernier message: 20/04/2008, 17h12
  3. probléme avec sprintf() sous linux
    Par moooona dans le forum C++
    Réponses: 5
    Dernier message: 11/04/2008, 01h48
  4. probléme sur sprintf
    Par cyranno dans le forum C
    Réponses: 3
    Dernier message: 30/11/2007, 22h01
  5. Problème avec sprintf
    Par LinuxUser dans le forum C
    Réponses: 9
    Dernier message: 18/05/2007, 15h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo