2011-02-07 18 views
8

Tùy thuộc vào các đối số dòng lệnh, tôi đang thiết lập một con trỏ tập tin trỏ tới một tệp được chỉ định hoặc stdin (cho mục đích đường ống). Sau đó, tôi chuyển con trỏ này đến một số hàm khác nhau để đọc từ tệp. Đây là chức năng nhận con trỏ của tệp:Sử dụng fseek với một con trỏ tập tin trỏ đến stdin

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; 
} 

Khi trỏ đến stdin, fseek dường như không hoạt động. Bằng cách đó, tôi có nghĩa là tôi sử dụng nó và sau đó sử dụng fgetc và tôi nhận được kết quả bất ngờ. Đây có phải là hành vi được mong đợi hay không và nếu có, làm cách nào để di chuyển đến các vị trí khác nhau trong luồng?

Ví dụ:

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

mã ví dụ của bạn có vẻ ổn cho tôi. (trừ khi tập tin không tồn tại, nhưng điều này không liên quan đến vấn đề của bạn) –

+0

có vẻ phù hợp với tôi. trình biên dịch là gì? bạn có thể thử in, bên trong hàm bar() cả hai con trỏ (stdin và myFile) để kiểm tra chúng giống nhau. – leonbloy

+0

@leonbloy: Tôi đã phát hiện ra rằng vấn đề là thực sự với 'fseek()'. Dường như nó không hoạt động khi con trỏ trỏ tới stdin? Bất kỳ suy nghĩ về điều này? (Cập nhật câu hỏi) –

Trả lời

12

Có, đó là hoàn toàn bình thường mà fseek sẽ không hoạt động trên stdin - nó sẽ bình thường chỉ làm việc trên một tập tin trên đĩa, hoặc một cái gì đó hợp lý tương tự.

Mặc dù nó thực sự là một điều POSIX, bạn thường có thể sử dụng if (isatty(fileno(myFile))) để có được ít nhất một ý tưởng khá tốt cho dù tìm kiếm sẽ làm việc trong một tập tin cụ thể. Trong một số trường hợp, isatty và/hoặc fileno sẽ có dấu gạch dưới hàng đầu (ví dụ: IIRC các phiên bản được cung cấp với trình biên dịch của Microsoft).

+0

Sau đó, tôi đoán câu hỏi của tôi là - và điều này có thể là ngu ngốc - làm thế nào tôi sẽ đi về di chuyển đến một chỉ số khác nhau trong dòng? Tôi nghĩ rằng sẽ có một giải pháp thanh lịch hơn là gọi 'fgetc (myFile)' trong một vòng lặp n lần? –

+4

@Tyler Treat: Không có - sự khác biệt cơ bản giữa các luồng và tệp. Về mặt khái niệm, đầu vào từ luồng không được lưu trữ ở bất cứ nơi nào - luồng không hoạt động, được tạo khi bạn sử dụng nó. Nếu bạn cần phải tìm kiếm xung quanh trong dữ liệu từ một dòng, bạn nên đọc nó vào bộ nhớ và tìm kiếm xung quanh đó (hoặc, nếu nó đặc biệt lớn, đọc nó vào một tập tin tạm thời). – caf

+1

Tôi không tìm thấy hỗ trợ trong spec C11 liên quan đến "nó hoàn toàn bình thường mà fseek sẽ không hoạt động trên stdin". Bạn có đặc điểm kỹ thuật C để hỗ trợ khi 'stdin' là một dòng văn bản? – chux

1

fseek() được dựa trên lseek(), và trang lseek người đàn ông thảo luận về lỗi có thể, bao gồm:

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

Nếu stdin được kết nối với một tty giả, tôi tin rằng nó sẽ có hành vi socket.

+1

ANSI C có nói gì về nó không? –

+0

Điều tốt nhất tôi có thể tìm thấy là N1256 7.19.3 Tệp 1 "Nếu tệp có thể hỗ trợ yêu cầu định vị (chẳng hạn như tệp đĩa, trái ngược với thiết bị đầu cuối)", nhưng tôi không thể tìm thấy thứ gì đó liên kết 'stdin' với nó. –