Тщательно выбирая сравнения, вы можете упростить использование '%'
. Вместо того, чтобы проверять, является ли 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
Просмотрите все и дайте мне знать, если у вас есть дополнительные вопросы.
person
David C. Rankin
schedule
06.02.2018
a % b
— это число между0
иb-1
. Если бы вы хотели число между1
иb
, что бы вы сделали? - person molbdnilo   schedule 06.02.2018if
отключается на единицу. Если вы это исправите, вам не придется неловко добавлять12 + 1
. - person DevSolar   schedule 06.02.2018m
не является отрицательным,m % 12
- это число от 0 до 11, так что ... (Вы были почти там.) - person molbdnilo   schedule 06.02.2018