2016-04-08 22 views
2

Bir programcının eski hikayesi, bazı kodları yazarak, beklenenden fazla bir şey yapmayı beklemediklerini, ancak kodun beklenmedik bir şekilde her şeyi ve doğru bir şekilde yaptıklarını yazıyor.Bu scanf() dönüşümü neden çalışıyor?

Bazı C programlama pratiği problemleri üzerinde çalışıyorum ve bir tanesi stdin'i içinde kod satırları olan bir metin dosyasına yönlendirmek, daha sonra scanf() ve printf() ile konsola yazdırmaktı. Yeni satır karakterlerini de yazdırmakla ilgili sıkıntı çekiyordum (çünkü scanf tipik olarak beyaz boşluk karakterleri yiyor) ve baştan başlamanıza karar verdiğimde birden çok koşul ve işaret içeren bir karmaşa karmaşası yazmıştı:

,

scanf("%[a-zA-Z -[\n]]", c); 
printf("%s", c); 

(c metin dosyanın içeriğinin tamamını alabilecek kadar büyük bir karakter tampon olduğu) Ve

işte, bu mükemmel çalıştı.

[\w\W -[\n]] 
[\w\d -[\n]] 
[. -[\n]] 
[.* -[\n]] 
[^\n] 

ama çalıştı olanların hiçbiri: I gibi, bu yüzden (dış destekler arasında) karakter sınıfı varyasyonları oluşturarak anlamaya çalıştı. Hepsi sadece bir karakteri okuyorlardı ya da rastgele bir karakter karmaşası yaratıyorlardı. '[^ \ n]', metin dosyası yeni satır karakterleri içerdiğinden çalışmaz, bu nedenle yalnızca tek bir satır yazdırır.

Hala çözemedim beri

, ben birilerinin bu iki soruların cevaplarını bilemez umuyorum:

  • neden "[a-zA-Z - [\ nn] ] "beklendiği gibi çalışıyor mu?
  • Metin dosyası harfler, sayılar ve simgeler içerir (':', '-', '>', belki başkaları); 'a-z', 'unicode' un '' unicode '' '' 'karakterleridir' ',' a-zA-Z 'de sayıları nasıl içerir?
  • Köşeli parantez içine girebildiğiniz sözdizimi, (tam olarak Python'dan aşina olduğum) regex'e çok benziyor. Bu sorunu çözmeye çalışmak için ne kullanabileceğimi okudum, ancak bu sözdiziminin regex'e göre ne olduğu ile ilgili herhangi bir bilgi bulamadım. Öyleyse nasıl farklı ve farklılar?

Bu muhtemelen scanf için iyi bir kullanım olmadığını biliyorum, ancak bir uygulama probleminden kaynaklandığı için, gerçek dünya sözleşmesinin bu kullanım için geçici olarak göz ardı edilmesi gerekir.

Teşekkürler!

+6

Karakter sınıflandırma formatı * değil * düzenli ifade. Lütfen ör. Daha fazla bilgi için [bu 'scanf' (ve aile) referansı] (http://en.cppreference.com/w/c/io/fscanf). –

+0

Bu biçim dizesinde "boşluk" dan "açık köşeli ayraç" a kadar bir menzil var. – user2357112

+0

C yuvalanmış karakter sınıflarına sahip değil mi? – velocirabbit

cevap

3

Rakamlar alıyorsunuz, çünkü karakter kümenizde "- [" harfiniz var. Bu, boşluktan (32) tüm karakterleri, ASCII (48-57) sayılarını içeren açık ayraç (91) anlamına gelir.

Diğer örnekleriniz de bunu içerir, ancak küçük harfleri (97-122) almanızı sağlayan "a-zA-Z" eksik. '\ W' gibi diziler, dizgenin kendisinde bilinmeyen çıkış dizileri olarak kabul edilir, bu nedenle \w sadece tek bir w olur. . ve * tam anlamıyla alınır. Düzenli ifadelerde olduğu gibi özel bir anlamı yoktur. Eğer (başında veya sonunda hariç) [ içine - eklerseniz

+0

C yuvalanmış karakter sınıflarına sahip değil mi? Bir sebepten dolayı düşündüm. Gerçi bunu kesinlikle açıklardı. – velocirabbit

+0

Sadece test ettim ve '% [- ~ \ n]' de istediğim gibi çalışıyor. – velocirabbit

0

sonra davranış uygulama-tanımlanır.

Bu, derleyici belgelerinizin davranışı tanımlaması gerektiği anlamına gelir, bu nedenle tanımladığınız davranışın ne olduğunu görmek için bu belgelere başvurmanız gerekir; bu, kodunuzun bazılarının neden çalıştığını ve bazılarının neden olmadığını açıklar.

Taşınabilir kod yazmak isterseniz, -'u tire ile eşleştirmek dışında kullanamazsınız.

İlgili konular