Bien programmer en langage C
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
-23%
Le deal à ne pas rater :
EVGA SuperNOVA 650 G6 – Alimentation PC 100% modulaire 650W, 80+ ...
77.91 € 100.91 €
Voir le deal

petite questions de la part d'un "débutant"

2 participants

Aller en bas

petite questions de la part d'un "débutant" Empty petite questions de la part d'un "débutant"

Message  flo Mer 4 Juin 2008 - 16:40

Bonjour, j'aimerais vous poser une question.

J'ai une première fonction qui permet de créer un fichier .dat elle s'appelle fdat

j'ai une autre fonction qui taite ce fichier .dat elle s'appelle ftrait

les deux fonctions sont de type void pour le moment et je mets donc moi même le nom du fichier dans la fonction ftrait.

Ce que j'aimerais, c'est dans ma fonction fdat retourne ce nom de fichier que je passerai en paramètre à ma deuxième fonction ftrait.
Ceci me permettra d'automatiser tout ça.

Comment puis-je faire ? Ce qui me gene c'est de retourner le nom du fichier je n'y arrive pas.
Par avance, merci

edit : je vais préciser, la chaine que je passe en paramètre dans ma fonction fdat je doit la concaténer à une chaine contenant l'extension.

en gros si je passe la chaine test en parametre dans ma fonction fdat je doit concaténer cette chaine "test" avec une chaine ".dat"
et c'est cette chaine concaténée que je vais renvoyer (test.dat donc)

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Jeu 5 Juin 2008 - 10:29

flo a écrit:
J'ai une première fonction qui permet de créer un fichier .dat elle s'appelle fdat

j'ai une autre fonction qui traite ce fichier .dat elle s'appelle ftrait

les deux fonctions sont de type void pour le moment et je mets donc moi même le nom du fichier dans la fonction ftrait.

Ce que j'aimerais, c'est dans ma fonction fdat retourne ce nom de fichier que je passerai en paramètre à ma deuxième fonction ftrait.
Ceci me permettra d'automatiser tout ça.

Comment puis-je faire ? Ce qui me gêne c'est de retourner le nom du fichier je n'y arrive pas.
Par avance, merci

edit : je vais préciser, la chaine que je passe en paramètre dans ma fonction fdat je doit la concaténer à une chaine contenant l'extension.

en gros si je passe la chaine test en parametre dans ma fonction fdat je doit concaténer cette chaine "test" avec une chaine ".dat"
et c'est cette chaine concaténée que je vais renvoyer (test.dat donc)
Si j'ai bien compris la situation, tu veux ceci :
Code:

  /* ajuster la taille selon les besoins réels ou utiliser l'allocation dynamique */
  char const fname[128] = "test";

  strcat (fname, ".dat");
  fdat (fname);
  ftrait (fname);
ou est-ce plus compliqué que ça ?
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Jeu 5 Juin 2008 - 11:29

Bonjour,
En fait le strcat se fait dans la fonction fdat.
Voici le prototype de ma fonction fdat (il est peut être faux) :
Code:
char *fdat(char *fname);

je l'utilise comme ceci

Code:
int main()
{
  char nom_fichier[20]= "test";
 
  fdat(nom_fichier);
 
//ensuite j'aimerais que ma fonction ftrait prenne en paramètre la chaîne de caractères
//retournée par la fonction fdat

}


//Ma fonction fdat que j'ai dû mal à implémenter

char *fdat(char *fname)
{
  char extension[5]=".dat";
//La concaténation que je n'arrive pas à faire

fopen(nom_du_fichier_apres_concatenation, "w")
/* traitements du fichier */

return nom_du_fichier_apres_concatenation // soit test.dat dans notre cas

}


J'espère que c'est plus clair, mon premier message ne l'était pas je m'en rends compte après relecture.
Si vous avez besoin de plus de précisions ou éclaircissements je les donnerai.
Mais en gros j'ai une chaine de caractere que je passe en paramètre à fdat qui va la concaténer avec une autre chaine représentant l'extension et retourner cette chaine concaténée qui sera elle meme passée en paramètre à ftrait.


