Reverse word order to read it from right to left

  • Thread starter lovecreatesbea...
  • Start date
L

lovecreatesbea...

I want to write a function to reverse the order of words to make it
read from right to left, but it doesn't work. Can you help me and
point out my mistakes. Thank you for your time.


#include <string.h>
#include <ctype.h>

/* Reverse order of words in a sentence in a string to read it from
right to
* left. * For example:
*
* " hello world !! ! "
*
* becomes
*
* " ! !! world hello "
*
* (heading and tailing blanks should be reserved):
*/

char *rttolt(char str[])
{
enum STATUS{SPC, NSPC, UNDEF};
char *p1 = str, *p2, *p3, ch;
int len = strlen(str);
enum STATUS prestt;

if (!str)
return NULL;
prestt = UNDEF;
for (; len != 0; len--){
if (!isspace(str[len - 1])){
switch ((int)prestt){
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
}
prestt = NSPC;
} else if (isspace(str[len - 1])){
switch ((int)prestt){
case NSPC:
for (p3 = &str[len]; !isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
}
prestt = SPC;
}
}
return str;
}

#include <stdio.h>
int main(void)
{
char a[] = "hello world !";

printf("%s, %d\n", a, strlen(a));
rttolt(a);
printf("%s, %d\n", a, strlen(a));
return 0;
}
 
O

osmium

I want to write a function to reverse the order of words to make it
read from right to left, but it doesn't work. Can you help me and
point out my mistakes. Thank you for your time.

<snip>

You forgot to explain the theory of operation. Should it work on n words
of just two words? Do the words have to be the same size? You seem to have
a fondness for switch statements that don't seem necessary. Some compilers
may accept the definition you have for the array, a. They don't have to.

Add a PNT macro and play around with where you call it. Change the data
sample to something more general and without punctuation for the early
attempts. I see non alphabetics creeping into the output.

If all else fails, add some commentary and repost.

Slight modifications embedded.

#include <string.h>
#include <ctype.h>

/* Reverse order of words in a sentence in a string to read it from
right to
* left. * For example:
*
* " hello world !! ! "
*
* becomes
*
* " ! !! world hello "
*
* (heading and tailing blanks should be reserved):
*/

#define PNT printf("debug %s\n", str)


char *rttolt(char str[])
{
enum STATUS{SPC, NSPC, UNDEF};
char *p1 = str, *p2, *p3, ch;
int len = strlen(str);
enum STATUS prestt;

if (!str)
return NULL;
prestt = UNDEF;
for (; len != 0; len--){
if (!isspace(str[len - 1])){
switch ((int)prestt){
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
//PNT;
}
//PNT;
break;
}
prestt = NSPC;
} else if (isspace(str[len - 1])){
switch ((int)prestt){
case NSPC:
for (p3 = &str[len]; !isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
PNT;
}
PNT;
break;
}
prestt = SPC;
}
}
return str;
}

#include <stdio.h>
int main(void)
{
char a[] = "abc defgh";

printf("%s, %d\n", a, strlen(a));
rttolt(a);
printf("%s, %d\n", a, strlen(a));
getchar();
return 0;
}
 
F

fred.l.kleinschmidt

I want to write a function to reverse the order of words to make it
read from right to left, but it doesn't work. Can you help me and
point out my mistakes. Thank you for your time.

#include <string.h>
#include <ctype.h>

/* Reverse order of words in a sentence in a string to read it from
right to
* left. * For example:
*
* " hello world !! ! "
*
* becomes
*
* " ! !! world hello "
*
* (heading and tailing blanks should be reserved):
*/

char *rttolt(char str[])
{
enum STATUS{SPC, NSPC, UNDEF};
char *p1 = str, *p2, *p3, ch;
int len = strlen(str);
enum STATUS prestt;

if (!str)
return NULL;
prestt = UNDEF;
for (; len != 0; len--){
if (!isspace(str[len - 1])){
switch ((int)prestt){
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
}
prestt = NSPC;
} else if (isspace(str[len - 1])){
switch ((int)prestt){
case NSPC:
for (p3 = &str[len]; !isspace(*p3); p3++){
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
}
prestt = SPC;
}
}
return str;

}

#include <stdio.h>
int main(void)
{
char a[] = "hello world !";

printf("%s, %d\n", a, strlen(a));
rttolt(a);
printf("%s, %d\n", a, strlen(a));
return 0;

A much cleaner, shorter, and more understandable algorithm:
1) invert the entire sentence
2) for each whitespace delimited substring in the sentence,
invert the substring.
 
