1

私はこれに数日間立ち往生しており、本当にイライラしています。

popen()コマンドラインプロセスを呼び出し、その出力を取得してC文字列に保存するために使用しています。使ってfgets()いたのですが、改行で切れるようなので使ってfread()います。唯一の問題は、返される C 文字列が時々めちゃくちゃになることです。

これが私のコードです:

const char *cmd = "date";//This the shell command
char buf[BUFSIZ];//Output of the command
FILE *ptr;
int c;

if ((ptr = popen(cmd, "r")) != NULL)
     while(fread(buf, sizeof(buf),1, ptr))
          while ((c = getchar()) != EOF)
               printf("output = %s", buf);

(void) pclose(ptr);

最終的な C 文字列には、存在しないはずの奇妙な文字が含まれている場合や、使用可能な文字列がない場合もあります。誰でも助けてもらえますか?):

編集: fgets() を使用するときに私が行っていたことは次のとおりです ただし、シェルコマンドはテキストを出力するものであれば何でもかまいません。「デート」だけじゃない。


if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFSIZ, ptr) != NULL)
printf("output = %s", buf);
(void) pclose(ptr);

4

4 に答える 4

3

fread読み取ったものの後に NUL ターミネータを挿入しません。戻り値を確認して、読み取った量を確認し、その量だけを出力する必要があります。で読み取る場合はfread、通常、次のfwrite順序で でデータを書き込みます。

long bytes;
while ((bytes=fread(buf, sizeof(buf), 1, ptr))>0)
    fwrite(buf, bytes, 1, stdout);
于 2011-07-14T21:17:14.127 に答える
3

まあ、fgetsそれを行う正しい方法です。

FILE *ptr;

if (NULL == (ptr = popen(cmd, "r"))) {
    /* ... */
}

while(fgets(buf, sizeof(buf), ptr) != NULL) {
    /* There is stuff in 'buf' */
}

あなたがうまくいかなかった理由fgetsは、あなたが何か間違ったことをしていたからだと思います。

さて、現在のコードで問題が発生していると思われる理由は次のとおりです。

  • fread実際に返された金額を確認していません
  • あなたは何かを読んでgetchar捨てています
  • NULバッファにターミネータがありません

これを正しく行うと、すべてが改善されます。fread合法的には、あなたが言ったよりも読む量が少なくなる可能性があります

于 2011-07-14T21:17:49.743 に答える
2

からの出力には、文字列を適切に終了するために必要な (NUL) 文字がdate含まれていません。'\0'読み取った文字数を追跡して、自分で NUL に入れます。

実際には、fgetsgetlineまたは同様のテキスト指向関数を使用して、 などのプログラムから読み取る必要がありますdategetline特に簡単です(そして、メモリ管理を行うので安全です):

FILE *fp = popen("date", "r");
char *ln = NULL;
size_t len = 0;

while (getline(&ln, &len, fp) != -1)
    fputs(ln, stdout);
free(ln);
pclose(fp);
于 2011-07-14T21:16:51.223 に答える
1

fread以下は、プロセス出力に使用する正しい方法popenです。

const char *cmd = "date";
char buf[BUFSIZ];
FILE *ptr;

if ((ptr = popen(cmd, "r")) != NULL) {
    /* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
    size_t byte_count = fread(buf, 1, BUFSIZ - 1, ptr);
    /* Apply null termination so that the read bytes can be treated as a string. */
    buf[byte_count] = 0;
    printf("%s\n", buf);
}

(void) pclose(ptr);

ご覧のとおり、主な問題は null 終了を正しく処理することです。の 2 つのサイズ パラメータfreadも重要です。1 文字ずつ読み取らせる必要があります。の場合、プロセスが何も出力せずに終了した場合にのみ 0 を返すことpopenに注意してください。プロセスが何かを印刷するのに長い時間がかかる場合、0 は返さfreadません。

出力が より大きい場合は、ループでBUFSIZラップできます。freadwhile

于 2015-08-26T03:37:16.747 に答える