Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
ROMan2947
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Re: Вопросы по С/С++ (СИ)

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3670115#p3670115"]ltoa(variable, rezult, 10);[/uquote] ну если б я знал про это, а знал я только про itoa, то воще вопросов не было бы :roll:
Реклама
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18637
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

ROMan2947 писал(а):если б я знал про это
надо знать инструментарий, с которым работаешь, без этого никак

интересно другое: как вы, не зная "этого" умудрялись ВЫВОДИТЬ такое число на дисплей? можете показать код?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

[uquote="ROMan2947",url="/forum/viewtopic.php?p=3670120#p3670120"]ну если б я знал про это, а знал я только про itoa, то воще вопросов не было бы :roll:[/uquote]
Это же аббревиатура :) Int To Ascii :)

Соответственно, ltoa - long to ascii :)
Аватара пользователя
ROMan2947
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Re: Вопросы по С/С++ (СИ)

Сообщение ROMan2947 »

[uquote="ARV",url="/forum/viewtopic.php?p=3670115#p3670115"]если русурсов достаточно (флеша хотя бы 4К).[/uquote] на эти случаю, решил работать с 64 и 128, так писать оптимально мне ещё далеко,так камешки должны вместить в себя всю лабуду, которую я готовлю для них :hunger:

Добавлено after 2 minutes 16 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3670125#p3670125"][
интересно другое: как вы, не зная "этого" умудрялись ВЫВОДИТЬ такое число на дисплей? можете показать код?[/uquote]
вечером, после работы выложу
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Заодно, если не сложно, покажите как сделали редактирование разрядов другим способом.
Хочется посмотреть на это извращение :)
Реклама
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Вопросы по С/С++ (СИ)

Сообщение Reflector »

[uquote="Аlex",url="/forum/viewtopic.php?p=3670133#p3670133"]Заодно, если не сложно, покажите как сделали редактирование разрядов другим способом.
Хочется посмотреть на это извращение :)[/uquote]
AVR давно не занимаюсь, но не поленился, создал проект для tiny13 и написал две функции, хотя проверить в работе на AVR не могу, только сравнить размер :) Сначала с массивом:

Код: Выделить всё

char result[16];

uint32_t replaceDigit(uint32_t value, uint8_t idx, uint8_t upDown)
{
	ltoa(value, result, 10);
	uint8_t digit = result[idx];
	if (upDown == 1 && digit < '9')  digit++;
	if (upDown == 0 && digit > '0')  digit--;
	return atol(result);
}

    volatile uint32_t val_ = 87'654'321;
    uint32_t val = val_;
    val_ = replaceDigit(val, 2, 1);
Теперь без массива:

Код: Выделить всё

uint32_t replaceDigit(uint32_t value, uint8_t idx, uint8_t upDown)
{
	static const uint32_t tbl[] = { 1, 10, 100, 1000, 10'000, 100'000, 1'000'000, 10'000'000 };
	uint32_t pval = tbl[idx];
	uint8_t digit = value / pval % 10;
	if (upDown == 1 && digit < 9)  value += pval;
	if (upDown == 0 && digit > 0)  value -= pval;
	return value;
}
Компилируем оба варианта на gcc с -Os, во втором случае размер меньше на 142 байта, при этом очевидно вторая функция и быстрее. Правда она возвращает только число, строки нет, собственно строка может и не понадобиться или какой-нибудь printf задействует свое преобразование, не вызывая atol, но даже дополнительно добавив atol все равно размер будет чуть меньше. Но это не все, второй подход позволяет очень просто добавлять ограничения, например, можно передавать максимум, внутри изменится лишь одна строка:

Код: Выделить всё

if (upDown == 1 && digit < 9 && value + pval <= maxValue)  value += pval;
.....

     val = replaceDigit(val, 2, 1, 87'657'654);
Все, 4 младших разряда можно увеличивать, 4 старших уже нельзя.
Реклама
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Вопросы по С/С++ (СИ)

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=3669835#p3669835"]это может и не проще, но правильнее по логике. а для float ваш алгоритм тоже подойдет? мой - да.[/uquote]
"Мой", "ваш" - в чём разница? И там и там - выделение цифр с помощью операций деления/умножения. Только в "вашем" - все цифры выделяются (и ненужные тоже), в "моём" - только нужная.
"Правильнее по-логике" - это делать ненужную работу что-ль? :dont_know:
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

