Не отображаются русские символы в СИ. Вместо них появляются английские аналоги

Рейтинг: 1Ответов: 1Опубликовано: 17.02.2023

Не отображаются русские символы в СИ. Вместо них появляются английские аналоги.

Можете сами скомпилировать если хотите. Помогите

Программа должна выводить список гласных букв, содержащихся в каждом слове, разделенном пробелом.

Но она выводит английские буквы. хотя я везде использую русские.

#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;
        }
    }
}

Ответы

▲ 0

Я бы настоятельно рекомендовал наладить вывод 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$ 

Что не понятно, спрашивайте в комментариях.