Перевернуть счетчик пропуская ноль
Может быть, простой вопрос, но я не могу разобраться с этим.
Я делаю какой-то счетчик месяцев, идея в том, что пользователь может нажать - или + и все равно достичь желаемого месяца: например, у меня есть: сегодня февраль, что-то вроде этого. Пользователь нажимает - 2 1 12 11 10 9 ...... Некоторые идут на + Проблема в том, что я не хочу, чтобы отображался нулевой тоб
SINT16 tempVal = pDate->month + upDown;
if (tempVal < 0) {
tempVal += (12+1);
}
pDate->month % (12 + 1);
Это то, что я придумала - оно переворачивает 12, а затем 0 или 1 0 12 Но я хочу избавиться от нуля. Любая помощь будет оценена:)
4 ответа
Вопрос очень неясный, но я попробую
SINT16 tempVal = pDate->month + upDown;
if (tempVal < 0) {
/* if you are at negative 1 - assuming upDown is either (1,-1) */
tempVal += (12); //just add the cycle value
}
//pDate->month % (12 + 1);
pDate->month = (pDate->month % 12) + 1;//modulo by the cycle and then shift output
для ясности по модулю 12 будут выводиться значения (0 - 11), поэтому +1 не следует включать в функцию по модулю
Если tempVal обнуляется, возьмите месяц как 12, иначе увеличьте его на 1:
SINT16 tempVal = pDate->month + upDown;
if (tempVal == 0) {
pDate->month = 12;
}//if month becomes more than 12,ie 13
else if(tempVal %12 == 1)
{
pData->month = 1;
}
else
{
pDate->month = tempVal;
}
Тщательно выбирая сравнения, вы можете упростить использование '%'
, Вместо проверки, если month = 12
или же month < 0
, проверьте, вызывает ли приращение month > 12
или же month < 1
, Это те точки, где 1
или же 12
являются обязательными.
Например, в универсальной функции для увеличения / уменьшения месяца на некоторое значение chg
Вы просто добавляете chg
к текущему месяцу, а затем применить тест, исправив month = month % 12
где month > 12
или установив month = month + 12
где month < 1
Например:
int monthchg (int *m, int chg)
{
*m += chg;
if (*m > 12) /* if month > 12, roll to month % 12 */
*m = *m % 12;
else if (*m < 1) /* if month < 1, add 12 to month */
*m += 12;
return *m;
}
Короткий пример, который переводит клавиатуру в неканонический или необработанный режим и принимает +/-
входы, чтобы изменить месяц или q
бросить курить можно:
#include <stdio.h>
#include <termios.h>
typedef struct {
struct termios old; /* orig keyboard settings */
struct termios new;
} kbmode;
kbmode *setkbmode (kbmode *k);
kbmode *restorekbmode (kbmode *k);
int monthchg (int *m, int chg)
{
*m += chg;
if (*m > 12) /* if month > 12, roll to month % 12 */
*m = *m % 12;
else if (*m < 1) /* if month < 1, add 12 to month */
*m += 12;
return *m;
}
int main (void) {
kbmode kb = { .old = {0} };
int dir, month = 6;
setkbmode (&kb); /* set kbd in raw-unbufered mode */
printf ("enter +/- to inc/decrement month ('q' to quit)\n");
for (;;) {
printf ("\n month : %2d : ", month);
fflush (stdout);
dir = getchar();
if (dir == '+')
monthchg (&month, 1);
else if (dir == '-')
monthchg (&month, -1);
else if (dir == 'q')
break;
else
puts ("invalid input - try again.");
}
putchar ('\n');
restorekbmode (&kb); /* restore original kbd settings */
return 0;
}
/* set keyboard in raw-unbufered mode */
kbmode *setkbmode (kbmode *k)
{
if (tcgetattr (0, &(k->old))) { /* save orig settings */
fprintf (stderr, "setkbmode() error: tcgetattr failed.\n");
return NULL;
} /* copy old to new */
k->new = k->old;
k->new.c_lflag &= ~(ICANON); /* new kbd flags */
k->new.c_cc[VTIME] = 0;
k->new.c_cc[VMIN] = 1;
if (tcsetattr (0, TCSANOW, &(k->new))) {
fprintf (stderr, "setkbmode() error: tcgetattr failed.\n");
return NULL;
}
return k;
}
kbmode *restorekbmode (kbmode *k)
{
/* reset original keyboard */
if (tcsetattr (0, TCSANOW, &(k->old))) {
fprintf (stderr, "restorekbmode() error: tcsetattr failed.\n");
return NULL;
}
return k;
}
Пример использования / Вывод
$ ./bin/month_roll
enter +/- to inc/decrement month ('q' to quit)
month : 6 : -
month : 5 : -
month : 4 : -
month : 3 : -
month : 2 : -
month : 1 : -
month : 12 : -
month : 11 : -
month : 10 : +
month : 11 : +
month : 12 : +
month : 1 : +
month : 2 : -
month : 1 : -
month : 12 : -
month : 11 : -
month : 10 : +
month : 11 : +
month : 12 : +
month : 1 : +
month : 2 : +
month : 3 : q
Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.
Мое предложение будет заключаться в том, чтобы сохранить счетчик месяцев в формате [0, 11] внутри кода, используя modulo(12) для обтекания. Это просто и облегчает понимание кода. Затем напишите функцию для отображения этого внутреннего представления [0, 11] во что-то, что пользователь захочет увидеть, то есть [1, 12], всякий раз, когда вы печатаете или каким-то образом отображаете значение для пользователя.
int16_t display_month(int16_t month)
{
return month + 1;
}
В этом случае очень просто вернуть месяц + 1, но в более общем случае отображения числа N на что-то, что не соответствует [0, N-1], я бы использовал массив для хранения этого отображения. Таким образом, отображение может быть чем угодно, не должно быть в порядке, и событие не должно быть целым числом.
int16_t display_month(int16_t month)
{
static int16_t index_to_month_map[] = {1,2,3,4,5,6,7,8,9,10,11,12};
return index_to_month_map[month];
}