Utilizarea getopt în C pentru argumentele liniei de comandă (Programare, C, Depanare, Argumente În Linia De Comandă, Getopt, Getopt Long)

sudobangbang a intrebat.

Lucrez la încercarea de a primi argumente în linia de comandă. Dacă vreau să am mai multe argumente opționale în linia de comandă, cum aș putea face acest lucru? De exemplu, puteți rula programul în următoarele moduri: (a este necesar în fiecare instanță, dar -b -c -d pot fi date opțional și în orice ordine)

./myprogram -a
./myprogram -a -c -d
./myprogram -a -d -b

Știu că al treilea argument al lui getopt() este reprezentat de opțiuni. Pot seta aceste opțiuni să fie „abc” dar modul în care am configurat switch case-ul va face ca bucla să se întrerupă la fiecare opțiune.

Comentarii

  • Poți să arăți cazul tău de comutare? –  > Por IsakBosman.
  • Vă rugăm să afișați bucla dvs. și switch bloc, deoarece bucla dvs. este cea care se termină prematur. În mod normal, bucla verifică doar dacă getopt a returnat -1, atribuind valoarea de întoarcere unei variabile pentru a fi utilizată în switch declarație. – user539810
  • IMO: cel mai bun mod de a prelua argumentele liniei de comandă este să folosiți make use of argc pentru a prelua numărul total de argumente și să folosiți *argv[] pentru a prelua argumentele. Unde argc este numărul de elemente din argv și argv[0] este numărul programului, iar argv[argc] va fi un pointer nul care indică sfârșitul listei de argumente din linia de comandă –  > Por user3629249.
1 răspunsuri
Cloud

Ordinea nu contează în măsura în care getopt() este în cauză. Tot ceea ce contează este al treilea argument al dvs. getopt() (adică: este șirul de format) este corect:

Următoarele șiruri de formate sunt toate echivalente:

"c:ba"
"c:ab"
"ac:b"
"abc:"

În cazul dvs. particular, șirul de format trebuie doar să fie ceva de genul "abcd", iar switch() este completată în mod corespunzător.

Următorul exemplu minim¹ vă va ajuta.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main (int argc, char **argv)
{
  int aflag = 0;
  int bflag = 0;
  char *cvalue = NULL;
  int index;
  int c;

  opterr = 0;

  while ((c = getopt (argc, argv, "abc:")) != -1)
  {
    switch (c)
      {
      case 'a':
        aflag = 1;
        break;
      case 'b':
        bflag = 1;
        break;
      case 'c':
        cvalue = optarg;
        break;
      case '?':
        if (optopt == 'c')
          fprintf (stderr, "Option -%c requires an argument.
", optopt);
        else if (isprint (optopt))
          fprintf (stderr, "Unknown option `-%c'.
", optopt);
        else
          fprintf (stderr,
                   "Unknown option character `\x%x'.
",
                   optopt);
        return 1;
      default:
        abort ();
      }
  }

  printf ("aflag = %d, bflag = %d, cvalue = %s
",
          aflag, bflag, cvalue);

  for (index = optind; index < argc; index++)
    printf ("Non-option argument %s
", argv[index]);
  return 0;
}

¹Exemplu preluat din manualul GNU

Comentarii

  • Eu nu aș scrie while bucla fără paranteze în jurul corpului său, chiar dacă nu ar fi trebuit să scriu bucla switch este, din punct de vedere logic, o singură instrucțiune. Totuși, acesta este un aspect de detaliu și, într-o anumită măsură, o preferință. În rest, codul este destul de bun. Atenția ta la detalii în raportarea opțiunilor necunoscute este impresionantă! (În mod normal, nu sunt atât de atent. De asemenea, în mod normal las getopt() să raporteze eroarea – nu setez opterr = 0;.) Este o idee bună să raportați utilizarea preconizată: fprintf(stderr, "Usage: %s [-ab][-c name] [file ...]
    ", argv[0]);
    atunci când este detectată eroarea. –  > Por Jonathan Leffler.
  • Îmi pare rău, sunt nou în C, care este scopul variabilei aflag bflag etc.?  > Por sudobangbang.
  • De asemenea, presupun că nu înțeleg cum se poate gestiona mai multe stegulețe dacă există o întrerupere? De exemplu, dacă chem -a -b -c, nu va atinge -a și apoi va întrerupe bucla înainte de a atinge instrucțiunile de caz ale lui b și c? –  > Por sudobangbang.
  • @ sudobangbangbang break va ieși doar dintr-un singur nivel/profunditate a unei bucle sau a unei instrucțiuni switch. Instrucțiunile break din exemplul de mai sus vor ieși din switch dar nu și din declarația while bucla care o cuprinde. –  > Por Cloud.