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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Сообщение Мikа »

Это я привёл просто пример.
На самом деле мне нужно, чтобы функция отработала с 6ю переменными, и потом сохранила в них изменения.

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

void decFunc1(unsigned char sl, unsigned char sh, unsigned char ml, unsigned char mh, unsigned char hl, unsigned char hh)
{
	if (sl>0)
	{
		sl--;
	}
	else
	{
		if (sh>0)
		{
			sh--;
			sl=9;
		}
		else
		{
			if (ml>0)
			{
				ml--;
				sh=5;
				sl=9;
			}
			else
			{
				if (mh>0)
				{
					mh--;
					ml=9;
					sh=5;
					sl=9;
				}
				else
				{
					if (hl>0)
					{
						hl--;
						mh=5;
						ml=9;
						sh=5;
						sl=9;
					}
					else
					{
						if (hh>0)
						{
							hh--;
							hl=9;
							mh=5;
							ml=9;
							sh=5;
							sl=9;
						}
						
					}
				}
			}
		}
	}
	return sl; //Добавление этих строк ничего не изменило, функция ничего не возвращает.
	return sh;
	return ml;
	return mh;
	return hl;
	return hh;
}
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Мikа писал(а):

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

unsigned char a=1;
unsigned char b=0;

void func(unsigned char C)
{
b=c++;
}

func(a);
Не совсем понял, что нужно получить. Но могу рассказать по шагам, что получается (допустим, что C = опечатка, имелось в виду c).

1. Итак, в начале a = 1, b = 0.
2. В коде вызывается func(a) (или func(1), что то же самое)
3. Переходим в функцию. Создаётся переменная с, которой присваивается значение a. То есть, c = 1.
4. Выполняется b = c. То есть b = 1.
5. Происходит инкремент c. То есть, c = 2.
6. Выходим из функции. Переменная c уничтожается (удаляется из стека).
Итог - a = 1, b = 1.
Последний раз редактировалось WiseLord Пт дек 20, 2013 16:12:23, всего редактировалось 1 раз.
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Мikа писал(а):На самом деле мне нужно, чтобы функция отработала с 6ю переменными, и потом сохранила в них изменения.
Тогда так работать не будет.

При вызове функции аргументы копируются. То есть, если вы вызвали, например, func(a), и внутри этой функции что-то с переменной a происходит - это происходит только внутри функции. Внешняя переменная не изменяется.

Далее, несколько return-ов подряд бессмысленны. После первого же будет выход из функции. Причём void функция ничего не возвращает, нужен просто return;.

Вам проще объявить эти 6 переменных глобально, а не передавать аргументами функции.

Ещё можно передавать в функцию аргументы по указателям. В C++ ещё можно и по ссылкам.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

Значения аргументов функции вы можете внутри функции менять сколько угодно, только вот на те переменные которые вы туда передали, это никак не повлияет.
Представьте себе ситуацию:
void decFunc1(unsigned char sl, unsigned char sh, unsigned char ml, unsigned char mh, unsigned char hl, unsigned char hh);
decFunc1(1,2,3,4,5,6); -- что по вашему должно произойти вообще? :)
return sl; //Добавление этих строк ничего не изменило, функция ничего не возвращает.
return sh;
return ml;
return mh;
return hl;
return hh;
это имеет ноль смысла вообще, по двум причинам: 1. После первого return произойдет выход из функции. 2. Функция void, соответственно нихрена не возвращает.

Я так понимаю, что нужно изменять значения аргументов функции. Для этого их надо передавать не по значению, а по адресу. И разыменовывать указатели везде, где они используются.

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

void decFunc1(unsigned char *sl, unsigned char *sh, unsigned char *ml, unsigned char *mh, unsigned char *hl, unsigned char *hh)
{
  if (*sl>0)
   {
      *sl--;
   }
   else
   {
      if (*sh>0)
...

}
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

WiseLord писал(а): Вам проще объявить эти 6 переменных глобально, а не передавать аргументами функции.
Не учите плохому :)
Контактная информация:
Реклама
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Сообщение Мikа »

К сожалению, тему функций только вот осваиваю в данный момент. Как всегда, методом проб и ошибок.
Ситуация такая:
Имеется 2 группы переменных, по 6 шт.
это:

digit_sl
digit_sh
digit_ml
digit_mh
digit_hl
digit_hl

и

A_sl
A_sh
A_ml
A_mh
A_hl
A_hl