U

user923005

I want to write a function to reverse the order of words to make it
read from right to left, but it doesn't work. Can you help me and
point out my mistakes. Thank you for your time.
[snip]
Push the words on a lifo and pop them when you have read all the
material.
 
C

CBFalconer

osmium said:
<snip>

You forgot to explain the theory of operation. Should it work on
n words of just two words? Do the words have to be the same size?
You seem to have a fondness for switch statements that don't seem
necessary. Some compilers may accept the definition you have for
the array, a. They don't have to.

The OP could take a look at freverse.c, a test program for the
ggets general purpose string input routine. See ggets.zip at:

<http://cbfalconer.home.att.net/download/>
 
T

Thad Smith

osmium said:
<snip>

You forgot to explain the theory of operation. Should it work on n words
of just two words?

With the definition given, "reverse the order of words" implies all the
words, unless otherwise specified.
Do the words have to be the same size?

Without specification to that effect, that wouldn't be required.

The biggest problem in the lack of definition of a word. Is
"thirty-three" one word or two? In standard English it is two, but
co-op is one word. What about non-alphabetic [single word] characters?
Is each one individually reversed or are any combinations of
non-alphabetic characters kept in the same order?
 
O

osmium

osmium said:
You seem to have a fondness for switch statements that don't seem
necessary.

I think you have in your mind the notion of a state machine and three
states, (SPC, NSPC, UNDEF) but you misunderstand the switch statement. For
example, here is an extract of one of your two *separate* switch statements.

switch ((int)prestt)
{
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++)
{
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
} // end of switch

where presstt contains the state The break at the end looks like it makes
sense, but look again. What effect can it possibly have? None.

prestt is either SPC or it's not, a simple if would be sufficient. So my
point was, either get rid of the switches or make them useful.

I suggest you rethink your logic and recode. Note that the simplest test
would be "a b" where the two words are a and b - get that working first.
The method prrposed by Fred Kleinschmidt sounds good to me for a student
exercies with no punctuation to handle other than the space.

To continue on your present path I think you want something like

switch(prestt)
(
case: SPC
case NSPC:
case:UNDEF:
} // end switch

Fill in the missing stuff.
 
K

Keith Thompson

osmium said:
I think you have in your mind the notion of a state machine and three
states, (SPC, NSPC, UNDEF) but you misunderstand the switch statement. For
example, here is an extract of one of your two *separate* switch statements.

switch ((int)prestt)
{
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++)
{
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
} // end of switch

where presstt contains the state The break at the end looks like it makes
sense, but look again. What effect can it possibly have? None.

prestt is either SPC or it's not, a simple if would be sufficient. So my
point was, either get rid of the switches or make them useful.
[...]

Certainly the OP's switch statement is poorly written, in several
ways. However, I habitually put a ``break;'' at the end of each case
of a switch statement, even if it does nothing. I think of the
``break;'' as being almost part of the syntax of a switch statement.
(Unless I want to fall through, but that's unusual, and if I do that I
add a prominent comment.)

For example:

switch (ch) {
case 'a': case 'A':
/* blah blah */
break;
case 'b': case 'B':
/* blah blah */
break;
default:
/* blah blah */
break;
}
 
L

lovecreatesbea...

[...]


I think you have in your mind the notion of a state machine and three
states, (SPC, NSPC, UNDEF) but you misunderstand the switch statement. For
example, here is an extract of one of your two *separate* switch statements.
switch ((int)prestt)
{
case SPC:
for (p3 = &str[len]; isspace(*p3); p3++)
{
ch = *p3;
for (p2 = &str[len - 1]; p2 >= p1; p2--)
*(p2 + 1) = *p2;
*p2 = ch;
p1++;
}
break;
} // end of switch
where presstt contains the state The break at the end looks like it makes
sense, but look again. What effect can it possibly have? None.
prestt is either SPC or it's not, a simple if would be sufficient. So my
point was, either get rid of the switches or make them useful.

[...]

Certainly the OP's switch statement is poorly written, in several
ways. However, I habitually put a ``break;'' at the end of each case
of a switch statement, even if it does nothing. I think of the
``break;'' as being almost part of the syntax of a switch statement.
(Unless I want to fall through, but that's unusual, and if I do that I
add a prominent comment.)

For example:

