9

具体的には、ここのコードサンプルはうまく機能しますが、文字列がファイルに保存されている場合に限ります。

生成された文字列(文字列変数に格納されている)を処理するために必要な場合がありますが、ファイル構造へのポインターであるため、fgetsの3番目のパラメーターが文字列変数で機能するように説得するのに問題があります。

または、文字列で使用できるfgetsと同等の機能があるのでしょうか。

助言がありますか?ありがとう!

4

7 に答える 7

10

簡単な答えを一緒にハッキングする精神で、ここに私が書いたばかりの「sgets」があります。fgetsをエミュレートしようとしますが、文字列入力を使用します。

編集モンテが指摘したバグを修正しました(ありがとう)。まったく同じ考えを持つ少なくとも15人の他の人が必死に同じことをしていると信じながら、ユーティリティを狂ったように入力しても、十分にテストされたコードにはなりません。悪い私。元のバージョンでは、後続の呼び出しに改行文字が含まれていました。

char *sgets( char * str, int num, char **input )
{
    char *next = *input;
    int  numread = 0;

    while ( numread + 1 < num && *next ) {
        int isnewline = ( *next == '\n' );
        *str++ = *next++;
        numread++;
        // newline terminates the line but is included
        if ( isnewline )
            break;
    }

    if ( numread == 0 )
        return NULL;  // "eof"

    // must have hit the null terminator or end of line
    *str = '\0';  // null terminate this tring
    // set up input for next call
    *input = next;
    return str;
}


int main( int argc, char* argv[] )
{
    // quick and dirty test
    char *str = "abc\ndefghitjklksd\na\n12345\n12345\n123456\nabc\n\n";
    char buf[5];

    while ( sgets( buf, sizeof( buf ), &str ))
        printf( "'%s'\n", buf );
}
于 2010-01-15T03:15:26.193 に答える
4

標準Cライブラリはその機能を提供していません。

しかし、AT&Tの安全で高速なI / Oライブラリは、メモリストリームを有効にし、ファイルAPIとその拡張機能を使用するためのラッパーコードも提供します。最後の更新は2005年2月からのものであるため、最終的にすべてのバグを解決したか、ルーク・ウィルソンが給与を支払っているため、それを維持する余裕がなくなりました:-(

パッケージはここからダウンロードできます

于 2010-01-15T02:06:02.377 に答える
3

sscanfがそれを行う必要があります。もちろん、セマンティクスは異なります。

于 2010-01-15T02:07:08.687 に答える
3

パイプを使用し、でパイプを開いてfdopenを取得しFILE *、そこから読み取ります。


#include <stdio.h>

int main (int argc, char *argv[])
{
    int pipes[2];
    FILE *write;
    FILE *read;
    char buffer[1000];

    pipe (pipes);

    read = fdopen (pipes[0], "r");
    write = fdopen (pipes[1], "w");
    fputs ("My\nlong\nstring\nin\nmany\nlines\n", write);
    fclose (write);

    while (fgets (buffer, sizeof(buffer), read) != NULL)
    {
        printf ("Found a line: %s", buffer);
    }

    fclose (read);

    return 0;
}
于 2010-01-15T03:32:49.033 に答える
2

文字列がすでにメモリにある場合は、改行でトークン化できます(strtok文字列の変更に問題がなく、再入可能性について心配する必要がない場合、または手動で使用strchrして別のバッファにコピーする場合)。 。

stdio関数が通常提供するようなプラットフォーム依存の改行変換は得られないため、メモリ内の文字列がたとえばCRLFラインターミネータを使用する場合は、特別な注意が必要になります。

于 2010-01-15T02:45:38.660 に答える
1

あなたがする必要があるのは、文字列の行末の線形検索を実行することです。これは、独自の文字列ストリーミングクラスの作成を開始するための小さなプログラムです。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct StringStream StringStream;

struct StringStream {
    const char *data;
    const char *position;
};

StringStream *
stringstream_new(const char *data)
{
    StringStream *self = malloc(sizeof (StringStream));

    self->data = self->position = data;

    return self;
}

void
stringstream_delete(StringStream *self)
{
    free(self);
}

char *
stringstream_gets(char *s, int n, StringStream *self)
{
    const char * eol;
    int i, len;

    if (NULL == self->position || '\0' == *self->position)
        return NULL;

    eol = strchr(self->position, '\n');

    if (eol) {
        len = eol - self->position + 1;
        len = len <= n ? len : n - 1;

        for (i = 0; i < len; ++i)
            s[i] = *self->position++;

    } else {
        for (i = 0; *self->position && i < n; ++i)
            s[i] = *self->position++;
            if ('\0' == *self->position)
                self->position = NULL;
            else
                ++self->position;
    }

    s[i] = '\0';

    return s;
}

int
main(int argc, char * argv[])
{
    static const int LEN = 100;
    static const char TEST_STRING[] =
        "line 0\n"
        "line 1\n"
        "line 2\n"
        "line 3\n"
        "line 4\n"
        "line 5\n"
        "line 6\n"
        "line 7\n"
        "line 8\n"
        "line 9\n";

    StringStream *stream;
    char buf[LEN];

    stream = stringstream_new(TEST_STRING);

    while (stringstream_gets(buf, LEN, stream))
        printf("gets: %s\n", buf);

    stringstream_delete(stream);

    return 0;
}
于 2010-01-15T03:01:54.473 に答える
0

fgets関数のソースコードを変更しました:

size_t  my_fgets( inBuf , n , outBuf )
unsigned char *inBuf;
size_t n;
unsigned char *outBuf;
{
    size_t len = 0;
    unsigned char *s;
    unsigned char *p, *t;

    if (n <= 0)             /* sanity check */
            return (-1);

    p =  inBuf;
    s = outBuf;

    n--;                    /* leave space for NUL */

    while (n != 0) {

        len = n;
        t = memchr((void *)p, '\n', strlen(p));

        //printf ("'p' found at position %d.\n", t -p + 1);

        if (t != NULL) {
            len = ++t -p;
            (void)memcpy((void *)s, (void *)p, len);
            s[len] = 0;
            return len;
        }

        (void)memcpy((void *)s, (void *)p, len);
        s += len;
        n -= len;

    }

    *s = 0;

    return len;

}

および主な機能:

int main(void)
{
    char *inBuf = "this \n"
                  "is \n"
                  "test \n";

    char outBuf[1024];

    my_fgets(inBuf,strlen(inBuf),outBuf);
    printf("outBuf:%s \n",outBuf);

    return 0;
}

および出力:

outBuf:this 
于 2014-01-04T11:03:34.407 に答える