LinuxForum.Fans
Тема

BASH и С\С++. Псевдографические символы.

Автор: gramozeka 23 сообщений 6695 просмотров
#166177

Вопрос : как на BASH'е или С\С++ напечатать псевдографические символы из расширенной таблицы "Box Drawing (2500—257F) & Block Elements (2580—259F)" ???
гуглил, гуглил -ни черта не нагуглил ...

#166188

gramozeka, ты о чём?
[console]$ echo "▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏"
▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏
[/console]

#166190

а, понял что нужно:
[console]$ echo -e "\xE2\x96\x91"
░
[/console]
Код ищется так:
1) копипастим нужный символ
[console]$ echo -n "╬" | xxd -c1
0000000: e2 .
0000001: 95 .
0000002: ac .
[/console]
2) подставляем найденные коды
[console]$ echo -e "\xE2\x95\xAC"
╬
[/console]

#166193
text
Unicode UTF-8:
0x00000000 — 0x0000007F: 0xxxxxxx
0x00000080 — 0x000007FF: 110xxxxx 10xxxxxx
0x00000800 — 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 — 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

имеем символ в UTF8
$ echo -e "\xE2\x96\x91"
E29691
111000101001011010010001
0010 010110 010001
0x2591
░

#166255

спасибо доктор .. smile

#166315

Немного изврата по мотивам обсуждения и таблицы:

text

#include <stdio.h>
main()
{
    unsigned int test = 0x00250c;
    unsigned int test1 = ((test & 0xF000)>>12) + ((test & 0xfc0)<<2) + ((test & 0x3f)<<16) + 0x8080e0;
    printf("%x %x\n",test1,0x8c94e2);
    unsigned int wchar[2] = {0x8c94e2, test1};
    int i;
    for (i = 0;i<2;i++)
        printf("%s\n", wchar+i);
}
#166325

voral, ну и на bash'е
[console]$ ./u2u.sh 0x2591
2 22 17
226 150 145
\xE2\x96\x91
░
[/console]

text
#!/bin/bash

M2=4096 M1=64 X="$1" (( Y = $X ))

(( B2 = Y / M2 )) (( Y -= B2 * M2 )) (( B1 = Y / M1 )) (( B0 = Y - B1 * M1 ))

echo $B2 $B1 $B0 (( B2 += 14 * 16 )) (( B1 += 128 )) (( B0 += 128 )) echo $B2 $B1 $B0

S=`printf "\x5Cx%X\x5Cx%X\x5Cx%X\n" $B2 $B1 $B0`

echo "$S" echo -e "$S"

#166371

ну раз такое дело ткните носом где об этих алгоритмах почитать .. а то я дальше своей подписи :O не продвинулся ..

#166375

gramozeka, про bash или про C?

#166379

drBatty да про обоих , я уж целый день упражняюсь , а такими темпами глядишь к пенсии и "Hello World !" в рамочке траурной осилю . smile

#166399
gramozeka написал:
ну раз такое дело ткните носом где об этих алгоритмах почитать .. а то я дальше своей подписи :O не продвинулся ..

я ни где не читал... Пришлось несколько софтин где с данными в хексе пришлось много работать да про работу с битами тут несколько раз последнее время говорили..... А с псевдографикой я не то что в линуксе я в си первый раз столкнулся, а из поса дока еще и про связь с utf8 узнал.... Стало интересно поковырять. Вот табличку варганил

text

#include <stdio.h>
unsigned int getcode(unsigned int index)
{
    return ((index & 0xF000)>>12) + ((index & 0xfc0)<<2) + ((index & 0x3f)<<16) + 0x8080e0;
}
unsigned int re(unsigned int index)
{
    return ((index & 0xFF0000)>>16) + (index & 0xff00) + ((index & 0xff)<<16);
}
main()
{
    unsigned int test1=0;
    unsigned int *wchar1 = &test1;
    int i;
    for (i = 0x2500;i<=0x259F;i++)
    {
        test1 = getcode(i);
        printf("%x\t%x\t%s\n",i, re(test1),wchar1);
    }
}
#166404

voral собсно это мне и нужно было , буду разбираться как это работает ...

#166421
voral написал:
Пришлось несколько софтин где с данными в хексе пришлось много работать да про работу с битами тут несколько раз последнее время говорили..... А с псевдографикой я не то что в линуксе я в си первый раз столкнулся, а из поса дока еще и про связь с utf8 узнал.... Стало интересно поковырять. Вот табличку варганил

между прочим - зря. так никто не делает.
битовые операции - слабое место С.

voral написал:
return ((index & 0xF000)>>12) + ((index & 0xfc0)<<2) + ((index & 0x3f)<<16) + 0x8080e0;

смените плюс на |.
оно конечно и так работает, но некрасиво.

#166423
text
#include <stdio.h>
#include <string.h>

unsigned getcode(unsigned index) { unsigned a = index & 0xF000; a >>=12; unsigned b = index & 0xfc0; b <<= 2; unsigned c = index & 0x3f; c <<=16; return a | b | c | 0x8080e0; }

unsigned re(unsigned index) { unsigned a = index & 0xFF0000; a >>= 16; unsigned b = index & 0xff00; unsigned c = index & 0xff; c <<= 16; return a | b | c; }

int main() { unsigned code; int i, j; char str[8]; printf("┏━━━━┯━━━━━━┯━┳━━━━┯━━━━━━┯━┳━━━━┯━━━━━━┯━┳━━━━┯━━━━━━┯━┓\n"); j = 1; for (i = 0x2500;i<=0x259F;i++) { if(j == 1) printf("┃"); code = getcode(i); memcpy(str, &code, sizeof(unsigned)); printf("%04x│%06x│%s┃", i, re(code), str); if(j >= 4) { printf("\n"); j = 0; } j++; } printf("┗━━━━┷━━━━━━┷━┻━━━━┷━━━━━━┷━┻━━━━┷━━━━━━┷━┻━━━━┷━━━━━━┷━┛\n"); return 0; }

#166433
drBatty написал:

между прочим - зря. так никто не делает.
битовые операции - слабое место С.

Если честно, я еще и их на этом примере не много погонял (много, что в итоге осталось за кадром) т.к. на практике с битовыми операциями сталкивался от силы пару раз.

drBatty написал:

смените плюс на |.
оно конечно и так работает, но некрасиво.

логично :)

#166474

это получается вы там что-то с битами химичите так ?? где почитать , дайте ссыль ... или на пальцах растолкуйте , теорию я читал , только как это с практикой сочетается ???

#166542
gramozeka написал:
или на пальцах растолкуйте

попробую...
итак: имеются три основные битовые операции:
1) инверсия

text
0 => 1
1 => 0

2)логическое И

text
0 & 0 => 0
0 & 1 => 0
1 & 0 => 0
1 & 1 => 1

3) логическое ИЛИ

text
0 | 0 => 0
0 | 1 => 1
1 | 0 => 1
1 | 1 => 1

В Си логические операции выполняются над всеми байтами сразу. Обычно используют тип unsigned, который имеет длину типичную для машинного слова (32 или 64 бита сегодня).
Есть ещё операция ^
x ^ y == x & ~y | ~x & y
Она работает как ИЛИ, только 1 ^ 1 => 0. Потому и называется "исключающее или", или короче XOR.

Приоритеты:
~ самый высокий (инверсия)
&
|

(из-за приоритетов & иногда называют "логическим умножением", а | "логическим сложением". Ну и из-за правил. Это действительно сложение, но по модулю 2. Т.е. двойка откидывается. Потому 1+1 => 2 => 2+0 => 0(mod2))

Биты двигать нельзя (К.О.), но слова из многих бит - можно. И влево, и вправо. Выдвигаемые биты бесследно исчезают (потому-то это слабое место - всегда надо помнить о потере информации).

x << n это сдвиг x влево на n битов. Операция бинарная, сам x не меняется.
x >> n это сдвиг вправо.

Сколько битов в unsigned - никто не знает. Биты выдвигаются в никуда. Потому пользоваться сдвигами в Си == ходить по минному полю.
Вот voral потренировался сегодня, завтра радостно что-то напишет. А после завтра это рухнет :O
Ибо, как именно двигаются слова - в стандарте не определено (особенно знаковые), а значит, сегодня они двигаются так, а завтра - эдак.

И тем не менее, их иногда приходится применять. Ибо - быстро. x<<1 это тоже самое, что x*2, но намного быстрее. (но опять-таки - не всегда. 128<<1 == 0, если 128 - это char).

Логические операции применяются шире. Иногда удобно делать логику именно на битах. ИМХО можно полагать, что unsigned это как минимум 32 бита. Хотя такой быдлокод ОБЯЗАТЕЛЬНО надо подробно прокоментировать, что-бы починить его, когда он сломается.

Кстати, чисто заменой побитовых операций на обычные, можно значительно ускорить работу программы (ага, как это и не парадоксально). В частности сказывается то, что CPU распараллеливает не только данные, но и операции. Потому далеко не факт, что одна операция над двумя битами будет быстрее, чем две операции над двумя числами. Ещё в iP1 появился второй конвейер.

#166573

записал в "полезности" ...
:D - буду изучать , кстати в учебнике об этом совсем мало и ни одного практического примера кроме умножения .. smile

#166580
gramozeka написал:
кстати в учебнике об этом совсем мало и ни одного практического примера кроме умножения ..

дык говорю-же: слабое место Си :(
не сказать что баг, но не иссякающий источник багов...
вроде побочных эффектов.

Кстати, приоритеты не очень логичные, и лучше не писать в одну строчку. Лучше по одной операции в одной строке. Тоже кладезь багов...

В паскакалях есть "наборы", которые, как я понял, те-же булевы операции. Но они огорожены. А тут... А ещё порядок байт вообще-говоря разный бывает, обычно сначала младший, но не всегда. Естественно, порядок байтов влияет на сдвиг.

На практике, сдвигами можно заменить умножение на константу. Например
(x << 1) + (x << 3) == 2*x+8*x == 10*x.
(опять таки не факт, что это быстрее. А если даже быстрее, не факт, что компилятор об этом не знает. Я уже так нарывался - мучаешься, пишешь... А потом оказывается, что компилятор написал даже лучше меня.)

#166590

поправка:

drBatty написал:
а | "логическим сложением". Ну и из-за правил. Это действительно сложение, но по модулю 2. Т.е. двойка откидывается. Потому 1+1 => 2 => 2+0 => 0(mod2))

сложение по модулю 2 это xor

drBatty написал:
Вот voral потренировался сегодня, завтра радостно что-то напишет. А после завтра это рухнет

С99 с его uint32_t спасёт отца русской демократии...

drBatty написал:
Естественно, порядок байтов влияет на сдвиг.

не должен, но я бы 3 раза проверил если бы работал с биг-эндингом... а вот приведение типов разного размера он может порушить...

Войдите или зарегистрируйтесь, чтобы ответить.