Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Оценка необходимой ширины


Автор: ТарасАтавин 29.8.2013, 07:52
Шрифтом Arial с ведущими нолями в шестнадцатеричном представлении цифрами 0123456789ABCDEF выводятся номера строк, известно, сколько цифр отведено под один номер, надо оценить максимальную ширину номера, чтоб сами строки начинать гарантировано правее. Желательно не перебирать при этом сами номера от нулевого до последнего.

Автор: Dem_max 29.8.2013, 07:58
GetTextExtentPoint32()

Автор: ТарасАтавин 29.8.2013, 08:54
Читайте: 
Цитата(ТарасАтавин @  29.8.2013,  07:52 Найти цитируемый пост)
Желательно не перебирать при этом сами номера от нулевого до последнего.
. А функцию эту я знаю и даже использую.

Автор: Amp 29.8.2013, 11:01
Вариант выкинуть Arial и взять моноширный шрифт не подходит?

Автор: ТарасАтавин 29.8.2013, 11:20
Желательно всё таки Arial. Но мне не надо точно. Мне надо близко и с гарантией. То есть разрешается слегка ошибиться в строну увеличения, но не в строну уменьшения. Какая из моих цифр в Arial шире всех?

Автор: xvr 29.8.2013, 13:03
Цитата(ТарасАтавин @  29.8.2013,  08:54 Найти цитируемый пост)
Читайте: 

Переберите цифры (от 0 до F), выберите с максимальной шириной, прибавьте межсимвольный промежуток и умножте на количество цифр в номере строки.

Автор: akizelokro 29.8.2013, 14:04
Переберите цифры от 0 до F для данного шрифта, которая из них окажется самой широкой, из той составьте строку с максимальным количеством цифр в номере, возьмите ширину, немного накиньте "шоб було" и задача будет решена.

Добавлено через 2 минуты и 15 секунд
Цитата(xvr @  29.8.2013,  13:03 Найти цитируемый пост)
Переберите цифры (от 0 до F), выберите с максимальной шириной, прибавьте межсимвольный промежуток и умножте на количество цифр в номере строки.


Опять я не успел!  smile 
А ведь это один из немногих вопросов, на которые я знал ответ.  smile 

Автор: ТарасАтавин 29.8.2013, 14:50
Код
 int          i;
 int          L;
 std::wstring s[16];
 SIZE         Size[16];
 s[0]=L"";
 s[1]=L"";
 s[2]=L"";
 s[3]=L"";
 s[4]=L"";
 s[5]=L"";
 s[6]=L"";
 s[7]=L"";
 s[8]=L"";
 s[9]=L"";
 s[10]=L"";
 s[11]=L"";
 s[12]=L"";
 s[13]=L"";
 s[14]=L"";
 s[15]=L"";
 L=sizeof(size_t)*2;
 for (i=L; i>0; --i)
 {
  s[0]+=L'0';
  s[1]+=L'1';
  s[2]+=L'2';
  s[3]+=L'3';
  s[4]+=L'4';
  s[5]+=L'5';
  s[6]+=L'6';
  s[7]+=L'7';
  s[8]+=L'8';
  s[9]+=L'9';
  s[10]+=L'A';
  s[11]+=L'B';
  s[12]+=L'C';
  s[13]+=L'D';
  s[14]+=L'E';
  s[15]+=L'F';
 }
 GetTextExtentPoint32W(Context, s[0].c_str(), L, &Size[0]);
 GetTextExtentPoint32W(Context, s[1].c_str(), L, &Size[1]);
 GetTextExtentPoint32W(Context, s[2].c_str(), L, &Size[2]);
 GetTextExtentPoint32W(Context, s[3].c_str(), L, &Size[3]);
 GetTextExtentPoint32W(Context, s[4].c_str(), L, &Size[4]);
 GetTextExtentPoint32W(Context, s[5].c_str(), L, &Size[5]);
 GetTextExtentPoint32W(Context, s[6].c_str(), L, &Size[6]);
 GetTextExtentPoint32W(Context, s[7].c_str(), L, &Size[7]);
 GetTextExtentPoint32W(Context, s[8].c_str(), L, &Size[8]);
 GetTextExtentPoint32W(Context, s[9].c_str(), L, &Size[9]);
 GetTextExtentPoint32W(Context, s[10].c_str(), L, &Size[10]);
 GetTextExtentPoint32W(Context, s[11].c_str(), L, &Size[11]);
 GetTextExtentPoint32W(Context, s[12].c_str(), L, &Size[12]);
 GetTextExtentPoint32W(Context, s[13].c_str(), L, &Size[13]);
 GetTextExtentPoint32W(Context, s[14].c_str(), L, &Size[14]);
 GetTextExtentPoint32W(Context, s[15].c_str(), L, &Size[15]);
 return Max(Size[0].cx, Size[1].cx, Size[2].cx, Size[3].cx, Size[4].cx, Size[5].cx, Size[6].cx, Size[7].cx, Size[8].cx, Size[9].cx, Size[10].cx, Size[11].cx, Size[12].cx, Size[13].cx, Size[14].cx, Size[15].cx);

