[C] Pb chaine de cacracteres...

Pb chaine de cacracteres... [C] - C - Programmation

Marsh Posté le 04-06-2005 à 20:52:52    

J'ai un petit problème pour nommer un fichier :/
J'ai deux tableaux dont je mets les valeurs dans un fichier. Cela ne me pose pas de problème.

Code :
  1. void allures (float RC)
  2. {
  3.     float X[50], Y[50];
  4.     int i;
  5.     FILE *fp;
  6.     fp=fopen("gain.dat", "w+t" );
  7.     for(i=0; i<decade*point; i++)
  8.     {
  9.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  10.              }
  11.     fclose(fp);


Seulement j'aimerais pouvoir donner le nom au fichier moi meme. Et je n'y arrive pas :(

Code :
  1. void allures (float RC)
  2. {
  3.     float X[50], Y[50];
  4.     int i;
  5.     FILE *fp;
  6.     char nom_fichier[20];
  7.     printf("\nVeuillez saisir le nom du fichier.\n" );
  8.     //je ne sais pas comment faire
  9.     fp=fopen(nom_fichier, "w+t" );
  10.     for(i=0; i<decade*point; i++)
  11.     {
  12.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  13.              }
  14.     fclose(fp);


J'ai essayé différents trucs mais sans jamais y arriver. Auriez-vous une idée ? :jap:

Reply

Marsh Posté le 04-06-2005 à 20:52:52   

Reply

Marsh Posté le 04-06-2005 à 20:58:16    

fgets (pense à enlever le \n final).

Reply

Marsh Posté le 04-06-2005 à 21:01:28    

Pillow a écrit :

fgets (pense à enlever le \n final).


 
J'ai essayé :

Code :
  1. printf("\nVeuillez saisir le nom du fichier." );
  2.     fgets(nom_fichier, sizeof(nom_fichier), stdin);
  3.     fp=fopen(nom_fichier, "w+t" );
  4.     for(i=0; i<decade*point; i++)
  5.     {
  6.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  7.              }
  8.     fclose(fp);


Merci :jap:
Mais ca ne marche pas :/ Et comment rajouter le .dat derrière ?

Reply

Marsh Posté le 04-06-2005 à 21:11:17    

Heureusement que j'ai précisé qu'il fallait enlever le '\n' final [:ddr555]. strshr est ton ami pour ça :o  
Pour rajouter le .dat : man strcat :o (attention à la longueur de la chaine!).
 
Pour être rigoureux, il faut que tu gères une éventuelle erreur pendant le fgets (indice: man fgets et une boucle while) et que tu gères correctement un EOF (man feof :o ).
Pense aussi à vérifier si le fopen a fonctionné (man fopen :o )

Reply

Marsh Posté le 04-06-2005 à 21:17:20    

Pillow a écrit :

Heureusement que j'ai précisé qu'il fallait enlever le '\n' final [:ddr555]. strshr est ton ami pour ça :o  
Pour rajouter le .dat : man strcat :o (attention à la longueur de la chaine!).
 
Pour être rigoureux, il faut que tu gères une éventuelle erreur pendant le fgets (indice: man fgets et une boucle while) et que tu gères correctement un EOF (man feof :o ).
Pense aussi à vérifier si le fopen a fonctionné (man fopen :o )


 
Pour le \n final c'est lequel dont tu parles ?
Excuses moi mais je ne comprends rien a ce que tu racontes après :/ Je suis débutant en C et ceci est un projet à réaliser (IUT 1ere année ), on nous a un peu guider pour ca :

Code :
  1. printf("\nVeuillez saisir le nom du fichier pour le gain." );
  2.     scanf(...,...) /*instruction a compléter*/
  3.     fp=fopen(nom_fichier, "w+t" );
  4.     for(i=0; i<decade*point; i++)
  5.     {
  6.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  7.              }
  8.     fclose(fp);


Donc si j'écoutes mes profs avec un scanf ca suffit mais je ne vois pas comment ca peut fonctionner :o

Reply

Marsh Posté le 04-06-2005 à 21:28:38    

scanf c'est le mal :o
fgets :o

Reply

Marsh Posté le 04-06-2005 à 21:30:10    

Joel F a écrit :

scanf c'est le mal :o
fgets :o


Ben je veux bien moi mais je l'ai jamais étudié :/
Donnez moi un coup de pouce svp, c'est la dernière chose qui me manque pour boucler mon programme !

Reply

Marsh Posté le 04-06-2005 à 21:32:42    

c'ets un sujet deja rabattu sur le forum, une chtite recherche portera ses fruits :)

Reply

Marsh Posté le 04-06-2005 à 21:35:31    

C'est vrai que ça fait peut être beaucoup de choses d'un coup [:petrus75]  
 
Alors pour commencer: scanf c'est le mal!. Beaucoup trop compliqué à utiliser correctement. Tu peux le dire à ton prof de ma part :o  
 
Quand je parle de "man machin", je veux parler des pages de manuel qu'on trouve dans les unix-like : si tu utilises gnu/linux, un bsd, ou un autre unix, il te suffit de taper "man fonction" dans un terminal pour voir comment fonction marche. Si tu as windows, tapes le "man fonction" dans google, tu trouveras probablement la page du manuel.
 
Le retour chariot dont je parle c'est celui ci (extrait de la page de manuel de fgets):

Si un retour-chariot (newline) est lu, il est placé dans le buffer.

C'est à dire que lorsque tu rentres le nom du fichier, suivi d'<entrée>, le retour à la ligne est copié à la fin du buffer, ce qui n'est pas ce que tu souhaites. Il faut donc l'enlever. Pour cela, il faut trouver sa position (avec strchr par exemple) et mettre un 0 à la place.
 
En ce qui concerne les gestions d'erreur : il peut se produire toutes sortes d'erreurs pendant l'appel à une fonction comme fgets, il faut donc que tu t'assures que tout c'est bien passé avant de continuer. Un autre extrait de la page de manuel de fgets:

gets()  et  fgets()  renvoient  le  pointeur  s  si  elles réussissent, et NULL en cas d'erreur,  ou  si  la  fin  de fichier  est  atteinte  avant  d'avoir pu lire au moins un caractère.

(n'utilise jamais jamais jamais gets).
Il y a un cas particulier intéressant parmi ces erreurs : la lecture d'EOF. Envoyer EOF est une façon courante pour un utilisateur de demander l'arrêt du programme.  
 
Pour fopen, il est possible que le fichier ne puisse pas être ouvert (par exemple, si le nom du fichier est invalide ou que l'utilisateur n'a pas les droits suffisants). Dans ce cas la fonction retourne NULL. Il te suffit de tester la valeur de fp après l'appel à fopen.
 
Pour plus de détails, fais une recherche sur le forum, tu trouveras moults exemples :o

Reply

Marsh Posté le 04-06-2005 à 21:41:38    

Merci pour toutes tes précisions :jap: J'essaye de chercher qqch sur le forum pour m'aider :)

Reply

Marsh Posté le 04-06-2005 à 21:41:38   

Reply

Marsh Posté le 04-06-2005 à 22:12:12    

Stefoufou a écrit :

J'ai essayé :
    fgets(nom_fichier, sizeof(nom_fichier), stdin);
    fp=fopen(nom_fichier, "w+t" );


Quels sont les mots que tu n'as pas compris dans
 
"pense à enlever le \n final"
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 04-06-2005 à 22:14:01    

Pillow a écrit :

Alors pour commencer: scanf c'est le mal!. Beaucoup trop compliqué à utiliser correctement. Tu peux le dire à ton prof de ma part :o  


Et de la mienne. Passe lui ça :
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-06-2005 à 10:51:55    

Stefoufou a écrit :

Pour le \n final c'est lequel dont tu parles ?
Excuses moi mais je ne comprends rien a ce que tu racontes après :/ Je suis débutant en C et ceci est un projet à réaliser (IUT 1ere année ), on nous a un peu guider pour ca :

Code :
  1. printf("\nVeuillez saisir le nom du fichier pour le gain." );
  2.     scanf(...,...) /*instruction a compléter*/
  3.     fp=fopen(nom_fichier, "w+t" );
  4.     for(i=0; i<decade*point; i++)
  5.     {
  6.              fprintf(fp, "%f    %f\n", X, Y[i]);
  7.              }
  8.     fclose(fp);


Donc si j'écoutes mes profs avec un scanf ca suffit mais je ne vois pas comment ca peut fonctionner :o


 
Le problème de "scanf", c'est que cette fonction ne contrôle pas le nb de caractères saisis par rapport à l'espace où les stocker. Autrement dit, tu peux saisir 150 lettres que scanf essaiera de ranger dans une zone de 20 octets => gros risque de plantage
Une fois que tu connais ce danger, tu peux choisir de l'ignorer en te disant "c'est moi qui saisi ma zone et je ferai gaffe de ne pas mettre un nom trop long" ou bien en te disant "je définis une zone très grosse comme cela je suis certain de ne pas dépasser".
Dans ce cas, voici ton code
 

Code :
  1. char nom_fichier[1024];
  2.     printf("\nVeuillez saisir le nom du fichier pour le gain: " );
  3.     fflush(stdout);    /* Pour afficher le message tout de suite */
  4.     scanf("%s", nom_fichier);
  5.     fp=fopen(nom_fichier, "w+t" );
  6.     for(i=0; i<decade*point; i++)
  7.     {
  8.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  9.     }
  10.     fclose(fp);


 
Sinon, tu peux utiliser "fgets" qui permet de saisir une chaîne de "n" octets. C'est à dire que "fgets" stoppe automatiquement dès que le nb d'octets saisis est atteint => tu ne dépasseras donc jamais ta zone de stockage.
Le pb (le soucis) de "fgets", c'est que cette fonction récupère tout ce que tu tapes, y compris le "return" qui valide ta saisie. Ce "return" est transformé en '\n' dans la zone de stockage mais dans ce cas particulier, il va te géner. Donc il faut l'enlever
 

Code :
  1. char nom_fichier[1024];
  2.     char *pt;
  3.     printf("\nVeuillez saisir le nom du fichier pour le gain: " );
  4.     fflush(stdout);    /* Pour afficher le message tout de suite */
  5.     fgets(nom_fichier, 1024, stdin);
  6.     /* On recherhce le '\n' */
  7.     pt=strchr(nom_fichier, '\n');
  8.     /* S'il y en a un, on le remplace par la valeur "fin de chaîne" */
  9.     if (pt != NULL)
  10.         *pt='\0';
  11.     fp=fopen(nom_fichier, "w+t" );
  12.     for(i=0; i<decade*point; i++)
  13.     {
  14.              fprintf(fp, "%f    %f\n", X[i], Y[i]);
  15.     }
  16.     fclose(fp);


 
Autre truc, "for (i=0; i < [i]opértion mathématique; i++)" c'est très mauvais parce que l'opération mathématique se fera à chaque itération de ta boucle => imagine le temps d'éxécution si l'opération est très longue à faire. Il vaut mieux faire "result=opértion mathématique et faire "for (i=0; i < result; i++)"


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 05-06-2005 à 10:55:52    

Sve@r a écrit :


Autre truc, "for (i=0; i < opértion mathématique; i++)" c'est très mauvais parce que l'opération mathématique se fera à chaque itération de ta boucle


 
Avec gcc 0.5.9 alpha release ? Paske moi gcc 4.0 en -O3 , bah il est assez gentil pour m'optimiser les inavriants de boucles :o

Reply

Marsh Posté le 05-06-2005 à 11:56:24    

Merci pour vos aides précieuses :jap:
J'ai bien essayer de m'inspirer et de bidouiller les codes que jai pu trouver par ci par la mais sans résultats.
 
Pour la boucle il vaut mieux que je remplace le decade*point par une constante contenant cette valeur ?

Reply

Marsh Posté le 05-06-2005 à 12:02:18    

Sve@r a écrit :

Le problème de "scanf", c'est que cette fonction ne contrôle pas le nb de caractères saisis par rapport à l'espace où les stocker. Autrement dit, tu peux saisir 150 lettres que scanf essaiera de ranger dans une zone de 20 octets => gros risque de plantage
Une fois que tu connais ce danger, tu peux choisir de l'ignorer en te disant "c'est moi qui saisi ma zone et je ferai gaffe de ne pas mettre un nom trop long" ou bien en te disant "je définis une zone très grosse comme cela je suis certain de ne pas dépasser".


Ou tu utilises un formateur

char nom_fichier[1024];
<...>
    scanf("%1023s", nom_fichier);


Mais la maintenance n'est pas simple et le problème du '\n' pendant n'est pas résolu...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-06-2005 à 12:03:45    

Joel F a écrit :

Avec gcc 0.5.9 alpha release ? Paske moi gcc 4.0 en -O3 , bah il est assez gentil pour m'optimiser les inavriants de boucles :o


Tout le monde n'utilise pas le même compilateur ni les mêmes options. Autant écrire du code correct tout de siuite quand ça ne coûte pas grand chose...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-06-2005 à 12:27:54    

Impossible de faire quoi que ce soit avec fgets :/ Tant pis j'arrive a quelque chose avec le scanf et même si c'est le mal ce n'est pas grave tant que ca fonctionne et que je peux rendre mon boulot :o
Encore merci à vous :jap:

Reply

Marsh Posté le 05-06-2005 à 13:40:03    

Emmanuel Delahaye a écrit :

Tout le monde n'utilise pas le même compilateur ni les mêmes options. Autant écrire du code correct tout de siuite quand ça ne coûte pas grand chose...


 
Certes mais bon, l'optimisation d'invariants de boucle est quand même quelque chose de base :|
Même VC6 le fait :o

Reply

Marsh Posté le 05-06-2005 à 15:17:13    

Stefoufou a écrit :

Impossible de faire quoi que ce soit avec fgets


Ca va pas beaucoup nous renseigner pour pouvoir t'aider. Poste le code qui ne fonctionne pas avec fgets()...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-06-2005 à 20:14:09    

J'ai fais un copier/coller du code de Sve@r, je n'ai pas d'erreur de compilation mais lorsque ca arrive sur le fgets quand j'execute le programme ca plante :/

Reply

Marsh Posté le 05-06-2005 à 20:41:48    

Stefoufou a écrit :

J'ai fais un copier/coller du code de Sve@r, je n'ai pas d'erreur de compilation mais lorsque ca arrive sur le fgets quand j'execute le programme ca plante :/


Evidemment, il manque une une enveloppe de fonction et quelques includes... A part ça

  • definir un fp de type FILE *
  • Retirer le 't' de "w+t" qui n'a aucun sens. (Quand au '+', j'ai un doute)
  • Tester fp avant de l'utiliser


Ceci fonctionne:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main (void)
{
   char nom_fichier[128];
 
   printf ("Veuillez saisir le nom du fichier pour le gain: " );
   fflush (stdout);             /* Pour afficher le message tout de suite */
   fgets (nom_fichier, sizeof nom_fichier, stdin);
 
   /* On recherche le '\n' */
   {
      char *pt = strchr (nom_fichier, '\n');
 
      /* S'il y en a un, on le remplace par la valeur "fin de chaîne" */
      if (pt != NULL)
      {
         *pt = 0;
      }
      else
      {
         /* sinon, on purge... */
         int c;
         while ((c = fgetc (stdin)) != '\n' && c != EOF)
         {
         }
      }
   }
 
   if (nom_fichier[0] != 0)
   {
      FILE *fp = fopen (nom_fichier, "w" );
 
      if (fp != NULL)
      {
         int i;
         int decade = 3;
         int point = 4;
         double X[] =
         {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
         double Y[] =
         {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
 
         for (i = 0; i < decade * point; i++)
         {
            fprintf (fp, "%f    %f\n", X[i], Y[i]);
         }
         fclose (fp);
      }
   }
   return 0;
}


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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