Кстати, во всём это есть один интересный момент. Если некий разряд (при, допустим, вращении энкодера), переходит из 9 в 0, нужно ли при этом разряд слева тоже увеличивать? Если нужно, то все эти свистопляски с строковым представлением сильно всё усложняют.

Имхо, лучше инкрементировать само число. Это, как правило, проще, и нужно чаще, чем показ пользователю. Например, данные приходят от какого-то датчика очень часто, а вывод на экран - на порядок реже. Гораздо проще и быстрее работать с одной сущностью - числом, а уже все преобразования в строку для показа пользователем делать только когда это нужно, т.е. при выводе.
Последний раз редактировалось WiseLord Пн июл 22, 2019 12:28:23, всего редактировалось 1 раз.
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Вопросы по С/С++ (СИ)

Сообщение jcxz »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3669940#p3669940"]Я бы редактировал и параллельно отображал строку, а в реальное значение пересчитывал только когда надо это значение применить или проверить на диапазон.[/uquote]
В исходном вопросе автора вообще не было слов про отображение.
А также ничего не было про float или про дни недели (которые тут уже подтягиваются).

Добавлено after 3 minutes 55 seconds:
[uquote="Аlex",url="/forum/viewtopic.php?p=3670077#p3670077"]
jcxz писал(а):Ну да - автору нужно изменить всего одну цифру, .... бла-бла-бла ...
Где одну то ? Ему нужно изменить число, состоящее из нескольких цифр !
Делать itoa (или ему подобное) для вывода на дисплей, а потом по индексу вычислять разряд, изменяя число на 1/10/100/1000/... - это проще ? Шутишь ? :facepalm:[/uquote]
Может стоит всё-таки прочитать исходное сообщение автора, а не фантазировать?
[uquote="ROMan2947",url="/forum/viewtopic.php?p=3669095#p3669095"]есть переменная типа UL. в ней хранится число,которое является показанием счетчика воды. максимальное число которое мне нужно это от 0 до 99999999 л. мне необходимо редактировать это число поразрядно,для задания данных ручками.[/uquote]
Прочитайте и подумайте на смыслом фразы "необходимо редактировать это число поразрядно".
И где Вы тут увидели про вывод ещё и на дисплей?? :shock:
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18637
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

Слово "редактировать" подразумевает действия человека. А человек не может ничего редактировать вслепую. Значит, он видит редактируемое число, и видет его не в бинарном формате, а в удобном десятичном.
То есть хоть топикстартер и не сказал, что число выводит, это так же естественно, как то, что он дышит. Хоть и не говорит об этом.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

Re: Вопросы по С/С++ (СИ)

Сообщение VladislavS »

ARV, с языка снял.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Reflector, Вы привели варианты разового изменения одно из разрядов числа. Ежу понятно, что если человеку где-то в программе нужно сделать только это, то второй вариант более оптимален во всём.
Но задача немного другая - редактировать одно большое число поразрядно. В этом случае, постоянно делать туда-сюда преобразование - глупо. Один раз сделал, отредактировал весь массив, а потом обратно.
jcxz писал(а):Может стоит всё-таки прочитать исходное сообщение автора, а не фантазировать?
Примените этот вопрос к себе. И внимательно почитайте задачу.
Фантазируете пока Вы здесь только один.
Аватара пользователя
ROMan2947
Грызет канифоль
Сообщения: 287
Зарегистрирован: Сб янв 23, 2016 00:59:59
Откуда: Чебоксары

Re: Вопросы по С/С++ (СИ)

Сообщение ROMan2947 »

[uquote="Аlex",url="/forum/viewtopic.php?p=3670133#p3670133"]Заодно, если не сложно, покажите как сделали редактирование разрядов другим способом.
Хочется посмотреть на это извращение :)[/uquote] основная функция setup_TEKpokazania() вызывается из пункта меню
Спойлер

Код: Выделить всё


static uint32_t const tPow10[] = {
	10000000ul,
	1000000ul,
	100000ul,
	10000ul,
	1000ul,
	100ul,
	10ul,
};

void write_TEKdata_setup_eeprom(char type_counter)
{
	TEK_data=0;
	for(uint8_t it=0;it<7;it++)
	{
		TEK_data+=masiv_razryadov[it]*tPow10[it]; // собираем число из разрядов
	}

	if (type_counter=='G')       eeprom_write_block(&TEK_data,&TEK_pokazania_GWS,4);
	else if (type_counter=='H')  eeprom_write_block(&TEK_data,&TEK_pokazania_HWS,4);

}

void read_TEKdata_setup_eeprom(char type_counter)
{
	TEK_data=0;
	if (type_counter=='G')       eeprom_read_block(&TEK_data,&TEK_pokazania_GWS,4);
	else if (type_counter=='H')  eeprom_read_block(&TEK_data,&TEK_pokazania_HWS,4);



	uint8_t it=0;
	unsigned long tek_TEMP=TEK_data;

	for(it=0;it<7;it++)
	{
		masiv_razryadov[it]=tek_TEMP/tPow10[it];  //разбиваем число на разряды
		tek_TEMP%=tPow10[it];

	}
}

static uint8_t flag =0;
void steep_function_TEK (uint8_t i)
{
	write_command(0x80|(cursor_address));
	char massiv1[7]={0};
	sprintf(massiv1,"%d",setup_buffer[i]);
	print_LCD(massiv1);
	write_command(0x80|cursor_address);
}

int setup_TEKpokazania(char type_counter)
{
	
	char GWSstring[13]={"GWS: counter"};  // шапка
	char HWSstring[13]={"HWS: counter"};  // шапка
	


	if(!flag)
	{
		read_TEKdata_setup_eeprom(type_counter);

		cursor_address=0x44;
		memcpy(setup_buffer,masiv_razryadov,7);
		write_command(clear_display); // очищаем дисплей
		write_command(0x80|0x02);
		if(type_counter=='G') print_LCD(GWSstring);    // печатаем шапку
		if(type_counter=='H') print_LCD(HWSstring);
		
		write_command(0x80|cursor_address);
		char massiv1[15]={0};
		sprintf(massiv1,"%d%d%d%d%d%d%d%c",setup_buffer[0],setup_buffer[1],setup_buffer[2],setup_buffer[3],setup_buffer[4],setup_buffer[5],setup_buffer[6],'l');
		print_LCD(massiv1);                 // пишем данные
		cursor_address=0x44;                // адресс курсора на позиция для мигания
		write_command(0x80|cursor_address); // устанвливаем курсор
		flag=1;
		write_command(0x0f);           // включаем курсор мигающий

		return 0;
	}

	write_command(0x0f); // включаем курсор мигающий
	static uint8_t steep_TEK = 1;

	switch(KeyCode)
	{
		cursor_address=0x44;
		case Enter:
		if(steep_TEK<0x07)
		{
			if(steep_TEK<0x07)
			{
				write_command(0x80|(cursor_address+=0x01));
			}
			
			i++;
			steep_TEK++;
		}
		else
		{
			memcpy(masiv_razryadov,setup_buffer,8);
			write_TEKdata_setup_eeprom(type_counter);
			i=0;
			steep_TEK = 1;
			write_command(clear_display); // очищаем дисплей
			write_command(0x80|0x02); //
			write_command(0xC);
			char massiv[15]={"SET count OK"};
			print_LCD(massiv);
			_delay_ms(2000);
			flag=0; Level=3; PtrPunkt=Ptr_config_function->Ptr5; (*PtrPunkt)();cursor_address=0x42; break;
		}
		break;

		case UP:  if ((setup_buffer[i]++)<9)  {steep_function_TEK(i); break;}
		if ((setup_buffer[i]++)>9)  {setup_buffer[i]=0; steep_function_TEK(i); break;}

		break;
		
		case DN: if ((setup_buffer[i]--)>0)  {steep_function_TEK(i); break;}
		if ((setup_buffer[i]--)>9)  {setup_buffer[i]=9; steep_function_TEK(i); break;}
		break;

		case Cancel: flag=0; Level=3; write_command(0xC);PtrPunkt=Ptr_config_function->Ptr5; steep_TEK = 1; cursor_address=0x42; (*PtrPunkt)();break;
	}
	return 0;
}
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Ну, всё нормально :)
Сильно не вчитывался, но судя по всему, работаете с массивом при редактировании. Что и хотелось до Вас донести.

