从使用fmemopen创建的流中读取宽字符

MD *_* XF 10 c unicode stream segmentation-fault widechar

我正在尝试从使用fmemopena 创建的流中读取宽字符char *.

char *s = "foo bar foo";
FILE *f = fmemopen(s,strlen(s),"r");

wchar_t c = getwc(f);
Run Code Online (Sandbox Code Playgroud)

getwc 抛出分段错误,我使用GDB检查.

我知道这是因为打开了流fmemopen,因为调用getwc正常打开的流正常工作.

是否存在广泛的char版本fmemopen,或者是否有其他方法可以解决此问题?

chq*_*lie 7

第二行应该是读FILE *f = fmemopen(s, strlen(s), "r");.发布后,fmemopen有未定义的行为,可能会返回NULL,导致getwc()崩溃.

更改fmemopen()线路并添加检查以NULL修复崩溃,但不符合OPs目标.

对于打开的流,似乎不支持广泛的方向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;
}
Run Code Online (Sandbox Code Playgroud)

在linux上运行:

default wide orientation: -1
selected wide orientation: -1
Run Code Online (Sandbox Code Playgroud)

没有输出,WEOF立即返回.

解释fwide(f, 0)从Linux手册页:

概要

#include <wchar.h>
int fwide(FILE *stream, int mode);
Run Code Online (Sandbox Code Playgroud)

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,则为宽字符方向,如果小于0,则为字节方向mode ).然后它返回一个表示当前方向的值,如上所述.

返回的流fmemopen()是面向字节的,不能更改为面向字符的宽字符.