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

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

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

Сообщение М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;
}
Почему я здесь и задаю тупые вопросы?
Потому что хочу научиться.
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение 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 раз.
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

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

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

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

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

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

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

Сообщение 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)
...

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

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

Сообщение BCluster »

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

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

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

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

Сообщение WiseLord »

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

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

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

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

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

Сообщение 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 зачем две одинаковые переменные в конце?
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

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

Сообщение vitalik_1984 »

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

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

Сообщение 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);
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

Сообщение М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 , именно, это часы. Индикацию делает отдельная функция. Эта функция призвана считать время в обратном порядке. Она точно работает, проверял :) Вопрос в правильном написании этого:
-Хочу вызвать функцию,
-Дать ей значения,
-Чтобы она произвела расчёт,
-И вернула мне изменённые в ходе расчёта переменные.

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

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

Сообщение 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 раза.
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

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

Сообщение BCluster »

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

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

Сообщение 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% коктейля "Рекурсивный"...
Аватара пользователя
unalex
Мучитель микросхем
Сообщения: 424
Зарегистрирован: Сб авг 25, 2007 22:02:05
Откуда: Германия, Viernheim

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

Сообщение unalex »

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

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

Сообщение 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% коктейля "Рекурсивный"...
Аватара пользователя
Мikа
Потрогал лапой паяльник
Сообщения: 343
Зарегистрирован: Пн апр 01, 2013 15:13:40
Откуда: Москва

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

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

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

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

Сообщение 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 - то, что по этому адресу лежит (значение переменной)).

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

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

Сообщение unalex »

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

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

int a, b;
int sum;

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

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