Übergeben Sie Argumente von der Befehlszeile an das C-Programm
Lesezeit: 6 Minuten
Ich bin also in Linux und möchte, dass ein Programm Argumente akzeptiert, wenn Sie es von der Befehlszeile aus ausführen.
Zum Beispiel,
./myprogram 42 -b -s
Dann würde das Programm diese Zahl 42 als int speichern und bestimmte Teile des Codes ausführen, je nachdem, welche Argumente es erhält, wie -b oder -s.
Das kanonische Format für eine Befehlszeile übergibt Optionsargumente wie „-b“ und „-s“ vor allen Nicht-Optionsargumenten wie „42“. Das standardmäßige, orthodoxe Befehlszeilenformat wäre also “./myprogram -b -s 42”. Vermeiden Sie es, von diesem Standard abzuweichen. […more in next comment…]
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int
main (int argc, char **argv)
{
int bflag = 0;
int sflag = 0;
int index;
int c;
opterr = 0;
while ((c = getopt (argc, argv, "bs")) != -1)
switch (c)
{
case 'b':
bflag = 1;
break;
case 's':
sflag = 1;
break;
case '?':
if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
return 1;
default:
abort ();
}
printf ("bflag = %d, sflag = %d\n", bflag, sflag);
for (index = optind; index < argc; index++)
printf ("Non-option argument %s\n", argv[index]);
return 0;
}
Sollte er/sie nicht zuerst „Hauptargumente vorübergehen“ verstehen? 😉
– Oscar Ryz
31. Januar 2009 um 5:42 Uhr
Es funktioniert unter Linux, weil die Funktion getopt() GNU getopt() ist und Sie normalerweise POSIXLY_CORRECT nicht in der Umgebung festlegen, und GNU getopt() dann Optionsargumente vor ‘Datei’-Argumenten verarbeitet, selbst wenn sie einem Dateiargument folgen wie im Beispiel. Auf POSIX-Plattformen funktioniert es nicht….
– Jonathan Leffler
31. Januar 2009 um 6:02 Uhr
….weil die 42 verhindert, dass die Optionen -b und -s als Optionen interpretiert werden. Natürlich ist auch das Design der Kommandozeile schlecht. Ich werde das in den Kommentaren zur Frage vermerken.
– Jonathan Leffler
31. Januar 2009 um 6:03 Uhr
@Jonathan: Die Frage hat das Tag linux. Deshalb GNU getopt() Beispiel ist hier angebracht.
– jfs
31. Januar 2009 um 6:27 Uhr
@JF Sebastian – ja, es hat ein Linux-Tag; Deshalb gibt es eine positive Bewertung von mir. Die Struktur einer Befehlszeile und die Reihenfolge der Argumente sollte sich nicht auf diese Eigenart verlassen; Nun, ich muss immer noch auf anderen Plattformen arbeiten, und GNU getopt ist auf anderen Plattformen nicht Standard (bei allem, was verfügbar ist).
– Jonathan Leffler
31. Januar 2009 um 15:25 Uhr
In C geschieht dies mit Argumenten, die an Ihr übergeben werden main() Funktion:
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
Weitere Informationen finden Sie online wie folgt Argumente zu main Artikel.
Entschuldigung – das ist keine schrecklich gute X-Referenz. Es gibt einen Fehler in der Aussage, dass „die Deklaration des Arguments argv oft die erste Begegnung eines unerfahrenen Programmierers mit Zeigern auf Arrays von Zeigern ist und sich als einschüchternd erweisen kann“ (argv ist ein Array von Zeigern, kein Zeiger auf ein Array von Zeigern).
– Jonathan Leffler
31. Januar 2009 um 6:18 Uhr
Außerdem zeigt die nächste Seite einen Ad-hoc-Optionsparser, anstatt die standardmäßigen getopt()- oder getopt_long()-Parser zu verwenden – was einfach ein schlechter Rat ist. Nein – es ist keine gute Referenz.
– Jonathan Leffler
31. Januar 2009 um 6:19 Uhr
In C ist eine Referenz auf ein Array eine Adresse, genau wie ein Zeiger eine Adresse ist. Daher kann argv sowohl als “ein Array” als auch als “ein Zeiger auf ein Array” bezeichnet werden. Dies ist eine der schönen Einfachheiten von C sowie einer der Punkte, an denen Verwirrungen auftreten.
– Shannon Nelson
31. Januar 2009 um 22:21 Uhr
jfs
Erwägen Sie die Verwendung getopt_long(). Es erlaubt sowohl kurze als auch lange Optionen in beliebiger Kombination.
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by `--verbose'. */
static int verbose_flag;
int
main (int argc, char *argv[])
{
while (1)
{
static struct option long_options[] =
{
/* This option set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
/* These options don't set a flag.
We distinguish them by their indices. */
{"blip", no_argument, 0, 'b'},
{"slip", no_argument, 0, 's'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
int c = getopt_long (argc, argv, "bs",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'b':
puts ("option -b\n");
break;
case 's':
puts ("option -s\n");
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
return 0;
}
Verwandt:
Welchen Befehlszeilenbefehlsstil bevorzugen Sie?
Was ist die allgemeine Syntax eines Unix-Shell-Befehls?
Werfen Sie einen Blick in die getopt-Bibliothek; Es ist so ziemlich der Goldstandard für diese Art von Dingen.
sastanin
Anstatt von getopt()können Sie auch die Verwendung in Betracht ziehen argp_parse() (eine alternative Schnittstelle zu derselben Bibliothek).
getopt ist mehr Standard (die Version nur mit kurzen Optionen ist Teil des POSIX-Standards), verwendet aber argp_parse ist oft einfacher, sowohl für sehr einfache als auch für sehr komplexe Optionsstrukturen, weil es Ihnen mehr Drecksarbeit abnimmt.
Aber ich war immer zufrieden mit dem Standard getopt.
NB GNU getopt mit getopt_long ist GNU LGPL.
“getopt is GNU LGPL”: Das hängt vom getopt ab. Es wurde mehrfach umgesetzt. Die in Mac OS X ist BSD-lizenziert.
– dmckee — Ex-Moderator-Kätzchen
31. Januar 2009 um 15:16 Uhr
Und AT&T veröffentlichte Mitte der 80er Jahre eines in der Public Domain oder etwas, das der Public Domain sehr nahe kommt. D McKees Argument ist sehr gültig – GNU getopt() [and getopt_long()] sind LGPL (oder ältere Versionen sind GPL); nicht alle Versionen von getopt() sind GPL oder LGPL.
– Jonathan Leffler
31. Januar 2009 um 15:32 Uhr
Gemeinschaft
Andere haben diesen auf den Kopf getroffen:
die Standardargumente zu main(int argc, char **argv) geben Ihnen direkten Zugriff auf die Befehlszeile (nachdem sie von der Shell entstellt und tokenisiert wurde)
Es gibt sehr standardmäßige Möglichkeiten, die Befehlszeile zu analysieren: getopt() und getopt_long()
aber wie Sie gesehen haben, ist der Code zu ihrer Verwendung etwas wortreich und ziemlich idomatisch. Ich verdränge es im Allgemeinen mit etwas wie:
typedef
struct options_struct {
int some_flag;
int other_flage;
char *use_file;
} opt_t;
/* Parses the command line and fills the options structure,
* returns non-zero on error */
int parse_options(opt_t *opts, int argc, char **argv);
Dann das Wichtigste zuerst:
int main(int argc, char **argv){
opt_t opts;
if (parse_options(&opts,argc,argv)){
...
}
...
}
Oder Sie könnten eine der in Argument-Parsing-Hilfsprogramme für C/UNIX vorgeschlagenen Lösungen verwenden.
“getopt is GNU LGPL”: Das hängt vom getopt ab. Es wurde mehrfach umgesetzt. Die in Mac OS X ist BSD-lizenziert.
– dmckee — Ex-Moderator-Kätzchen
31. Januar 2009 um 15:16 Uhr
Und AT&T veröffentlichte Mitte der 80er Jahre eines in der Public Domain oder etwas, das der Public Domain sehr nahe kommt. D McKees Argument ist sehr gültig – GNU getopt() [and getopt_long()] sind LGPL (oder ältere Versionen sind GPL); nicht alle Versionen von getopt() sind GPL oder LGPL.
– Jonathan Leffler
31. Januar 2009 um 15:32 Uhr
13938600cookie-checkÜbergeben Sie Argumente von der Befehlszeile an das C-Programmyes
Das kanonische Format für eine Befehlszeile übergibt Optionsargumente wie „-b“ und „-s“ vor allen Nicht-Optionsargumenten wie „42“. Das standardmäßige, orthodoxe Befehlszeilenformat wäre also “./myprogram -b -s 42”. Vermeiden Sie es, von diesem Standard abzuweichen. […more in next comment…]
– Jonathan Leffler
31. Januar 2009 um 6:06 Uhr
Siehe Abschnitt 12 (Hilfskonventionen) der Basisdefinitionen des POSIX-Standards unter opengroup.org/onlinepubs/009695399/toc.htm.
– Jonathan Leffler
31. Januar 2009 um 6:07 Uhr
@Jonathan Leffler: Die Reihenfolge spielt keine Rolle.
getopt_long
Funktion macht unabhängig von der Reihenfolge das Richtige. Siehe meine Antwort.– jfs
31. Januar 2009 um 6:16 Uhr