1

マルチバイト文字列 (stdin から取得) をワイド文字列に単純に変換することになっている、私が書いたこのスニペットを参照してください。mbsrtowcscppreference のドキュメントとドキュメントを読んだ後、mbstate_tそれは有効だと思いました:

#include <stdio.h>
#include <wchar.h>
#include <errno.h>
#include <stdlib.h>
#include <error.h>

int main()
{
        char *s = NULL; size_t n = 0; errno = 0;
        ssize_t sn = getline(&s, &n, stdin);
        if(sn == -1 && errno != 0)
                error(EXIT_FAILURE, errno, "getline");
        if(sn == -1 && errno == 0) // EOF
                return EXIT_SUCCESS;

        // determine how big should be the allocated buffer
        const char* cs = s; mbstate_t st = {0}; // cs to avoid comp. warnings
        size_t wn = mbsrtowcs(NULL, &cs, 0, &st);
        if(wn == (size_t)-1)
                error(EXIT_FAILURE, errno, "first mbsrtowcs");

        wchar_t* ws = malloc((wn+1) * sizeof(wchar_t));
        if(ws == NULL)
                error(EXIT_FAILURE, errno, "malloc");

        // finally convert the multibyte string to wide string
        st = (mbstate_t){0};
        if(mbsrtowcs(ws, &cs, wn+1, &st) == (size_t)-1)
                error(EXIT_FAILURE, errno, "second mbsrtowcs");

        if(printf("%ls", ws) < 0)
                error(EXIT_FAILURE, errno, "printf");

        return EXIT_SUCCESS;
}

はい、これは ASCII 文字列で機能します。しかし、非 ASCII 文字列を処理しようとしているまさにその理由は、ASCII テーブルを超えて分音記号をサポートしたいからです! そして、それは失敗します。への最初の呼び出しは でmbsrtowcs失敗しますEILSEQ。これは、マルチバイト文字列が無効であることを示しています。しかし、奇妙なことに、 で検査するとgdb、有効なようです! gdb(正しく表示される限り)。このスニペットに非 ASCII 文字列を入力してgdbing した場合の効果を以下で確認してください。

m@m-X555LJ:~/wtfdir$ gcc -g -o wtf wtf.c
m@m-X555LJ:~/wtfdir$ ./wtf
asa
asa
m@m-X555LJ:~/wtfdir$ ./wtf
ąsa
./wtf: first mbsrtowcs: Invalid or incomplete multibyte or wide character
m@m-X555LJ:~/wtfdir$ gdb ./wtf
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./wtf...done.
(gdb) break 18
Breakpoint 1 at 0x93b: file wtf.c, line 18.
(gdb) r
Starting program: /home/m/wtfdir/wtf 
ąsa

Breakpoint 1, main () at wtf.c:18
18          size_t wn = mbsrtowcs(NULL, &cs, 0, &st);
(gdb) p cs
$1 = 0x555555756260 "ąsa\n"
(gdb) c
Continuing.
/home/m/wtfdir/wtf: first mbsrtowcs: Invalid or incomplete multibyte or wide character
[Inferior 1 (process 5612) exited with code 01]
(gdb) quit

これが重要な場合、私は Linux を使用しており、ロケール エンコーディングは UTF8 のようです。

m@m-X555LJ:~$ locale charmap
UTF-8

(これが、これが機能すると予想した理由printf("ąsa\n");です。Linuxでは機能する傾向がありますが、Windowsでは機能しない傾向があります)

私は何が欠けていますか?私は何を間違っていますか?

4

0 に答える 0