switch (ch) {
case 'a': case 'A':
/* blah blah */
break;
case 'b': case 'B':
/* blah blah */
break;
default:
/* blah blah */
break;
}

Thank you for the suggestion.

Now I come up with my new code shown as follow. It has some
improvement. It works with space separated sentence. The sad thing is
that it doesn't work with input like:
char a2[] = "a b c d";
char a4[] = "a b c d";

but it still works with input like:
char a3[] = " a b c d ";
char a[] = " hello code monkey ";

I print out a test result diagram as following.



/
*******************************************************************************
* Reverse order of words in a string to read it from right to left.
For example
* "hello code monkey" becomes "monkey code hello"

******************************************************************************/

char *rttolt(char *p)
{
enum STATUS {SPC, NSPC, UNDEF} prestt = UNDEF;
const char BLK = ' ';
char *p1, *p2, *p3, ch;

for (p1 = p; *p1; p1++)
;
p1--;
prestt = UNDEF;
for (p2 = p; p2 != p1; p2++){
if (*p2 != BLK){
if (prestt == SPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = NSPC;
} else if (*p2 == BLK){
if (prestt == NSPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = SPC;
}
}
return p;
}


#include <stdio.h>
int main(void)
{
char a2[] = "a b c d";
char a4[] = "a b c d";

char a3[] = " a b c d ";
char a[] = " hello code monkey ";

printf(" [%s]\n", a);
rttolt(a);
printf(" [%s]\n", a);
return 0;
}



Run: D:\working\c\a.out
[ hello code monkey ]
35: [hello code monkey ]
51: [hell code monkey o ]
51: [hel code monkey lo ]
51: [he code monkey llo ]
51: [h code monkey ello ]
51: [ code monkey hello ]
35: [ code monkey hello ]
35: [code monkey hello ]
51: [cod monkey e hello ]
51: [co monkey de hello ]
51: [c monkey ode hello ]
51: [ monkey code hello ]
35: [ monkey code hello ]
35: [monkey code hello ]
51: [monke y code hello ]
51: [monk ey code hello ]
51: [mon key code hello ]
51: [mo nkey code hello ]
51: [m onkey code hello ]
51: [ monkey code hello ]
[ monkey code hello ]

Press the Enter key to return to Source Insight...
 
S

santosh

(e-mail address removed) wrote:
[snip suggestions from osmium and Keith Thompson]
Thank you for the suggestion.

Now I come up with my new code shown as follow. It has some
improvement. It works with space separated sentence. The sad thing is
that it doesn't work with input like:
char a2[] = "a b c d";
char a4[] = "a b c d";

but it still works with input like:
char a3[] = " a b c d ";
char a[] = " hello code monkey ";

I print out a test result diagram as following.

/********************************************************************
* Reverse order of words in a string to read it from right to left.
For example
* "hello code monkey" becomes "monkey code hello" */
/*********************************************************************/

char *rttolt(char *p)
{
enum STATUS {SPC, NSPC, UNDEF} prestt = UNDEF;
const char BLK = ' ';
char *p1, *p2, *p3, ch;

for (p1 = p; *p1; p1++)
;
p1--;
prestt = UNDEF;
for (p2 = p; p2 != p1; p2++){
if (*p2 != BLK){
if (prestt == SPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = NSPC;
} else if (*p2 == BLK){
if (prestt == NSPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = SPC;
}
}
return p;
}


#include <stdio.h>
int main(void)
{
char a2[] = "a b c d";
char a4[] = "a b c d";

char a3[] = " a b c d ";
char a[] = " hello code monkey ";

printf(" [%s]\n", a);
rttolt(a);
printf(" [%s]\n", a);
return 0;
}

<snip output>

Why so complex. Here is a simpler version that, AFAICT, conforms to your
specification.

/* reverse the word order in 'src' to 'dest' */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

void wrdrev(char *src, char *dest)
{
char *i, *j, *k;

i = j = k = src + (strlen(src)-1);
while (i >= src) {
if (isspace((unsigned char)*i)) {
*dest++ = *i--;
k = j = i;
}
else {
while (!isspace((unsigned char)*j) && j >= src) k = --j;
for (j += 1; j <= i; j++) *dest++ = *j;
i = j = k;
}
}
*dest = '\0';
return;
}

int main(void)
{
char a[] = " mad code monkey !! ";
char b[] = " mad code monkey !! ";
wrdrev(a, b);
printf("a = %s\nb = %s\n", a, b);
return 0;
}

$ ./wrdrev
a = mad code monkey !!
b = !! monkey code mad
$
 
S

santosh

santosh said:
(e-mail address removed) wrote:
[snip suggestions from osmium and Keith Thompson]
Thank you for the suggestion.

Now I come up with my new code shown as follow. It has some
improvement. It works with space separated sentence. The sad thing is
that it doesn't work with input like:
char a2[] = "a b c d";
char a4[] = "a b c d";

but it still works with input like:
char a3[] = " a b c d ";
char a[] = " hello code monkey ";

I print out a test result diagram as following.

/********************************************************************
* Reverse order of words in a string to read it from right to left.
For example
* "hello code monkey" becomes "monkey code hello" */
/*********************************************************************/
<snip code & output>

Why so complex. Here is a simpler version that, AFAICT, conforms to your
specification.

/* reverse the word order in 'src' to 'dest' */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

void wrdrev(char *src, char *dest)
{
char *i, *j, *k;

i = j = k = src + (strlen(src)-1);
while (i >= src) {
if (isspace((unsigned char)*i)) {
*dest++ = *i--;
k = j = i;
}
else {
while (!isspace((unsigned char)*j) && j >= src) k = --j;
for (j += 1; j <= i; j++) *dest++ = *j;
i = j = k;
}
}
*dest = '\0';
return;
}

Sorry to "lovecreatesbeauty" for presenting flawed code. The above function
invokes undefined behaviour when the pointers 'i' and 'j' are decremented
below the value of 'src.' The fix though is simple and I leave it as an
exercise for the OP.

<snip rest>
 
L

lovecreatesbea...

santosh wrote: [...]
/* reverse the word order in 'src' to 'dest' */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void wrdrev(char *src, char *dest)
{
char *i, *j, *k;
i = j = k = src + (strlen(src)-1);
while (i >= src) {
if (isspace((unsigned char)*i)) {
*dest++ = *i--;
k = j = i;
}
else {
while (!isspace((unsigned char)*j) && j >= src) k = --j;
for (j += 1; j <= i; j++) *dest++ = *j;
i = j = k;
}
}
*dest = '\0';
return;
}

Sorry to "lovecreatesbeauty" for presenting flawed code. The above function
invokes undefined behaviour when the pointers 'i' and 'j' are decremented
below the value of 'src.' The fix though is simple and I leave it as an
exercise for the OP.

Please come to my code first. I update my code, this version fixes the
previous bug.

The prototypes of our functions are different. you use two parameters
and don't change the original argument.

I use only one parameter and alter the original copy of argument. Is
it bad style?


/
*******************************************************************************
* Reverse order of space separated words, for example:
* "hello code monkey" becomes "monkey code hello"

******************************************************************************/

char *wrdrvs(char *p)
{
enum STATUS {SPC, NSPC, UNDEF} prestt = UNDEF;
const char BLK = ' ';
char *p1, *p2, *p3, ch;

for (p1 = p; *p1; p1++)
;
p1--;
prestt = UNDEF;
for (p2 = p; p2 <= p1; p2++){
if (*p2 != BLK){
if (prestt == SPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = NSPC;
} else if (*p2 == BLK){
if (prestt == NSPC){
while (p2 > p){
ch = *(p2 - 1);
for (p3 = p2; p3 <= p1; p3++)
*(p3 - 1) = *p3;
*--p3 = ch;
p2--, p1--;
}
}
prestt = SPC;
}
}
return p;
}
 
L

lovecreatesbea...

(e-mail address removed) wrote: [...]
/* reverse the word order in 'src' to 'dest' */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

void wrdrev(char *src, char *dest)
{
char *i, *j, *k;

i = j = k = src + (strlen(src)-1);
while (i >= src) {
if (isspace((unsigned char)*i)) {
*dest++ = *i--;

i may point to one past the first array element
k = j = i;
}
else {
while (!isspace((unsigned char)*j) && j >= src) k = --j;

so does j
 
S

santosh

(e-mail address removed) wrote: [...]
/* reverse the word order in 'src' to 'dest' */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

void wrdrev(char *src, char *dest)
{
char *i, *j, *k;

i = j = k = src + (strlen(src)-1);
while (i >= src) {
if (isspace((unsigned char)*i)) {
*dest++ = *i--;

i may point to one past the first array element
k = j = i;
}
else {
while (!isspace((unsigned char)*j) && j >= src) k = --j;

so does j

Yes, I acknowledged it in the other post. The fix is simple though.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top