Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Ben Bacarisse Newsgroups: comp.programming Subject: Re: Coding while drunk and stoned take 2. (Yes, I know this is a cross post) Date: Thu, 27 Feb 2020 21:00:36 +0000 Organization: A noiseless patient Spider Lines: 72 Message-ID: <87ftevvj7v.fsf@bsb.me.uk> References: <0b8d1b58-3651-47ed-a2b8-63dc1d659c91@googlegroups.com> <87y2souis2.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: reader02.eternal-september.org; posting-host="c5b2f88804383f9a4f3ed96188f26610"; logging-data="12879"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/EPde9xxVj/OmoVmd0TVD96ut9VHSKXYQ=" Cancel-Lock: sha1:sKJF+HEjabniD08Vb73XWO5vVuU= sha1:cBUWLTGP/w7YsqRuFfShR4zkJoE= X-BSB-Auth: 1.9a598ea1950a2a550eb9.20200227210036GMT.87ftevvj7v.fsf@bsb.me.uk Xref: csiph.com comp.programming:10695 Julio Di Egidio writes: > On Thursday, 27 February 2020 16:55:29 UTC+1, Ben Bacarisse wrote: >> "Chad Altenburg, Ph.D." writes: > >> > My gut feeling says this isn't right. But I have no idea how this >> > could be done in one loop. >> >> Here's a C solution. It's messy because the natural way to do string >> things in C is to pass an array to take the result. You then need to >> pass a size so the function does not write out-of-bounds. But to be >> useful the function should keep going and return the size that's needed >> even when there was no room this time: >> >> #include >> >> size_t zipzap(const char *src, char *dst, size_t n) >> { >> size_t i = 0; >> while (*src) { >> if (i < n) >> dst[i] = *src; >> i += 1; >> if (src[0] == 'z' && src[1] && src[2] == 'p') { >> if (i < n) >> dst[i] = 'p'; >> i += 1; >> src += 3; >> } >> else src += 1; >> } >> dst[i <= n ? i : n-1] = 0; >> return i + 1; >> } >> >> int main(int argc, char **argv) >> { >> char z[10]; >> for (int a = 1; a < argc; a++) { >> size_t required = zipzap(argv[a], z, sizeof z); >> printf("%s -> %s (%zu)\n", argv[a], z, required); >> } >> } >> >> The more "scripty" way -- allocating the result -- looks simpler: >> >> char *zipzap_str(const char *src) >> { >> char result[strlen(src) + 1], *dst = result; >> while (*src) { >> *dst++ = *src++; >> if (src[-1] == 'z' && src[0] && src[1] == 'p') { >> *dst++ = 'p'; >> src += 2; >> } >> } >> *dst++ = 0; >> char *rp = malloc(dst - result); >> return rp ? strcpy(rp, result) : 0; >> } > > Man, that hurts... Yes, it's grim. It's just three explicit patterns in Haskell: zipzap s = case s of [] -> [] 'z':_:'p' : rest -> 'z':'p' : zipzap rest c : rest -> c : zipzap rest -- Ben.