8 Haziran 2017 Perşembe

getopt metodu

Giriş
Şu satırı dahil ederiz.
#include <unistd.h>
argp yöntemi, getopt yöntemine göre biraz daha gelişmiş özellikler sunar.

1. Terminoloji
Komut satırında kullanılan seçenekler için bir çok farklı format/yöntem var. Belki önce terminolojiye bakmak lazım

Command Argument : uygulamaya geçilen parametre değer anlamına gelir.
Flag : Bir yeteneği açıp/kapatan bayrak. Uzun (long flag) veya kısa (short flag) hali olabilir
Flag Argument : Yeteneğe geçilen parametre değeri. Açıklaması şöyle
Many flags accept an option called a "flag argument" (not to be confused with a "command argument"). In general a command's parameters can be in any order, but flags that accept options must have the option directly after the flag. That way, the command doesn’t get confused by non-flag arguments.
Argument Almayan Flag ve Argument Alan Flag'in Birlikte Kullanımı
Şu iki yöntem de kullanılabilir. Burada argument almayan flag ve argument alan flag birlikte veya ayrı ayrı yazılıyor. Her iki durumda da argument boşluk ile ayrılmış durumda
tar -x -f archive.tar
tar -xf archive.tar
Argument Alan Flag'in Ayracı
Ayraç olarak boşluksuz, boşluklu (blank), eşittir (=) vs gibi şeyler kullanılabilir. Açıklaması şöyle
A flag and its option can be separated by a space or an equals sign =. Interestingly, short flags (but not long flags) can even skip the space, although many people find it much easier to read with the space or equals sign.
Şöyle yaparız
tar -f archive.tar
tar -f=archive.tar
tar -farchive.tar
Eğer long flag kullanıyorsak bir tane ayraç olması iyidir.  Açıklaması şöyle
Long flags must have a space or equals sign to separate the flag from its option.
Şöyle yaparız
git log --pretty=oneline git log --pretty oneline

2. POSIX Satırı Formatları
Farklı farklı formatlar karşısında POSIX kendi standardını koymuş. Ne kadar uygulandığı tartışmalı tabii :) POSIX utility convention şöyle. getopt() POSIX yöntemini uyguluyor
utility_name[-a][-b][-c option_argument]
    [-d|-e][-f[option_argument]][operand...]
- Eğer option argument mecburi ise boşluk (blank) ile ayrılıyor
- Eğer option argument mecburi değil, isteğe bağlı ise option'a bitişik (boşluksuz) yazılıyor

3. getopt() İçin Seçenek Parametreleri - Option Argument
Açıklaması şöyle
Anything that uses getopt() should accept both -xfoo and -x foo for option -x that takes an argument.

4. Nasıl Kullanırız
GNU ile getopt fonksiyonu kullanılarak komut satırı parse edilebilir. getopt argc, argv ve parse edilmesi istenen seçenekleri alır. Çağrı sonunda global bazı değişkenlere değer atar. Bu global değişkenler

optarg, optind, optopt

isimlerine sahiptirler.

5. Return Type
getopt -1 dönünceye kadar tekrar tekrar çağrılabilir. Döngü içinde şöyle kullanırız.
int c;
opterr = 0;
while ((c = getopt (argc, argv, "abc:")) != -1) {...}
seçenek parse edilemezse '?' karakteri döndürülür.

optsring parametresi - seçenekler 
Açıklaması şöyle
optstring is a string containing the legitimate option characters. If such a character is followed by a colon, the option requires an argument, so getopt() places a pointer to the following text in the same argv-element, or the text of the following argv-element, in optarg. Two colons mean an option takes an optional arg; if there is text in the current argv-element (i.e., in the same word as the option name itself, for example, "-oarg"), then it is returned in optarg, otherwise optarg is set to zero. [...]
1. Seçeneğin sonuda : karakteri yoksa, seçenek flag gibidir. Sadece tanımlı olup olmaması ile ilgileniyoruzdur.

Örnek
Mesela
"nt:"
Seçeneğinde sadece n parametresi olması ile ilgileniyoruzdur. Uygulamayı şöyle çağırabiliriz.
./a.out -t 30
Kodlarken şöyle yaparız.
while ((opt = getopt(argc, argv, "nt:")) != -1) {
  switch (opt) {
  case 'n':
    flags = 1;
    break;
  case 't':
    nsecs = atoi(optarg);
    tfnd = 1;
    break;
  default: /* '?' */
    fprintf(stderr, "Usage: %s [-t nsecs] [-n] name\n",argv[0]);
    exit(EXIT_FAILURE);
  }
}
Örnek
test -a -b -c foo şeklinde çağrılabilen bir uygulamamız olsun.
-a yani sadece bayrak olarak kullanılan bir değerin atanıp atanmadığı getopt sonucuna göre şöyle elde edilir.
switch (c)
{
  case 'a':
    aflag = 1;
    break;
}
2. Seçeneğin sonunda : karakteri varsa, arkasından bir parametre değeri geliyor anlamına gelir.

Örnek
-c parametre şeklinde kullanılan bir seçeneğin değeri optarg ile kontrol elde edilir.
switch (c)
{
  case 'c':
    cvalue = optarg;
    break;
}
3. Eğer seçenek sonunda 2 tane :: karakteri varsa arkasından gelen parametre seçime bağlı anlamına gelir. Şöyle yaparız.
while( (arg = getopt(argc, argv, "p::")) != -1 ){

switch (arg){
  case 'p': 
    if (optarg != NULL)
    {
      char op = *optarg;
      if (op=='c') {...}
    }
    else
    {
      printf("optarg is NULL\n");
      
      }
    }
}
optarg nedir
optarg string olduğu için string metodlarına sokulabilir.
while ((option = getopt(argc, argv,"k:j:c:p:i:o:d:")) != -1) {
  switch (option) {
    case 'i' :
      if(strlen(optarg) < 7 || strlen(optarg) > 21)
      {
        ...
      }
      adres = optarg;
      break;
      ...
    default: print_usage();
      exit (EXIT_FAILURE);
  }
}
optarg ilgili bir soru burada.

optind nedir
Açıklaması şöyle
The variable optind is the index of the next element to be processed in argv.
Elimizde şöyle bir kod olsun
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
  char optStr[] = "ab";
  int c;

  while ((c = getopt(argc, argv, optStr)) != -1) {
    printf("optind: %d\n", optind);
    switch (c) {
      case 'a':
        printf("-a\n"); 
        break;
      case 'b':
        printf("-b\n"); 
        break;
      case '?':
        printf("error\n");
        break;
    }
  }

  return 0;
}
Şöyle yaparız.
./a.out -ab

optind: 1
-a //Birinci seçenek
optind: 2
-b //İkinci seçenek
opterr nedir
Açıklaması şöyle
If getopt() does not recognize an option character, it prints an error message to stderr, stores the character in optopt, and returns '?'. The calling program may prevent the error message by setting opterr to 0.
Eğer hata mesajı gösterilmesin istiyorsak getopt() çağrısından önce şöyle yaparız.
opterr = 0;






Hiç yorum yok:

Yorum Gönder