exc/k&r/03-control-flow/03-03.c

76 lines
1.6 KiB
C

#include <stdio.h>
#include <ctype.h>
#define SIZE 1000
/* check if c1-c2 is valid range */
#define IS_RANGE(c1, c2) ( \
(isdigit(c1) && isdigit(c2)) || \
(islower(c1) && islower(c2)) || \
(isupper(c1) && isupper(c2)) \
)
int getstr(char *s, int n);
void expand(char *s, char *t, int n);
/* copy stdin to string, run expand, print output */
int main()
{
char s[SIZE], t[SIZE];
if (getstr(s, SIZE) < 0)
printf("warning : overlfow on input\n");
expand(s, t, SIZE);
printf("%s\n", t);
return 0;
}
/* macro for checking overlfow of t in expand(s, t, n) */
#define CHECK_OVERFLOW(i, n) \
do { \
if (i >= n-1) { \
printf("warning : overflow in expand\n"); \
goto terminate; \
} \
} while (0)
/* expand: expand a-z from s to to abc...xyz in t (of size n), same for
* digits and uppercase letters */
void expand(char *s, char *t, int n)
{
int i = 0;
if (*s == '\0')
goto terminate;
int c;
for (t[i++] = *(s++); *s != '\0'; s++, i++) {
if (*s == '-' && IS_RANGE(*(s-1), *(s+1))) {
for (c = *(s-1) + 1; c < *(s+1); c++, i++) {
CHECK_OVERFLOW(i, n);
t[i] = c;
}
s++;
}
CHECK_OVERFLOW(i, n);
t[i] = *s;
}
terminate:
t[i] = '\0';
}
/* getstr: copies stdin to array s of length n, returns size of string or
* -1 if overflow */
int getstr(char *s, int n)
{
int i, c;
for (i = 0; (c = getchar()) != EOF; i++) {
if (i >= n-1) {
s[i] = '\0';
return -1;
}
s[i] = c;
}
s[i] = '\0';
return i;
}