我正在尝试从使用创建的流中读取宽字符 fmemopen
用一个 char *
。
char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");
wchar_t c = getwc(f);
getwc
抛出分段错误,我使用GDB检查。
我知道这是因为打开了流 fmemopen
因为打电话 getwc
在正常打开的流上正常工作。
是否有广泛的char版本 fmemopen
,还是有其他方法来解决这个问题?
我正在尝试从使用创建的流中读取宽字符 fmemopen
用一个 char *
。
char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");
wchar_t c = getwc(f);
getwc
抛出分段错误,我使用GDB检查。
我知道这是因为打开了流 fmemopen
因为打电话 getwc
在正常打开的流上正常工作。
是否有广泛的char版本 fmemopen
,还是有其他方法来解决这个问题?
第二行应该是读 FILE *f = fmemopen(s, strlen(s), "r");
。如发布, fmemopen
有未定义的行为,可能会返回 NULL
, 什么导致 getwc()
坠毁。
改变了 fmemopen()
行并添加支票 NULL
修复崩溃,但不符合OP的目标。
在打开的流上似乎不支持宽方向 fmemopen()
,至少对于GNU C库。注意 fmemopen
未在C标准中定义,但在POSIX.1-2008中未定义,并且在许多系统(如OS / X)上不可用。
以下是您的程序的更正和扩展版本:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
int main(void) {
const char *s = "foo bar foo";
FILE *f = fmemopen((void *)s, strlen(s), "r");
wchar_t c;
if (f == NULL) {
printf("fmemopen failed: %s\n", strerror(errno));
return 1;
}
printf("default wide orientation: %d\n", fwide(f, 0));
printf("selected wide orientation: %d\n", fwide(f, 1));
while ((c = getwc(f)) != WEOF) {
printf("read %lc (%d 0x%x)\n", c, c, c);
}
return 0;
}
在linux上运行:
default wide orientation: -1
selected wide orientation: -1
没有输出, WEOF
立即归还。
解释 fwide(f, 0)
来自linux手册页:
概要
#include <wchar.h> int fwide(FILE *stream, int mode);
什么时候
mode
是零,fwide()
函数确定当前的方向stream
。如果是,则返回正值stream
是宽字符导向的,即,如果允许宽字符I / O但不允许char I / O.如果是,则返回负值stream
是面向字节的,即,如果允许char I / O但是不允许宽字符I / O.如果,它返回零stream
还没有方向;在这种情况下,下一个I / O操作可能会改变方向(如果是char I / O操作,则为面向字节,如果是宽字符I / O操作,则为宽字符方向)。一旦流具有方向,它就无法更改并持续直到流关闭。
什么时候
mode
是非零的,fwide()
函数首先尝试设置stream
方向(如果模式大于0,则以宽字符为导向;如果是,则为字节方向mode
小于0)。然后它返回一个表示当前方向的值,如上所述。
返回的流 fmemopen()
是面向字节的,不能改为宽字符。
你的第二行没有使用正确数量的参数,是吗? 修正
FILE *fmemopen(void *buf, size_t size, const char *mode);
的glibc的 fmemopen
才不是 (全) 支持广角AFAIK。还有 open_wmemstream()
,它支持宽字符,但仅用于写作。
是 _UNICODE
界定?看到 wchar_t阅读。
也,您是否将语言环境设置为支持Unicode的编码,例如, setlocale(LC_ALL, "en_US.UTF-8");
?看到 这里。
我已经更改了我的代码并采用了@chqrlie中的代码,因为它更接近OP代码但添加了语言环境,否则无法为扩展/ Unicode字符生成正确的输出。
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <stdlib.h>
#include <locale.h>
int main(void)
{
setlocale(LC_ALL, "en_US.UTF-8");
const char *s = "foo $€ bar foo";
FILE *f = fmemopen((void *)s, strlen(s), "r");
wchar_t c;
if (f == NULL) {
printf("fmemopen failed: %s\n", strerror(errno));
return 1;
}
printf("default wide orientation: %d\n", fwide(f, 0));
printf("selected wide orientation: %d\n", fwide(f, 1));
while ((c = getwc(f)) != WEOF) {
printf("read %lc (%d 0x%x)\n", c, c, c);
}
return 0;
}
您可以使用 getwc()
仅适用于无定向或面向广播的流。从 getwc()
手册页: 流不具有方向,或者是宽方向的。
如果流已经具有方向,则无法更改流方向。从 fwide()
手册页: 在已具有方向的流上调用此函数无法更改它。
用glibc打开流 fmemopen()
具有字节方向,因此不能以任何方式进行广泛定向。如上所述 这里 uClibc的 具有 fmemopen()
例程没有这个限制。
结论:您需要使用 uClibc的 或另一个图书馆或自己做 fmemopen()
。