Нужно сделать такую проверку, чтобы использования getwchar было корректным решением(на неподдерживаемых платформах это вызовет ошибку компиляции, но это будет правильное поведение, чем выдавать дичь.)
wchar не обязан быть юникодом...
#ifndef __STDC_ISO_10646__
#error "wchar_t wide characters have to be Unicode code points"
#endif
Если нужно именно UTF8 представление(именно там будет 0xd0, 0xb0 ), то тогда только считывать строки целиком (потому что один UTF8 символ может занимать разное количество байт)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[] = u8"\u0430";
size_t len = strlen(str);
for (size_t i = 0; i < len; ++i)
{
printf("str[%zu]: 0x%.02hhX\n", i, str[i]);
}
char buffer[512] = {0};
scanf("%511s", buffer);
printf("buffer = %s\n", buffer);
len = strlen(buffer);
for (size_t i = 0; i < len; ++i)
{
printf("buffer[%zu]: 0x%.02hhX\n", i, buffer[i]);
}
}
./a.out str[0]: 0xD0
str[1]: 0xB0
а
buffer = а
buffer[0]: 0xD0
buffer[1]: 0xB0
Ладно, хоть и оффтоп так как тег темы C, а я писал на С++, но решил поделиться и кодом разбора. Понятно что есть куда улучшать, но может кому-то будет полезно для старта
#include <string>
#include <iostream>
#include <cinttypes>
#include <ciso646>
#include <cassert>
using namespace std;
static string get_utf8_character(const char* str)
{
assert (str != nullptr);
size_t len{0};
uint8_t byte{static_cast<uint8_t>(*str)};
if (byte < 128) {
len = 1;
} else if (byte < 224) {
len = 2;
} else if (byte < 240) {
len = 3;
} else if (byte < 248) {
len = 4;
} else if (byte < 252) {
len = 5;
} else {
len = 6;
}
return string(str, str + len);
}
class utf8string_iterator
{
const char* s {nullptr};
public:
explicit utf8string_iterator (const char* str)
: s{str}
{}
string operator*() const
{
return get_utf8_character(s);
}
utf8string_iterator& operator++()
{
auto temp (get_utf8_character (s));
s += temp.size();
return *this;
}
bool operator!= (const utf8string_iterator) const
{
return (s != nullptr) and (*s != '\0');
}
};
class utf8string_range
{
const char* s {nullptr};
public:
explicit utf8string_range (const char* str)
: s{str}
{}
utf8string_iterator begin() const
{
return utf8string_iterator{s};
}
utf8string_iterator end() const
{
return utf8string_iterator{nullptr};
}
};
int main()
{
for (auto ut8_chars : utf8string_range("Hello, 日本語と Мир!"))
{
cout << ut8_chars << endl;
}
}
getwchar получает 0x0430, а надо 0xd0b0, каким символом и является. …а надо 0xd0b0, каким символом и является. …0xd0b0, каким символом и является. …0xd0b0
Я уже свой деюникодер кидал сюда, впрочем кину ещë раз
int utfprocesschar(int in)
{
static int m = -1, k = 0; //multibyte state
static int uc = 0; //unicode char
if( !in )
{
m = -1;
k = 0;
uc = 0;
return 0;
}
// Get character length
if(m == -1)
{
uc = 0;
if( in >= 0xF8 )
return 0;
else if( in >= 0xF0 )
uc = in & 0x07, m = 3;
else if( in >= 0xE0 )
uc = in & 0x0F, m = 2;
else if( in >= 0xC0 )
uc = in & 0x1F, m = 1;
else if( in <= 0x7F)
return in; //ascii
// return 0 if we need more chars to decode one
k=0;
return 0;
}
// get more chars
else if( k <= m )
{
uc <<= 6;
uc += in & 0x3F;
k++;
}
if( in > 0xBF || m < 0 )
{
m = -1;
return 0;
}
if( k == m )
{
k = m = -1;
return in;
}
return 0;
}
переделай в цикл с getchar, убери статики и оно будет потокобезопасно.
дорогие всё никак не исчезающие любители приравнивать wchar к «юникоду»:
1) приведите выдержку из стандарта вашей любимой сишечки где wchar приравнен к «юникоду»
2) потрудитесь объяснить что такое «юникод». Вы вообще в курсе что это название стандарта и что способов кодирования юникода легко и непринуждённо наберётся с десяток в любом варианте применения?