С ними надо делать одно и то же, но в разное время.
Есть функция, которая должна с ними работать (приведённая выше, соответственно).
Внутри функции, в местах подстановки переменных, стоят sl, sh, ml, mh, hl, hh.
Вот вопрос, как правильно функцию объявить, и как правильно из неё эти значения обратно получить. Вот. :dont_know:

UPD: Так, так, так :) Кажется, уловил ошибку. Щас попробую
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Язык C или C++?
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Сообщение Мikа »

Язык С++, ATMEL Studio 6, ATmega32
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

Я вам уже написал. Вы читаете сообщения? :)
Переписываете свою функцию согласно этим рекомендациям:

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

void decFunc1(unsigned char *sl, unsigned char *sh, unsigned char *ml, unsigned char *mh, unsigned char *hl, unsigned char *hh)
{
  if (*sl>0)
   {
      *sl--;
   }
   else
   {
      if (*sh>0)
...

}
вызываете функцию для этих переменных, например:
Мikа писал(а): digit_sl
digit_sh
digit_ml
digit_mh
digit_hl
digit_hl

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

decFunc1(&digil_sl, &digil_sh, &digil_ml, &digil_mh,  &digil_hl, &digil_hl);
PS зачем две одинаковые переменные в конце?
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень

Сообщение vitalik_1984 »

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

Сообщение WiseLord »

Соглашусь.

Для C++ можно не указателями делать (не переписывать код), а определить функцию вот так:
void decFunc1(char &sl, char &sh, char &ml, char &mh, char &hl, char &hh)
{
...
}
И вызывать как обычно:
decFunc1(digit_sl, digit_sh, digit_ml, digit_mh, digit_hl, digit_hh);
Контактная информация:
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Сообщение Мikа »

BCluster, да, я всё читаю, очень внимательно, иногда даже записываю в блокнот (серьёзно). Но вы написали сообщение, когда я писал ответ. Когда я его написал, я прочитал ваше и добавил в своё UPD. Вот щас пробую :)

Попробовал, всёравно не работает. Если подставляю на исполнение функцию напрямую, без аргументов decFunc(); , то работает (без 1 в конце, это копия функции, но без меняющихся переменных внутри).

Функция сейчас была вот такая:
Спойлер

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

void decFunc1(unsigned char *sl, unsigned char *sh, unsigned char *ml, unsigned char *mh, unsigned char *hl, unsigned char *hh)
{
	if (*sl>0)
	{
		*sl--;
	}
	else
	{
		if (*sh>0)
		{
			*sh--;
			*sl=9;
		}
		else
		{
			if (*ml>0)
			{
				*ml--;
				*sh=5;
				*sl=9;
			}
			else
			{
				if (*mh>0)
				{
					*mh--;
					*ml=9;
					*sh=5;
					*sl=9;
				}
				else
				{
					if (*hl>0)
					{
						*hl--;
						*mh=5;
						*ml=9;
						*sh=5;
						*sl=9;
					}
					else
					{
						if (*hh>0)
						{
							*hh--;
							*hl=9;
							*mh=5;
							*ml=9;
							*sh=5;
							*sl=9;
						}
					}
				}
			}
		}
	}
}
Вызывалась таким образом:

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

decFunc1(&A_sl, &A_sh, &A_ml, &A_mh, &A_hl, &A_hh);
Щас должен идти в институт, продолжу изучать вечером, большое спасибо за ответы, видимо, до скорого :)

UPD: vitalik_1984 , именно, это часы. Индикацию делает отдельная функция. Эта функция призвана считать время в обратном порядке. Она точно работает, проверял :) Вопрос в правильном написании этого:
-Хочу вызвать функцию,
-Дать ей значения,
-Чтобы она произвела расчёт,
-И вернула мне изменённые в ходе расчёта переменные.

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

Сообщение WiseLord »

Код наподобие такого значительно понятнее и проще.
Спойлер

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

#include <stdio.h>

void time2dig(long time, char &hh, char &hl, char &mh, char &ml, char &sh, char &sl)
{
	sl = time % 10;
	sh = time / 10 % 6;
	ml = time / 60 % 10;
	mh = time / 360 % 6;
	hl = time / 3600 % 10;
	hh = time / 36000;
}

long dig2time(char hh, char hl, char mh, char ml, char sh, char sl)
{
	return sl + 6*sh + 60*ml + 360 * mh + 3600 * hl + 36000 * hh;
}

