簡體   English   中英

C回退來自命令輸出的FILE指針

[英]C Rewind FILE pointer coming from a command output

當我嘗試使用rewind或fseek再次查看並檢查輸出命令以執行其他操作時,我的命令輸出出現問題,這是部分代碼:

#include <stdio.h>
#include <string.h>
#include <stdlib.h> 
int  main(){
     FILE *pf;
     int nhd=1;
     size_t b_size = 80;
     char *data = malloc(b_size * sizeof(char));
     pf = popen("/sbin/mycmd -s","r");

     while(-1 != getline(&data, &b_size, pf))
          nhd++;

     fseek (pf , 0 , SEEK_SET); // rewind(pf);

     while(-1 != getline(&data, &b_size, pf))
          nhd++;
     printf("%i\n",nhd);
     pclose(pf);
     free(data);
} 

它應該輸出命令行數的兩倍,但是倒帶或出現任何無法正常工作的情況(如當我使用真實文件時)。 我該怎么辦?

並非所有的流都是可搜索的,例如那些具有短暫內容的流,例如管道或套接字。 根據C11 7.21.9.2 The fseek function /6

fseek函數僅對無法滿足的請求返回非零值。

因此,您確實需要檢查它是否有效。 並使用fseek()而不是rewind() ,后者沒有錯誤提示。

一種方法是先讀取十個字節,然后嘗試返回到開頭。 如果可行,請繼續進行下去。 如果沒有,請進行痛苦的抱怨並退出。

如果無法找到該流,但是您需要能夠進行備份,則需要自己存儲它。

例如,即使數據來自管道的標准輸入,也沒有阻止您在讀取時將其寫入臨時文件並在需要備份時使用該文件的情況。

由於需要確定是從臨時文件中讀取還是讀取管道中的新數據,這可能會變得很復雜,但是有時很難避免復雜性。

如果您確實真的只是想將輸出翻倍,並且fd不是文件,請省略fseek()並關閉管道並重新打開它,然后第二次執行讀取循環。 同樣,nhd應該從0而不是1開始,以獲取讀取的行的准確計數。 如果您的目標涉及更多,那么您應該指出您的目標。 我並不驚訝fseek()在非文件上不起作用。 該文檔指的是文件,但也模糊地表示“流”

更新:注釋表明輸入兩次通過的原因是要預先計算以確定分配的數量。 或者,使用鏈接列表通過malloc()動態分配數據,從而無需預先計數/預先分配:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 256

typedef struct list {
    struct list *next;
    char *string;
} LIST;

LIST *head, *p;

int 
main(int argc, argv) 
{
    FILE *fp;
    char line[MAX_LINE];

    if ((fp = fopen(argv[1], "r")) == NULL) {
         fprintf(stderr, "Error opening %s\n", argv[1]);
         exit(-1);
    }
    while(fgets(line, sizeof(line), fp)) {
        LIST *n = malloc(sizeof(LIST));  
        n->string = strdup(line);
        n->next = NULL;
        p = (head == NULL) ? head = n : p->next = n;
    }
    fclose(fp);

    for(p = head; p; p != NULL; p->next)
        printf("%s", p->string);

    // 
    // . . . do whatever
    // 

    /*
     * Free list when unneeded
     */
    for(p = head; p != NULL; ) {
        printf("%s", p->string);
        LIST *saved = p->next
        free(p->string);
        free(p);
        p = saved;
    }
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM