http://qs321.pair.com?node_id=589993


in reply to Five Ways to Reverse a String of Words (C#, Perl 5, Perl 6, Ruby, Haskell)

Here's a version in plain ANSI C. Yikes, that looks bad compared to the one liners. :-)

#include <stdio.h> #include <stdlib.h> #include <string.h> /* reverse a string in place, return str */ static char* reverse(char* str) { char* left = str; char* right = left + strlen(str) - 1; char tmp; while (left < right) { tmp = *left; *left++ = *right; *right-- = tmp; } return str; } static int reverseWords( const char* instr, /* in: string of words */ char* outstr) /* out: reversed words */ /* (caller must ensure big enough) */ { char* p; char* buf; *outstr = '\0'; if ((buf = (char*)malloc(strlen(instr)+1)) == NULL) { fprintf(stderr, "oops, out of memory\n"); return -1; } strcpy(buf, instr); reverse(buf); if ((p = strtok(buf, " \t")) == NULL) { free(buf); return 0; } strcpy(outstr, reverse(p)); outstr += strlen(p); while ((p = strtok(NULL, " \t")) != NULL) { *outstr++ = ' '; strcpy(outstr, reverse(p)); outstr += strlen(p); } free(buf); return 0; } int main() { char instr[256]; char outstr[256]; strcpy(instr, " one two \t three four "); reverseWords(instr, outstr); printf("in='%s' out='%s'\n", instr, outstr); return 0; }

Updated 17-Dec: Added improved version without the ugly malloc/strtok below:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> static const char* get_next_word(const char* pstart, const char* p, si +ze_t* len) { const char* pend; while (p >= pstart && isspace(*p)) --p; if (p < pstart) return NULL; pend = p-- + 1; while (p >= pstart && !isspace(*p)) --p; *len = pend - ++p; return p; } static void reverseWords( const char* instr, /* in: string of words */ char* outstr) /* out: reversed words */ /* (caller must ensure big enough) */ { const char* p = instr + strlen(instr) - 1; size_t len; if ((p = get_next_word(instr, p, &len)) == NULL) { *outstr = '\0'; return; } memcpy(outstr, p, len); outstr += len; while ((p = get_next_word(instr, --p, &len)) != NULL) { *outstr++ = ' '; memcpy(outstr, p, len); outstr += len; } *outstr = '\0'; return; } int main() { char instr[256]; char outstr[256]; strcpy(instr, " one two \t three four "); reverseWords(instr, outstr); printf("in='%s' out='%s'\n", instr, outstr); return 0; }

Replies are listed 'Best First'.
Re^2: Five Ways to Reverse a String of Words (ANSI C version)
by salva (Canon) on Mar 06, 2015 at 12:28 UTC
    A reverse-words-in-place C version:
    #include <stdio.h> #include <stdlib.h> char * readlinef(FILE *stream) { int buffer_len = 0; int len = 0; char *buffer; while (1) { int c = fgetc(stream); switch (c) { case '\n': if (!len) continue; case EOF: if (buffer) buffer[len] = '\0'; return buffer; default: if (len >= buffer_len) { buffer_len = buffer_len * 2 + 100; buffer = (char *)realloc(buffer, buffer_len + 1); } buffer[len++] = c; } } } void reverse(char *start, char *end) { while (start < --end) { char tmp = *end; *end = *start; *(start++) = tmp; } } char * skip_spaces(char *p) { while (isspace(*p)) p++; return p; } char * skip_word(char *p) { while (*p && !isspace(*p)) p++; return p; } int main(int argc, char *argv[]) { char *line; while (line = readlinef(stdin)) { char *start = line; while (1) { char *word_start = skip_spaces(start); char *word_end = skip_word(word_start); if (word_start == word_end) { if (start != line) start--; break; } reverse(start, word_end); start += word_end - word_start; if (*start == '\0') break; start++; } reverse(line, start); *start = '\0'; fprintf(stdout, "%s\n", line); free(line); } }

      My try inspired by bitingduck's triple reverse:

      #include <stdio.h> #include <string.h> void reverse( char*p, int n ) { char c, *e = p+n-1; n /= 2; while( n-- ) c = *p, *p++ = *e, *e-- = c; } char *reverseWords( char*line ) { int len = (int)strlen( line ); char *p = line, *p1 = line, *e = line+len; reverse( line, len ); while( p <= e ) { if( *p == 32 || *p == 0 ) { reverse( p1, (int)( p - p1) ); p1 = p+1; } ++p; } return line; } int main( int argc, char **argv ) { char line[ 1024 ]; printf( "%s\n", reverseWords( gets_s( line, 1024 ) ) ); return 0; }

      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
      In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
Re^2: Five Ways to Reverse a String of Words (ANSI C version)
by Anonymous Monk on Sep 30, 2008 at 11:09 UTC
    supper !
      You'll need mayonnaise to swallow that.

       

        ill give you some mayonnaise
Re^2: Five Ways to Reverse a String of Words (ANSI C version)
by oiskuu (Hermit) on Mar 06, 2015 at 15:13 UTC

    A somewhat condensed, C99 version:

    #include <stdio.h> #include <ctype.h> #include <string.h> char *str_rwords(char *s) { int n = strlen(s); char t[n], *e = t + n, *d = e, *s0; do { for (s0 = s; *s && isalpha(*s); s++); if ((n = s - s0)) { if (d != e) *--d = ' '; d = memcpy(d - n, s0, n); } } while (*s++); return strndup(d, e - d); } int main(void) { puts(str_rwords(" one two \t three four ")); }