void decTime(long &time)
{
	time--;
	// Если нужно, чтобы досчитав до нуля, время стало 23:59:59
	if (time < 0)
		time = 86399;
	return;
}

void incTime(long &time)
{
	time++;
	// Если нужно, чтобы досчитав до нуля, время стало 23:59:59
	if (time > 86399)
		time = 0;
	return;
}

int main(void)
{
	long time;
	char hh=0, hl=0, mh=0, ml=1, sh=0, sl=7;

	time = dig2time(hh, hl, mh, ml, sh, sl);

	for (int i = 0; i < 20; i++)
	{
		// Задержка 1 сек.
		decTime(time);
		time2dig(time, hh, hl, mh, ml, sh, sl);
		printf("%05d = %d%d:%d%d:%d%d\n", time, hh, hl, mh, ml, sh, sl);
	}
	return 0;
}
Опять же, легко и наращивать, и уменьшать время, если хранить его в одной переменной.
Тут смотря что Вам надо, всё можно улучшить, информации просто не так много. То же деление не самое быстрое действие, особенно если код для микроконтроллера.

P.S. На чистом СИ будет как-то так:
Спойлер

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

#include <stdio.h>

void time2dig(long time, char *hh, char *hl, char *mh, char *ml, char *sh, char *sl)
{
	*sl = time % 10;
	*sh = time / 10 % 6;
	*ml = time / 60 % 10;
	*mh = time / 360 % 6;
	*hl = time / 3600 % 10;
	*hh = time / 36000;
}

long dig2time(char *hh, char *hl, char *mh, char *ml, char *sh, char *sl)
{
	return *sl + *sh * 6 + *ml * 60 + *mh * 360  + *hl * 3600  + *hh * 36000;
}

void decTime(long *time)
{
	(*time)--;
	// Если нужно, чтобы досчитав до нуля, время стало 23:59:59
	if (*time < 0)
		*time = 86399;
	return;
}

void incTime(long *time)
{
	(*time)++;
	// Если нужно, чтобы досчитав до нуля, время стало 23:59:59
	if (*time > 86399)
		*time = 0;
	return;
}

int main(void)
{
	long time;
	char hh=0, hl=0, mh=0, ml=1, sh=0, sl=7;

	time = dig2time(&hh, &hl, &mh, &ml, &sh, &sl);

	for (int i = 0; i < 20; i++)
	{
		// Задержка 1 сек.
		decTime(&time);
		time2dig(time, &hh, &hl, &mh, &ml, &sh, &sl);
		printf("%05d = %d%d:%d%d:%d%d\n", time, hh, hl, mh, ml, sh, sl);
	}
	for (int i = 0; i < 20; i++)
	{
		// Задержка 1 сек.
		incTime(&time);
		time2dig(time, &hh, &hl, &mh, &ml, &sh, &sl);
		printf("%05d = %d%d:%d%d:%d%d\n", time, hh, hl, mh, ml, sh, sl);
	}
	return 0;
}
Последний раз редактировалось WiseLord Пт дек 20, 2013 17:08:46, всего редактировалось 2 раза.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев

Сообщение BCluster »

Что значит не работает? :) Как именно не работает?
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Сообщение unalex »

загнали данные в структуру, передали функции в виде структуры, функция вернула структуру
как выариант можно отправлять указатель на структуру и в функции эту структуру модифицировать

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

	typedef struct
	{
		unsigned char sl;
		unsigned char sh;
		unsigned char ml;
		unsigned char mh;
		unsigned char hl;
		unsigned char hh;
	} myStruct;

	myStruct current =
	{ 1, 2, 3, 4, 5, 6 };

	myStruct decFunc1(myStruct current)
	{
		if (current.sl > 0)
		{
			current.sl--;
		}
		else if (current.sh > 0)
		{
			current.sh--;
			current.sl = 9;
		}
		else if (current.ml > 0)
		{
			current.ml--;
			current.sh = 5;
			current.sl = 9;
		}
		else if (current.mh > 0)
		{
			current.mh--;
			current.ml = 9;
			current.sh = 5;
			current.sl = 9;
		}
		else if (current.hl > 0)
		{
			current.hl--;
			current.mh = 5;
			current.ml = 9;
			current.sh = 5;
			current.sl = 9;
		}
		else if (current.hh > 0)
		{
			current.hh--;
			current.hl = 9;
			current.mh = 5;
			current.ml = 9;
			current.sh = 5;
			current.sl = 9;
		}
		
		return current;
	}
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Мучитель микросхем
Аватара пользователя
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Сообщение unalex »

только что заметил - используются положительные переменные
наверное в плане быстроействия проще сравнивать их с нулем, чем выяснять что они больше нуля?
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Мучитель микросхем
Аватара пользователя
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Сообщение unalex »

с указателями

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

	struct myStruct
	{
		unsigned char sl, sh, ml, mh, hl, hh;
	};

	struct myStruct current, *p;
	
	void decFunc1(struct current *p)
	{
		if (p->sl > 0)
		{
			p->sl--;
		}
		else if (p->sh > 0)
		{
			p->sh--;
			p->sl = 9;
		}
		else if (p->ml > 0)
		{
			p->ml--;
			p->sh = 5;
			p->sl = 9;
		}
		else if (p->mh > 0)
		{
			p->mh--;
			p->ml = 9;
			p->sh = 5;
			p->sl = 9;
		}
		else if (p->hl > 0)
		{
			p->hl--;
			p->mh = 5;
			p->ml = 9;
			p->sh = 5;
			p->sl = 9;
		}
		else if (p->hh > 0)
		{
			p->hh--;
			p->hl = 9;
			p->mh = 5;
			p->ml = 9;
			p->sh = 5;
			p->sl = 9;
		}
	}
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Потрогал лапой паяльник
Аватара пользователя
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

Сообщение Мikа »

BCluster, ничего не происходит :) На дисплее отображается число, хотя оно должно уменьшаться. Возможно, проблема в чём-то ещё. Щас попробую найти :)
WiseLord, вариант с делением выгляди гораздо лучше :) но щас вопрос не в алгоритме, а в том, почему не работает функция :)
unalex, со структурами ещё не знаком, кажется, пришло время :)
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Мikа писал(а):BCluster, ничего не происходит :) На дисплее отображается число, хотя оно должно уменьшаться
Если Вы всё ещё не перешли на указатели или передачу по ссылке, то число и не должно уменьшаться.

Если вдруг пропустили - ещё раз повторю. При вызове функции все её аргументы скрыто копируются в новые переменные, с которыми функция может что угодно делать - все изменения будут ТОЛЬКО внутри функции и никак не повлияют на значения этих переменных снаружи.

Для того, чтобы указать, что надо не копировать переменные, а использовать те, что в аргументах, нужно либо функцию объявлять не как func(int a), а как func (int &a) (так можно только в C++), либо передавать в функцию не переменную, а указатель на неё (указатель - это по сути адрес ячейки памяти, в которой лежит переменная). Сравните:

Ваш вариант:
Сама функция:
void func (unsigned char sl, ...)
{
sl--;
...
}

Вызов:
sl = 3;
func (sl, ...);

При вызове функции создастся копия (передача аргумента по значению) переменной sl (внутренняя для функции). Она и уменьшится на 1. А при выходе из фунции - просто уничтожится. Внешняя же sl так и останется равна 3.

Вариант, допустимый в C++:
Сама функция:
void func (unsigned char &sl, ...)
{
sl--;
...
}

Вызов:
sl = 3;
func (sl, ...);

Теперь, посколько функция объявлена с &, это означает, что копия переменной не будет создаваться (передача аргумента по ссылке), и функция будет изменять ту же внешнюю переменную sl.

Вариант для C с указателями:
Сама функция:
void func (unsigned char *sl, ...)
{
(*sl)--;
...
}

Вызов:
sl = 3;
func (&sl, ...);

Теперь в функцию передаётся не переменная-значение, а указатель (адрес ячейки памяти, в которой хранится переменная). Соответственно, и при вызове надо писать &sl (&sl означает адрес переменной sl), а внутри функции - использовать *sl (sl внутри функции означает указатель адрес (мы ведь адрес передали в функцию), а *sl - то, что по этому адресу лежит (значение переменной)).

Вот такой своего рода ликбез.
Контактная информация:
Мучитель микросхем
Аватара пользователя
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

Сообщение unalex »

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

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

int a, b;
int sum;

int add(int op1, int op2)
{
	return(op1+op2);
}
...
sum = add(a,b);
Коктейль "Рекурсивный": 20% спирта, 30% воды, 50% коктейля "Рекурсивный"...
Ответить

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