c - How can I reverse the letters in each word of a string -
how can reverse words of string characters , numbers. example:
this start! siht si eht trats!
i've written code reverses (also '!'); output is:
siht si eht !trats
code:
#include<stdio.h> void reverse(char *begin, char *end); void reversewords(char *s) { char *word_begin = s; char *temp = s; while(isalnum(*temp) || *temp ) { temp++; if (*temp == '\0') { reverse(word_begin, temp-1); } else if(*temp == ' ') { reverse(word_begin, temp-1); word_begin = temp+1; } } } void reverse(char *begin, char *end) { char temp; while (begin < end) { temp = *begin; *begin++ = *end; *end-- = temp; } } int main() { char s[50]; scanf("%[^\n]",&s); char *temp = s; reversewords(s); printf("%s", s); getchar(); return 0; }
the reverse()
function have useful tool need. many traditional versions rely on passing start of text reversed, purposes, passing pointers first , last characters of range reversed neat. use unchanged except trivia. make static
because make every function (except main()
) static
unless there's header declares , used more 1 source file — there's 1 source file code.
all have identify start , end of each word in text. best done nested loops — 1 on 'not reached end of input string', , within that, skip on non-alphabetic (non-word) characters, record start of word, skip on alphabetic (word) characters, reverse word between start , end, , repeat outer loop.
that leads code this.
#include <ctype.h> #include <stdio.h> #include <string.h> static void reverse(char *begin, char *end) { while (begin < end) { char temp = *begin; *begin++ = *end; *end-- = temp; } } static void reversewords(char *s) { while (*s != '\0') { while (*s != '\0' && !isalnum((unsigned char)*s)) s++; char *word = s; while (isalnum((unsigned char)*s)) s++; reverse(word, s-1); } } int main(void) { char s[1024]; while (fgets(s, sizeof(s), stdin) != 0) { s[strcspn(s, "\n")] = '\0'; printf("in: [%s]\n", s); reversewords(s); printf("out: [%s]\n", s); } return 0; }
the (unsigned char)
cast necessary correctly handle accented characters in single-byte code set such iso 8859-15 on machine plain char
signed type.
sample output:
this start! in: [this start!] out: [siht si eht trats!] , isn't end. in: [and isn't end.] out: [dna siht nsi't eht dne.] neither leading blanks nor trailing ones interfere in: [ neither leading blanks nor trailing ones interfere ] out: [ rehtien gnidael sknalb ron gniliart seno erefretni ] lots..of=intermediate=punctuation@interruptions.com^give&no&&&trouble in: [ lots..of=intermediate=punctuation@interruptions.com^give&no&&&trouble ] out: [ stol..fo=etaidemretni=noitautcnup@snoitpurretni.moc^evig&on&&&elbuort ]
note if decide apostrophes should counted part of word (so "doesn't
" maps "t'nseod"
rather "nseod't"
in code above), need fix condition in loops. @ point, i'd create static inline
function job:
static inline int is_word_char(int c) { return isalpha(c) || c == '\''; }
note <ctype.h>
reserves words starting is
(and to
) followed lower-case letter; using name is_word_char()
avoids such reserved words. also, function defined take int
, functions in <ctype.h>
, simple consistency.
the reverse words function becomes:
static void reversewords(char *s) { while (*s != '\0') { while (*s != '\0' && !is_word_char((unsigned char)*s)) s++; char *word = s; while (is_word_char((unsigned char)*s)) s++; reverse(word, s-1); } }
it possible generalize reversewords()
passing suitable pointer-to-function:
static void reversewords(char *s, int (*is_word)(int)) { while (*s != '\0') { while (*s != '\0' && !is_word((unsigned char)*s)) s++; char *word = s; while (is_word((unsigned char)*s)) s++; reverse(word, s-1); } }
now you'd remove inline
is_word_char()
because need actual function function pointer, , can use:
reversewords(s, isalnum); reversewords(s, is_word_char);
the downside of degree of generalization cost of actual function call classify each character, losing possibilities of inlining classifier function.
sidelight on debugging
i typed preliminary version of answer reversewords()
function looking this:
static void reversewords(char *s) { while (*s != '\0') { while (!isalnum((unsigned char)*s)) s++; char *word = s; while (isalnum((unsigned char)*s)) s++; reverse(word, s-1); } }
the difference in !isalnum
loop — there isn't check null byte there. realized code must skipping past null byte(s). instrumenting this:
static void reversewords(char *s) { while (*s != '\0') { while (/**s != '\0' &&*/ !isalnum((unsigned char)*s)) { printf("= %d", *s); s++; } putchar('\n'); char *word = s; while (isalnum((unsigned char)*s)) s++; reverse(word, s-1); } }
and running on "this start!" produced far output:
this start! in: [this start!] = 32 = 32 = 32 = 33= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0= -49= 0= -24 = -48= 41= 96 = -122= 46 = -1= 127= 0= 0= -120= -124= 46 = -1= 127= 0= 0 …many lines omitted… = -1= 127= 0= 0= -118= -113= 46 = -1= 127= 0= 0= -65= -113= 46 = -1= 127= 0= 0= 0= 0= 0= 0= 0= 0= 0= 0 = 95 = 61= 46= 47 out: [siht si eht trats!]
the output appeared sane — code poking around sorts of places shouldn't have been.
the revised code safe long null byte fails "is word character" test.
Comments
Post a Comment