Menu

C'de Komut Satırı Argümanları: argc, argv ve Güvenli Ayrıştırma

Bir C programının komut satırını nasıl okuduğu - argc ve argv'nin anatomisi, argümanlar üzerinde dolaşma, argv[0]'ın ne tuttuğu, atoi yerine strtol ile sayıya dönüştürme ve hepsini bir araya getiren küçük bir hesap makinesi.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Terminalden çalıştırdığınız her programa argüman verilebilir: gcc -Wall hello.c -o hello dört tane geçirir. Kendi C programlarınız kendilerininkini main üzerindeki iki parametreden okur ve mekanizmanın tamamı budur - kütüphane çağrısı yok, kurulum yok.

İmza

Şimdiye kadar bu belgelerdeki her örnek int main(void) kullandı. Diğer standart biçim komut satırını alır:

int main(int argc, char *argv[]) {
    /* ... */
}
  • argc ("argument count"), program adı dahil kaç argüman olduğudur.
  • argv ("argument vector"), bir metin dizisidir. char *argv[], "char'a göstericilerden oluşan dizi" demektir ki bu bir C metinleri dizisidir.

char **argv da aynı sıklıkta göreceğiniz eşdeğer bir yazımdır; dizi parametreleri göstericiye dönüşür, dolayısıyla ikisi aynı şeyi bildirir.

Argüman vermek için editörün Args panelini kullanın (her alan bir argümandır), sonra Çalıştır'a basın. Üç alan deneyin: merhaba, dunya, 42.

Anatomi

./greet Ada Lovelace çalıştırmak şunu üretir:

İndeksDeğer
argv[0]"./greet"çağrıldığı hâliyle program adı
argv[1]"Ada"ilk gerçek argüman
argv[2]"Lovelace"ikinci gerçek argüman
argv[3]NULLsonlandırıcı
argc3argv[0] dahil sayı

Akılda tutulmaya değer dört olgu:

  • argc pratikte en az 1'dir, çünkü argv[0] program adıdır. Gerçek argümanlar 1. indeksten başlar; onlar üzerindeki döngülerin i = 1'den başlamasının sebebi budur.
  • Her şey bir metindir. ./prog 42 size iki karakterden oluşan "42"'yi verir, asla 42 sayısını değil. Dönüştürmek sizin işiniz.
  • argv[argc], NULL'dur. Standart bunu garanti eder, dolayısıyla isterseniz diziyi argc olmadan dolaşabilirsiniz: for (char **p = argv + 1; *p != NULL; p++).
  • Kelimeleri kabuk böler, programınız değil. ./prog "Ada Lovelace" tek bir argümandır; tırnaklar kabuk tarafından tüketilir ve argv'ye hiç ulaşmaz.

Okumadan Önce Kontrol Etmek

Geçirilmemiş bir argüman boş bir metin değildir - dokunmaya hakkınız olmayan bellektir. Her zaman önce argc'yi doğrulayın:

O minik programda iki gelenek var, ikisi de Unix araçlarında standart:

  • Kullanım mesajı stdout'a değil stderr'e gider, böylece bir yere borulanan çıktıyı kirletmez.
  • main'den sıfırdan farklı bir dönüş, programı çalıştıran her neyse ona başarısızlığı bildirir. 0 başarı demektir; başka her şey bir şeylerin ters gittiğini. Kabuk betikleri bunu kontrol eder.

Sabit yazılmış bir isim yerine argv[0] yazdırmak, program yeniden adlandırılmış ya da farklı bir yoldan erişilmiş olsa bile mesajın kullanıcının programı çağırma biçimiyle eşleşmesi demektir.

Sayısal Argümanları Dönüştürmek

argv[1] metindir. Aritmetik yapmak için onu dönüştürmeniz gerekir ve kullanılacak fonksiyon <stdlib.h>'deki strtol'dür:

10, 20 ve 30 değerlerini üç ayrı Args alanı olarak ekleyin, sonra hata yolunu görmek için birini muz ile değiştirin.

strtol'ün üçüncü parametresi tabandır: ondalık için 10, on altılık için 16 ya da bir 0x veya baştaki sıfır önekinden otomatik algılamak için 0. İkincisi, tüketmediği ilk karaktere giden bir göstericinin nereye saklanacağıdır ve hata denetimini mümkün kılan da budur:

  • end == text, hiçbir şey ayrıştırmadı demektir - argüman bir sayıyla başlamadı.
  • *end != '\0', sayıdan sonra artık metin vardı demektir, dolayısıyla "12abc" sessizce 12 olmak yerine reddedilir.
  • errno == ERANGE, değerin long'u taşırdığı anlamına gelir.

Daha kısa olan ve bunların hiçbirini bildiremeyen atoi ile karşılaştırın:

int n = atoi(argv[1]);   /* "muz" -> 0, "0" -> 0, taşma -> tanımsız */

atoi geçersiz girdi için 0 döndürür ki bu gerçek bir sıfırdan ayırt edilemez. Girdi programınızın dışından geldiğinde strtol (ve kayan nokta için strtod) kullanın. Daha fazlası metin dönüşümü sayfasında.

Küçük Bir Hesap Makinesi

Hepsini bir araya getirelim - bir sayı, bir operatör ve bir sayı alan bir program:

12 + 30, sonra 7 x 6, sonra 5 / 0 deneyin.

op == "+" yerine strcmp(op, "+") == 0 olduğuna dikkat edin. char * değerlerini == ile karşılaştırmak içerikleri değil adresleri karşılaştırır ve aynı metin için bile yanlış olurdu. Bkz. metin fonksiyonları.

* yerine x gerçek hayattan bir ayrıntıdır: çoğu kabuk, programınız daha çalışmadan önce çıplak bir *'ı geçerli dizindeki dosya listesine genişletir. Tırnak içine almak ('*') da işe yarar, ama kabuğun yok saydığı bir karakter seçmek daha dostçadır.

Bayrakları Ayrıştırmak

Seçenekler geleneksel olarak - ile başlar. Basit, elle yazılmış bir döngü yaygın durumları halleder:

Dört Args alanıyla deneyin: -v, -n, 3, merhaba.

argv[++i]'den önceki i + 1 >= argc kontrolü önemli satırdır: değer bekleyen bir seçenek, değerin gerçekten orada olduğunu doğrulamalıdır, yoksa son argüman olarak -n dizinin sonunun ötesini okur. Gerçek Unix sistemlerinde <unistd.h>'deki getopt bunların hepsini sizin için yapar, -vn3 gibi birleştirilmiş kısa seçenekler dahil; bir programın ikiden üçten fazla bayrağı olduğunda ona uzanmaya değer.

Tarayıcı Editöründe Argümanlar

Bu sayfadaki editör blokları sizin için derlenip çalıştırılır ve Args paneli, bir terminalde program adından sonra yazacaklarınızı yazdığınız yerdir. Add arg ile eklediğiniz her alan, tam olarak argv'de tek bir kayıt olur - arada bir kabuk yoktur, dolayısıyla hiçbir şey boşluklardan bölünmez ve tırnak gerekmez: merhaba dunya içeren bir alan, tek bir merhaba dunya argümanı olarak gelir. -n 3 merhaba geçirmek için üç alan ekleyin. Paneli boş bırakmak argc == 1 verir - argc < 2 korumasının ilk çalıştırmada devreye girmesinin ve onu yazmaya değmesinin sebebi budur.

Sık Yapılan Hatalar

  • argc'yi kontrol etmeden argv[1]'i okumak. Hiç argüman geçirilmediğinde tanımsız davranıştır - ve bu alandaki en yaygın çökme.
  • Döngüyü i = 0'dan başlatmak. Bu, program adını veriymiş gibi işler.
  • argv[1]'i sayı olarak görmek. Siz dönüştürene kadar metindir.
  • Kullanıcı girdisinde atoi kullanmak. Kötü bir argümanı sıfırdan ayırt etmenin yolu yoktur.
  • Metinleri == ile karşılaştırmak. strcmp kullanın.
  • argv metinlerinin içine yazmak. Onları değiştirmeye standart izin verir ama alan sınırlı ve platforma bağlıdır; bir şeyi değiştirmeniz gerekiyorsa kendi tamponunuza kopyalayın.

Sıkça Sorulan Sorular

C'de argc ve argv nedir?

Bunlar int main(int argc, char *argv[])'nin iki parametresidir. argc, program adı dahil komut satırı argümanlarının sayısıdır; argv ise bu argümanların metin olarak dizisidir. argv[0] program adıdır, argv[1] ilk gerçek argümandır ve argv[argc] her zaman NULL'dur.

Bir C programına nasıl argüman geçilir?

Terminalde çalıştırılabilir dosyanın adından sonra yazın: ./program merhaba 42. Bu argc == 3 verir; argv[1] "merhaba" metni, argv[2] ise "42" metnidir. Bu sayfadaki editörde argümanlar terminal yerine Args paneline yazılır.

C'de bir komut satırı argümanı int'e nasıl dönüştürülür?

strtol kullanın: char *end; long n = strtol(argv[1], &end, 10); ardından end'in hâlâ başlangıcı göstermediğini (hiçbir şey ayrıştırılmadı) ve *end'in '\0' olduğunu (artık çöp yok) kontrol edin. atoi daha kısadır ama hem "0" hem "muz" için 0 döndürür, dolayısıyla hata bildiremez.

C'de argv[0] nedir?

Programın çağrıldığı isim - genellikle ./program ya da tam yol. Kullanım mesajlarında (fprintf(stderr, "kullanim: %s DOSYA\n", argv[0])) işe yarar, böylece mesaj kullanıcının onu gerçekten nasıl çağırdığıyla eşleşir. Sıra dışı durumlarda boş bir metin olabilir, o yüzden var olduğunu varsaymayın.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA