Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/48: Рейтинг темы: голосов - 48, средняя оценка - 5.00
28 / 27 / 7
Регистрация: 11.06.2011
Сообщений: 387

Как узнать длину строки, содержащей кириллицу?

06.04.2015, 18:04. Показов 11521. Ответов 40
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Сделал такой код
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
#include <string>
#include <iostream>
 
int main (int argc, char * argv[]){
 
    std::string test="проверка";
 
    std::cout << "length: " << test.length() << std::endl;
 
    return 1;
}
ответ получил
length: 16
Почему так, я понимаю. Потому что два байта на букву вышло. Есть какие то готовые функции, чтобы посчитать реальное количество символов ? Может что-то можно указать, что строка содержит UTF-8 и работать нужно с ней соответственно ?

OS: Linux
Локаль: ru_RU.UTF-8
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.04.2015, 18:04
Ответы с готовыми решениями:

Как узнать длину строки TCHAR?
Как узнать длину строки? TCHAR szText = _T(&quot;&quot;); Добавлено через 1 минуту 1 IntelliSense: идентификатор &quot;_tsclen&quot; не...

Как узнать длину строки
Как узнать длину строки?

Как узнать длину строки
Казалось бы, вопрос глупый. Берём что-то наподобие string s = &quot;Veterinar&quot;; int len = s.Length; В итоге узнаём длину строки. Но при...

40
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
07.04.2015, 10:18
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от admsasha Посмотреть сообщение
проверка, length: 16
Так это может еще зависить от кодировки исходника.
admsasha, используй библиотеку, которую предложили выше. Вот мой небольшой пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <fstream>
#include <string>
#include <utf8.h>
 
int utf8_count(const std::string& utf8)
{
   auto first = utf8.begin();
   auto last = utf8.end();
   int utf8_count = 0;
   while (first < last)
   {
      auto it = std::next(first);
      utf8::next(first, last);
      if (it != first) ++utf8_count;
   }
   return utf8_count;
}
 
int main()
{
   std::ifstream ifs1("file1_utf8.txt"); // 8 русских символрв (2 байта на символ)
   std::ifstream ifs2("file2_utf8.txt"); // 3 иэроглифа (3 байта на символ)
   std::string utf8_str1, utf8_str2;
 
   ifs1 >> utf8_str1;
   ifs2 >> utf8_str2;
   std::cout << "8 symbols (" << utf8_str1.length() << " bytes)\n";
   std::cout << "3 symbols (" << utf8_str2.length() << " bytes)\n";
 
   std::cout << "utf8 symbols: " << utf8_count(utf8_str1) << "\n";
   std::cout << "utf8 symbols: " << utf8_count(utf8_str2) << "\n";
}
Вложения
Тип файла: txt file1_utf8.txt (16 байт, 3 просмотров)
Тип файла: txt file2_utf8.txt (9 байт, 2 просмотров)
0
28 / 27 / 7
Регистрация: 11.06.2011
Сообщений: 387
07.04.2015, 12:51  [ТС]
DiffEreD, почему не просто
C++
1
size_t dist = utf8::distance(utf8_str1.begin(),utf8_str1.end())
?
1
 Аватар для DiffEreD
1458 / 795 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
07.04.2015, 14:12
Да, так проще. Недосмотрел.
0
0 / 0 / 0
Регистрация: 01.08.2024
Сообщений: 1
27.11.2024, 20:27
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Функция для подсчета букв в строке
int countLetters(string& str) {
    int count = 0;
    int k1=0;
    int k2=0;
    int k3=0;
    int k4=0;
    string A="!@#$%^&*()_+{}[]=-?|/.,<>~` ";
    string B="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (char& c : str) {
        for (char& c1 : A){
            if (c==c1){
                k1=k1+1;
            }
        }
        for (char& c2 : B){
            if (c==c2){
                k3=k3+1;
            }
        }
        k2++;
    }
    count = (k2-k3-k1)/2+k3;
    return count;
}
0
87 / 87 / 18
Регистрация: 11.06.2018
Сообщений: 302
27.11.2024, 22:06
JustDanya, я б на твоём месте постеснялся такое выкладывать.
0
 Аватар для volodin661
7174 / 2351 / 354
Регистрация: 10.12.2013
Сообщений: 8,152
28.11.2024, 00:21
разница между годом 2015 и годом 2024

ВОПРОС: C++; what library function compute length of the string with utf-8 characters ?
ОТВЕТ:
n C++, to compute the length of a string containing UTF-8 characters, the standard library function std::string::length() (or std::string::size()) will give you the number of bytes in the string, not the number of characters or code points, since UTF-8 characters can vary in length (from 1 to 4 bytes).

If you want to compute the number of characters (code points) in a UTF-8 encoded string, you'll need to handle multi-byte sequences properly.

Here’s how you can do it using the C++ Standard Library with UTF-8 encoded strings:
Option 1: Using std::wstring and std::codecvt (C++11)

Although C++11 doesn't directly handle UTF-8 to Unicode code points conversion, you can use the std::codecvt facet to convert a UTF-8 string to a wide-character string (std::wstring), and then get the length in terms of Unicode code points. This method is deprecated in C++17 and later, but it still works in C++11 and C++14.
Option 2: Using std::u8string and manual decoding (C++17 onwards)

For better support, starting with C++17, you can work with std::u8string (UTF-8 encoded string literal) and manually decode the string to get the number of code points. Here's how to do it:
Example code using std::u8string:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>
#include <stdexcept>
 
// Function to count UTF-8 code points in a string
size_t count_utf8_characters(const std::string& str) {
    size_t count = 0;
    size_t i = 0;
    while (i < str.size()) {
        unsigned char c = str[i];
        if ((c & 0x80) == 0) {
            // 1-byte character (ASCII)
            ++i;
        } else if ((c & 0xE0) == 0xC0) {
            // 2-byte character
            i += 2;
        } else if ((c & 0xF0) == 0xE0) {
            // 3-byte character
            i += 3;
        } else if ((c & 0xF8) == 0xF0) {
            // 4-byte character
            i += 4;
        } else {
            throw std::invalid_argument("Invalid UTF-8 byte sequence");
        }
        ++count;
    }
    return count;
}
 
int main() {
    std::string utf8_str = u8"Hello, 世界";  // Example UTF-8 string
    std::cout << "Number of UTF-8 characters: " << count_utf8_characters(utf8_str) << std::endl;
    return 0;
}
Explanation:

This code defines a function count_utf8_characters that iterates over the UTF-8 string, recognizing the byte patterns for 1-byte, 2-byte, 3-byte, and 4-byte UTF-8 characters.
It handles each character by checking the leading byte of the UTF-8 sequence to determine how many bytes to skip and then increments the count for each character.
This ensures that you are counting the number of Unicode code points, not just the number of bytes.

Output:

For the string "Hello, 世界":
Java
1
Number of UTF-8 characters: 9
Here, "Hello, " is 7 ASCII characters (1 byte each), and "世界" consists of 2 UTF-8 characters (3 bytes each).
Important Considerations:
  • UTF-8 is variable-length encoding, and the number of bytes per character can vary.
  • The std::string::length() function gives you the length in bytes, not in characters.
  • If you're working with Unicode code points (characters), you'll need to decode the bytes appropriately (as done in the example).
0
274 / 206 / 30
Регистрация: 26.11.2022
Сообщений: 908
28.11.2024, 00:54
самое забавное начинается дальше - ибо количество кодепоинтов в строке не всегда соответствует количеству символов.
некоторые символы получаются из двух кодепоинтов ))
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 01:27
Цитата Сообщение от admsasha Посмотреть сообщение
std::string test="проверка";
Ну это пример то нехороший.
Надо было и русские и английские символы туда поместить.
Русские могут быть по два байта, а английские всегда однобайтные. (utf8)
Тогда в натуре интересно будет.

Добавлено через 28 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <windows.h>
#include <iostream>
 
int main()
{
    setlocale(LC_ALL, "RUSSIAN");
 
    char utf8[35]
{ 0xd0,0x97,0xd0,0xb4,0xd0,0xb5,0xd1,0x81,0xd1,0x8c,0x20,0xd0,0xbb,0xd0,0xb5,0xd0,0xb6,0xd0,0xb8,0xd1,0x82,0x20,0x75,0x74,0x66,0x38 };
    
    std::string test = utf8;
    
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, test.c_str(), -1, NULL, 0);
 
    
printf("%d - реальное количество символов \n%d - strlen(test \n", wchars_num, strlen(test.c_str()));
 
    
    wchar_t* wstr = new wchar_t[wchars_num];
MultiByteToWideChar(CP_UTF8, 0, test.c_str(), -1, wstr, wchars_num);
 
