Программа, обрабатывающая символы строки
Написал программу, которая проходит по строке и считает, сколько раз встречается каждый символ. В консоли программа выводит символы (по возрастанию их кодов в кодировке) и их количество повторений. Но проблема в том, что с некоторыми строками возникают проблемы. Так он неверно считывает строку є№ё·¶µґіІ±°Ї®¬«Є©Ё§¦Ґ¤ и выводит неправильные символы и их подсчёт. Скорее всего, это связано с тем, что эти символы не входят в кодировку ASCII. Для символов в пределах этой кодировки всё работает, но с символами из unicode уже беда.
#include <stdio.h>
int main() {
unsigned char input_string[81000];
fgets(input_string, sizeof(input_string), stdin);
int char_counts[100000] = {0};
for (int i = 0; input_string[i] != '\0'; i++) {
char_counts[(int)input_string[i]]++;
}
for (int i = 0; i < 100000; i++) {
if (char_counts[i] > 0 && (char)i != '\n') {
printf("%c=%d\n", (char)i, char_counts[i]);
}
}
return 0;
}
Изменение 04.12.2023:
Использовал библиотеку wchar.h
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, ""); // установка локали
wchar_t input_string[81000];
fgetws(input_string, sizeof(input_string), stdin);
int char_counts[65536] = { 0 }; // расширение до 65536 для поддержки Unicode
for (int i = 0; input_string[i] != '\0'; i++) {
char_counts[(int)input_string[i]]++;
}
for (int i = 0; i < 65536; i++) {
if (char_counts[i] > 0 && (wchar_t)i != '\n') {
wprintf(L"%lc=%d\n", (wchar_t)i, char_counts[i]);
}
}
return 0;
}
Но весь смех в том, что в онлайн компиляторе всё корректно работает, а на моём visual studio вместо некоторых символов печатаются просто пробелы)) Менял настройки кодировок проекта, но это не помогло. Хочу вообще понять, можно ли решить данную задачу без использования сторонних библиотек, таких как wchar?
Ответы (1 шт):
Код ниже разбирает текст в кодировке UTF8 на отдельные символы. Сделан грубо, но работает. Как пример сойдёт:
#include <stdbool.h>
#include <stdio.h>
bool read_utf8_char(int *ord, char s[5]) {
int chr = getc(stdin);
if (chr == EOF) {
return false;
}
s[0] = (char)chr;
int k = 0;
if (chr >> 7 == 0) {
*ord = chr;
} else if (chr >> 5 == 6) {
k = 1;
*ord = chr & 31;
} else if (chr >> 4 == 14) {
k = 2;
*ord = chr & 15;
} else if (chr >> 3 == 30) {
k = 3;
*ord = chr & 7;
}
for (int i = 0; i < k; ++i) {
int chr = getc(stdin);
if (chr == EOF) {
return false;
}
s[i + 1] = (char)chr;
*ord = (*ord << 6) | (chr & 63);
}
s[k + 1] = '\0';
return true;
}
int main() {
int ord;
char s[5];
while (read_utf8_char(&ord, s)) {
printf("%s %10d %10x\n", ((ord < 32) ? "?" : s), ord, ord);
}
}
$ gcc -std=c11 -pedantic -Wall -Wextra -Werror -Wwrite-strings -Wconversion dump-chars.c $ echo "є№ё·¶µґіІ±°Ї®¬«Є©Ё§¦Ґ¤" | ./a.out є 1108 454 № 8470 2116 ё 1105 451 · 183 b7 ¶ 182 b6 µ 181 b5 ґ 1169 491 і 1110 456 І 1030 406 ± 177 b1 ° 176 b0 Ї 1031 407 ® 174 ae 173 ad ¬ 172 ac « 171 ab Є 1028 404 © 169 a9 Ё 1025 401 § 167 a7 ¦ 166 a6 Ґ 1168 490 ¤ 164 a4 ? 10 a