Страница 306 из 386

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

Добавлено: Пн июл 22, 2019 12:31:18
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:

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

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

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

Добавлено: Пн июл 22, 2019 16:53:11
VladislavS
ARV, с языка снял.

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

Добавлено: Пн июл 22, 2019 17:14:30
Аlex
Reflector, Вы привели варианты разового изменения одно из разрядов числа. Ежу понятно, что если человеку где-то в программе нужно сделать только это, то второй вариант более оптимален во всём.
Но задача немного другая - редактировать одно большое число поразрядно. В этом случае, постоянно делать туда-сюда преобразование - глупо. Один раз сделал, отредактировал весь массив, а потом обратно.
jcxz писал(а):Может стоит всё-таки прочитать исходное сообщение автора, а не фантазировать?
Примените этот вопрос к себе. И внимательно почитайте задачу.
Фантазируете пока Вы здесь только один.

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

Добавлено: Пн июл 22, 2019 21:01:22
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;
}

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

Добавлено: Вт июл 23, 2019 02:04:02
А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' :)

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

Добавлено: Вт июл 23, 2019 09:16:19
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];

   }

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

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

PS: А вышеприведённый код - это конечно какой-то тихий ужас просто..... :o

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

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

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

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

Добавлено: Вт июл 23, 2019 11:16:30
WiseLord
ARV писал(а):вы всерьез считаете, что может существовать необходимость менять разряд, допустим, 100 раз в секунду, в то время как показывать человеку 3 раза в секунду?
А ведь именно так и есть. Например, счётчик каких-то прерываний, происходящих, скажем, 100 раз в секунду. В прерывании просто берём то самое число (одно!) и инкрементируем (ну, или добавляем +10 или +100 - не важно). И нет необходимости тут же его раскладывать на символы. Это проще сделать именно тогда когда придёт время отображать.

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

Добавлено: Вт июл 23, 2019 12:04:32
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)

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

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

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

Начал изучать C++

Добавлено: Вс авг 18, 2019 15:44:05
Trully
Добра всем.
Приступил к изучению C++. Появились коекакие размышления. Первое с чем столкнулся при создании проекта - Reduced C, Reduced C++. Покачто не понял в чем там дело и чем конкретно отличается от Standart. Оставил на потом.
Познакомился с понятием классов, объектов, методов. Посмотрел как это лежит в памяти. Разобрался с наследованием классов. Прикольная штука особенно protected. Это то чего не хватало в С.
Что не понравилось - чтобы вызвать функцию из класса нужно сначала создать объект. Возможно есть какието другие способы. Слышал про шаблоны функций но пока до них не дошел. Возможно там есть ответы на мои вопросы.
Про конструкторы понятно. А вот что с деструкторами, когда они вызываются и что в них нужно писать применительно к микроконтроллерам это пока не понятно. Создал класс и объект - конструктор вызывается, а вызова деструктора не видно. Еще надо разобраться с множественными наследованиями ибо это архиважная вещь.
Перегрузка функций прикольная штука но пока не понятно насколько она реально востребована, ведь приходится в голове держать то что имя одинаковое но список параметров разный.
Пока еще не пробовал чето конкретное делать. Только на отвлеченных примерах типа a+b, x+y. Потому еще не очень понимаю как это все будет на практике ложиться. Там в списке глав еще много пунктов есть я так смотрю. Но все по порядку.

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

Добавлено: Пн авг 19, 2019 11:10:01
da-nie
чтобы вызвать функцию из класса нужно сначала создать объект.
Создайте статическую функцию в классе и вызывайте её без создания объекта.
Создал класс и объект - конструктор вызывается, а вызова деструктора не видно.
Деструктор вызывается при уничтожении объекта.
Еще надо разобраться с множественными наследованиями ибо это архиважная вещь.
Вообще лучше не используйте. Это антипаттерн в большинстве случаев. Но что такое виртуальное наследование посмотрите. :)
Разобрался с наследованием классов. Прикольная штука особенно protected. Это то чего не хватало в С.
Это используйте по-минимуму. Лучше аггрегация, чем наследование. :)
Перегрузка функций прикольная штука но пока не понятно насколько она реально востребована, ведь приходится в голове держать то что имя одинаковое но список параметров разный.
Используется для своих целей. А так, IDE должна подсказывать варианты. Не подсказывает? Плохая IDE.
Там в списке глав еще много пунктов есть я так смотрю. Но все по порядку.
stl посмотрите. :) Но не запускайте на микроконтроллерах. :-D

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

Добавлено: Пн авг 19, 2019 18:50:14
Trully
Благодарю за ответы.
Про статическую функцию - попробовал, самое то. Хорошо. Но конструктор при этом уже не вызывается. Логично - нет объекта нет и конструктора.
Про деструктор - это понятно, что он вызывается при удалении объекта. Но вот как удалить объект и что писать в деструкторе - освобождение памяти? - это пока не понятно. Возможно это в операционных системах востребовано. А пока что если объект создан, его фиг удалишь из памяти. Разве при динамическом выделении памяти как в С через malloc. Возможно я еще просто не дошел до таких тонкостей.
До virtual только что добрался в прочтении. Однако как я понял, это несколько иное. Множественное наследование обеспечивает иерархию подключений. В virtual пока еще только вникаю, пробую пробовать на примерах. Агрегация? Пока еще не знаю что это такое. Я еще мыслю масштабами Си.
IDE должна подсказывать варианты. Не подсказывает?
Подсказывает! :)) я даже не успеваю еще подумать а она уже подсказывает.

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

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

Добавлено: Пн авг 19, 2019 19:20:03
Reflector
[uquote="Trully",url="/forum/viewtopic.php?p=3685649#p3685649"]До virtual только что добрался в прочтении.[/uquote]
Что хоть за книга? Если там какой-нибудь С++03, то считай что читаешь описание половины языка :)

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

Добавлено: Пн авг 19, 2019 19:48:17
Trully
Читаю вот это http://www.c-cpp.ru/books/dlya-chego-nu ... ye-funkcii и вот это http://cppstudio.com/cat/274/ . Даже если это всего половина языка то мне пока хватит для того чтобы написать свой первый холлоуворлд на С++. Сами ведь знаете, что для того чтобы что то изучить надо вначале вникнуть в основы а потом уже копаться в тонкостях.

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

Добавлено: Пн авг 19, 2019 20:40:54
WiseLord
Trully писал(а):Но вот как удалить объект
Самое простое - если объект создан на стеке внутри некоей области видимости (например, внутри фигурных скобок в if() {} или типа того). После выхода из этой области объект уничтожается и вызовется деструктор.

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

Добавлено: Пн авг 19, 2019 20:51:37
da-nie
Но вот как удалить объект и что писать в деструкторе - освобождение памяти?
Объект удаляется как обычная переменная - при выходе из области видимости (не относится к объектам, созданным в куче, т.е. через new). У вас, видимо, объект глобальный, вот и не удаляется. Создайте его как локальную переменную. В деструкторе вы пишете то, что считаете нужным. Выделяли память? Освобождаете. Открывали файл? Закрываете. Ну и так далее.
Разве при динамическом выделении памяти как в С через malloc.
Никогда не создавайте объекты иначе, чем через new. И не удаляйте иначе, чем через delete. С квадратными скобками delete[](имя массива объектов), если выделяли массив объектов - это важно. Иначе получите вызов деструктора только для первого объекта массива. Исключение составляют всякие умные указатели - они сами удалят объект или массив. Но это уже stl.
В virtual пока еще только вникаю, пробую пробовать на примерах.
При наследовании через virtual в класс добавляется не сам класс, от которого унаследовано, а ссылка на него. Таким образом, при множественном ромбовидном наследовании у вас не окажется у каждого класса, от которых вы унаследовались свой экземпляр базового класса (суперкласса).
Агрегация? Пока еще не знаю что это такое.
Вот тут посмотрите. :) https://habr.com/ru/post/354046/

И очень важно: обязательно посмотрите на полиморфизм и концепцию интерфейсов. Это крайне важная вещь. Не наследование (исключая наследование от интерфейса), а полиморфизм вам пригодится больше всего.

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

Добавлено: Пн авг 19, 2019 22:11:43
Trully
Угу, пошел читать. Похоже что С++ идеологически сложнее Си.
Про видимость переменной объекта - я создавал их все в main без вложенностей. Пробовал и глобальный объект тоже. Теперь понятно почему не получалось с деструктором. А про то как работает стек это я хорошо знаю еще с чистого Си, с этим проблем нет.