wprintf(L"%s", wstr);
    
delete[] wstr;
 
    getchar();
    return 0;
}
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 01:31

У меня таких ситуёвин не возникало.
У меня в string вставляет ANSI.
Я намоделировал.
Вообще нормальные люди на винде делают так.
Есть и на плюсах функции для конвертирования.
C++
1
2
std::wstring_convert<std::codecvt_utf8<wchar_t>> wconv;
                            std::wstring wstr = wconv.from_bytes(cut_ptr);
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 01:56
Вот вам то же самое на плюсах.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <codecvt>
int main()
{
    setlocale(LC_ALL, "RUSSIAN");
 
    char utf8[35]
{ 0xd0,0x97,0xd0,0xb4,0xd0,0xb5,0xd1,0x81,0xd1,0x8c,0x20,0xd0,0xbb,0xd0,0xb5,0xd0,0xb6,0xd0,0xb8,0xd1,0x82,0x20,0x75,0x74,0x66,0x38 };
    
std::wstring_convert<std::codecvt_utf8<wchar_t>> wconv;
         
wprintf(L"%s\n %d", wconv.from_bytes(utf8).c_str(),
                    wcslen(wconv.from_bytes(utf8).c_str()));
 
getchar();
    return 0;
}
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 02:01

Здесь похоронен utf8
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
28.11.2024, 10:03
Цитата Сообщение от Aledveu Посмотреть сообщение
некоторые символы получеются из двух кодепоинтов ))
Это тогда уже философский вопрос получается, что мы считаем: символы или знакоместа.

Вообще, на мой взгляд, вопрос "сколько символов в строке utf8" - бессмысленный. Вернее сказать так: если он реально возникает, то в проекте у нас явно не в той кодировке всё используется. Как минимум в месте возникновения этого вопроса.
Ибо если нам надо просто сохранять и строки и туда-сюда их гонять - то у нас не должно возникать вопросов "сколько в них символов", только "сколько байтов надо для хранения".
А если нужна какая-то посимвольная обработка - то надо выбирать кодировки с фиксированным размером символа в байтах, иначе эффективности нам не видать.
Хотя, в мире, где миллионы запросов и даже передача параметров между по сути функциями выполняется всякими джей-сонами - о какой вообще эффективности может идти речь
Сплошное надругательство над природными ресурсами
1
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
28.11.2024, 10:13
Цитата Сообщение от KSergey9 Посмотреть сообщение
Это тогда уже философский вопрос получается
Нужно выбрать форму нормализации: NFD, NFC, NFKD, NFKC.
Цитата Сообщение от KSergey9 Посмотреть сообщение
то надо выбирать кодировки с фиксированным размером символа в байтах
Это никак не поможет, например для combining characters.
Всё что вам даст постоянство в байтах - количество code-point'ов.
0
274 / 206 / 30
Регистрация: 26.11.2022
Сообщений: 908
28.11.2024, 12:54
Цитата Сообщение от KSergey9 Посмотреть сообщение
то надо выбирать кодировки с фиксированным размером символа в байтах
Это типичная ошибка - вы хоть utf32 используйте - всё равно придётся считать количество знакомест.
А делать это приходится когда вы пытаетесь показать символы на экране или чтобы вписаться в размеры окна или области на экране.
Поэтому utf8 предлагает вам просто сэкономить память ибо затраты на расчёт всё равно никуда не деть.
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 12:59
Я эффективно на char изобретаю.
Русский / английский работает. А другие я не понимай.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
if (!perm_delet) {// Если не запрещено писать строку
    // -----------------------------------
    short n{ 6 };
    static int store = n;
if (store == n)comp_0 = (char*)calloc(BUFSIZ * (n+1), sizeof(char));
 
if (store-- && !*cut_ptr) {// Буфер для строк. Что бы на realoc по одному символу не приходило.
    strcat(comp_0, msg.c_str()); strcat(comp_0, "\r\n");
         }
        else {
             strcat(comp_0, msg.c_str());// Последний "\r\n" не ставить. Ввалит функция.
        add_line(&ms, comp_0, volume);// Писать в массив всё не найденное(Функция с realloc)
            store = n;
            free(comp_0);
            comp_0 = NULL;
             }// -----------------------------------
          //add_line(&ms, msg.c_str(), volume);// Писать в массив всё не найденное(Функция с realloc)
        if (edit_txt_len && *cut_ptr) {// Алгоритм для увеличения мусорных расстояний между линками в файле
        
short ln_count = (short)dist(mersenne);// Случайное количество строчек
        
        if (((cnt[lst_lndx_count] - cnt[lst_lndx_count - 1]) - 1) < 6) {
char *comp = (char*)calloc(BUFSIZ*6, sizeof(char));// Обнулённый массив для сохранения строки,
            
            std::string msg_n;
    while (getline(myfile, msg_n) && ln_count--) {
        strcat(comp, msg_n.c_str()); strcat(comp, "\r\n");
            }
    *(strrchr(comp, '\r')) = '\0';// Отрезать последний "\r\n"
    add_line(&ms, comp, volume);
            free(comp);
        }
        ++lst_lndx_count;
    }      }
        } 
           }// Скобка чтения файла
       if (comp_0 != NULL) {// Если пара строк осталась в буфере то догнать в главный массив
           *(strrchr(comp_0, '\r'))='\0';
add_line(&ms, comp_0, volume);// Писать в массив всё не найденное(Функция с realloc)
           free(comp_0);
                }
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
28.11.2024, 14:26
Цитата Сообщение от Aledveu Посмотреть сообщение
всё равно придётся считать количество знакомест.
Количество знакомест или количество символов?
Короче, это какая-то философия пошла - что именно подразумевать под понятием "символ". Сначала надо о терминах договориться. В том числе и о рамках задачи "заменить символ в строке" - что именно под этим подразумевается.

