Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: Five Ways to Reverse a String of Words (ANSI C version)

by eyepopslikeamosquito (Canon)
on Dec 15, 2006 at 08:36 UTC ( #589993=note: print w/ replies, xml ) Need Help??


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; }


Comment on Re: Five Ways to Reverse a String of Words (ANSI C version)
Select or Download Code
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 salva (Abbot) 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 oiskuu (Friar) 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 ")); }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://589993]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2015-05-22 11:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    In my home, the TV remote control is ...









    Results (455 votes), past polls