具体来说,此处的代码示例效果很好,但仅当字符串存储在文件中时。
有时我需要它来处理生成的字符串(存储在字符串变量中),但我无法说服 fgets 的第三个参数使用字符串变量,因为它是指向 FILE 结构的指针。
或者也许有一个与 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 库确实启用了内存流,并且还提供了包装代码以使用 FILE API 及其扩展。最后一次更新是从 2005 年 2 月开始的,所以他们要么终于解决了所有的错误,要么现在卢克威尔逊在工资单上,他们再也负担不起维护它了:-(
包可以在这里下载。
sscanf应该这样做。当然语义不同。
使用管道,然后打开管道fdopen
以获得 a 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;
}
If the string is already in memory, you could tokenize on newlines (either with strtok
if you're okay with mutating the string and if don't need to worry about re-entrancy, or by manually using strchr
and copying to a separate buffer yourself).
You wouldn't get platform-dependent newline conversion that the stdio functions would normally give you, however, so some extra care would be needed if your strings in memory use, say, CRLF line terminators.
您需要做的就是对字符串中的行尾执行线性搜索。这是一个小程序,可帮助您开始编写自己的字符串流类。
#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