С другой стороны, тема топика "Как узнать длину строки, содержащей кириллицу?", что существенно сужает круг неоднозначностей, т.к. всё отлично умещается
а) в кодировку с фиксированной длиной символа
б) не возникает никаких проблем с combining characters.

Добавлено через 1 минуту
Цитата Сообщение от Aledveu Посмотреть сообщение
когда вы пытаетесь показать символы на экране или чтобы вписаться в размеры окна или области на экране.
Это вообще абсолютно другая задача так-то, включающая в себя катастрофически бОльшее количество параметров, которые необходимо учесть.

Добавлено через 2 минуты
Я уже как-то высказывал здесь мысль, что задачи все эти - явно учебные, причем очень начального уровня. И явно взятые из методичек 30-ти летней давности, когда никаких проблем с utf-кодировками вообще не было у студентов.

И вот мне очень не понятно: когда преподы до сих пор задают задачки всё из тех же методичек - что они подразумевают?
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 14:42
Цитата Сообщение от KSergey9 Посмотреть сообщение
какая-то философия пошла
Философ...
filt_file(3).mp4
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 16:23

Для тех кто не китаец, но очень любит обрабатывать китайский.
0
 Аватар для Наталья8
639 / 397 / 68
Регистрация: 09.03.2016
Сообщений: 4,376
28.11.2024, 17:18
А вообще серьёзно...
Наверное можно настроить компилятор, что бы он в string, utf8 не вписывал?
0
28.11.2024, 17:39

Не по теме:

Цитата Сообщение от KSergey9 Посмотреть сообщение
т.к. всё отлично умещается
До первого копипаста с википедии текста с ударением :)

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
28.11.2024, 17:39

Как узнать длину строки?
Как узнать длинну строки string xc = &quot;asdfghjk&quot;; byte l = xc.length(); выше код дает сбой, кажеться он поределят...

Как узнать длину строки в пикселях?
Я там внизу спрашивала как узнать длину строки в пикселях. У меня строка есть и шрифт я знаю каким хочу ее печатать. Мне надо поточнее ее...

Как узнать длину строки в байтах?
Есть код: using (FileStream fs = File.Create(fileName)) { using (BinaryWriter binWriter =...

Как узнать длину массива(строки)
Пишу программу в WinAVК. Есть переменная указатель на массив: u08 *CMD_GSM_PTR; // Указатель на команду Переменная: u08 temp; ...

Как узнать длину строки в твипах?
... в твипах? Которая лежит в RichEdit да еще и неизвестно как отформатирована. С уважением NickStaves


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
После закрытия оутлука продолжает висеть процесс в диспетчере задач
Maks 27.10.2026
С недавнего времени в продакшене возникла проблема: при закрытии оутлука в диспетчере задач продолжал висеть процесс outlook. exe. Проблема возникла после установки MS Office 2021 LTSC на машинах, под. . .
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. https:/ / youtu. be/ VpfFZSUDGnQ. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru