Vinnaren i pepparkakshustävlingen!
2023-08-11, 10:08
  #1
Medlem
Hej flashback, jag är ganska ny till C och övar en del på språket. Just nu skriver jag en del command line program och då så har jag skrivit ett litet program som skriver ut hur många linjer som är i en textfil. Jag har gjort i programmet att man kan ge argument -p ( p: ) eller -h. -h är såklart "hjälp" eller "usage" som skrivs ut men jag vill undvika att man ska kunna använda båda samtidigt. Jag kan visa källkoden om det behövs, säg bara till om ni vill se.
Citera
2023-08-11, 10:30
  #2
Moderator
vhes avatar
Disclaimer: Jag kan inte C särskilt bra, men jag utgår från att getopt där funkar som de implementationer av getopt jag sett på andra håll. C-varianten är väl trots allt urmodern?

Du kan inte hindra att någon använder multipla "inkompatibla" flaggor. Du får helt enkelt hantera det på bästa sätt. I det här fallet är det gissningsvis så att du vill skriva ut hjälptext och avbryta programmet om användaren anget -h, och helt enkelt strunta i vad användaren anget till -p (vad den nu än betyder).
Citera
2023-08-11, 10:46
  #3
Medlem
Citat:
Ursprungligen postat av vhe
Disclaimer: Jag kan inte C särskilt bra, men jag utgår från att getopt där funkar som de implementationer av getopt jag sett på andra håll. C-varianten är väl trots allt urmodern?

Du kan inte hindra att någon använder multipla "inkompatibla" flaggor. Du får helt enkelt hantera det på bästa sätt. I det här fallet är det gissningsvis så att du vill skriva ut hjälptext och avbryta programmet om användaren anget -h, och helt enkelt strunta i vad användaren anget till -p (vad den nu än betyder).

Jag har testat med några andra program tom t.ex GNU wc och cat. Båda av dom verkar (som jag uppfattar det) kunna stoppa allt annat om jag anger --help
Citera
2023-08-11, 11:02
  #4
Moderator
vhes avatar
Citat:
Ursprungligen postat av gssempsmmw
Jag har testat med några andra program tom t.ex GNU wc och cat. Båda av dom verkar (som jag uppfattar det) kunna stoppa allt annat om jag anger --help

Ja, precis. Är det det du undrar hur man gör?

Du har gissningsvis en switch/case-sats som hanterar dina options i main-metoden? I den case-sats som hanterar -h, skriv ut din hjälptext och gör helt sonika return 0; eller exit(0); så programmet avbryts.

GNU cat använder[0] ett makro[1] för att hantera just -h, gissningsvis för att de vill ha det likadant gjort i alla sina coreutils. De förbereder med en atexit[2] som stänger stdout() däremot. Ingen aning om ifall det är strikt nödvändigt. Jag har mest arbetat med högnivåspråk där sådant löses åt en, men jag har svårt att tro att kärnan inte hanterar öppna filhandtag vid processavslut åt dig.

[0] https://git.savannah.gnu.org/cgit/co...src/cat.c#n632
[1] https://git.savannah.gnu.org/cgit/co.../system.h#n347
[2] https://git.savannah.gnu.org/cgit/co...src/cat.c#n577
Citera
2023-08-11, 11:37
  #5
Medlem
Citat:
Ursprungligen postat av vhe
Ja, precis. Är det det du undrar hur man gör?

Du har gissningsvis en switch/case-sats som hanterar dina options i main-metoden? I den case-sats som hanterar -h, skriv ut din hjälptext och gör helt sonika return 0; eller exit(0); så programmet avbryts.

GNU cat använder[0] ett makro[1] för att hantera just -h, gissningsvis för att de vill ha det likadant gjort i alla sina coreutils. De förbereder med en atexit[2] som stänger stdout() däremot. Ingen aning om ifall det är strikt nödvändigt. Jag har mest arbetat med högnivåspråk där sådant löses åt en, men jag har svårt att tro att kärnan inte hanterar öppna filhandtag vid processavslut åt dig.

[0] https://git.savannah.gnu.org/cgit/co...src/cat.c#n632
[1] https://git.savannah.gnu.org/cgit/co.../system.h#n347
[2] https://git.savannah.gnu.org/cgit/co...src/cat.c#n577

Jag kanske var lite oklar med vad jag menade men ja, jag undrar hur man gör. Jag kan kolla länkarna som du gav mig, tack.
Citera
2023-08-11, 12:29
  #6
Medlem
SvenHelsings avatar
Du får nog visa din kod. Har väldigt svårt att se vad det är som är svårt med det du vill göra. Kom ihåg att formatera inlägget med CODE-taggar.

Eller ja, här har du ungefär hur du kan göra. Kopierade och moddade lite kod jag hittade. Den har horribel gnu-indentering, men det orkar jag inte fixa.
Kod:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

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

  opterr = 0;

  // Loopa igenom alla argument och kolla vilka som är satta
  while ((c = getopt (argc, argv, "abc:")) != -1)
    switch (c)
      {
      case 'h':
        hflag = 1;
        break;
      case 'p':
        pflag = 1;
        break;
      case 'c':
        cvalue = optarg;
        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;
      default:
        abort ();
      }

  if(hflag) { // Om h-flaggan är satt
      print_help_message();
      exit(EXIT_SUCCESS);
  }  
__________________
Senast redigerad av SvenHelsing 2023-08-11 kl. 13:16.
Citera
2023-08-11, 14:12
  #7
Medlem
Kod:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "utils.h"

#define USAGE "Usage: countln [filename] [-p filename]\n"
int main (int argc, char *argv[]) {


size_t lines;
int opt;
int returnval;

while ((opt = getopt(argc, argv, "p:h")) != -1) {
        switch (opt) {
        
	    case 'p':

            returnval = COUNT_LINES_IN_FILE_POSIX(optarg, &lines);
            if (returnval == 1) {
                return EXIT_FAILURE;
            }
            fprintf(stdout, "Number of lines: %ld\n", lines);
	    break;

        case 'h':

            fprintf(stdout, "%s", USAGE);
            return EXIT_SUCCESS;

        break;

        default: 
            fprintf(stderr, "%s", USAGE);
            return EXIT_FAILURE;
        }
}
    
    if (argc == 1) {
        fprintf(stderr, "%s: Please provide a file.\n%s", argv[0], USAGE);
	    return EXIT_FAILURE;
    } 
    
    if (argc == 2) {
        returnval = COUNT_LINES_IN_FILE(argv[1], &lines);
        if (returnval == 1) {
            return EXIT_FAILURE;
        }
        fprintf(stdout, "Number of lines: %ld\n", lines);
    }

return EXIT_SUCCESS;

}

Jag är fortfarande lite ny till detta så allt kanske inte är helt "rätt"
__________________
Senast redigerad av gssempsmmw 2023-08-11 kl. 14:18.
Citera
2023-08-11, 14:36
  #8
Medlem
Citat:
Ursprungligen postat av gssempsmmw
Jag är fortfarande lite ny till detta så allt kanske inte är helt "rätt"

Ofta lägger man enbart parsning av argumenten i loopen med getopt eftersom man vill göra det möjligt att använda mer än en option.
Citera

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Det är enkelt att registrera ett nytt konto

Bli medlem

Logga in

Har du redan ett konto? Logga in här

Logga in