2011-02-07 19 views
8

Komut satırı argümanlarına bağlı olarak, bir dosya tanıtıcısını belirtilen bir dosyaya veya stdin'e (borulama amacıyla) işaret edecek şekilde ayarlıyorum. Ardından bu işaretçiyi dosyadan okumak için bir dizi farklı işleve geçiriyorum. stdin işaret zamanlardaFceek'i stdin'e işaret eden bir dosya tanıtıcısıyla kullanma

FILE *getFile(int argc, char *argv[]) { 
    FILE *myFile = NULL; 
    if (argc == 2) { 
     myFile = fopen(argv[1], "r"); 
     if (myFile == NULL) 
      fprintf(stderr, "File \"%s\" not found\n", argv[1]); 
    } 
    else 
     myFile = stdin; 
    return myFile; 
} 

, fseek çalışmak görünmüyor: Burada dosya işaretçisi almak için fonksiyonudur. Bununla, onu kullanıyorum ve fgetc kullanıyorum ve beklenmedik sonuçlar alıyorum. Bu beklenen davranış mı, eğer öyleyse, akıştaki farklı konumlara nasıl geçebilirim? Örneğin

:

int main(int argc, char *argv[]) { 
    FILE *myFile = getFile(argc, argv); // assume pointer is set to stdin 
    int x = fgetc(myFile); // expected result 
    int y = fgetc(myFile); // expected result 
    int z = fgetc(myFile); // expected result 

    int foo = bar(myFile); // unexpected result 

    return 0; 
} 

int bar(FILE *myFile) { 
    fseek(myFile, 4, 0); 
    return fgetc(myFile); 
} 
+0

Örnek kodunuz benim için iyi görünüyor. (Dosya mevcut olmadığı zaman, ancak bu sizin sorununuz ile ilgili değilse) –

+0

bana uygun görünüyor. hangi derleyici? yazdırmayı deneyebilirsiniz, bar() işlevinin her ikisi de işaretçileri (stdin ve myFile) aynı olduklarını kontrol etmek için. – leonbloy

+0

@leonbloy: Sorunun aslında fseek() ile olduğunu keşfettim. Görünüşe göre işaretçi stdin'e işaret ettiğinde işe yaramıyor mu? Bu konuda bir fikrin var mı? (Soru şu anda) –

cevap

12

Evet, fseekstdin üzerinde çalışmaz çok normal - normalde sadece bir disk dosyasına üzerinde çalışacağız falan makul benzer.

Bu gerçekten bir POSIX olayı olsa da, genellikle belirli bir dosyada çalışacak olup olmadığına ilişkin oldukça iyi bir fikir edinmek için if (isatty(fileno(myFile)))'u kullanabilirsiniz. Bazı durumlarda, isatty ve/veya fileno, önde gelen alt çizgilere sahip olacaktır (ör. Microsoft'un derleyicileriyle sağlanan sürümler IIRC).

+0

Sonra sanırım sorum şu: ve bu aptalca olabilir - akışta farklı bir dizine geçmek için nasıl giderim? Bir döngüde 'fgetc' (myFile) 'i çağırmaktan daha zarif bir çözüm olacağını düşünürdüm? –

+4

@Tyler Treat: Yok - akışlar ve dosyalar arasındaki temel fark bu. Kavramsal olarak, bir akıştan gelen giriş hiçbir yerde saklanmaz - bir akım, tükettiğinizde üretilen geçici bir şeydir. Bir akıştan veriyi araştırmak isterseniz, onu belleğe okuyup orada aramalısınız (ya da özellikle büyükse, geçici bir dosyaya okuyun). – caf

+1

"Fseek'in stdin üzerinde çalışmayacağı tamamen normaldir" ile ilgili C11 spesifikasyonunda destek bulamıyorum. 'Stdin' bir metin akışı olduğunda bunu desteklemek için C belirtiminiz var mı? – chux

1

fseek() lseek() dayanır ve lseek adam sayfası dahil olmak üzere mümkün hataları ele almaktadır: stdin sahte tty'den bağlıysa

[ESPIPE]   Fildes is associated with a pipe, socket, or FIFO. 

, bunun soket davranışa sahip olacağına inanıyoruz.

+1

ANSI C bu konuda bir şey söyledi mi? –

+0

En bulabildiğim, N1256 7.19.3 Dosya 1 idi. "Bir dosya konumlandırma isteklerini destekleyebilir (örneğin, bir terminalin aksine bir disk dosyası gibi)", ancak stdin'i ona bağlayan bir şey bulamadım. –

İlgili konular