Dernière édition par flo le Jeu 5 Juin 2008 - 13:12, édité 1 fois

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Jeu 5 Juin 2008 - 13:12

flo a écrit:Bonjour,
En fait le strcat se fait dans la fonction fdat.
C'est pas une bonne idée...


Voici le prototype de ma fonction fdat (il est peut être faux) :
Code:
char *fdat(char *fname);

je l'utilise comme ceci

Code:
int main()
{
  char nom_fichier[20]= "test";
 
  fdat(nom_fichier);
}


//Ma fonction fdat que j'ai dû mal à implémenter

char *fdat(char *fname)
{
  char extension[5]=".dat";
//La concaténation que je n'arrive pas à faire et le return

return ?

}
Eh oui, tout le problème est là. Tu n'as pas le droit de retourner l'adresse d'un variable locale, car elle n'existe plus après exécution de la fonction. J'ai donné une solution. Elle ne va pas ?
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Jeu 5 Juin 2008 - 13:14

Je teste et je vous dis.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Jeu 5 Juin 2008 - 13:23

Oui ca marche très bien vous avez raison.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Jeu 5 Juin 2008 - 13:33

flo a écrit:Oui ca marche très bien vous avez raison.
Il est un principe de bonne conception qui veut que l'on sépare les traitements.

Unix rules : "Do one thing, but do it well"
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Mar 17 Juin 2008 - 12:36

Bonjour, j'ai à nouveau une question à vous poser. Il s'agit de compatibilé Windows et Linux pour un programme.
J'utilise le logiciel gnuplot pour générer des graphiques au format png.
Ce logiciel est multi-plateforme.
Pour le moment j'ai pris la version Windows donc avec l'exécutable.
Voilà la façon dont j'appelle mon programme gnuplot.
Code:
char commande[150];
    const char *nomfichier = "histo.gnu";
    const char *cheminexe = "C:\\gnuplot\\bin\\wgnuplot.exe"; //A passer en chemin relatif par la suite
    int i=0;

    fichier = fopen(nomfichier, "w");


    if (fichier2 != NULL)
    {
    fprintf(fichier, "le script gnuplot....");
 
      sprintf(commande,"start \ %s %s", cheminexe, nomfichier);
      system(commande);   
    }
//Si ce programme vous parait moyen ou peut être amélioré dites le moi.
Cela marche bien et me crée mon image png à partir du graphique (option propre à gnuplot).
Cependant sous Linux cela ne marchera pas. Pour appeler gnuplot sous linux il faut faire dans le shell gnuplot monfichier.gnu.
Est-ce que un system("gnuplot monfichier.gnu"); marche sous Linux ? je suis sous une distribution Xp et je n'ai pas accès à une distribution Linux je n'ai pas de logiciel de virtualisation disponible....

Si oui comment faire pour tester l'OS dans lequel on est ?
Il suffirait donc de faire un simple test d'OS puis d'appeler gnuplot de deux façons différentes après avoir passé tous les chemins absolus en relatifs bien sûr.
Merci pour vos réponses.

PS: une petite question annexe.
Je dois me connecter à une base de données Oracle.
l'entreprise dans laquelle je me trouve utilise le PRO*C.
j'ai vu qu'il existait une librairie OCILIB qui permettait de se connecter également à une base Oracle.
Les deux façons se valent-elles ou l'une est-elle meilleur que l'autre ?

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Mar 17 Juin 2008 - 13:58

flo a écrit:Bonjour, j'ai à nouveau une question à vous poser. Il s'agit de compatibilé Windows et Linux pour un programme.
J'utilise le logiciel gnuplot pour générer des graphiques au format png.
Ce logiciel est multi-plateforme.
Pour le moment j'ai pris la version Windows donc avec l'exécutable.
Voilà la façon dont j'appelle mon programme gnuplot.
Code:
char commande[150];
    const char *nomfichier = "histo.gnu";
    const char *cheminexe = "C:\\gnuplot\\bin\\wgnuplot.exe"; //A passer en chemin relatif par la suite
    int i=0;

    fichier = fopen(nomfichier, "w");


    if (fichier2 != NULL)
    {
    fprintf(fichier, "le script gnuplot....");
 
      sprintf(commande,"start \ %s %s", cheminexe, nomfichier);
      system(commande);   
    }
