-1
votes

Inventer un analyseur d'argument simple en c

Je sais que je peux simplement utiliser GetOPT ou une autre bibliothèque pour ce produit, mais je réinvente la roue. Je ne veux pas simplement m'asseoir ici et penser que "Opt opt ​​viens d'analyser automatiquement l'option pour vous".

Voici ce que j'ai créé: P>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct option_properties
{
    char *arglong;
    int tag;
};


int main(int argc, char **argv){

    struct option_properties options[] =
    {
        {"--input",  0},
        {"--output", 1},
        {"NULL", 2}
    };

    int i;
    int flag;
    int k = 1;
    for (; k < argc; k++){ //part 0
        printf("%d\n", k);
        for (i = 0; i < 3; i++){ // part 1
        if (!strcmp(argv[k], options[i].arglong)){ // part 2
                switch (options[i].tag) //part 3
                    {
                    case 0:
                        printf("argument input: %s\n", argv[k+1]);
                        break;
                    case 1:

                        printf("argument output: %s\n", argv[k+1]);
                        break;
                    default:
                        break;

                    }
                break;              
            }
        }       
    }
}

c

4 commentaires

Essayez-vous de réinventer la roue juste pour le plaisir / l'apprentissage ou existe-t-il une fonctionnalité dans GetOpt qui vous manque?


@klutt GetOpt est bon, je veux juste apprendre à créer un analyseur arg. En faisant, je sais ce que ça fait et je peux le modifier pour mes préférences.


Comment savez-vous que cela ne détecte pas une option invalide? Essayez GDB, c'est assez petit code de déboguer et vous pouvez le faire en quelques minutes.


Je ne peux pas voir un printf pour une option non valide!


4 Réponses :


0
votes

Avant votre pour en boucle sur Options , définissez une version Boolean Variabele trouvée sur false . Lorsque vous trouvez une correspondance, définissez-la sur true .

Après la boucle, vérifiez la valeur de trouvé . Si c'est faux Imprimez une sorte de message d'erreur.


2 commentaires

Ne pensez-t-il pas aussi qu'un argument suivi de l'option (ex -input bonjour. Bonjour est l'ARG) est également une option invalide?


@hareamjari Vous devez traiter les arguments d'option à l'intérieur de la boucle, probablement dans votre relevé . Si une option a un argument, vous devez augmenter manuellement k .



1
votes

Voici quelques suggestions:

  • Utilisez Tailleof (Options) / Tiazof (Struct option_properties) au lieu de 3 .
  • en utilisant Tailleof () , vous pouvez faire sans {"null", 2} . .
  • déplacer int k = 1 INTER pour () : pour (int k = 1; k .
  • Je vous conseille vivement d'arrêter d'utiliser des caractères d'onglets pour indenter votre code. Changez vos paramètres d'éditeur sur les insertions d'onglets-4-espaces.

    Pour vérifier si une option est invalide, vous pouvez ajouter un int trouvé = 0 variable que vous définissez sur 1 si ! STRCMP (argv [k ], options [i] .arglong) est vrai. Et vous vérifiez trouvé après le pour (i = 0; i <3; i ++) boucle.


0 commentaires

0
votes

La question devrait plutôt être une option valide. Les personnes venant de Windows ont souvent une attente complètement différente de la façon dont les paramètres ressemblent, par ex. commencer par une barre oblique à la place un moins. Ce qui est valable, c'est donc complètement dépendant complètement et d'être considéré comme une fonctionnalité de convivialité, si vous le résolvez à une manière courante.

Je pense que vous avez déjà dans votre programme le chemin de code des options non valides. C'est le Par défaut: dans votre relevé de commutateur. Mais ce que je n'aime pas sur votre code, c'est que vous utilisez Numéros magiques , que vous avez défini dans struct option_properties . L'inconvénient est que vous devez vous rappeler le mappage entre l'option et un numéro, qui est sujette d'erreur, en particulier avec plus d'options. Vous pouvez améliorer cela en utilisant un Enum au lieu d'avoir des noms significatifs pour votre case .

Mais je considérerais une solution plate encore plus simple. J'ai écrit tel et il itère sur un pointeur de char. Regardez à quel point c'est: xxx


0 commentaires

0
votes

Alors je le résolve moi-même:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct option_properties
{
    char *arglong;
    int tag;
};


int main(int argc, char **argv){

    struct option_properties options[] =
    {
        {"--input",  0},
        {"--output", 1},
        {"NULL", 2}
    };

    enum {

        input = 0,
        output = 1
    };
    printf("%d\n", argc);

    int i;
    int flag;
    int k = 1;
    for (; k < argc; ){
        for (i = 0; i < 3; i++){
            if (!strcmp(argv[k], options[i].arglong)){
                switch (options[i].tag)
                    {
                    case input:
                        printf("argument input: %s\n", argv[k+1]);
                        break;
                    case output:

                        printf("argument output: %s\n", argv[k+1]);
                        break;
                    default:
                        printf("unk %s\n", argv[k]);
                        exit(1);
                    }
                    printf("1\n");
                    k += 2;
                break;  
            }
            else {
                if (i == 2) {
                    printf("Ooooops: %s %d", argv[k], k);
                    exit(1);
                }
            }            

        }       
    }
}


1 commentaires

Vous pouvez améliorer encore ce code en réorganisant l'ENUM et STRT, puis utilisez également les valeurs ENUM Entrée et sortie dans la structure. Cela éliminerait complètement les nombres magiques. De plus, de nombreuses normes de style de codage rédigeraient des valeurs ENUM en majuscules et avec un préfixe, par ex. utilisateurs.ece.cmu.edu/~eno/coding/ccodingStandard. HTML # Endame