[英]Read wide char from a stream created with fmemopen
我正在尝试从使用带有char *
fmemopen
创建的流中读取宽字符。
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
立即返回。
来自linux手册页的fwide(f, 0)
解释:
概要
#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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.