Автор: Dem_max 29.8.2013, 15:09
Цитата(ТарасАтавин @ 29.8.2013,  14:50)
Код
 int          i;
 int          L;
 std::wstring s[16];
 SIZE         Size[16];
 s[0]=L"";
 s[1]=L"";
 s[2]=L"";
 s[3]=L"";
 s[4]=L"";
 s[5]=L"";
 s[6]=L"";
 s[7]=L"";
 s[8]=L"";
 s[9]=L"";
 s[10]=L"";
 s[11]=L"";
 s[12]=L"";
 s[13]=L"";
 s[14]=L"";
 s[15]=L"";
 L=sizeof(size_t)*2;
 for (i=L; i>0; --i)
 {
  s[0]+=L'0';
  s[1]+=L'1';
  s[2]+=L'2';
  s[3]+=L'3';
  s[4]+=L'4';
  s[5]+=L'5';
  s[6]+=L'6';
  s[7]+=L'7';
  s[8]+=L'8';
  s[9]+=L'9';
  s[10]+=L'A';
  s[11]+=L'B';
  s[12]+=L'C';
  s[13]+=L'D';
  s[14]+=L'E';
  s[15]+=L'F';
 }
 GetTextExtentPoint32W(Context, s[0].c_str(), L, &Size[0]);
 GetTextExtentPoint32W(Context, s[1].c_str(), L, &Size[1]);
 GetTextExtentPoint32W(Context, s[2].c_str(), L, &Size[2]);
 GetTextExtentPoint32W(Context, s[3].c_str(), L, &Size[3]);
 GetTextExtentPoint32W(Context, s[4].c_str(), L, &Size[4]);
 GetTextExtentPoint32W(Context, s[5].c_str(), L, &Size[5]);
 GetTextExtentPoint32W(Context, s[6].c_str(), L, &Size[6]);
 GetTextExtentPoint32W(Context, s[7].c_str(), L, &Size[7]);
 GetTextExtentPoint32W(Context, s[8].c_str(), L, &Size[8]);
 GetTextExtentPoint32W(Context, s[9].c_str(), L, &Size[9]);
 GetTextExtentPoint32W(Context, s[10].c_str(), L, &Size[10]);
 GetTextExtentPoint32W(Context, s[11].c_str(), L, &Size[11]);
 GetTextExtentPoint32W(Context, s[12].c_str(), L, &Size[12]);
 GetTextExtentPoint32W(Context, s[13].c_str(), L, &Size[13]);
 GetTextExtentPoint32W(Context, s[14].c_str(), L, &Size[14]);
 GetTextExtentPoint32W(Context, s[15].c_str(), L, &Size[15]);
 return Max(Size[0].cx, Size[1].cx, Size[2].cx, Size[3].cx, Size[4].cx, Size[5].cx, Size[6].cx, Size[7].cx, Size[8].cx, Size[9].cx, Size[10].cx, Size[11].cx, Size[12].cx, Size[13].cx, Size[14].cx, Size[15].cx);

