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 :

Nommer fichier de sortie en foncton des arguments d'entrée


Sujet :

C

  1. #1
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut Nommer fichier de sortie en foncton des arguments d'entrée
    Bonjour,

    supposons un programme "file_name.cpp":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
      FILE * p_file;
      p_file = fopen( "output.txt" , "w" );
      fprintf( p_file, "Hello World !\n" );
      fclose (p_file );
    }
    Maintenant, je désire ajouter:
    int a = 2;
    et que le fichier de sortie s'appelle output_2.txt
    cad en fonction de la valeur de a

    un peu comme le printf: ("output_%i.txt", a)

    mais ça ne marche pas avec le fopen()...

    l'un d'entre vous aurait-il un conseil ?

    Merci d'avance

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Salut et bienvenue sur les forums de developper.com


    En fait, c'est facile, il faut d'abord construire une chaîne contenant le nom du fichier avec le numéro, ce que tu peux faire avec la fonction sprintf ... Voilà !

    Pour info, test toujours le retour de fopen pour le cas où la création ou l'ouverture du fichier échouerais et aussi, les fichiers source en C on l'extension .c et non pas .cpp qui est pour le C++ !

  3. #3
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    merci pour la réponse !
    mais je n'rrive pas à utiliser sprintf (malgré la page du manuel)

    Voilà ce que j'écris:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
      int a = 5;
      FILE * p_file;
      char * file_name;
      sprintf( file_name, "output_%i.txt", a );
      p_file = fopen( file_name , "w" );
      fprintf( p_file, "Hello World !\n" );
      fclose ( p_file );
    ça compile bien avec: gcc -o file_name file_name.c
    mais après ./file_name
    ça me renvoie Segmentation Fault

    et sinon, o`u pourrai-je trouver des infos pour le test de fopen ?

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par walrus_55
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      int a = 5;
      char * file_name;
      sprintf( file_name, "output_%i.txt", a );
    ça compile bien avec: gcc -o file_name file_name.c
    Euh, non...

    http://emmanuel-delahaye.developpez....tm#cfg_compilo

    mais après ./file_name
    ça me renvoie Segmentation Fault
    Ce n'est pas étonnant. Tu définis un pointeur non initialisé et tu passes sa valeur à une fonction. Le comportement est donc indéterminé.

    Il faut passer une valeur valide. Le plus simple, ici, est de passer l'adresse du premier élément d'un tableau de char.

  5. #5
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    alors j'ai un peu arrangé le code selon vos conseils et ça donne ça:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      int a = 10;
      char s[] = "output_.txt";
      char *file_name = &s;
      sprintf( file_name, "output_%i.txt", a );
      FILE * p_file;
      p_file = fopen( file_name , "w" );
      fprintf( p_file, "Hello World !\n" );
      fclose ( p_file );
    mais quand je compile avec: "gcc -o file_name file_name.c"
    ça me donne: "warning: initialization from incompatible pointer type"
    pour la ligne "char *file_name = &s;"
    mais ça compile quand même
    et quand j'exécute avec "./file_name"
    ça crée bien le fichier "output_10.txt"

    donc je ne comprends pas le warning à propos du "incompatible pointer type"...

  6. #6
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    ça y est, j'ai compris
    il faut préciser

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *file_name = &s[0];
    pour initialiser le pointeur

    donc, c'est bon, c'est résolu.
    Merci

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par walrus_55
    ça y est, j'ai compris
    il faut préciser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *file_name = &s[0];
    Oui, ce qui s'écrit aussi s + 0 ou encore s... Attention à la taille réservée. pour 10, il faut 2 caractères. Et ca n'ira que jusqu'à 99. A toi d'être prévoyant...

    Mais tu aurais pu tout simplement écrire (par exemple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
      /* exemple de numerotation de 000 a 999 */
     
       int a = 10;
       char file_name[] = "output_999.txt";
       sprintf (file_name, "output_%03d.txt", a );
     
       FILE * p_file = fopen( file_name , "w" );
       if (p_file != NULL)
       {
          fprintf( p_file, "Hello World !\n" );
          fclose ( p_file );
       }

  8. #8
    Membre éclairé Avatar de Bayard
    Inscrit en
    Juin 2002
    Messages
    861
    Détails du profil
    Informations forums :
    Inscription : Juin 2002
    Messages : 861
    Points : 716
    Points
    716
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char s[] = "output_.txt";
    char *file_name = &s;
    1) -> char *file_name = s me parait plus logique
    2) à quoi sert de faire une chaine et de déclarer un pointeur dessus ?

    Je propose:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include <stdio.h>
     
    #define C_MAX 128
     
    void main(void)
    {
      int a = 10;
      char file_name[C_MAX];
     
      FILE * p_file;
      sprintf( file_name, "output_%i.txt", a );
      p_file = fopen( file_name , "w" );
      if (p_file != NULL)
      {
    	fprintf( p_file, "Hello World !\n" );
    	fclose ( p_file );
      }
    }
    La valeur de fopen est testé. Il y a un limitation dans le nombre de digits du à la taille de file_name, mais je suis optimiste

    Ceci n'est pas testé...

  9. #9
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut introduire un "float" dans une chaîne
    mais ça entraîne un Segmentation Fault si l'on veut ajouter un float. Par ex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    float a = 0.2;
    char s[] = "a_.txt";
    char *file_name = &s[0];
    sprintf( file_name, "a_%f.txt", a );
    FILE * p_file;
    p_file = fopen( file_name , "w" );
    fprintf( p_file, "Hello World !\n" );
    fclose ( p_file );
    avec gdb, on voit que ça bloque à la ligne "fprintf( p_file, "Hello World !\n" );"

    je pense que le fait d'avoir un float dans la chaine s pose problème. Y a-t-il une solution ?

  10. #10
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Bayard
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char s[] = "output_.txt";
    char *file_name = &s;
    2) à quoi sert de faire une chaine et de déclarer un pointeur dessus ?
    apparemment, j'ai besoin d'avoir un pointeur comme argument d'entrée de sprintf
    et pour cela, je dois l'initialiser, donc avec la 1e valeur de la chaîne s

  11. #11
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par walrus_55
    mais ça entraîne un Segmentation Fault si l'on veut ajouter un float. Par ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float a = 0.2;
    char s[] = "a_.txt";
    Il faut lire les réponses précédentes. Problème de taille...

  12. #12
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    Avec le code suivant, je n'ai pas de problème de taille...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      float a = 0.0002;
      char file_name[] = "a_.txt";
      sprintf( file_name, "a_%f.txt", a );
     
      FILE * p_file = fopen( file_name , "w" );
      if ( p_file != NULL )
        {
          fprintf( p_file, "Hello World !\n" );
          fclose ( p_file );
        }
    alors je ne vois pas trop pourquoi je devrais spécifier par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char file_name[] = "a_999.txt";
    quelles précautions dois-je prendre ?

  13. #13
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par walrus_55
    Avec le code suivant, je n'ai pas de problème de taille...
    Tu n'en sais rien. Tu as fait les calculs ? Tu a vérifié que le 0 final de la chaine originale n'avait pas été altéré ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <stdio.h>
    #include <assert.h>
     
    int main (void)
    {
       float a = 0.0002;
       char file_name[] = "a_.txt";
       sprintf (file_name, "a_%f.txt", a);
     
       assert (file_name[sizeof "a_.txt" - 1] == 0);
       return 0;
    }
    Ca n'a pas loupé : Comportement indéfini !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Assertion failed: file_name[sizeof "a_.txt" - 1] == 0, file main.c, line 10
     
    This application has requested the Runtime to terminate it in an unusual way.
    Please contact the application's support team for more information.
     
    Press ENTER to continue.
    Citation Envoyé par walrus_55
    alors je ne vois pas trop pourquoi je devrais spécifier par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char file_name[] = "a_999.txt";
    quelles précautions dois-je prendre ?
    Il faut que le tableau de destination soit suffisement grand, et ça doit être le résultat d'une étude ou d'un codage intelligent, et non la simple constatation de 'ça marche ou ça ne marche pas', qui ne prouve rien.

    Le C, c'est pas un langage de bricoleur. Il faut être extrêmement prudent avec la taille des tableaux, car il n'y a aucun contrôle. C'est au programmeur d"être vigilant.

    Je rappelle :
    1 - qu'écrire au-delà d'un tableau provoque un comportement indéfini
    2 - qu'un comportement indéfini n'est pas forcément visible.

    Le format décimal des flottants est particulièrement bavard par défaut.

    Par exemple : 0.1 -> "0.100000"

    Ceci fonctionne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    #include <stdio.h>
    #include <assert.h>
     
    int main (void)
    {
       #define S_INIT "a_0.000000.txt"
       float a = 0.0002;
       char file_name[] = S_INIT;
       sprintf (file_name, "a_%f.txt", a);
     
       assert (file_name[sizeof S_INIT - 1] == 0);
     
       printf ("'%s'\n", file_name);
     
       return 0;
    }
    C'est d'ailleurs une idée étrange d'utiliser un format décimal de flottant pour une numérotation textuelle. Il pourrait y avoir des surprises : le '.' pourrait être transformé en ',' etc. Qu'est-ce qui ne va pas avec les entiers formatés comme je l'ai montré ?

  14. #14
    Futur Membre du Club
    Inscrit en
    Mars 2007
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 11
    Points : 6
    Points
    6
    Par défaut
    C'est d'ailleurs une idée étrange d'utiliser un format décimal de flottant pour une numérotation textuelle. Il pourrait y avoir des surprises : le '.' pourrait être transformé en ',' etc. Qu'est-ce qui ne va pas avec les entiers formatés comme je l'ai montré ?
    En fait, j'ai écrit un programme qui prend plusieurs arguments, certains étant des entiers, d'autres des flottants.
    ./main -T 100 -N 20 -u 0.0001

    Lorsqu'il tourne, ce programme remplit un fichier avec des valeurs calculées.

    Mais j'avais envie de pouvoir lire les paramètres d'entrée directement sur le nom du fichier de sortie (c'est pratique quand on a bcp de fichiers de sortie et que l'on teste bcp de paramètres différents...)

    D'ou mes questions...

    ------------------------

    Par ailleurs,
    Le C, c'est pas un langage de bricoleur.
    D'accord, cependant, je n'ai pas trop le choix. Quand il faut s'y mettre tout seul, eh bien on fait ce qu'on peut. J'ai lu des polycopiés disponibles sur internet, j'ai lu des codes sources, et je m'efforce de faire de mon mieux.
    En bien sûr, je remercie sincèrement tous ceux qui m'ont aidé.

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

Discussions similaires

  1. Passer des arguments en entrée à une application
    Par pcouas dans le forum Android
    Réponses: 3
    Dernier message: 29/01/2015, 13h02
  2. [Compiler] Comment passer des arguments d'entrée et de sortie ?
    Par nahouto dans le forum MATLAB
    Réponses: 5
    Dernier message: 08/07/2009, 15h00
  3. Réponses: 3
    Dernier message: 22/01/2009, 15h11
  4. Réponses: 1
    Dernier message: 23/07/2007, 11h00
  5. Réponses: 10
    Dernier message: 16/06/2007, 16h07

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