Страница 174 из 386
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:05:05
М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;
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:06:05
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.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:11:37
WiseLord
Мikа писал(а):На самом деле мне нужно, чтобы функция отработала с 6ю переменными, и потом сохранила в них изменения.
Тогда так работать не будет.
При вызове функции аргументы
копируются. То есть, если вы вызвали, например,
func(a), и внутри этой функции что-то с переменной
a происходит - это происходит только
внутри функции. Внешняя переменная не изменяется.
Далее, несколько return-ов подряд бессмысленны. После первого же будет выход из функции. Причём void функция ничего не возвращает, нужен просто
return;.
Вам проще объявить эти 6 переменных глобально, а не передавать аргументами функции.
Ещё можно передавать в функцию аргументы по указателям. В C++ ещё можно и по ссылкам.
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:16:14
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)
...
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:17:03
BCluster
WiseLord писал(а):
Вам проще объявить эти 6 переменных глобально, а не передавать аргументами функции.
Не учите плохому

Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:22:41
М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.
Вот вопрос, как правильно функцию объявить, и как правильно из неё эти значения обратно получить. Вот.
UPD: Так, так, так

Кажется, уловил ошибку. Щас попробую
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:26:24
WiseLord
Язык C или C++?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:27:44
Мikа
Язык С++, ATMEL Studio 6, ATmega32
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:28: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 зачем две одинаковые переменные в конце?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:32:56
vitalik_1984
Плохо когда человек дает на рассмотрение алгоритм или функциию сам слабо представляя зачем они нужны.
Может лучше задать тех условия? Например я считаю это и это и результат должен быть тут и тут.
Или нужно передать по юарт это и то. Получить в ответ контрольную сумму.
И показать что сам при этом смог сделать.
Судя по названиями переменных это банальные часы
Может проще разделить счет часов минут,секунд и индикацию в разные функции?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:38:37
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);
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:43:19
М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 , именно, это часы. Индикацию делает отдельная функция. Эта функция призвана считать время в обратном порядке. Она точно работает, проверял

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

Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:55:36
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;
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 16:59:37
BCluster
Что значит не работает?

Как именно не работает?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 17:23:41
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;
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 17:30:18
unalex
только что заметил - используются положительные переменные
наверное в плане быстроействия проще сравнивать их с нулем, чем выяснять что они больше нуля?
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 17:56:20
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;
}
}
Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 20:54:43
Мikа
BCluster, ничего не происходит

На дисплее отображается число, хотя оно должно уменьшаться. Возможно, проблема в чём-то ещё. Щас попробую найти
WiseLord, вариант с делением выгляди гораздо лучше

но щас вопрос не в алгоритме, а в том, почему не работает функция
unalex, со структурами ещё не знаком, кажется, пришло время

Re: Вопросы по С/С++ (СИ)
Добавлено: Пт дек 20, 2013 23:41:35
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 - то, что по этому адресу лежит (значение переменной)).
Вот такой своего рода ликбез.
Re: Вопросы по С/С++ (СИ)
Добавлено: Сб дек 21, 2013 00:26:15
unalex
WiseLord писал(а):При вызове функции все её аргументы скрыто копируются в новые переменные, с которыми функция может что угодно делать - все изменения будут ТОЛЬКО внутри функции и никак не повлияют на значения этих переменных снаружи.
никто не запрещает функции возвращать результат операции для дальнейшей обработки
Код: Выделить всё
int a, b;
int sum;
int add(int op1, int op2)
{
return(op1+op2);
}
...
sum = add(a,b);