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