I had this interview question like a year ago and was asked to code, on a piece of paper, how to reverse each word of a string. Since I am used to Java, I proposed the obvious answer of using split + reverse, which are native commands in Java. I was then told I couldn't use those, so I floundered and ended up with a really terrible solution (even though it technically would've worked).
Anyway, it was bugging me lately, so I gave it a shot in straight C, which I am not very good at, so it took me a good while to actually get it working.
I was wondering:
- Is this a good solution?
- Have I forgotten anything obvious?
- Have I done anything non-kosher in the C world?
Again, I'm not very good at C, so even small points will probably help me out.
#include <stdio.h>
void reverseString(char* start, char* end){
while (start < end){
char temp = *start;
*start = *end;
*end = temp;
++start;
--end;
}
}
char* word_start_index(char* p)
{
while((*p != '0円') && (*p == ' ')){
++p;
}
if(*p == '0円')
return NULL;
else
return p;
}
char* word_end_index(char* p)
{
while((*p != '0円') && (*p != ' ')){
++p;
}
return p-1;
}
void main(){
char arr[] = "kevin is a good programmer";
char* test = arr;
while (test != '0円'){
char* curWordStart = word_start_index(test);
if (curWordStart == NULL)
break;
char* curWordEnd = word_end_index(curWordStart);
reverseString(curWordStart, curWordEnd);
test = curWordEnd + 1;
}
printf("%s \n", arr);
}
Also, would taking a different approach, like in higher level languages of breaking the string into an array of strings (so I guess a 2D array of chars), then stepping through and reversing each one, be a good approach as well? I thought about this first and was unable to hash it out.
-
1\$\begingroup\$ Another thing that you need to consider is that words are not always terminated by a space. Punctuation also counts!.:,;? And, being awkward, what about numbers? \$\endgroup\$Glenn Rogers– Glenn Rogers2012年11月05日 12:19:32 +00:00Commented Nov 5, 2012 at 12:19
4 Answers 4
I have a few issues with in your code:
Consistency in naming - use either camelCase or not_camel_case but don't mix
consistency in braces. The opening brace for a function goes in the first column.
word_start_index
andword_end_index
should take aconst
parameterword_start_index
is the same asstrspn(string, " ");
or if you are also looking for punctuation,strspn(string, " \t\n.,;:");
word_end_index
- as forword_start_index
but usestrcspn
(note the 'c')word_end_index
as a function (ie not in your context) fails for an empty string or a string starting with a space (it returns the char before the string starts).variable
test
inmain()
is misnamed. I would prefer something that shows it is a string.the test
while (test != '0円')
inmain()
is wrong - should be*test != '0円'
. Your loop always exits from thebreak
no return or parameters in main()
Also, arguably the position of the stars in your pointers is wrong. I prefer char* p
to be written char *p
, which makes it clear that it is p that takes the star. Consider code such as char* a, b;
. This is bad because it gives the impression that b is a pointer.
-
\$\begingroup\$ Thanks for the comments! Do you think taking a different approach like in higher level languages of breaking the string into an array of string (so I guess a 2-d array of chars), then stepping through and reversing each one would be good approach as well? I thought about this first and was unable to hash it out. \$\endgroup\$KDiTraglia– KDiTraglia2012年11月05日 15:11:39 +00:00Commented Nov 5, 2012 at 15:11
-
\$\begingroup\$ No, your approach is fine \$\endgroup\$William Morris– William Morris2012年11月05日 15:16:44 +00:00Commented Nov 5, 2012 at 15:16
-
\$\begingroup\$ OK, thanks for the details, I was definitely unclear about how some of the pointers need to be declared and compared and had some trial and error there. The camel case issues were just a result of copy pasting a bit off the web, but again thanks for the help. \$\endgroup\$KDiTraglia– KDiTraglia2012年11月05日 15:18:37 +00:00Commented Nov 5, 2012 at 15:18
-
\$\begingroup\$ @WilliamMorris, hello, what is the benefit of changing the parameters to const? Thank you. \$\endgroup\$user85591– user855912015年12月31日 21:07:36 +00:00Commented Dec 31, 2015 at 21:07
I like it; nice and logical and easy to follow.
The only change I would make is the test for space.
*p == ' '
I would replace this with
isspace(*p)
I also met this question during a interview several years before, the string was null-terminated and separated by spaces. my idea was same as yours, just save some lines of code, comments in line.
// Reverse the characters between pointer p and q
void ReverseWord(char* p, char* q)
{
while(p < q)
{
char t = *p ;
*p++ = *q ;
*q-- = t ;
}
}
// Reverse all words in a sentence.
void ReverseSentence(char *s)
{
char *p = s ; // point to the start position of a word
char *q = s ; // point to the end position of a word(white space or '0円')
while(*q != '0円') // While string not ends
{
if (*q == ' ') // Get a word?
{
ReverseWord(p, q - 1) ;
q++ ; // move to next word
p = q ;
}
else
q++ ;
}
ReverseWord(p, q - 1) ; // Reverse the last word
}
Mine is also very similiar:
#include <stdio.h>
#include <ctype.h>
void reverse(char *p, char *q)
{
while (p<q)
{
char t = *p;
*p++ = *q;
*q-- = t;
}
}
char *reverse_each_word(char* str)
{
char *p, *q = str;
while(*q)
{
p = q; while(*p && !isalnum(*p)) p++; // Skip non-word chars
q = p; while(*q && isalnum(*q)) q++; // Skip word chars
if(*p) reverse(p, q-1);
}
return str;
}
int main()
{
char str[] = "An answer on http://codereview.stackexchange.com/questions/18229";
printf("%s\n", str);
printf("%s\n", reverse_each_word(str));
return 0;
}
Explore related questions
See similar questions with these tags.