Partage
  • Partager sur Facebook
  • Partager sur Twitter

Probleme argument fonction main

Anonyme
    23 janvier 2007 à 19:14:17

    Bonsoir à tous

    je me permet de poster car j'ai un petit probleme sur un programme console en C. Avant tout voila la source

    /*Encodeur V2*/

    /* TODO (): Trouver un moyen d'avoir le chemin relatif du fichier a encrypter ! */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    void encryptAndWrite(char *cle, FILE *source, FILE *cible);
    void clean(char *sale);

    int main(int argc, char *argv[])
    {
        /*declaration variables*/
        char nomCible[100] = " ", nomSource[100], cle[50], tampon[100];
        FILE *source = NULL, *cible = NULL;
        int i, j = 0;
        /* fin declaration variables*/

        if (argc <= 1)
        {
            printf("Entrez le nom du fichier source : ");                           //soit le fichier source est specifié a l'execution ...
            fgets(nomSource, sizeof(nomSource), stdin);
            clean(nomSource);
        }
        else                                                                        //soit le programme a des parametres
        {
            strcpy(tampon, argv[1]);                                                //on copie le chemin absolu
            if (strrchr(tampon, '\\') == NULL)                                      //si le fichier est passe en parametre
            {
                    strcpy(nomSource, tampon);                                      //on store directement le nom passé
            }
            else                                                                    //si le fichier est dropé (chemin absolu)
            {
                i = tampon - strrchr(tampon, '\\');                                 //on assigne i a la position du dernier \ trouvé
                if (i < 0)
                {
                    i = -i;                                                         //on s'assure que i soit positif
                }
        /* FIXME (): Ne prend pas les fichiers dropés !! */
                do
                {
                    nomSource[j] = tampon[i + 1];                                   //et on fait une boucle pour enlever le \ et avoir le nom du fichier
                    i++;
                    j++;
                } while(tampon[i] != '\0');
            }
            clean(nomSource);
            printf("Fichier source : %s (taille du nom : %d)\n", nomSource, strlen(nomSource));
        }

            printf( "\nEntrez le nom a donner au fichier encrypte (si aucun choix"
                " le nouveau fichier se nommera : ancien-fichier.enc) : ");
            fgets(nomCible, sizeof(nomCible), stdin);                               //On demande le fichier destination
        if (nomCible[0] == '\n')
        {
    /* TODO (): Trouver un moyen de gerer l'extension pour pas avoir .enc.enc.enc */
            strcpy(nomCible, nomSource);
            strcat(nomCible, ".enc");
            printf("%s", nomCible);
        }
        clean(nomCible);

            printf("\nVeuillez saisir la cle qui servira a encrypter vos fichiers (limite a 50 caractere !) : ");
        fgets(cle, sizeof(cle), stdin);                                             //On store la cle ...
        clean(cle);                                                                 //Et on vire le \n en ajoutant le \0

        source = fopen(nomSource, "rb");
        cible = fopen(nomCible, "wb");

        if (source == NULL)
        {
            printf("Erreur ouverture fichier source.\nLe programme va s'interrompre.\n");
            system("pause");
            exit (1);
        }

        if (cible == NULL)
        {
            printf("Erreur ouverture fichier cible.\nLe programme va s'interrompre.\n");
            system("pause");
            exit (1);
        }

            encryptAndWrite(cle, source, cible);
            fclose(source);
            fclose(cible);
            system("pause");
            return 0;
    }

    // NOTE (): Fonction d'encodage/decodage
    void encryptAndWrite(char *cle, FILE *source, FILE *cible)
    {
         /*declaration variables*/
        char tampon = {0};
        int j = 0, sortie;
         /* fin declaration variables*/


        do
        {
            if (cle[j] == '\0')                                                     //Instruction de RAZ de l'incrementation de la cle
            {
                    j = 0;
            }
            //fread(&tampon, sizeof(char), 1, source);
            tampon = fgetc(source);                                                 //On lit ...
            sortie = tampon ^ cle[j];                                               //On XOR ...
            fwrite(&sortie, sizeof(char), 1, cible);                                //Et on ecrit
        } while (tampon != EOF);

    }

    /* NOTE (): fonction pour enlever le enter des entrées utilisateurs */
    void clean(char *sale)
    {
        if (sale[strlen(sale) - 1] == '\n')
        {
            sale[strlen(sale) - 1] = '\0';
        }
    }


    C'est un programme de crytptage realisé suite a la lecture du tuto de Geo.669. En essayant de l'ameliorer au fur et à mesure, j'ai essayé de diversifié les modes de captures du fichier source : soit on entre le nom à l'invite (si les arguments du main n'en precise pas), soit le nom est passé en argument dans une ligne de commande, soit, pour finir, le fichier est dropé directement sur l'icone de la console.

    c'est sur dernier point que le probleme reside, quand je fais glisser le fichier à encoder sur l'icone de mon programme, ce dernier arrive bien a extraire le nom du fichier source à partir du chemin absolu passé a la fonction main (printf de la ligne 48) mais le fichier ne s'ouvre pas en lecture. Si quelqu'un a une idée du probleme j'accepte volontiers un coup de main. =)

    De plus, existe-t-il un moyen de debugger le programme quand je veux cliquer-deplacer un fichier sur le programme de console ? j'entends demarrer gdb en passant des parametres au fichier à lancer.


    Toute critique quant a la disposition, mise en forme ou sur le codage en generale sera bienvenue aussi. =)

    merci par avance.
    • Partager sur Facebook
    • Partager sur Twitter
      23 janvier 2007 à 20:27:14

      Pour la réponse à ta question, lorsque tu fais un drag and drop sur l'icône tu récupères le chemin absolu, et ta fonction de traitement enlève le chemin, donc l'ouverture échoue parce que ton programme ne trouve pas le fichier source.

      Pour répondre à la question subsidiaire, oui c'est possible, mais je ne suis pas sûr que gdb puisse le faire. La technique est un peu barbare mais elle marche très bien à condition que le debugger soit capable de reprendre la main, s'il n'en est pas capable le programme est fermé immédiatement sans autre forme de procès. L'astuce consiste à forcer un breakpoint par programme, pour cela il suffit de placer un appel à l'interruption 3 à l'endroit où veut que le debugger prenne la main. par exemple dans ton programme :


      /*Encodeur V2*/

      /* TODO (): Trouver un moyen d'avoir le chemin relatif du fichier a encrypter ! */
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>

      void encryptAndWrite(char *cle, FILE *source, FILE *cible);
      void clean(char *sale);

      int main(int argc, char *argv[])
      {
          /*declaration variables*/
          char nomCible[100] = " ", nomSource[100], cle[50], tampon[100];
          FILE *source = NULL, *cible = NULL;
          int i, j = 0;
          /* fin declaration variables*/

      /****************************************************************
      *                 ATTENTION BREAKPOINT HARD                     *
      *        A SUPPRIMER DES QUE LE PROBLEME EST CORRIGE            *
      *****************************************************************/

          __asm int 3
      /****************************************************************/

          if (argc <= 1)
          {
              printf("Entrez le nom du fichier source : ");                           //soit le fichier source est specifié a l'execution ...
              fgets(nomSource, sizeof(nomSource), stdin);
              clean(nomSource);
          }
          else                                                                        //soit le programme a des parametres
          {
              strcpy(tampon, argv[1]);                                                //on copie le chemin absolu
              if (strrchr(tampon, '\\') == NULL)                                      //si le fichier est passe en parametre
              {
                      strcpy(nomSource, tampon);                                      //on store directement le nom passé
              }
              else                                                                    //si le fichier est dropé (chemin absolu)
              {
                  i = tampon - strrchr(tampon, '\\');                                 //on assigne i a la position du dernier \ trouvé
                  if (i < 0)
                  {
                      i = -i;                                                         //on s'assure que i soit positif
                  }
          /* FIXME (): Ne prend pas les fichiers dropés !! */
                  do
                  {
                      nomSource[j] = tampon[i + 1];                                   //et on fait une boucle pour enlever le \ et avoir le nom du fichier
                      i++;
                      j++;
                  } while(tampon[i] != '\0');
              }
              clean(nomSource);
              printf("Fichier source : %s (taille du nom : %d)\n", nomSource, strlen(nomSource));
          }

              printf( "\nEntrez le nom a donner au fichier encrypte (si aucun choix"
                  " le nouveau fichier se nommera : ancien-fichier.enc) : ");
              fgets(nomCible, sizeof(nomCible), stdin);                               //On demande le fichier destination
          if (nomCible[0] == '\n')
          {
      /* TODO (): Trouver un moyen de gerer l'extension pour pas avoir .enc.enc.enc */
              strcpy(nomCible, nomSource);
              strcat(nomCible, ".enc");
              printf("%s", nomCible);
          }
          clean(nomCible);

              printf("\nVeuillez saisir la cle qui servira a encrypter vos fichiers (limite a 50 caractere !) : ");
          fgets(cle, sizeof(cle), stdin);                                             //On store la cle ...
          clean(cle);                                                                 //Et on vire le \n en ajoutant le \0

          source = fopen(nomSource, "rb");
          cible = fopen(nomCible, "wb");

          if (source == NULL)
          {
              printf("Erreur ouverture fichier source.\nLe programme va s'interrompre.\n");
              system("pause");
              exit (1);
          }

          if (cible == NULL)
          {
              printf("Erreur ouverture fichier cible.\nLe programme va s'interrompre.\n");
              system("pause");
              exit (1);
          }

              encryptAndWrite(cle, source, cible);
              fclose(source);
              fclose(cible);
              system("pause");
              return 0;
      }

      // NOTE (): Fonction d'encodage/decodage
      void encryptAndWrite(char *cle, FILE *source, FILE *cible)
      {
           /*declaration variables*/
          char tampon = {0};
          int j = 0, sortie;
           /* fin declaration variables*/


          do
          {
              if (cle[j] == '\0')                                                     //Instruction de RAZ de l'incrementation de la cle
              {
                      j = 0;
              }
              //fread(&tampon, sizeof(char), 1, source);
              tampon = fgetc(source);                                                 //On lit ...
              sortie = tampon ^ cle[j];                                               //On XOR ...
              fwrite(&sortie, sizeof(char), 1, cible);                                //Et on ecrit
          } while (tampon != EOF);

      }

      /* NOTE (): fonction pour enlever le enter des entrées utilisateurs */
      void clean(char *sale)
      {
          if (sale[strlen(sale) - 1] == '\n')
          {
              sale[strlen(sale) - 1] = '\0';
          }
      }


      Attention c'est un breakpoint hard codé, if fait partie du code du programme. Il le fera planter s'il n'y a pas de debugger pour reprendre la main, c'est donc à utiliser uniquement quand on ne peut pas faire autrement. Ne le laissez jamais plus longtemps que nécessaire et signalez le avec un gros commentaire bien visible.
      • Partager sur Facebook
      • Partager sur Twitter
      Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
      Anonyme
        23 janvier 2007 à 20:42:50

        Citation : int21h

        Pour la réponse à ta question, lorsque tu fais un drag and drop sur l'icône tu récupères le chemin absolu, et ta fonction de traitement enlève le chemin, donc l'ouverture échoue parce que ton programme ne trouve pas le fichier source.



        Bonsoir int21h,

        merci pour la piste du chemin, je pensais qu'en dropant le fichier sur l'icone j'aurai l'equivalent du parametre passé en console (absolu au lieu de relatif) et etant donné que le fichier se situé dans le meme repertoire que le programme (pour tester) cela ne poserait pas de probleme.

        donc a ce moment la, il faudrait que je récupère le chemin absolu, ensuite créer une fonction pour doubler tous les \ du chemin (pour que le fopen comprenne le chemin) et ensuite injecter le tout dans une variable que je passerai à mon fopen. suis-je sur la bonne piste ? =)

        ps merci pour le tips du breakpoint en hard, ca pourra me servir. =)
        • Partager sur Facebook
        • Partager sur Twitter
          23 janvier 2007 à 21:13:36

          Non il ne faut pas les doubler dans les chaines de chemin que tu vas récupérer. Le caractère \ est utilisé pour indiquer un caractère spécial comme par exemple le '\n' qui indique un saut de ligne. Ici le '\n' ne représente qu'un seul caractère qui est le retour à la ligne. Dans la mémoire '\n' est remplacé par sa valeur réelle qui n'est pas affichable. Pour dire au compilateur de mettre un \ dans une chaine on utilise le caractère spécial '\\' dont la valeur réelle est '\'. La chemin que tu reçois est correct, tu n'as pas besoin de le modifier.
          • Partager sur Facebook
          • Partager sur Twitter
          Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
            23 janvier 2007 à 21:39:31

            Citation : SirJulio

            Toute critique quant a la disposition, mise en forme ou sur le codage en generale sera bienvenue aussi.


            D'entrée, 2 bons points :
            - Présentation du code correcte
            - Compilation sans warnings chez moi.

            Mon analyse partielle... Je dois me coucher...
            /*Encodeur V2*/

            /* TODO (): Trouver un moyen d'avoir le chemin relatif du fichier a encrypter ! */
            #include <stdio.h>
            #include <stdlib.h>
            #include <string.h>

            /* -ed-
            void encryptAndWrite(char *cle, FILE *source, FILE *cible);
            void clean(char *sale);

            inutile de separer les prototypes ici.
            Il suffit de definir avant d'utiliser :
            */


            // NOTE (): Fonction d'encodage/decodage
            static void encryptAndWrite (char *cle, FILE * source, FILE * cible)
            {
               /*declaration variables */
               char tampon = { 0 };
               int j = 0, sortie;
               /* fin declaration variables */

               do
               {
                  if (cle[j] == '\0')       //Instruction de RAZ de l'incrementation de la cle
                  {
                     j = 0;
                  }
                  //fread(&tampon, sizeof(char), 1, source);
                  tampon = fgetc (source)//On lit ...
                  sortie = tampon ^ cle[j]; //On XOR ...
                  fwrite (&sortie, sizeof (char), 1, cible); //Et on ecrit
               }
               while (tampon != EOF);

            }

            /* NOTE (): fonction pour enlever le enter des entrées utilisateurs */
            static void clean (char *sale)
            {
            /* -ed-
                if (sale[strlen(sale) - 1] == '\n')
                {
                    sale[strlen(sale) - 1] = '\0';
                }

            Tu appelles 2 fois strlen(), c'est une fois de trop.
            Il manque la purge du flux si le '\n'est pas present...
            */

               /* search */
               char *p = strchr (sale, '\n');
               if (p != NULL)
               {
                  /* kill */
                  *p = 0;
               }
               else
               {
                  /* purge */
                  int c;
                  while ((c = getchar ()) != '\n' && c != EOF)
                  {
                  }
               }
            }

            int main (int argc, char *argv[])
            {
               /*declaration variables */
               char nomCible[100] = " ", nomSource[100], cle[50] /*, tampon[100] */ ;
               /* fin declaration variables */

               if (argc < 1)
               {
                  //soit le fichier source est specifié a l'execution ...
                  printf ("Entrez le nom du fichier source : ");
                  /* -ed- pour assurer l'affichage... */
                  fflush (stdout);
                  fgets (nomSource, sizeof (nomSource), stdin);
                  clean (nomSource);
               }
               else                         //soit le programme a des parametres
               {
                  /* -ed-
                     strcpy (tampon, argv[1]); //on copie le chemin absolu

                     il vaut mieux faire une copie dynamique avec strdup()
                     (POSIX.1, donc tres portable).
                   */


                  char *tampon = strdup (argv[1]);
                  if (tampon != NULL)
                  {
            #if 0
                     /* -ed- eviter de multiplier les appels aux fonctions.
                        C'est couteux. en temps si les chaines sont longues.
                      */

                     if (strrchr (tampon, '\\') == NULL) //si le fichier est passe en parametre
                     {
                        strcpy (nomSource, tampon); //on store directement le nom passé
                     }
                     else                   //si le fichier est dropé (chemin absolu)
                     {
                        i = tampon - strrchr (tampon, '\\'); //on assigne i a la position du dernier \ trouvé
                        if (i < 0)
                        {
                           i = -i;          //on s'assure que i soit positif
                        }
                        /* FIXME (): Ne prend pas les fichiers dropés !! */
                        do
                        {
                           nomSource[j] = tampon[i + 1]; //et on fait une boucle pour enlever le \ et avoir le nom du fichier
                           i++;
                           j++;
                        }
                        while (tampon[i] != '\0');
                     }
            #else
                     char *p = strrchr (tampon, '\\');
                     if (p == NULL)         //si le fichier est passe en parametre
                     {
                        strcpy (nomSource, tampon); //on store directement le nom passé
                     }
                     else                   //si le fichier est dropé (chemin absolu)
                     {
                        int i = (int) (tampon - p); //on assigne i a la position du dernier \ trouvé
                        int j = 0;
                        if (i < 0)
                        {
                           i = -i;          //on s'assure que i soit positif
                        }
                        /* FIXME (): Ne prend pas les fichiers dropés !! */
                        do
                        {
                           nomSource[j] = tampon[i + 1]; //et on fait une boucle pour enlever le \ et avoir le nom du fichier
                           i++;
                           j++;
                        }
                        while (tampon[i] != '\0');
                     }
            #endif

                     clean (nomSource);
                     printf ("Fichier source : %s (taille du nom : %d)\n", nomSource,
                             strlen (nomSource));

                     free (tampon), tampon = NULL;
                  }
               }

               printf ("\nEntrez le nom a donner au fichier encrypte (si aucun choix"
                       " le nouveau fichier se nommera : ancien-fichier.enc) : ");
               fgets (nomCible, sizeof (nomCible), stdin); //On demande le fichier destination
               if (nomCible[0] == '\n')
               {
            /* TODO (): Trouver un moyen de gerer l'extension pour pas avoir .enc.enc.enc */
                  strcpy (nomCible, nomSource);
                  strcat (nomCible, ".enc");
                  printf ("%s", nomCible);
               }
               clean (nomCible);

               printf
                  ("\nVeuillez saisir la cle qui servira a encrypter vos fichiers (limite a 50 caractere !) : ");
               fgets (cle, sizeof (cle), stdin); //On store la cle ...
               clean (cle);                 //Et on vire le \n en ajoutant le \0
               {
                  FILE *source = fopen (nomSource, "rb");

                  if (source != NULL)
                  {
                     FILE *cible = fopen (nomCible, "wb");
                     if (cible != NULL)
                     {
                        encryptAndWrite (cle, source, cible);
                        fclose (source);
                     }
                     else
                     {
                        printf
                           ("Erreur ouverture fichier cible.\nLe programme va s'interrompre.\n");
                     }
                     fclose (cible);
                  }
                  else
                  {
                     printf
                        ("Erreur ouverture fichier source.\nLe programme va s'interrompre.\n");
                  }
               }
               return 0;
            }


            • Partager sur Facebook
            • Partager sur Twitter
            Music only !
            Anonyme
              23 janvier 2007 à 23:42:02

              Citation : -ed-

              Citation : SirJulio

              Toute critique quant a la disposition, mise en forme ou sur le codage en generale sera bienvenue aussi.


              D'entrée, 2 bons points :
              - Présentation du code correcte
              - Compilation sans warnings chez moi.

              analyse en cours ...





              Oui au tout debut, je codais a la goret (cf ton site :), qui m'a ete fort utile au passage), l'objectif etant que ca compile et au diable les warnings. Mais a l'usage j'essaie de faire les choses proprement ce qui m'aide enormement au moment du debug pour isoler les erreurs.


              Citation : int21h

              Non il ne faut pas les doubler dans les chaines de chemin que tu vas récupérer. Le caractère \ est utilisé pour indiquer un caractère spécial comme par exemple le '\n' qui indique un saut de ligne. Ici le '\n' ne représente qu'un seul caractère qui est le retour à la ligne. Dans la mémoire '\n' est remplacé par sa valeur réelle qui n'est pas affichable. Pour dire au compilateur de mettre un \ dans une chaine on utilise le caractère spécial '\\' dont la valeur réelle est '\'. La chemin que tu reçois est correct, tu n'as pas besoin de le modifier.



              D'accord je pense avoir compris. En fait si j'entre moi meme le chemin dans les sources du programme dans une chaine je serai obligé de doubler les \ pour faire comprendre au programme que je veux des \ mais si le programme le recupere de lui meme alors la chaine stockée (et in fine restituée) sera correcte.

              • Partager sur Facebook
              • Partager sur Twitter
                24 janvier 2007 à 0:11:13

                C'est ça :)
                • Partager sur Facebook
                • Partager sur Twitter
                Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
                  24 janvier 2007 à 0:17:41

                  Citation : int21h

                  L'astuce consiste à forcer un breakpoint par programme, pour cela il suffit de placer un appel à l'interruption 3 à l'endroit où veut que le debugger prenne la main. par exemple dans ton programme :



                  /****************************************************************
                  *                 ATTENTION BREAKPOINT HARD                     *
                  *        A SUPPRIMER DES QUE LE PROBLEME EST CORRIGE            *
                  *****************************************************************/

                      __asm int 3



                  Horriblement pas portable... Ici, quasiment tout le monde utilise MinGW, donc gcc, qui utilise la syntaxe AT&T pour l'assembleur (une horreur). Je pense qu'il ne faut pas trop parler de ça ici, c'est la boite de Pandore...

                  Quand au debug, printf() fait l'affaire dans 95% des cas...
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Music only !
                  Anonyme
                    24 janvier 2007 à 0:49:03

                    Je passe le probleme en resolu car cela ne venait pas de la source et de la recuperation du nom de cette derniere mais tout simplement que lorsque je rentrais le nom de la cible je le faisais en relatif (nom_du_fichier.ext au lieu de c:\blabla\....)

                    je suppose que cela vient du fait que si un est en absolu l'autre doit l'etre aussi car relatif/relatif ca marche, absolu/absolu ca marche mais en melangeant les deux ca plante.
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Probleme argument fonction main

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown