okays... so i'm looking for some kind of a standard algorithm that doesn't take long.
i thought going backwards, finding the first space, writing the last word and nulling (is that even possible?) each char, but that doesn't really sound good to me. I've seen some people say you should double reverse...i can reverse the whole string but i kinda gotta deal with multiple spaces, for example:
" this is a string "
output:
"string a is this"
help!

Recommended Answers

All 5 Replies

okays... so i'm looking for some kind of a standard algorithm that doesn't take long.
i thought going backwards, finding the first space, writing the last word and nulling (is that even possible?) each char, but that doesn't really sound good to me. I've seen some people say you should double reverse...i can reverse the whole string but i kinda gotta deal with multiple spaces, for example:
" this is a string "
output:
"string a is this"
help!

You have two separate tasks for this problem. One, you need to isolate all of the words and stick them in an array or a vector or however you would like to store them. How to do this will probably depend on how the entire sentence is originally stored. I'm guessing it is in a big string that contains "this is a string"? If so, for the first part (isolating the words), the find function may help to find those spaces that separate words:
http://www.cplusplus.com/reference/string/string/find.html

Once you have your array of strings, each element of the array holding one word, there are easy ways to reverse the array. I would suggest going through the array and swapping elements:

Original:

this
is
a
string

First pass (swap first and last):

string
is
a
this

Second pass (swap second to first and second to last):

string
a
is
this

All elements have been swapped after going halfway through the array, so after two swaps (2 is half of the array size of 4), we're done.

I happened to have already made quite a few functions to help do this.
for example:

GetWord(char *text, char *gaps, int bzIndex /* 0 based index */);
cout << GetWord(  "#[]Hello_{World::"  ,   "#[]_{:"  , 0); // Returns "Hello"
cout << GetWord(  "#[]Hello_{World::"  ,   "#[]_{:"  , 1); // Returns "World"

This code does what your asking:

#include<iostream>
using namespace std;

inline char *SubStr(char *text, int beg, int end) {
	register int len = end - beg;
	char *cut = new char[len];
	memcpy_s(cut,(rsize_t)len, &text[beg], (size_t)len);
	cut[len] = '\0';
	return cut;
}

inline bool TextContains(char *txt, char ch) {
	while(*txt++)if (*(txt-1)==ch)return 1;
	return 0;
}

char *GetWord(char *text, char *gaps, int bzIndex) {
	int i = 0, sc = 0, ec = 0, g = 0;
	for (; text[i] && TextContains(gaps, text[i]); i++);
	for (sc = i; text[i]; i++) {
		if (TextContains(gaps, text[i])) {
			while (text[i] && TextContains(gaps, text[i+1])) i++;
			if (++g == bzIndex) sc=i+1;
		} else if (g == bzIndex) {
			while (text[i] && !TextContains(gaps, text[i])) i++;
			ec = i;
			break;
		}
	}
	return SubStr(text, sc, ec);
}

int CountWords(char *text, char *gaps) {
	register bool t = 0, ot = 0;
	register int wc = 0, i = 0;
	while (TextContains(gaps, text[i])) i++;
	for (;text[i];i++) {
		t = TextContains(gaps, text[i]);
		if (t != ot) wc++;
		ot = t;
	}
	return (wc/2)+1;
}

int main() {
	char str[] = " this is a string ";
	for (int i = CountWords(str, " ")-1; i >= 0; i--) {
		cout << GetWord(str, " ", i) << (i != 0 ? " " : "");
	}
	cin.ignore();
	return 0;
}

Hope it helps!

Umm, i finally came up with this, it's a result of my first idea of nulling... hope you people don't mind, i often mix c# and c++ cause i like the cstdio input.. this is the final thing, please post any ideas of making it shorter...

#include <cstdio>
#include <cstring>

int lraz(char s[100])
{   int p;
    for(int i = strlen(s); i >= 0; i--)
                if(s[i] == ' ')
                        {
                        p = i;
                        break;
                        }
    return p;
}
int addnull(char s[100])
{
    for(int i = strlen(s); i >= 0; i--)
    s[i+1] = s[i];
    s[0] = ' ';
}

int main( void )
{   
    char str1[100], str2[100];
    gets(str1);
    addnull(str1);
    while(strlen(str1) > 1)
    {
                    for(int i = lraz(str1)+1; i <= strlen(str1); i++)
                    {
                            printf("%c", str1[i]);
                            if(i == strlen(str1))
                            printf("");
                    }
                    str1[lraz(str1)] = NULL;
    } 
    for(int i = 0; i < strlen(str1); i++)
    printf("%c", str1[i]);
    
    scanf("\n");
    return 0;
}

i guess you all know c# here anyways... I'd also appreciate any comments on the code, i'm only starting c#/c++ and i wanna do best i can (i'm studying for competitions and stuff like that) Thanks alot!!!

> i finally came up with this, it's a result of my first idea of nulling...
Clever solution! Ed likes it, and to be honest, the only way Ed could improve on it would be to clean up the code a bit, make it tighter, and add Edward's style:

#include <cstdio>
#include <cstring>
#include <cctype>

int IsEnd(char ch)
{
  return ch == '\0' || isspace(ch);
}

int IndexOfLastWord(char *src)
{
  int start = strlen(src) - 1;

  // Skip trailing whitespace
  while (start > 0 && isspace(src[start]))
    --start;

  // Skip trailing non-whitespace
  while (start > 0 && !isspace(src[start]))
    --start;

  // Reverse back over a leading space
  if (isspace(src[start]))
    ++start;

  return start;
}

int main()
{   
  char s[100];

  fgets(s, sizeof s, stdin);

  while (s[0] != '\0') {
    int start = IndexOfLastWord(s);

    for (int i = start; !IsEnd(s[i]); ++i)
      putchar(s[i]);

    // Separate the words
    putchar(' ');

    // Remove the word that was just printed
    s[start] = '\0';
  }

  putchar('\n');
}

> please post any ideas of making it shorter...
Shorter doesn't equal better. Sometimes you have to make it longer to get better code. :)

> int lraz(char s[100])
lraz isn't a good name. Even after reading the code and understanding what it does, Edward still can't fathom the name of the function...

> void addnull(char s[100])
addnull doesn't actually add a null, it prepends a space.

> gets(str1);
Edward can't in good conscience critique code that uses gets without the obligatory mention that it's unsafe and to use fgets instead even though they don't work exactly the same. ;) Here's a utility function that copies gets but puts a limit on the number of characters that it'll read:

char *awesome_gets(char *dst, int limit)
{
  char *result = fgets(dst, limit, stdin);

  if (result != NULL) {
    // Trim the newline character
    char *nl = strchr(dst, '\n');

    if (nl != NULL)
      *dst = '\0';
  }

  return result;
}

> str1[lraz(str1)] = NULL;
NULL is 0 in C++ and 0 is identical to '\0', but when Ed sees NULL, she thinks of pointers. It's a good practice to use '\0' for characters, NULL for pointers, and 0 for everything else.

umm, yeah, i use some stuff from my own language for the variable and function names...and i'm not too creative at doing that to be honest..:P
i made the space adding function cause it didn't print the last word when there was no space... didn't bother why really cause the extra space seemed to fix it. thanks for the tips, Ed!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.