LINUX.ORG.RU

Как посчитать длину MBCS-строки без учёта концевых пробелов (на C)?

 , ,


0

1

Дано:
есть ANSI строка.

Надо:
посчитать её длину без концевых пробелов.

Нужно научиться вычислять длину строки без концевых пробелов правильно.

А почему бы не зайти с обратно стороны, обрезать строку, удалив все конечные пробелы и взять ее длину?

Kronick
()
Ответ на: комментарий от Kronick

Потому что именно так и было сделано, и это привело к ошибке. Всю историю читай по ссылке в стартовом посте

Einstok_Fair ★★☆
() автор топика

пока нравится вот эа функция:
http://man7.org/linux/man-pages/man3/mbsrtowcs.3.html

перебирать по одному символу
запоминать последний непробел

Единственное что меня смущает - неясно, к тому ли семейству функций эта функция принаделжит. Может она для другой кодировки...

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

Я имею ввиду брать по 2 символа и проверять их, то есть встретил ты «0x0420» - и понял что это не пробел, встретил «0х0020» - пробел. А дальше как я описал в первом посте.

Kronick
()
Ответ на: комментарий от Einstok_Fair

Судя по твоему основному вопросу о букве «Р», у тебя не UTF-8, так как в ней буква «Р» не может быть закодирована как 0x0420.

uuwaan ★★
()

YПОРNHУM

Сабж.

mos ★★☆☆☆
()
Ответ на: комментарий от uuwaan

верное наблюдение. Но дело в том, что я не отлаживал пошагово а только на исходники смотрел и предположения делал, да тестовый пример прогнал.

#include <ctype.h> // isspace

WCHAR *stringUnicode

while ((StringLen > 0) && (isspace ((int) ((unsigned char) *(Src + StringLen - 1)))))
			StringLen--;
		if (StringLen == 0)
StringLen = 1;

тестовый пример показывает, что концевые буква(или буквы) Р отрезаются этим кодом.

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)

У юникода всё что после 0x7F — признак многобайта, насколько я знаю. Вот и думай как посчитать.

a1batross ★★★★★
()

https://ru.wikipedia.org/wiki/UTF-8

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

Kronick
()
Ответ на: комментарий от Einstok_Fair

Как-то так. Пляски с перекастом указателя через int не понятно зачем там.

while ((StringLen > 0) && iswspace(Src[StringLen-1]))
  StringLen--;
if (StringLen == 0)
 StringLen = 1;

uuwaan ★★
()
Ответ на: комментарий от uuwaan

Да, твой код работает! Да здравствует СССР!

Einstok_Fair ★★☆
() автор топика

никак. понятие «пробел» там отсутствует. как и длина. есть только iswspace().

dzidzitop ★★
()
Ответ на: комментарий от uuwaan

Пляски с перекастом указателя через int не понятно зачем там.

Нет там никаких плясок. зарыменовывается *(str+len-1), char преобразуется в unsigned char, а он в int.

vodz ★★★★★
()
Последнее исправление: vodz (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

а зачем?

Вам уже незачем, это работает (и только так правильно и никак иначе) только для однобайтных кодировок.

vodz ★★★★★
()
Ответ на: комментарий от uuwaan

Вот именно, что однобайтных. А там wchar_t. Поэтому и непонятно, зачем перекасты.

Ох. Нет там никакой ошибки! Это правильный код, который не расчитан был для многобайтников. Потому надо его менять полностью. Но никаких плясок там нет и не было.

vodz ★★★★★
()

mbtowc() извлекает из мультибайтовой строки один мультибайтовый символ и конвертирует его в широкий символ. iswspace() проверяет, является ли широкий символ пробелом. Значит в цикле извлекаешь, проверяешь, приращиваешь счетчик байтов или символов, смотря что тебе нужно.

iliyap ★★★★★
()
Ответ на: комментарий от Kronick

ТС сам пишет, значит у него UTF-8, разве нет?

Это было предположение взятое из воздуха, которое надо бы перепроверить, но лень.

Возможно, что это было неверное предположение.

Работает же...

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от dzidzitop

и в какой же реализации символ пробела имеет код != 32? или когда в играх пишут case event.key == 32 это значит антипаттерн такой и когда-то это работать перестанет ведь код пробела зависит от реализации а на АСКИ все чихали ашга

anonymous
()
Ответ на: комментарий от annulen

спасибо, интересная заметка, думаю в будущем пригодится

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от anonymous

В любой, не основанной на ASCII. А когда в стандарте C базовый набор символов будет объявлен ASCII - тогда и пусть пишут.

В отличие от таких писателей тот же glibc разрабатывается с оглядкой на кроссплатформенность. Для справки, посмотри на реализацию std::from_chars там - увидишь switch на весь латинский алфавит. От дурости своей они его там написали, и от глупости.

Но поскольку кроссплатформенный код на C любители обмазаться сишкой писать не могут - то и будет мне поступать бесконечная вереница таких постов как у тебя.

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.