Ужос  smile 
Код из 5 строчек превратить в 200

Автор: akizelokro 29.8.2013, 15:22
Йолки! а это что такое? Есть же форматирование чисел для представления в виде текста.
Вот код перебора:

Код

WCHAR buffer[32];
int number = 0;
int max_width = 0;
for (int i = 0x00; i < 17; i++)
{
      wsprintf(buffer, "%x", i);
      CSize size = pDC->GetTextExtent(buffer);
      if(size.cx > max_width)
     {
             number = i;
            max_width = size.cx;
     }
}



таким образом получаешь число, которые шире остальным в данном контексте устройства (или шрифт смени для CDC или замени функцию GetTextExtent на ту, которая тебе удобней.  Дальше уже работаешь с этим числом.
И не лень тебе было всё это сверху писать?

Ладно, научишься, будешь быстро потом всё делать. Новый язык всегда в принципе со скрипом осваивается

Автор: ТарасАтавин 29.8.2013, 16:11
Цитата(akizelokro @  29.8.2013,  15:22 Найти цитируемый пост)
Вот код перебора:
Вот как раз спринтф и есть ужас. Даже с учётом заранее вычисленного размера буфера. Кроме того, я избавился от лишних вложенных вызовов. И не полагаюсь на умножение ширины отдельного символа.

Добавлено через 3 минуты и 44 секунды
Цитата(akizelokro @  29.8.2013,  15:22 Найти цитируемый пост)
И не лень тебе было всё это сверху писать?
Я вообще люблю "вручную" перебирать массивы от 512-ти элементов, а такой малышь - это у меня впервые.

Автор: akizelokro 29.8.2013, 18:32
Цитата(ТарасАтавин @  29.8.2013,  16:11 Найти цитируемый пост)
Вот как раз спринтф и есть ужас. Даже с учётом заранее вычисленного размера буфера. Кроме того, я избавился от лишних вложенных вызовов. И не полагаюсь на умножение ширины отдельного символа.


Это понятно, что у всех программистов есть свои привычки. Когда же работаешь в команде или пишешь код, который будет потом сопровождаться годами и сопровождаться, возможно, другими людьми, то начинают играть роли другие сущности.
Первая из них это логичность кода. У меня, когда я гляну на этот код, первое что возникнет в мыслях, что там какой-то убойный алгоритм, который ну никак нельзя было упростить. Тут я сам исхожу из тех же простых причин, что применение алгоритма должно быть оправдано исходя из логики программы и зависящей от этого читабельностью. И если я там вижу массив из множества элементов, то думаю, что это так и должно быть (ввиду логического принципа бритвы Оккама).

И не предлагал я умножать на ширину. У меня было предложение собрать строку из n символов с максимальной шириной и взять её реальный размер. Возможно, это несколько нерациональней.

Не говоря уже о том, что время деньги и ты мог бы потратить время ещё на чо-то рациональней.

Автор: ТарасАтавин 29.8.2013, 19:15
Цитата(akizelokro @  29.8.2013,  18:32 Найти цитируемый пост)
Это понятно, что у всех программистов есть свои привычки. Когда же работаешь в команде или пишешь код, который будет потом сопровождаться годами и сопровождаться, возможно, другими людьми, то начинают играть роли другие сущности.
Не другие, а именно эти. Надёжность и безопасность кода не имеет значения, если он будет выброшен к вечеру. И тогда можно юзать спринтфы, сканфы и тому подобный ужас. Если же код должен поддерживаться хотябы неделю, то можно юзать только те функции, которые или сами заботятся о буферах, или спрашивают их размеры в параметрах.

Добавлено через 2 минуты и 18 секунд
Цитата(akizelokro @  29.8.2013,  18:32 Найти цитируемый пост)
У меня было предложение собрать строку из n символов с максимальной шириной и взять её реальный размер. Возможно, это несколько нерациональней.
А я что сделал?

Автор: akizelokro 30.8.2013, 06:29
Цитата(ТарасАтавин @  29.8.2013,  19:15 Найти цитируемый пост)
Не другие, а именно эти. Надёжность и безопасность кода не имеет значения, если он будет выброшен к вечеру. И тогда можно юзать спринтфы, сканфы и тому подобный ужас. Если же код должен поддерживаться хотябы неделю, то можно юзать только те функции, которые или сами заботятся о буферах, или спрашивают их размеры в параметрах.


Есть и безопасные версии у sprintf, и прочих подобных Сшных функций. Если есть желание, то можно использовать их. Если нет желания использовать их ввиду других причин, то можно искать аналоги (обсуждение темы у Слэтера в "Новые сложные задачи на С++) почти в самом начале книги. 
Лично же у меня представление о безопасности кода (при переносимости), действительно, несколько своеобразное.  В нём я исхожу из законов Мёрфи в не меньшей степени представляя это так, что обязательно найдутся некие программисты, которые при модификации кода сделают в нём ошибки всевозможного характера. И, понимая это, от части окончательных проверок ухожу, потому что некий программист сможет обойти все проверки и превратить работающий код в генерирующий ошибки.


Цитата

А я что сделал?

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

Автор: akizelokro 30.8.2013, 07:24
В той части своей подоплёки, в которой являюсь мистиком, я с глубоким душевным трепетом наблюдаю за воистину мистическим отражением тенденций разнообразия Универсума, как то в плане воплощения бесконечного множества ошибок, реализуемого неким абстрактным программистом в конкретных кусках кода, так и полумистической борьбой с бесконечным множеством ошибок, ведущейся некими конкретными программистами, и подозреваю в этом не только отражения глубинных тенденций Универсума, но и проявление его бесконечной мощности как некоего множества. smile 

Автор: ТарасАтавин 30.8.2013, 08:11
Цитата(akizelokro @  30.8.2013,  06:29 Найти цитируемый пост)
А не знаю. Я увидел большое количество строк, в которых шло обращение ко всем элементам массива, я понял, что это что-то мощное и потрясенный глубиной замысла творца, я поверил ему на "слово", не разбираясь в деталях этого внушительного сооружения 
Я сгенерил 16 возможных номеров, имеющих одно свойство: в каждом номере все цифры одинаковы. Ширина символа ведь не зависит от соседних цифр, всё таки лигатура - отдельный составной символ, так что номер из одних максимально широких символов и будет максимально широким. Далее я измерил экранные размеры всех этих строк и выбрал из них максимальную ширину. Это легко читается, в отличие от монструозных кодов в первом параметре спринтфа, из-за каждого из которых надо месяц рыть справочник кодов. При этом непредстказуемое поведение системы при переполнении буферов исключено тем же самым отказом от спринтфа.

Автор: akizelokro 30.8.2013, 10:24
Цитата(ТарасАтавин @  30.8.2013,  08:11 Найти цитируемый пост)
Я сгенерил 16 возможных номеров, имеющих одно свойство: в каждом номере все цифры одинаковы. Ширина символа ведь не зависит от соседних цифр, всё таки лигатура - отдельный составной символ, так что номер из одних максимально широких символов и будет максимально широким. Далее я измерил экранные размеры всех этих строк и выбрал из них максимальную ширину. Это легко читается, в отличие от монструозных кодов в первом параметре спринтфа, из-за каждого из которых надо месяц рыть справочник кодов. При этом непредстказуемое поведение системы при переполнении буферов исключено тем же самым отказом от спринтфа.


Ну даже если так, то всё равно нечитабельно.

Код

char symbol[] = {'0' , '1' ......... ,'F' };

выглядит гораздо понятней.

и генерирование очередной строки можно делать в цикле.
и не надо столько писанины

Автор: ТарасАтавин 2.9.2013, 05:12
Цитата(akizelokro @  30.8.2013,  10:24 Найти цитируемый пост)
Ну даже если так, то всё равно нечитабельно.
Что не читабельного? Функция Max?

Автор: Dem_max 2.9.2013, 05:47
Цитата

Функция Max?


Это просто пи...детс....

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)