//Si ce programme vous parait moyen ou peut être amélioré dites le moi.
Le '\' dans la chaine n'a aucun sens, car '\ ' n'est pas une séquence standard. Si tu veux ce caractère, c'est '\\'.

De plus, je ne comprends pas pourquoi tu ouvres le fichier. Il semble que tu confondes 2 choses. Soit tu manipules le fichier directement dans ton programme C et tu utilises effectivement fopen(), les fonctions d'écriture qui vont bien et fclose(), soit tu confies ce travail à une application externe (ici, gnuplot) et dans ce cas tu te contentes de forger la ligne de commande qui va bien. En principe, Windows reconnait le séparateur de chemins '/'

Le 'start' est inutile. Il suffit de faire :

Code:

    char commande[150];
    const char *nomfichier = "histo.gnu";
    const char *cheminexe = "C:/gnuplot/bin/wgnuplot.exe";

    sprintf(commande,"%s %s", cheminexe, nomfichier);
    system(commande);   
En s'assurant que la taille de commande est suffisante.

Cela marche bien et me crée mon image png à partir du graphique (option propre à gnuplot).
Cependant sous Linux cela ne marchera pas. Pour appeler gnuplot sous linux il faut faire dans le shell gnuplot monfichier.gnu.
Est-ce que un system("gnuplot monfichier.gnu"); marche sous Linux ? je suis sous une distribution Xp et je n'ai pas accès à une distribution Linux je n'ai pas de logiciel de virtualisation disponible....

Si oui comment faire pour tester l'OS dans lequel on est ?
Il suffirait donc de faire un simple test d'OS puis d'appeler gnuplot de deux façons différentes après avoir passé tous les chemins absolus en relatifs bien sûr.
Oui, il suffit de changer la commande en fonction de l'OS. Comme le code est recompilé, il suffit d'une compilation conditionnelle :
Code:

    char commande[150];
    const char *nomfichier = "histo.gnu";
#if defined (WIN32)
    const char *cheminexe = "C:/gnuplot/bin/wgnuplot.exe";
#elif defined (linux)
    const char *cheminexe = "gnuplot";
#else
#error undefined for this system
#endif
    sprintf(commande,"%s %s", cheminexe, nomfichier);

    system(commande);   

Je dois me connecter à une base de données Oracle.
l'entreprise dans laquelle je me trouve utilise le PRO*C.
j'ai vu qu'il existait une librairie OCILIB qui permettait de se connecter également à une base Oracle.
Les deux façons se valent-elles ou l'une est-elle meilleur que l'autre ?
Désolé, je n'ai aucune expérience probante dans ce domaine. Il y a un forum consacré à la programmation des BD sur Developpez.
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Mar 17 Juin 2008 - 14:24

-ed a écrit:
De plus, je ne comprends pas pourquoi tu ouvres le fichier. Il semble que tu confondes 2 choses. Soit tu manipules le fichier directement dans ton programme C et tu utilises effectivement fopen(), les fonctions d'écriture qui vont bien et fclose(), soit tu confies ce travail à une application externe (ici, gnuplot) et dans ce cas tu te contentes de forger la ligne de commande qui va bien. En principe, Windows reconnait le séparateur de chemins '/'
En fait il manque la fermeture du fichier lorsque j'ai fait le copier/coller de mon code.
J'ouvre le fichier car il va contenir mon script gnuplot.
Je crée un fichier .gnu qui contiendra mon script puis j'appelle gnuplot.
Voila le code en entier.
Code:


fichier = fopen(nomfichier, "w");


    if (fichier != NULL)
    {

        fprintf(fichier, "set terminal png transparent\n");
        fprintf(fichier, "set title \"Courbe evolutive ville de %s\" font \"Arial,16\" tc rgbcolor \"dark-blue\"\n", nom_ville);
        fprintf(fichier, "set output \"courbe.png\"\n"
                          "set xlabel \"Evolution en Heures\" tc  lt 4\n"
                          "set ylabel \"Concentration en ug/m3\" tc lt 4\n"
                          "set xtics nomirror rotate by -45 font \"Arial,9\"\n"
                          "set ytics nomirror\n"
                          "set key inside horizontal c t box lw 1.2\n"
                          "set style data histogram\nset xtics (");

      fprintf(fichier, "plot \"test.dat\" u 1:2  w filledcurv x1 lt 2, '' u 1:2:4 w filledcur above lt 1\n");

    fclose(fichier);//je ferme mon fichier, il contient maintenant mon script gnu

    fichier = NULL;
        sprintf(commande,"start \ %s %s", cheminexe, nomfichier);//je lance gnuplot pour qu'il crée mon image


        system(commande);

    }

Merci pour votre réponse je vais tester ça sous le serveur Linux si j'arrive à avoir l'accès.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Mar 17 Juin 2008 - 14:44

OK, je te laisse faire les essais. Attention à poster du code complet, c'est plus clair...
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Mar 17 Juin 2008 - 17:13

Ca marche encore une fois. merci beaucoup.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Ven 20 Juin 2008 - 11:41

Bonjour, c'est encore moi.
j'ai un petit problème avec une allocation mémoire et l'utilisation du realloc.
J'utilise tout ceci dans du Pro*C mais le problème est un problème C.
Je vais poster le code et essayer d'expliquer ce que je souhaite faire
Code:


/***
déclaration d'un entête Oracle avant le main
***/
#define NB_MAX_MES 10

EXEC SQL BEGIN DECLARE SECTION;

float lati[NB_MAX_MES];

//je ne mets pas la requete qui est lourde et plutot inutile

EXEC SQL END DECLARE SECTION;

//dans le main

