2011-07-27 15 views
13

Temel olarak stdin'in giriş yapıp yapmadığını test etmek istiyorum (örneğin, eğer yankı ve boru gibi). Çalışan çözümler buldum ama çirkinler ve çözümlerin temiz olmasını seviyorum. linux üzerindestdin C++ (windows ve/veya linux) için giriş yapıp yapmadığını test edin

Bunu kullanın:

bool StdinOpen() { 
    FILE* handle = popen("test -p /dev/stdin", "r"); 
    return pclose(handle) == 0; 
} 

ben daha fazla hata işleme eklemek gerektiğini biliyorum, ama bu noktada dışında bulunuyor. Pencerelerde

Bunu kullanın: linux için iyi, ama ben bir boru kullanmadan çağırabilir eşdeğer API'leri (test -f $file için gibi fopen($file, "r") != NULL yapın) ne olduğunu bilmek istiyorum

bool StdinOpen() { 
    static HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); 
    DWORD bytes_left; 
    PeekNamedPipe(handle, NULL, 0, NULL, &bytes_left, NULL); 
    return bytes_left; 
} 

. Ben open("/dev/stdin", "r") yapabildiğim ve aynı şeyi yapabildiğim bir mürekkebim var ama bunu yapmanın en iyi yolunu bilmek istiyorum.

Özet: Eğer pencereler için daha iyi bir çözüm biliyorsanız, ben linux için test -p /dev/stdin için yerine kullanabilirsiniz API'leri bilmek istiyorum, ve.

+0

Standart girdi bir dosya tanıtıcısıysa (bir borudan ziyade) 'PeekNamedPipe' çözümünüz başarısız olur. Ayrıca, 'handle' değişkeniniz statik olmamalıdır. Uygulamanız çalışırken tanıtıcı yönlendirilirse, daha sonra kendinizi şaşırtacaksınız. –

+0

@Billy: Bir tanıtıcının rasgele yeniden yönlendirilebileceğini sanmıyorum. Elbette, stdin'i düşündüğünüzü değiştirebilirsin, ama eski sap hala orada. Ama ilk kısım hakkında hemfikirim. – Mehrdad

+0

Lionel B, Linux için http://bytes.com/topic/c/answers/841283-how-make-non-blocking-call-cin adresinde bazı kodlar sağlar - tartışma da okumaya değer. –

cevap

13

Burada POSIX (Linux) için bir çözüm var: Windows'ta anketin eşdeğerinin ne olduğundan emin değilim. Unix'te, 0 numaralı dosya tanıtıcı standart giriştir.

#include <stdio.h> 
#include <sys/poll.h> 

int main(void) 
{ 
     struct pollfd fds; 
     int ret; 
     fds.fd = 0; /* this is STDIN */ 
     fds.events = POLLIN; 
     ret = poll(&fds, 1, 0); 
     if(ret == 1) 
       printf("Yep\n"); 
     else if(ret == 0) 
       printf("No\n"); 
     else 
       printf("Error\n"); 
     return 0; 
} 

Test:

$ ./stdin 
No 
$ echo "foo" | ./stdin 
Yep 
+0

Bu tam olarak istediğim şey. Şimdi, giriş arabelleğinin boyutunu nasıl ölçebileceğinizi söyleyebilseydim sonsuza dek minnettar olurdum, ama bir soru domuz gibi görünmek istemiyorum. – norcalli

+0

Girişi almak için read() öğesini kullanabilirsiniz. Önce dosya tanımlayıcısını 0, fcntl() kullanarak engellemeyi engellemek için ayarlayın, ardından okunan(), daha fazla gelen veri olmadığında okunan bayt sayısını veya 0 değerini döndürecektir. – Antti

+2

+1. Yaygın olarak kullanılan başka bir alternatif ise 'select()' - kavramsal olarak benzer kullanımdır. Bunların, işletim sisteminden, açıklayıcıdan yeni veriler mevcut olup olmadığını sorması çok önemlidir - eğer bu seviyede çalışıyorsanız, doğrudan bir tanımlayıcıda da 'read()' kullanmalısınız, kütüphaneyi kullanamazsınız. seviye stdin akışları veya 'std :: cin' (yeni bir arabellek uygulaması sağlamadıkça). –

1

bu işe olmaz mı?