Единственное, что резануло глаз :

Код: Выделить всё

      char massiv1[15]={0};
      sprintf(massiv1,"%d%d%d%d%d%d%d%c",setup_buffer[0],setup_buffer[1],setup_buffer[2],setup_buffer[3],setup_buffer[4],setup_buffer[5],setup_buffer[6],'l');
Тут можно и без sprintf обойтись.
Подсказка: ascii код цифры = цифра + '0' :)
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Вопросы по С/С++ (СИ)

Сообщение Reflector »

[uquote="Аlex",url="/forum/viewtopic.php?p=3670326#p3670326"]Но задача немного другая - редактировать одно большое число поразрядно. В этом случае, постоянно делать туда-сюда преобразование - глупо. Один раз сделал, отредактировал весь массив, а потом обратно.[/uquote]
Я когда писал свои функции преобразования, то сравнивал скорость с sprintf, правда на STM32, и мой вариант был быстрее в 8.5 раз, а тут 7 разрядов числа против одного, т.е. преобразование числа целиком, которое делается один раз, может быть в 60 раз медленнее извлечения одного разряда, которое делается при каждом изменении :) И не обязательно преобразовывать туда-сюда, можно сделать и так:

Код: Выделить всё

uint8_t replaceDigit(uint32_t& value, uint8_t idx, uint8_t upDown)
{
   static const uint32_t tbl[] = { 1, 10, 100, 1000, 10'000, 100'000, 1'000'000, 10'000'000 };
   uint32_t pval = tbl[idx];
   uint8_t digit = value / pval % 10;
   if (upDown == 1 && digit < 9)  value += pval, digit++;
   if (upDown == 0 && digit > 0)  value -= pval, digit--;
   return digit;
}
Теперь функция возвращает цифру которая и будет выводиться на дисплей, без никаких обратных преобразований. При этом не будет глобального массива и не будет этого:

Код: Выделить всё

   TEK_data=0;
   for(uint8_t it=0;it<7;it++)
   {
      TEK_data+=masiv_razryadov[it]*tPow10[it]; // собираем число из разрядов
   }

   uint8_t it=0;
   unsigned long tek_TEMP=TEK_data;

   for(it=0;it<7;it++)
   {
      masiv_razryadov[it]=tek_TEMP/tPow10[it];  //разбиваем число на разряды
      tek_TEMP%=tPow10[it];

   }
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Вопросы по С/С++ (СИ)

Сообщение jcxz »

[uquote="Reflector",url="/forum/viewtopic.php?p=3670555#p3670555"]Теперь функция возвращает цифру которая и будет выводиться на дисплей, без никаких обратных преобразований. При этом не будет глобального массива и не будет этого:[/uquote]
...А если, к примеру, даже нужно и визуализировать процесс редактирования на графическом LCD, то во многих LCD (например на ILI9341 подключенном по SPI) имеющих встроенную видео-ОЗУ, можно отправлять в LCD только изменяемый прямоугольный регион пикселов. Что будет намного быстрее и экономнее по ресурсам. И совсем не нужно всё число переводить в строку.
Уж не говоря о том, что сам процесс редактирования (редактирование - это не обязательно человеком, может просто инкремент какой-то позиции по некоторому событию) - это совсем не отображение. И по времени и по месту в коде они скорей всего не будут совпадать. Так как отображение - не имеет смысла делать чаще, чем человек может увидеть, а изменение (редактирование) - должно происходить по некоторым событиям (нажатиям кнопок, переключениям энкодера и т.п.) совсем никак не связанным с процессом отображения.

PS: А вышеприведённый код - это конечно какой-то тихий ужас просто..... :o
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18637
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

