Не отображаются русские символы в СИ. Вместо них появляются английские аналоги
Не отображаются русские символы в СИ. Вместо них появляются английские аналоги.
Можете сами скомпилировать если хотите. Помогите
Программа должна выводить список гласных букв, содержащихся в каждом слове, разделенном пробелом.
Но она выводит английские буквы. хотя я везде использую русские.
#pragma execution_character_set("utf-8")
#include <stdio.h>
#include <string.h>
#include <wchar.h>
void ifcharinset(wchar_t c, wchar_t* vowels, int* setvowels);
int main() {
wchar_t str[100] = L"Языки программирования";
wchar_t x[256] = { L'f', L' ', L'\0' };
wcscat(str, x);
wcscpy(x, str);
wcscpy(str, x);
wprintf(L"%ls\n", str);
wchar_t vowels[100] = { L'а', L'е', L'Ы', L'и', L'о', L'у', L'Ю', L'Я', L'э', L'Я' };
int setvowels[100] = {0};
int k = 0;
for (int i = 1; i < wcslen(str); i++) {
if (str[i] != L' ' && str[i-1] == L' ')
k++;
if (str[i] != L' ' && str[i-1] == L' ' && k > 1 ) {
for(int ii = 0; ii < wcslen(vowels); ii++) {
if (setvowels[ii] == 0)
vowels[ii] = 0;
setvowels[ii] = 0;
}
}
if (str[i] != L' ') {
ifcharinset(str[i], vowels, setvowels);
for(int ii = 0; ii < wcslen(vowels); ii++) {
if (setvowels[ii] == 1)
wprintf(L"%lc", vowels[ii]);
}
wprintf(L"\n");
}
}
for (int i = 0; i < wcslen(vowels); i++) {
if (vowels[i] != 0)
wprintf(L"%lc ", vowels[i]);
}
return 0;
}
void ifcharinset(wchar_t c, wchar_t* vowels, int* setvowels) {
for(int i = 0; i < wcslen(vowels); i++) {
if (c == vowels[i]) {
setvowels[i] = 1;
}
}
}
Ответы (1 шт):
Я бы настоятельно рекомендовал наладить вывод utf-8 в вашей системе и использовать эту кодировку для решения.
Собственно, все что нужно знать о кодировке для этой задачи описано в https://ru.wikipedia.org/wiki/UTF-8
Программа на Си может выглядеть вот так:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
// returns length in bytes of utf-8 symbol
// for invalid symbols returns 1 too
// see https://ru.wikipedia.org/wiki/UTF-8
int
utf8_len (const char *s)
{
static int step[32] = {[0 ... 15] = 1, // 0xxx xxxx ascii
[16 ... 23] = 1, // 10xx xxxx invalid
[24 ... 27] = 2, // 110x xxxx 2-bytes utf-8
3, 3, // 1110 xxxx 3 bytes utf-8
4, // 1111 0xxx 4 bytes utf-8
1 // 1111 1xxx invalid
};
return step[((unsigned char *)s)[0] >> 3];
}
// for valid utf-8 symbol
// returns length in bytes of valid utf-8 symbol
// puts unicode to `*puc` and zero terminated utf8 bytes to `utf8_sym[]`
// 0 if invalid first byte
// -N if invalid N-th byte
int
get_utf8_sym (const char *str, int *puc, char utf8_sym[])
{
utf8_sym[0] = *str; utf8_sym[1] = 0;
int s = utf8_len(str);
static int mask[5] = {0, 0, 0x1f, 0xf, 0x7};
int uc = 0;
if (s == 1 && (*str & 0x80))
return 0;
uc = *str & mask[s];
for (int i = 1; i < s; i++) {
if ((str[i] & 0xc0) != 0x80)
return -i;
utf8_sym[i] = str[i]; utf8_sym[i + 1] = 0;
uc = (uc << 6) | (str[i] & 0x3f);
}
if (puc)
*puc = uc;
return s;
}
int
is_rus_vowel (const char *symbol)
{
#define RUS_VOWELS "АЕЁИОУЫЭЮЯаеёиоуыэюя"
return strstr(RUS_VOWELS, symbol) ? 1 : 0;
}
// returns number of different vowels in the `word[]`
// put this vowels to the `v_set[]`
int
get_rus_vowels (const char *word, char v_set[])
{
int j = 0, n_v = 0;
v_set[j] = 0;
for (int i = 0, step; word[i]; i += step) {
char c[5];
step = get_utf8_sym(word + i, 0, c);
if (step <= 0) {
/* if you want to check invalid utf-8 character in the text: * /
fprintf(stderr, "'%s': invalid utf-8 symbol in pos %d (code %d byte: 0x%02x)\n",
word, i, step, word[i - step] & 0xff);
/ **/
step = 1;
continue;
}
if (step == 2) // this symbol can be russian
if (is_rus_vowel(c)) {
if (!strstr(v_set, c)) { // check duplicate
v_set[j++] = word[i], v_set[j++] = word[i + 1];
n_v++;
v_set[j] = 0;
}
}
}
return n_v;
}
// returns position of word in `s[]`
// or EOF if there are no words
// puts length of the word (in bytes) into `*wlen`
int
get_word (const char *s, int *wlen)
{
#define W_SEPARATORS " \n\r\t"
int pfx_l = strspn(s, W_SEPARATORS); // skip initial spaces
if (!s[pfx_l])
return EOF;
*wlen = strcspn(s + pfx_l, W_SEPARATORS); // all non-spaces are taken as a word
return pfx_l;
}
int
main (int ac, char *av[])
{
char str[100] = "Языки программирования";
char *cur_ptr = str;
for (int word_start = 0, word_len = 0;
(word_start = get_word(cur_ptr, &word_len)) != EOF;
cur_ptr += (word_start + word_len)) {
char word[word_len + 1];
memcpy(word, cur_ptr + word_start , word_len); word[word_len] = 0;
char rus_vowels[word_len + 1];
int n = get_rus_vowels(word, rus_vowels);
printf("'%s' has %d russian vowels: [%s]\n",
word, n, rus_vowels);
}
return 0;
}
Как видите, все очень просто. Основная логика реализована в функции get_rus_vowels() с использованием стандартных строковых функций.
Транслируем и запускаем:
avp@avp-desktop:~/avp/hashcode$ gcc t-utf8-rus-vowel.c && ./a.out
'Языки' has 3 russian vowels: [Яыи]
'программирования' has 4 russian vowels: [оаия]
avp@avp-desktop:~/avp/hashcode$
Что не понятно, спрашивайте в комментариях.