diff --git a/k&r/05-pointers-and-arrays/05-01-02.c b/k&r/05-pointers-and-arrays/05-01-02.c new file mode 100644 index 0000000..f220ac9 --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-01-02.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +int getint(int *p); +int getfloat(float *p); + +/* ungetchar: push char c back to input stream */ +#define ungetchar(c) ungetc(c, stdin) + + +/* tests getfloat, prints input to output, puts valid numbers + * in brackets : n -> [n] */ +int main() +{ + float x; + int r; + while ((r = getfloat(&x)) != EOF) + if (!r) { + int c; + putchar(getchar()); + while (!isdigit(c = getchar()) && c != EOF && c != '-' && c != '+') + putchar(c); + ungetchar(c); + } else + printf("[%g]", x); + return 0; +} + +/* we assert that EOF is negative */ +static_assert(EOF < 0, "EOF is not a negative number"); + +/* ugetint: gets unsigned int from input to n + * n must be intialized by caller + * takes optional arguments for loop increment + * last char read is stored in varvar_c */ +#define ugetint(var_c, n, ...) \ + do { \ + for (; isdigit(var_c = getchar()); __VA_ARGS__) \ + n = 10 * (n) + var_c - '0'; \ + } while (0) + +/* getint : gets int from input and overwrites it to p + * returns 1 on valid integer, 0 if no integer is found + * and EOF on EOF. */ +int getint(int *p) +{ + int c; + if ((c = getchar()) == EOF) + return EOF; + + /* handle sign */ + int sign = (c == '-') ? -1 : ((c == '+') ? 1 : 0); + if (sign) + c = getchar(); + if (!isdigit(c)) { /* not a number */ + ungetchar(c); + if (sign) + ungetchar((sign > 0) ? '+' : '-'); + return 0; + } + + *p = c - '0'; + ugetint(c, *p); + ungetchar(c); + *p *= (sign) ? sign : 1; + return 1; +} + +#define DEC_SEP X('.') X(',') +#define EXP_SEP X('e') X('E') + +/* getfloat : gets float from input and overwrites it to p + * returns 1 on valid integer, 0 if no integer is found + * and EOF on EOF. */ +int getfloat(float *p) +{ + char flag; + int n; + if ((flag = getint(&n)) < 1) /* not a number */ + return flag; + *p = n; + + int exp, c = getchar(); + /* fractional part */ +#define X(C) c == C || + if (DEC_SEP 0) { + n = exp = 0; + ugetint(c, n, exp--); + *p += n * pow(10, exp); + } +#undef X + /* exponent part */ +#define X(C) c == C || + if ((EXP_SEP 0) && getint(&exp)) { + *p *= pow(10, exp); + } else + ungetchar(c); + return 1; +} diff --git a/k&r/05-pointers-and-arrays/05-03.c b/k&r/05-pointers-and-arrays/05-03.c new file mode 100644 index 0000000..0f5e146 --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-03.c @@ -0,0 +1,40 @@ +#include + +char *strcat(char *s, const char *t); +char *strcpy(char *t, const char *s); +size_t strlen(const char *s); + +/* passes args to strcat, prints result */ +int main(int argc, char *argv[]) +{ + if (argc < 3) + return 1; + char s[strlen(argv[1]) + strlen(argv[2])]; + strcat(strcpy(s, argv[1]), argv[2]); + printf("%s\n", s); +} + +/* strcat: concat string t to end of string s */ +char *strcat(char *s, const char *t) +{ + int slen = strlen(s); + return strcpy(s + slen, t) - slen; +} + +/* strcpy: copy string s to t */ +char *strcpy(char *t, const char *s) +{ + char *tc = t; + while ((*t++ = *s++)) + ; + return tc; +} + +/* strlen: return length of string s (without \0) */ +size_t strlen(const char *s) +{ + const char *sc = s; + while (*s++) + ; + return s - sc - 1; +} diff --git a/k&r/05-pointers-and-arrays/05-04.c b/k&r/05-pointers-and-arrays/05-04.c new file mode 100644 index 0000000..f265135 --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-04.c @@ -0,0 +1,21 @@ +#include +#include + +int strend(const char *s, const char *t); + +/* passes args to strend, prints result */ +int main(int argc, char *argv[]) +{ + if (argc < 3) + return 1; + printf("%s\n", (strend(argv[1], argv[2])) ? "true" : "false"); + return 0; +} + +/* strend: returns 1 if t == end of s otherwise false */ +int strend(const char *s, const char *t) +{ + size_t s_len = strlen(s); + size_t t_len = strlen(t); + return (s_len >= t_len) && !strcmp(s + s_len - t_len, t); +} diff --git a/k&r/05-pointers-and-arrays/05-05.c b/k&r/05-pointers-and-arrays/05-05.c new file mode 100644 index 0000000..a5b11f2 --- /dev/null +++ b/k&r/05-pointers-and-arrays/05-05.c @@ -0,0 +1,64 @@ +#include +#include + +char *strncpy(char *t, const char *s, size_t n); +char *strncat(char *t, const char *s, size_t n); +int strncmp(const char *s, const char *t, size_t n); + +/* strlen: returns string length (w/o '\0') */ +size_t strlen(const char *s) +{ + const char * const sc = s; + while (*s++) + ; + return s - sc - 1; +} + +/* takes args s1, s2, n and passes them to the above declared + * functions, prints the results */ +int main(int argc, char *argv[]) +{ + if (argc < 4) + return 1; + + int n = atoi(argv[3]); + char s[strlen(argv[1]) + strlen(argv[2]) + 1]; + /* strncpy */ + printf("strncpy: %s\n", strncpy(s, argv[1], n)); + /* strncat */ + printf("strncat: %s\n", strncat(s, argv[2], n)); + /* strncmp */ + int comp = strncmp(argv[1], argv[2], n); + printf("strncmp: %.*s ", n, argv[1]); + putchar((comp > 0) ? '>' : (comp < 0) ? '<' : '='); + printf(" %.*s\n", n, argv[2]); + + return 0; +} + +/* strncpy: copies at most n chars from s to t, returns t*/ +char *strncpy(char *t, const char *s, size_t n) +{ + char * const tc = t; + while (n-- && (*t++ = *s++)) + ; + *t = '\0'; + return tc; +} + +/* strncat: concats at most n chars of s to t, returns t */ +char *strncat(char *t, const char *s, size_t n) +{ + strncpy(t + strlen(t), s, n); + return t; +} + +/* strncmp: compares at most n chars of s and t */ +int strncmp(const char *s, const char *t, size_t n) +{ + if (!n) + return 0; + while (--n && *s && (*s == *t)) + s++, t++; + return *s - *t; +}