jcxz писал(а):можно отправлять в LCD только изменяемый прямоугольный регион пикселов. Что будет намного быстрее и экономнее по ресурсам
это вот вообще никак не сязано с тем, как лучше редактировать строку :) поскольку при посимвольной правке всегда известно, какой именно символ изменился, и можно выводить только его - это дело чисто вкуса и "экономии" ресурсов, до исчерпания которых вряд ли кто добирался хоть раз.
jcxz писал(а):Так как отображение - не имеет смысла делать чаще, чем человек может увидеть, а изменение (редактирование) - должно происходить по некоторым событиям (нажатиям кнопок, переключениям энкодера и т.п.) совсем никак не связанным с процессом отображения.
теперь я понимаю, окуда берутся гении разработки интерфейсов :) вы всерьез считаете, что может существовать необходимость менять разряд, допустим, 100 раз в секунду, в то время как показывать человеку 3 раза в секунду? ;)

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

Мой уютный бложик... заходите!
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение WiseLord »

ARV писал(а):вы всерьез считаете, что может существовать необходимость менять разряд, допустим, 100 раз в секунду, в то время как показывать человеку 3 раза в секунду?
А ведь именно так и есть. Например, счётчик каких-то прерываний, происходящих, скажем, 100 раз в секунду. В прерывании просто берём то самое число (одно!) и инкрементируем (ну, или добавляем +10 или +100 - не важно). И нет необходимости тут же его раскладывать на символы. Это проще сделать именно тогда когда придёт время отображать.
jcxz
Мудрый кот
Сообщения: 1731
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: Вопросы по С/С++ (СИ)

Сообщение jcxz »

[uquote="ARV",url="/forum/viewtopic.php?p=3670622#p3670622"]вы всерьез считаете, что может существовать необходимость менять разряд, допустим, 100 раз в секунду, в то время как показывать человеку 3 раза в секунду? ;)[/uquote]
Причём тут "100 раз в секунду"? Если изменяется пользователем, то это происходит в ответ например на нажатия клавиш или энкодера или приход пакетов по радио-интерфейсу - т.е. события обрабатываемые соответствующими устройствами ввода в соответствующих обработчиках событий от этих устройств. А вывод на LCD - это совсем другой процесс, и совсем другой драйвер/участок кода.
Это если писать с умом, а не валить всё в одну кучу.

Добавлено after 4 minutes 12 seconds:
[uquote="ARV",url="/forum/viewtopic.php?p=3670622#p3670622"]еще не факт, что многоразрядное деление не проиграет однобайтному сложению-вычитанию[/uquote]
Подумайте ещё немного и может поймёте что вашего любимого преобразования числа в строку деление вообще не нужно 8)
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18637
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Вопросы по С/С++ (СИ)

Сообщение ARV »

WiseLord писал(а):А ведь именно так и есть.
совсем не так есть. вы перепутали интерфейс человек-МК с интерфейсом МК-периферия. когда человек воздействует на число (а именно этот момент тут рассматривается) нет необходимости изменять число чаще, чем отображать. в случае, когда число изменяется "само по себе" данная проблема вообще не возникает, ибо все изменения делаются стандартными элементарными арифметическими операторами Си без дележа на разряды и т.п.
jcxz писал(а):А вывод на LCD - это совсем другой процесс, и совсем другой драйвер/участок кода
что процесс/участок другой - разве кто спорил? речь о том, что только после каждого изменения числа надо уведомить тот другой участок о необходимости отобразить число. не чаще и не реже - ровно на каждое изменение. можно и чаще, можно и реже - но не нужно.

и тут мы неизбежно возвращаемся к истокам: чтобы отобразить число, нам нужно его символьное представление, которое получается из "аппаратного" путем преобразования число-строка. раз есть строка, то технически проще и менее затратно её и править, оставив обратное преобразование "на потом". выигрыш достигается по всем статьям: и быстродействию, и занятым ресурсам ОЗУ и т.п. и, хоть вы и отбросили это, достигается универсализм в подходах к редактированию вообще чего угодно - поменяются только "границы допустимости" тех или иных символов, а общий алгоритм не изменится.
jcxz писал(а):преобразования числа в строку деление вообще не нужно
может и не нужно, но пока что все реализации в данной теме (последние страницы) без этого не обходятся. хотя можно и многоэтажным if-ом обойтись - было бы желание :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «Разные вопросы по МК»