Ü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…]

    – 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

Benutzeravatar von Christian C. Salvadó
Christian C. Salvado

Du könntest benutzen getopt.

 #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

Benutzeravatar von jfs
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.

Benutzeravatar von sastanin
sastanin

Anstatt von getopt()können Sie auch die Verwendung in Betracht ziehen argp_parse() (eine alternative Schnittstelle zu derselben Bibliothek).

Aus libc-Handbuch:

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

Benutzeravatar der Community
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

1393860cookie-checkÜbergeben Sie Argumente von der Befehlszeile an das C-Programm

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy