繁体   English   中英

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

[英]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()返回的流是面向字节的,不能更改为面向字符的宽字符。

  1. 你的第二行没有使用正确数量的参数,是吗? 修正

    FILE *fmemopen(void *buf, size_t size, const char *mode);

  2. glibc的fmemopen没有 (全) 支持宽字符AFAIK。 还有open_wmemstream() ,它支持宽字符,但仅用于写入。

  3. _UNICODE定义了吗? 请参阅wchar_t阅读
    此外 ,您是否将语言环境设置为支持Unicode的编码,例如setlocale(LC_ALL, "en_US.UTF-8"); 看到这里

  4. 考虑使用临时文件 考虑使用fgetwc / 4代替。

我已经更改了我的代码并采用了@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;
}
  1. 您只能在无定向或面向getwc()的流上使用getwc() getwc() 手册页流不具有方向,或者是面向广的。

  2. 如果流已经有方向,则无法更改流方向。 fwide() 手册页在已经有方向的流上调用此函数无法更改它。

  3. 用glibc打开的流fmemopen()具有字节方向,因此不能以任何方式进行广泛定向。 如此处所述 uClibc具有fmemopen()例程,没有此限制。

结论:您需要使用uClibc或其他库或自己fmemopen()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM