scanf biçim dizesi - scanf format string
Bir tarama biçimi dizisi ( taranmış ), bir giriş dizesinin düzenini belirtmek için çeşitli işlevlerde kullanılan bir kontrol parametresidir . Fonksiyonlar daha sonra dizeyi bölebilir ve uygun veri türlerinin değerlerine çevrilebilir . Dizi tarama işlevleri genellikle standart kitaplıklarda sağlanır .
Burada kullanılan "scanf" gelen C kütüphanesi işlevi bu tür popüler, ancak bu tür fonksiyonları C öncesine ve diğer adlar gibi, kullanılan readf içinde ALGOL 68 . Biçimlendirilmiş girdi ( ayrıştırma ) sağlayan scanf biçim dizeleri, biçimlendirilmiş çıktı ( şablon oluşturma ) sağlayan printf biçim dizelerinin tamamlayıcısıdır . Bunlar, daha karmaşık ve esnek ayrıştırıcılara veya şablon motorlarına kıyasla basit işlevsellik ve sabit format sağlar, ancak birçok amaç için yeterlidir.
Tarih
Mike Lesk 'ın taşınabilir giriş / çıkış kütüphanesi de dahil olmak üzere scanf , resmen Unix parçası haline geldi Version 7 .
Kullanım
scanf Bulunan fonksiyon, C , sayı ve diğer girdi okur veri türleri ile ilgili standart giriş (genellikle bir komut satırı arayüzü ya da benzer türden bir metin kullanıcı arabirimi ).
Aşağıdaki C kodu , standart giriş akışından değişken sayıda biçimlendirilmemiş ondalık tamsayı okur ve her birini ayrı satırlara yazdırır:
#include <stdio.h>
int main(void)
{
int n;
while (scanf("%d", &n) == 1)
printf("%d\n", n);
return 0;
}
Yukarıdaki program tarafından işlendikten sonra, düzensiz aralıklı tamsayı listesi gibi
456 123 789 456 12
456 1
2378
aşağıdaki gibi sürekli aralıklarla görünecek:
456 123 789 456 12 456 1 2378
Bir kelimeyi yazdırmak için:
#include <stdio.h>
int main(void)
{
char word[20];
if (scanf("%19s", word) == 1)
puts(word);
return 0;
}
Programcının programın okumasını istediği veri türü ne olursa olsun, argümanlar ( &n yukarıdaki gibi) belleğe işaret eden işaretçiler olmalıdır . Aksi takdirde işlev, girdi almaya çalıştığınız değişkenin bellek konumuna işaret etmek yerine belleğin yanlış bölümlerinin üzerine yazmaya çalışacağından doğru şekilde çalışmayacaktır.
Son örnekte, bir adres bir operatör ( & ) olan olmayan değişken için kullanılan: olarak word bir adıdır dizisi arasında char birinci bir işaretçi eşdeğer (bir adrese değerlendirmesini tüm durumlarda) olduğu gibi, dizinin öğesi. İfade &word , anlamsal olarak sayısal olarak aynı değeri değerlendirirken, tamamen farklı bir anlama sahiptir, çünkü dizinin bir öğesi yerine tüm dizinin adresini temsil eder. Dizelere scanf çıktı atarken bu gerçeğin akılda tutulması gerekir .
As scanf yalnızca standart girdi, birçok programlama dilleri okumak için belirlenmiş arayüzleri gibi, PHP gibi türevleri vardır sscanf ve fscanf fakat scanf kendisi.
Dize belirtimlerini biçimlendir
Biçimlendirme tutucuları olarak scanf bu daha fazla ya da daha az aynıdır printf onun ters fonksiyonu. Printf'de olduğu gibi, POSIX uzantısı n$ tanımlanmıştır.
Bir biçim dizesinde nadiren sabitler (yani, yer tutucuları biçimlendirmeyen karakterler ) vardır, bunun başlıca nedeni, bir programın genellikle bilinen verileri okumak için tasarlanmaması, ancak scanf açıkça belirtilirse bunları kabul etmemesidir. Bunun istisnası, girdideki tüm boşluk karakterlerini atan bir veya daha fazla boşluk karakteridir.
En sık kullanılan yer tutuculardan bazıları şunlardır:
-
%a: Onaltılı gösteriminde kayan nokta sayısını tarayın. -
%d: Bir tamsayıyı işaretli ondalık sayı olarak tarayın . -
%i: Bir tamsayıyı işaretli sayı olarak tarayın. Benzer%dfakat yorumladığını olarak numara onaltılık öncesinde0xve sekizlik öncesinde zaman0. Örneğin, dizge031kullanılarak 31%dve kullanılarak 25 okunur%i. İçindeki bayrakh,%hia'ya dönüştürmeyishortvehhbirchar. -
%u: Ondalık için taraunsigned int(C99 standardında giriş değeri eksi işaretinin isteğe bağlı olduğunu unutmayın; bu nedenle, bir eksi işareti okunursa, hiçbir hata ortaya çıkmaz ve sonuç, ikisinin negatif bir sayının tamamlayıcısı , muhtemelen çok büyük bir değer olacaktır. Bakınızstrtoul().) Buna bağlı olarak,%hubirunsigned shortve bir%hhuiçin tararunsigned char. -
%f: Normal ( sabit nokta ) gösterimde bir kayan nokta numarasını tarayın . -
%g,%G: Normal veya üstel gösterimde bir kayan nokta numarasını tarayın.%gküçük harf%Gkullanır ve büyük harf kullanır. -
%x,%X: Bir tamsayıyı işaretsiz onaltılık sayı olarak tarayın . -
%o: Bir tamsayıyı sekizlik sayı olarak tarayın . -
%s: Bir karakter dizisini tarayın . Tarama beyaz boşlukta sona erer . Dizenin sonunda bir boş karakter saklanır, bu da sağlanan tamponun belirtilen girdi uzunluğundan en az bir karakter daha uzun olması gerektiği anlamına gelir. -
%c: Bir karakter (karakter) tarayın. Hiçbir boş karakter eklenir. - boşluk : Herhangi bir boşluk karakteri, sıfır veya daha fazla boşluk karakteri için taramayı tetikler . Boşluk karakterlerinin sayısının ve türünün her iki yönde de eşleşmesi gerekmez.
-
%lf: Çift kayan noktalı sayı olarak tarayın . "Long" tanımlayıcıyla "Float" biçimi. -
%Lf: Uzun çift kayan noktalı sayı olarak tarayın . "Float", "long long" tanımlayıcısını biçimlendirir. -
%n: Hiçbir şey beklenmiyor. Girişten bu kadar uzakta tüketilen karakterlerin sayısı, int'e bir gösterici olması gereken bir sonraki işaretçiye kadar saklanır. Bu bir dönüştürme değildir ve işlevin döndürdüğü sayıyı artırmaz.
Yukarıda sayısal olarak modifiye bileşiğin kullanılabilen l , L "uzun" ve "çok uzun bir" yüzde sembol ve harf arasında standı modifiye. Yüzde sembolü ile harfler arasında, long varsa değiştiricilerden önce taranacak karakter sayısını belirten sayısal değerler de olabilir . Yüzde simgesinden hemen sonra gelen isteğe bağlı bir yıldız işareti ( * ), bu biçim belirleyicisi tarafından okunan verinin bir değişkende saklanmayacağını belirtir. Bu bırakılan değişken için biçim dizesinin arkasındaki hiçbir argüman dahil edilmemelidir.
ff Printf değiştirici giriş ve çıkışı modları arasındaki farkları neden scanf içinde mevcut değildir. ll Ve hh tadil C90 standart mevcut değildir, ancak C99 standart mevcuttur.
Biçim dizesine bir örnek
"%7d%s %c%lf"
Yukarıdaki biçim dizesi ilk yedi karakteri ondalık tamsayı olarak tarar, ardından kalanını bir boşluk, satırsonu veya sekme bulunana kadar bir dize olarak okur, ardından ilk boşluk olmayan karakter bulunana kadar beyaz boşluğu tüketir, sonra bu karakteri tüketir, ve son olarak kalan karakterleri ikili olarak tarar . Bu nedenle, sağlam bir program, scanf aramanın başarılı olup olmadığını kontrol etmeli ve uygun işlemi yapmalıdır . Giriş doğru formatta değilse, hatalı veriler yine de giriş akışında olacaktır ve yeni girişin okunabilmesi için atılması gerekir. Bundan kaçınan alternatif bir yöntem, fgets okunan dizeyi kullanmak ve sonra incelemektir. Son adım, sscanf örneğin, ile yapılabilir .
Çok sayıda float türü karakterin a, e, f, g olması durumunda , birçok uygulama en çok aynı ayrıştırıcıya daraltmayı seçer. Microsoft MSVCRT bunu e, f, g ile yapar , glibc ise dördü ile yapar.
Güvenlik açıkları
scanf biçim dizisi saldırılarına karşı savunmasızdır . Biçimlendirme dizesinin dize ve dizi boyutları için sınırlamalar içerdiğinden emin olmak için büyük özen gösterilmelidir. Çoğu durumda, bir kullanıcıdan gelen girdi dizesi boyutu isteğe bağlıdır ve scanf işlev yürütülmeden önce belirlenemez . Bu, %s uzunluk belirleyicileri olmayan yer tutucuların kullanımının doğası gereği güvenli olmadığı ve arabellek taşmaları için yararlanılamayacağı anlamına gelir . Diğer bir olası sorun, dinamik biçimlendirme dizelerine, örneğin yapılandırma dosyalarında veya diğer kullanıcı kontrollü dosyalarda saklanan biçimlendirme dizelerine izin vermektir. Bu durumda, biçimlendirme dizesi önceden kontrol edilmedikçe ve sınırlamalar uygulanmadıkça, dize boyutlarının izin verilen girdi uzunluğu belirtilemez. Bununla ilgili , gerçek vararg listesiyle eşleşmeyen ek veya uyumsuz biçimlendirme yer tutuculardır . Bu yer tutucular, belirli vararj uygulamasına bağlı olarak yığından kısmen çıkarılabilir veya istenmeyen veya hatta güvensiz işaretçiler içerebilir .
Ayrıca bakınız
Referanslar
Dış bağlantılar
- - Sistem Arayüzleri Referansı, Tek UNIX Spesifikasyonu , Açık Grup'tan Sayı 7
- İçin C ++ başvurusu
std::scanf