从使用 fmemopen 创建的流中读取宽字符
Read wide char from a stream created with fmemopen
我正在尝试从使用 fmemopen
和 char *
创建的流中读取宽字符。
char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");
wchar_t c = getwc(f);
getwc
抛出一个分段错误,我用 GDB 检查过。
我知道这是因为使用 fmemopen
打开了流,因为在打开的流上调用 getwc
正常工作。
是否有 fmemopen
的宽字符版本,或者是否有其他方法可以解决此问题?
你的第二行没有使用正确数量的参数,是吗?已更正
FILE *fmemopen(void *buf, size_t size, const char *mode);
glibc 的 fmemopen
不 (完全) 支持宽字符 AFAIK。还有open_wmemstream()
,支持宽字符,只是为了写。
是否定义了_UNICODE
?参见 wchar_t reading。
另外,您是否将语言环境设置为支持 Unicode 的编码,例如 setlocale(LC_ALL, "en_US.UTF-8");
?参见 here。
我更改了我的代码并采用了@chqrlie 的代码,因为它更接近 OP 代码但添加了语言环境,否则它无法为 extended/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;
}
第二行应显示为 FILE *f = fmemopen(s, strlen(s), "r");
。如发布的那样,fmemopen
具有未定义的行为并且可能 return 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
立即 returned。
linux 手册页中对 fwide(f, 0)
的解释:
SYNOPSIS
#include <wchar.h>
int fwide(FILE *stream, int mode);
When mode
is zero, the fwide()
function determines the current orientation of stream
. It returns a positive value if stream
is wide-character oriented, that is, if wide-character I/O is permitted but char I/O is disallowed. It returns a negative value if stream
is byte oriented, i.e., if char I/O is permitted but wide-character I/O is disallowed. It returns zero if stream
has no orientation yet; in this case the next I/O operation might change the orientation (to byte oriented if it is a char I/O operation, or to wide-character oriented if it is a wide-character I/O operation).
Once a stream has an orientation, it cannot be changed and persists until the stream is closed.
When mode
is nonzero, the fwide()
function first attempts to set stream
's orientation (to wide-character oriented if mode is greater than 0, or to byte oriented if mode
is less than 0). It then returns a value denoting the current orientation, as above.
由 fmemopen()
编辑的流 return 是面向字节的,不能更改为面向宽字符。
您只能在无向或宽向流上使用 getwc()
。来自 getwc()
man page: 流应该还没有方向,或者是宽方向的。
如果流已经有方向,则无法更改流方向。来自 fwide()
man page:在已经有方向的流上调用此函数无法更改它。
用 glibc 的 fmemopen()
打开的流具有字节方向,因此不能以任何方式面向宽。正如所描述的 here uClibc 有 fmemopen()
没有这个限制的例程。
结论:您需要使用 uClibc 或其他库或自己制作 fmemopen()
。
我正在尝试从使用 fmemopen
和 char *
创建的流中读取宽字符。
char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");
wchar_t c = getwc(f);
getwc
抛出一个分段错误,我用 GDB 检查过。
我知道这是因为使用 fmemopen
打开了流,因为在打开的流上调用 getwc
正常工作。
是否有 fmemopen
的宽字符版本,或者是否有其他方法可以解决此问题?
你的第二行没有使用正确数量的参数,是吗?已更正FILE *fmemopen(void *buf, size_t size, const char *mode);
glibc 的
fmemopen
不(完全)支持宽字符 AFAIK。还有open_wmemstream()
,支持宽字符,只是为了写。是否定义了
_UNICODE
?参见 wchar_t reading。
另外,您是否将语言环境设置为支持 Unicode 的编码,例如setlocale(LC_ALL, "en_US.UTF-8");
?参见 here。
我更改了我的代码并采用了@chqrlie 的代码,因为它更接近 OP 代码但添加了语言环境,否则它无法为 extended/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;
}
第二行应显示为 FILE *f = fmemopen(s, strlen(s), "r");
。如发布的那样,fmemopen
具有未定义的行为并且可能 return 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
立即 returned。
linux 手册页中对 fwide(f, 0)
的解释:
SYNOPSIS
#include <wchar.h> int fwide(FILE *stream, int mode);
When
mode
is zero, thefwide()
function determines the current orientation ofstream
. It returns a positive value ifstream
is wide-character oriented, that is, if wide-character I/O is permitted but char I/O is disallowed. It returns a negative value ifstream
is byte oriented, i.e., if char I/O is permitted but wide-character I/O is disallowed. It returns zero ifstream
has no orientation yet; in this case the next I/O operation might change the orientation (to byte oriented if it is a char I/O operation, or to wide-character oriented if it is a wide-character I/O operation).Once a stream has an orientation, it cannot be changed and persists until the stream is closed.
When
mode
is nonzero, thefwide()
function first attempts to setstream
's orientation (to wide-character oriented if mode is greater than 0, or to byte oriented ifmode
is less than 0). It then returns a value denoting the current orientation, as above.
由 fmemopen()
编辑的流 return 是面向字节的,不能更改为面向宽字符。
您只能在无向或宽向流上使用
getwc()
。来自getwc()
man page: 流应该还没有方向,或者是宽方向的。如果流已经有方向,则无法更改流方向。来自
fwide()
man page:在已经有方向的流上调用此函数无法更改它。用 glibc 的
fmemopen()
打开的流具有字节方向,因此不能以任何方式面向宽。正如所描述的 here uClibc 有fmemopen()
没有这个限制的例程。
结论:您需要使用 uClibc 或其他库或自己制作 fmemopen()
。