instruction de commutation et la fonction getopt () en C
-
28-09-2019 - |
Question
Je suis en train d'analyser les arguments dans la ligne de commande à l'aide switch
et getopt()
. La structure est très simple: j'ai un makefile
, un .c
et un fichier .h
. Ceci est la première fois que je l'aide du commutateur, alors je pourrais faire quelques erreurs de base. Je l'ai utilisé ce lien comme guide pour commutateur
et
Si vous voyez des erreurs de base Veuillez me le faire savoir.
makefile:
make:lunar
lunar: lunar.o
gcc -Wall -std=c99 -g -o lunar lunar.o -lm
lunar.o: lunar.c lunar.h
gcc -Wall -std=c99 -g -c lunar.c
clean:
-rm -f *.o lunar core
/////////////////////////////////////
lunar.c
int main (int argc, char *argv[]){
int i;
int c = 0;
int gravity = 0;
int thrust = 0;
opterr = 0;
while ((c = getopt (argc, argv, "gtf:")) != -1)
switch (c){
case 'g':
gravity = argv[optind];
break;
case 't':
thrust = argv[optind];
break;
case 'f':
argument = argv[optind];
break;
case '?':
if (optopt == 'c')
fprintf(stderr, "Option -%c requires
an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option
`-%c'.\n", optopt);
else
fprintf (stderr, "Unknown option
character `\\x%x'.\n",
optopt);
return 1;
defult:
abort ();
}
printf ("gravity is %d and thrust is %d.\n",
gravity, thrust);
for (int index = optind ; index < argc ; index++ ){
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
}
///////////////////////////////////
lunar.h
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>
#define MAX_WORD 256
La solution
Ne pas oublier que « default
» a « a » en elle -. Vous venez de code avec une étiquette indiquant qu'ils l'étiquette (non utilisée) defult
, plutôt que compte tenu de l'interrupteur d'un cas par défaut
On ne sait pas pourquoi vous pensez que optopt
pourrait être « c » ou doit être traitée spécialement quand il est « c »; il pourrait être une gueule de bois d'une édition antérieure.
Vous traitez le « g » et « t » options que si elles prennent des arguments, mais l'appel à getopt()
ne pas la liste après les deux points. Si l'interrupteur est à croire, vous avez besoin que l'argument soit "g:t:f:"
.
En outre, vous devriez utiliser le char *
appelé optarg
au lieu d'essayer d'utiliser argv[optind]
. Vous utilisez optind
après que la boucle a terminé à traiter des arguments supplémentaires ( "nom de fichier).
En outre, étant donné que gravity
et thrust
sont des nombres entiers, vous devez convertir les chaînes en nombres entiers. La façon facile (en ignorant largement les erreurs possibles) est avec:
gravity = atoi(optarg);
Si vous voulez faire le traitement des erreurs, appelez une fonction pour faire les rapports de vérification et d'erreurs.
Je recommande de mettre des accolades autour de la déclaration de switch
, ou autour du corps de la déclaration de while
:
while ((c = getopt(argc, argv, "g:f:t:")) != -1)
{
switch (c)
{
...
}
}
Il est pas strictement nécessaire, mais il est (IMNSHO) plus facile à lire le code avec les accolades supplémentaires. Pour une seule instruction de ligne, je n'ai aucun problème; mais pour une déclaration complexe comme l'interrupteur, je recommande les accolades supplémentaires.
doit être à l'extérieur "return 0;
la boucle for
. À l'heure actuelle, la boucle arrête le premier argument non-option.
Le makefile est fondamentalement bien. Finalement, vous allez utiliser plusieurs macros et plus de drapeaux d'avertissement de compilation, mais les seuls problèmes que je remarquai que le compilateur est également l'endroit était la faute de frappe dans le cas par défaut et la non-conversion de chaînes en nombres entiers.
PROGRAM = lunar
SOURCE = lunar.c
HEADER = ${SOURCE:.c=.h}
OBJECT = ${SOURCE:.c=.o}
CFLAGS = -std=c99 -Wall -g
LDFLAGS =
LDLIBS = -lm
all: ${PROGRAM}
${PROGRAM}: ${OBJECT}
${CC} ${CFLAGS} -o $@ ${OBJECT} ${LDFLAGS} ${LDLIBS}
${OBJECT}: ${SOURCE} ${HEADER}
${CC} ${CFLAGS} -c ${SOURCE}
clean:
-rm -f *.o ${PROGRAM} core