具体的には、ここのコードサンプルはうまく機能しますが、文字列がファイルに保存されている場合に限ります。
生成された文字列(文字列変数に格納されている)を処理するために必要な場合がありますが、ファイル構造へのポインターであるため、fgetsの3番目のパラメーターが文字列変数で機能するように説得するのに問題があります。
または、文字列で使用できるfgetsと同等の機能があるのでしょうか。
助言がありますか?ありがとう!
簡単な答えを一緒にハッキングする精神で、ここに私が書いたばかりの「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 );
}
標準Cライブラリはその機能を提供していません。
しかし、AT&Tの安全で高速なI / Oライブラリは、メモリストリームを有効にし、ファイルAPIとその拡張機能を使用するためのラッパーコードも提供します。最後の更新は2005年2月からのものであるため、最終的にすべてのバグを解決したか、ルーク・ウィルソンが給与を支払っているため、それを維持する余裕がなくなりました:-(
パッケージはここからダウンロードできます。
sscanfがそれを行う必要があります。もちろん、セマンティクスは異なります。
パイプを使用し、でパイプを開いて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;
}
文字列がすでにメモリにある場合は、改行でトークン化できます(strtok
文字列の変更に問題がなく、再入可能性について心配する必要がない場合、または手動で使用strchr
して別のバッファにコピーする場合)。 。
stdio関数が通常提供するようなプラットフォーム依存の改行変換は得られないため、メモリ内の文字列がたとえばCRLFラインターミネータを使用する場合は、特別な注意が必要になります。
あなたがする必要があるのは、文字列の行末の線形検索を実行することです。これは、独自の文字列ストリーミングクラスの作成を開始するための小さなプログラムです。
#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;
}
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