tpop

The Practice of Programming - Solutions
Log | Files | Refs

commit d96884ab2efe1565a4492ec95d4c8d6bb810ed2a
parent 9638d22a9a85472930449602bcb6447313623b3c
Author: zerous Naveen Narayanan <zerous@nocebo.space>
Date:   Sat,  9 Mar 2019 21:01:58 +0100

Fix bug - next ptr not set properly after realloc

Diffstat:
Msw.c | 130++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 79 insertions(+), 51 deletions(-)

diff --git a/sw.c b/sw.c @@ -1,57 +1,55 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <assert.h> -/* shuffle newline terminated strings */ +/* shuffle newline/whitespace terminated words */ void shuffle(char *, int); +int mstrlen(char *); +char *mstrcpy(char *, char *); int -main(int argc, char **argv) +main(void) { - char c, *s, *n, *t; + int c; + char *beg, *next, *s; int nword; - size_t gf; + size_t siz; - (void) argc; - (void) argv; - - gf = 512; - s = n = NULL; + siz = 512; + beg = next = NULL; nword = 0; for (;(c = getc(stdin)) != EOF;) { - if (n == NULL || n >= (s + (gf - 512))) /* first time */ + if (next == NULL || (next - beg) >= (siz - 512)) /* first time */ { - t = realloc(s, gf); - if (t != NULL) { - s = t; - n = t; - *n++ = c; - gf += 512; + if ((s = realloc(beg, siz)) != NULL ) { + next = s + (next - beg); + beg = s; + *next++ = c; + siz += 512; } else { printf("err: realloc\n"); return 1; } } else if (c == '\n' || c == ' ') { - *n++ = '\0'; + *next++ = '\0'; nword++; } else { - *n++ = c; + *next++ = c; } } - /* shuffle(s, nword); */ + shuffle(s, nword); - for (char *t = s; t < n;) { + for (char *t = beg; t < next;) { printf("%s\n", t); - t += strlen(t) + 1; + t += mstrlen(t) + 1; } - free(s); + free(beg); return 0; } @@ -59,49 +57,79 @@ main(int argc, char **argv) void shuffle(char *s, int nword) { - char w[128]; + char buf1[128], buf2[128]; + int k, q, l; + char *str1, *str2; - for (int i = 0; i < nword ; i++) + for (int i = 0; i < nword && nword > 1; i++) { - int k, q, l, r; - char *m, *n; - - + /* get two rand word indexes */ q = rand()%(nword - 1); - l = rand()% (nword - 1); - k = 0; + l = rand()%(nword - 1); + k = 0; + for (char *t = s; k < nword; k++) { if (k == l) - m = t; + str1 = t; else if (k == q) - n = t; - r = strlen(t); - t += r + 1; + str2 = t; + t += mstrlen(t) + 1; } - assert(strlen(m) < 128); - assert(strlen(n) < 128); + if (mstrlen(str1) > 128 || mstrlen(str2) > 128) { + printf("word too long\n"); + return; + } - if (strlen(m) == strlen(n)) { - strcpy(w, m); - strcpy(m, n); - strcpy(n, w); + if (mstrlen(str1) == mstrlen(str2)) { + mstrcpy(buf1, str1); + mstrcpy(str1, str2); + mstrcpy(str2, buf1); } else { - strcpy(w, m); - int t = strlen(m) - strlen(n); - if (m > n) { - memmove((n + strlen(n) + 1 + t), (n + strlen(m) + 1), - m - (n + strlen(n) + 1)); + mstrcpy(buf1, str1); + mstrcpy(buf2, str2); + int t = mstrlen(str1) - mstrlen(str2); + if (str1 > str2) { + memmove((str2 + mstrlen(str2) + 1 + t), /* move words between the words being swapped */ + (str2 + mstrlen(str2) + 1), + str1 - (str2 + mstrlen(str2) + 1)); + mstrcpy(str2, buf1); + mstrcpy(str1 + t, buf2); } - else if (m < n) { - memmove((m + strlen(m) + 1 - t), (m + strlen(m) + 1), - n - (m + strlen(m) + 1)); + else if (str1 < str2) { + memmove((str1 + mstrlen(str1) + 1 - t), /* move words between the words being swapped */ + (str1 + mstrlen(str1) + 1), + str2 - (str1 + mstrlen(str1) + 1)); + mstrcpy(str1, buf2); + mstrcpy(str2 - t, buf1); } - strcpy(m, n); - strcpy(n, w); } } } + +char * +mstrcpy(char *a, char *b) +{ + int i; + for (i = 0; b[i] != '\0'; i++) + { + a[i] = b[i]; + } + a[i] = '\0'; + + return a; +} + +int +mstrlen(char *a) +{ + int i; + + for (i = 0; a[i] != '\0'; i++) + ; + + return i; +}