int main()
{

size_t taille= 1;
   float *latitude = malloc (taille * sizeof * latitude);//j'alloue un bloc de taille 1 est-ce bon ?
   float *longitude;
   float *derniere_valeur;
   char **nom_mesure;
   char **libelle;
   char **nom_court;

numret=0;
EXEC SQL WHENEVER NOT FOUND GOTO pas_trouve;
EXEC SQL WHENEVER SQLERROR GOTO error_export_ge;
EXEC SQL OPEN tout_station;//ouverture d'un curseur contenant la requête
while(1)//Boucle infinie
{
   EXEC SQL FETCH tout_station //On effectue le fetch
   INTO :lati; //qu'on insère dans notre tableau
   //gestion des erreurs
   pas_trouve :
   if (sqlca.sqlcode < 0 || sqlca.sqlcode == 1403)  finBoucle = TRUE; //S'il le fetch ne renvoie rien on sort de la boucle. code : 1403
   
   printf("%d\n", sqlca.sqlerrd[2]);//sqlca.sqlerrd[2] aura pour valeur 10 puis 20 puis 30 puis 40 puis 50 puis 60 puis 66
   
            realloc(latitude, sqlca.sqlerrd[2]* sizeof * latitude);
            //realloc(latitude, sqlca.sqlerrd[2]); donne la meme chose

           
   for ( i = 0 ; i < sqlca.sqlerrd[2]-numret; i++)
   {
   
      latitude[i+numret]=lati[i];
      
      printf(" %f \n", latitude[i+numret]);
   }
   
   numret = sqlca.sqlerrd[2];
   
   if (finBoucle == TRUE) break;
   
   
}
error_export_ge:

En fait je crée un tableau statique de float dans la déclaration oracle de 10 colonnes.
Le résultat de ma requete me renvoie 66 enregistrement.
Donc que se passe-t-il ?
Mon curseur une fois ouvert va exécuter la requete et enregistrer les 10 premières données dans le tableau lati[]
Puis comme il y a encore des données (sqlca.sqlcode != 1403) le fetch va prendre les 10 enregistrements suivants et les mettre à nouveau dans le tableau lati[] en écrasant les données. Pour éviter de les perdre il faut donc les copier dans un tableau dynamique à chaque fois, c'est mon tableau float *latitude.
Je souhaite donc augmenter la taille de mon tableau à chaque tour de fetch.
Si mon tableau initial est de 10 et que j'ai 66 enregistrements alors il y aura 7 tours de fetch.
et la réallocation plante et j'ai une erreur de segmentation....

Si je prends un tableau initial de 100 (lati[100]) il n'y aura qu'un tour de fetch car 100>66 enregistrements et là ca ne plante pas et ca copie bien.
Cependant dans mon cas j'ai 66 enregistrements mais peut être que lorsque le programme sera lancé il y en aura plus.

Le problème vient donc du realloc à chaque tour de fetch je pensais pourtant qu'il ferait un bloc de 10 puis 20 etc...
Si vous avez besoinde plus d'explications n'hésitez pas.
merci

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Ven 20 Juin 2008 - 12:16

flo a écrit:j'ai un petit problème avec une allocation mémoire et l'utilisation du realloc.
Je vais poster le code et essayer d'expliquer ce que je souhaite faire
<...>
En fait je crée un tableau statique de float dans la déclaration oracle de 10 colonnes.
Le résultat de ma requete me renvoie 66 enregistrement.
Donc que se passe-t-il ?
Je vais essayer d'analyser le problème de façon générale et non en fonction de Pro*C que je ne connais pas.

En fait, il s'agit de lire une fichier contenant des valeurs et de créer un tableau dynamique en fonciton du nombre de valeurs lues.

Comme tu l'as noté, les 2 données importantes sont :
- l'adresse du tableau alloué
- le nombre d'éléments du tableau

Je conseille donc de mettre ces données dans une structure unique :
Code:
struct tab
{
  size_t nb;
  float *tab;
};
Ensuite, oui, tu peux décider de démarrer avec un enregistrement. Mais pour savoir où tu en es, je conseille d'ajouter un index d'écriture :
Code:
struct tab
{
  size_t nb;
  size_t i_ecr;
  float *tab;
};
on peut maintenant instancier et initialiser la structure :
Code:

  struct tab latitude;

  latitude.i_ecr = 0;
  latitude.nb= 1;
  latitude.i_ecr = malloc(sizeof *latitude.tab * latitude.nb);

  if (latitude.i_ecr != NULL)
  {

      etc.
Ensuite, dans la boucle de lecture, on écrit à la position courante de l'index d'écriture, pouis on l'incrémente de 1. Si on atteint le nombre d'éléments, on réalloue le double de la taille :
Code:

  latitude.tab[latitude.i_ecr] = get_float();
  latitude.i_ecr++;
  if (latitude.i_ecr == latitude.nb)
  {
      void *p = realloc (latitude.tab , sizeof *latitude.tab * latitude.nb * 2);
      if (latitude.i_ecr != NULL)
      {
        latitude.tab = p;
        latitude.nb *= 2;

etc.
Voilà pour le principe. Je te laisse transposer ça dans ton application. Je conseille quand même de faire des fonctions. Voici une version générique de tableau automatique :

http://mapage.noos.fr/emdel/clib.htm
Module FARR
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Ven 20 Juin 2008 - 16:40

j'ai réussi à l'appliquer à mon programme, c'était pas de la tarte surtout avec les tableaux de caractères à deux dimensions.
mais votre exemple "généraliste" m'a bien aidé merci.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  -ed- Ven 20 Juin 2008 - 17:12

flo a écrit:j'ai réussi à l'appliquer à mon programme, c'était pas de la tarte surtout avec les tableaux de caractères à deux dimensions.
Oui, mais je pense que c'est comme ça qu'on progresse...
-ed-
-ed-
Admin
Admin

Messages : 290
Date d'inscription : 26/05/2008
Age : 67
Localisation : Paris 14eme arrondissement (75, France)

http://bien-programmer.fr

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  flo Ven 20 Juin 2008 - 17:22

Oui c'est sûr, si on ne réfléchit jamais on n'avance pas.

flo
Bavard
Bavard

Messages : 11
Date d'inscription : 04/06/2008

Revenir en haut Aller en bas

petite questions de la part d'un "débutant" Empty Re: petite questions de la part d'un "débutant"

Message  Contenu sponsorisé


Contenu sponsorisé


Revenir en haut Aller en bas

Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
Ne ratez plus aucun deal !
Abonnez-vous pour recevoir par notification une sélection des meilleurs deals chaque jour.
IgnorerAutoriser